Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 48 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,16 @@ pdm add telegramify-markdown -G mermaid
- If you are developing an *LLM application* or need to send potentially **super-long text**, please
check:[playground/telegramify_case.py](https://github.com/sudoskys/telegramify-markdown/blob/main/playground/telegramify_case.py)

We have two main functions: `markdownify` and `telegramify`.
- If you want to write TelegramV2 format text directly in bot, please check:[playground/standardize_case.py](https://github.com/sudoskys/telegramify-markdown/blob/main/playground/standardize_case.py)

`markdownify`: Just converts raw Markdown text to Telegram's MarkdownV2 format.
We have three main functions: `markdownify`, `telegramify`, and `standardize`.

`markdownify`: Just converts raw Markdown text to Telegram's MarkdownV2 format, used for LLM like ChatGPT.

`telegramify`: Spilt long text into multiple chunks, convert format and use Interpreter to render code block to File,
Image etc.
Image etc, used for LLM bot developers who want do more with Telegram's MarkdownV2 format.

`standardize`: Convert unstandardized Telegram's MarkdownV2 format to standardized format(convenient for bot developers write something directly in bot).

> `Interpreter` can be easily customized to inspect the rendering process in `telegramify`.

Expand Down Expand Up @@ -155,6 +159,47 @@ print(converted)
please
check: [playground/telegramify_case.py](https://github.com/sudoskys/telegramify-markdown/blob/main/playground/telegramify_case.py)

### `standardize`

```python
import telegramify_markdown
from telegramify_markdown.customize import get_runtime_config

# Customize symbols (optional)
markdown_symbol = get_runtime_config().markdown_symbol
markdown_symbol.head_level_1 = "📌" # Customize the first level title symbol
markdown_symbol.link = "🔗" # Customize the link symbol

# Telegram MarkdownV2 format text
telegram_v2 = r"""
# Title
*bold \*text*
_italic \*text_
__underline__
~strikethrough~
||spoiler||
*bold _italic bold ~italic bold strikethrough ||italic bold strikethrough spoiler||~ __underline italic bold___ bold*

```python
pre-formatted fixed-width code block written in the Python programming language
```

>Block quotation started
>Block quotation continued
>The last line of the block quotation
"""

# Standardize processing
converted = telegramify_markdown.standardize(telegram_v2)

# Send to Telegram
bot.send_message(
chat_id,
converted,
parse_mode="MarkdownV2" # Must use MarkdownV2 parsing mode
)
```

## 🔨 Supported Input

- [x] Headings (Levels 1-6)
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions playground/max_line.py → feature-test/debug_maxline.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import telegramify_markdown
from telegramify_markdown import customize
from telegramify_markdown.customize import get_runtime_config

customize.strict_markdown = True
get_runtime_config().strict_markdown = True

md = """
[Treating Otitis Externa in Dogs | Today's Veterinary Practice](https://todaysveterinarypractice.com/dermatology/treating-otitis-externa-in-dogs/)
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
from telebot import TeleBot

import telegramify_markdown
from telegramify_markdown.customize import markdown_symbol
from telegramify_markdown.customize import get_runtime_config
from telegramify_markdown.type import ContentTypes

markdown_symbol = get_runtime_config().markdown_symbol

tips = """
telegramify_markdown.telegramify
telegramify_markdown.telegramify

The stability of telegramify_markdown.telegramify is unproven, please keep good log records.

Expand All @@ -25,7 +27,7 @@

markdown_symbol.head_level_1 = "📌" # If you want, Customizing the head level 1 symbol
markdown_symbol.link = "🔗" # If you want, Customizing the link symbol
md = pathlib.Path(__file__).parent.joinpath("t_longtext.md").read_text(encoding="utf-8")
md = pathlib.Path(__file__).parent.parent.joinpath('playground').joinpath("t_longtext.md").read_text(encoding="utf-8")


async def main():
Expand Down
15 changes: 15 additions & 0 deletions feature-test/latex_render_case2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

import matplotlib.pyplot as plt

from matplotlib import rcParams
rcParams['text.usetex'] = True

txte = r"The \emph{characteristic polynomial} $\chi(\lambda)$ of the $3 \times 3$~matrix \\ $\left( \begin{array}{ccc} a & b & c \\ d & e & f \\g & h & i \end{array} \right) $ \\is given by the formula\\ $ \chi(\lambda) = \left| \begin{array}{ccc} \lambda - a & -b & -c \\ -d & \lambda - e & -f \\ -g & -h & \lambda - i \end{array} \right|. $"


plt.text(0.0, 0.0, txte, fontsize=14)
ax = plt.gca()
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)

plt.show()
78 changes: 69 additions & 9 deletions playground/markdownify_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@

import telegramify_markdown

customize = telegramify_markdown.customize.get_runtime_config() # Get the global Customize singleton instance

# Customize the markdownify
telegramify_markdown.customize.strict_markdown = False # we need send underline text
customize.strict_markdown = False # treat `__` as underline instead of bold
print("strict_markdown:", customize.strict_markdown)

# Test html tags
html_t = telegramify_markdown.markdownify(
"Hello, World! HTML: <strong>Hello, World!</strong>",
Expand Down Expand Up @@ -68,28 +72,27 @@
'\_', '\*', '\[', '\]', '\(', '\)', '\~', '\`', '\>', '\#', '\+', '\-', '\=', '\|', '\{', '\}', '\.', '\!'
_ , * , [ , ] , ( , ) , ~ , ` , > , # , + , - , = , | , { , } , . , !
We will remove the \ symbol from the original text.
**bold text**
*bold text*
_italic text_
__underline__
~no valid strikethrough~
~~strikethrough~~
~strikethrough~
||spoiler||
*bold _italic bold ~~italic bold strikethrough ||italic bold strikethrough spoiler||~~ __underline italic bold___ bold*
__underline italic bold__
*bold & _italic & __underline & ~~strikethrough & ||spoiler||~~__**_*
__underline _italic *bold*_**__
[link](https://www.google.com)
- [ ] Uncompleted task list item
- [x] Completed task list item
> Quote

>Multiline Quote In Markdown it's not possible to send multiline quote in telegram without using code block or html tag but telegramify_markdown can do it.
>Multiline Quote In Markdown it's not possible to send multiline quote in telegram without using code block or html tag but telegramify_markdown can do it.
---
Text

Text

Text
> If you quote is too long, it will be automatically set in expandable citation.
> If you quote is too long, it will be automatically set in expandable citation.
> This is the second line of the quote.
> `This is the third line of the quote.`
> This is the fourth line of the quote.
Expand Down Expand Up @@ -124,13 +127,70 @@
latex_escape=True
)
print(converted)
# export Markdown to Telegram MarkdownV2 style.

load_dotenv()
telegram_bot_token = os.getenv("TELEGRAM_BOT_TOKEN", None)
chat_id = os.getenv("TELEGRAM_CHAT_ID", None)
bot = TeleBot(telegram_bot_token)
bot.send_message(
chat_id,
converted,
parse_mode="MarkdownV2" # IMPORTANT: Need Send in MarkdownV2 Mode.
parse_mode="MarkdownV2" # IMPORTANT: Must be sent with "MarkdownV2" parse mode
)

MARKDOWN_SYNTAX = r"""
__bold__
**bold text**
_italic text_
*italic text*
~~strikethrough~~
~not a strikethrough~
||spoiler||
"""
# **bold & _italic & __underline & ~strikethrough & ||spoiler||~__****_**

TELEGRAM_SYNTAX = r"""
__underline__
*bold text*
_italic text_
~strikethrough~
~~not a strikethrough~~
||spoiler||
"""
# *bold & _italic & __underline & ~~strikethrough & ||spoiler||~~__**_*


SYNTAX: dict[str, dict[str, list[str]]] = {
"MARKDOWN": {
"underline": [], # Not supported in Markdown
"bold": ["__", "**"],
"italic": ["_", "*"],
"strike": ["~~"],
},
"TELEGRAM": {
"underline": ["__"],
"bold": ["*"],
"italic": ["_"],
"strike": ["~"],
}
}

def generate_expected_strings(syntax: str, func: callable) -> str:
strings = []
for key, values in SYNTAX[syntax].items():
for token in values:
wrap = lambda x: token + x + token
input = wrap("text")
output = func(input).strip()
print(f" {wrap(key):14} => {func(wrap(key)).strip()}")
strings.append(func(f"- Given `{input}`, which becomes `{output}`, we get: {wrap(key)}"))
return "".join(strings)


def generate_output_string(syntax: str, func: callable) -> str:
case = telegramify_markdown.markdownify(f"\n# {syntax} syntax")
print("\n" + case.replace("\\", "").strip())
return case + generate_expected_strings(syntax, func)

bot.send_message(chat_id, generate_output_string("MARKDOWN", telegramify_markdown.markdownify) + telegramify_markdown.markdownify(MARKDOWN_SYNTAX), parse_mode="MarkdownV2")
bot.send_message(chat_id, generate_output_string("TELEGRAM", telegramify_markdown.standardize) + telegramify_markdown.standardize(TELEGRAM_SYNTAX), parse_mode="MarkdownV2")
12 changes: 5 additions & 7 deletions playground/use_case.py → playground/simple_case.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re

import telegramify_markdown
from telegramify_markdown.customize import markdown_symbol
from telegramify_markdown.customize import get_runtime_config

markdown_symbol = get_runtime_config().markdown_symbol

markdown_symbol.head_level_1 = "📌" # If you want, Customizing the head level 1 symbol
markdown_symbol.link = "🔗" # If you want, Customizing the link symbol
Expand All @@ -18,7 +18,7 @@
>1231

"""
test_md = """
test_md = r"""
**bold text**
||spoiler||
"""
Expand All @@ -34,7 +34,7 @@
$ f(x) = \frac{1}{x} $
"""

emoji="""
emoji = r"""
[inline URL](http://www.example.com/)
[inline mention of a user](tg://user?id=123456789)
![👍](tg://emoji?id=5368324170671202286)
Expand All @@ -45,5 +45,3 @@

converted = telegramify_markdown.markdownify(emoji)
print(converted)


57 changes: 57 additions & 0 deletions playground/standardize_case.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os

from dotenv import load_dotenv
from telebot import TeleBot

import telegramify_markdown
from telegramify_markdown.customize import get_runtime_config

markdown_symbol = get_runtime_config().markdown_symbol
markdown_symbol.head_level_1 = "📌" # If you want, Customizing the head level 1 symbol
markdown_symbol.link = "🔗" # If you want, Customizing the link symbol
telegram_v2=r"""
# Title
*bold \*text*
_italic \*text_
__underline__
~strikethrough~
||spoiler||
*bold _italic bold ~italic bold strikethrough ||italic bold strikethrough spoiler||~ __underline italic bold___ bold*
[inline URL](http://www.example.com/)
[inline mention of a user](tg://user?id=123456789)
![👍](tg://emoji?id=5368324170671202286)
`inline fixed-width code`
```
pre-formatted fixed-width code block
```
```python
pre-formatted fixed-width code block written in the Python programming language
```

>Block quotation started
>Block quotation continued
>Block quotation continued
>Block quotation continued
>The last line of the block quotation


**>The expandable block quotation started right after the previous block quotation
>It is separated from the previous block quotation by an empty bold entity
>Expandable block quotation continued
>Hidden by default part of the expandable block quotation started
>Expandable block quotation continued
>The last line of the expandable block quotation with the expandability mark||
"""

converted = telegramify_markdown.standardize(telegram_v2)

# Compare Line
load_dotenv()
telegram_bot_token = os.getenv("TELEGRAM_BOT_TOKEN", None)
chat_id = os.getenv("TELEGRAM_CHAT_ID", None)
bot = TeleBot(telegram_bot_token)
bot.send_message(
chat_id,
converted,
parse_mode="MarkdownV2" # IMPORTANT: Must be sent with "MarkdownV2" parse mode
)
File renamed without changes.
8 changes: 4 additions & 4 deletions playground/telegramify_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
from telebot import TeleBot

import telegramify_markdown
from telegramify_markdown.customize import markdown_symbol
from telegramify_markdown.customize import get_runtime_config
from telegramify_markdown.interpreters import BaseInterpreter, MermaidInterpreter
from telegramify_markdown.type import ContentTypes

tips = """
telegramify_markdown.telegramify
telegramify_markdown.telegramify

The stability of telegramify_markdown.telegramify is unproven, please keep good log records.

Expand All @@ -25,8 +25,8 @@
bot = TeleBot(telegram_bot_token)

# Customizing global rendering options
markdown_symbol.head_level_1 = "📌" # If you want, Customizing the head level 1 symbol
markdown_symbol.link = "🔗" # If you want, Customizing the link symbol
get_runtime_config().markdown_symbol.head_level_1 = "📌" # If you want, Customizing the head level 1 symbol
get_runtime_config().markdown_symbol.link = "🔗" # If you want, Customizing the link symbol
md = pathlib.Path(__file__).parent.joinpath("t_longtext.md").read_text(encoding="utf-8")


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "telegramify-markdown"
version = "0.4.3"
version = "0.4.4"
description = "Makes it easy to send Markdown in Telegram MarkdownV2 style"
authors = [
{ name = "sudoskys", email = "coldlando@hotmail.com" },
Expand Down
Loading