diff --git a/docs/source/formatting.rst b/docs/source/formatting.rst new file mode 100644 index 0000000..89d35f2 --- /dev/null +++ b/docs/source/formatting.rst @@ -0,0 +1,10 @@ +================== +Formatting options +================== + + + +.. automodule:: telebot.formatting + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/index.rst b/docs/source/index.rst index 596f901..5156271 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -49,6 +49,7 @@ Content async_version/index calldata util + formatting diff --git a/examples/asynchronous_telebot/formatting_example.py b/examples/asynchronous_telebot/formatting_example.py new file mode 100644 index 0000000..2e418ea --- /dev/null +++ b/examples/asynchronous_telebot/formatting_example.py @@ -0,0 +1,52 @@ +from telebot.async_telebot import AsyncTeleBot +from telebot import formatting + +bot = AsyncTeleBot('token') + + +@bot.message_handler(commands=['start']) +async def start_message(message): + await bot.send_message( + message.chat.id, + # function which connects all strings + formatting.format_text( + formatting.mbold(message.from_user.first_name, escape=True), # pass escape=True to escape special characters + formatting.mitalic(message.from_user.first_name, escape=True), + formatting.munderline(message.from_user.first_name, escape=True), + formatting.mstrikethrough(message.from_user.first_name, escape=True), + formatting.mcode(message.from_user.first_name, escape=True), + separator=" " # separator separates all strings + ), + parse_mode='MarkdownV2' + ) + + # just a bold text using markdownv2 + await bot.send_message( + message.chat.id, + formatting.mbold(message.from_user.first_name, escape=True), + parse_mode='MarkdownV2' + ) + + # html + await bot.send_message( + message.chat.id, + formatting.format_text( + formatting.hbold(message.from_user.first_name, escape=True), + formatting.hitalic(message.from_user.first_name, escape=True), + formatting.hunderline(message.from_user.first_name, escape=True), + formatting.hstrikethrough(message.from_user.first_name, escape=True), + formatting.hcode(message.from_user.first_name, escape=True), + separator=" " + ), + parse_mode='HTML' + ) + + # just a bold text in html + await bot.send_message( + message.chat.id, + formatting.hbold(message.from_user.first_name, escape=True), + parse_mode='HTML' + ) + +import asyncio +asyncio.run(bot.polling()) \ No newline at end of file diff --git a/examples/formatting_example.py b/examples/formatting_example.py new file mode 100644 index 0000000..29df2d3 --- /dev/null +++ b/examples/formatting_example.py @@ -0,0 +1,51 @@ +from telebot import TeleBot +from telebot import formatting + +bot = TeleBot('TOKEN') + + +@bot.message_handler(commands=['start']) +def start_message(message): + bot.send_message( + message.chat.id, + # function which connects all strings + formatting.format_text( + formatting.mbold(message.from_user.first_name, escape=True), # pass escape=True to escape special characters + formatting.mitalic(message.from_user.first_name, escape=True), + formatting.munderline(message.from_user.first_name, escape=True), + formatting.mstrikethrough(message.from_user.first_name, escape=True), + formatting.mcode(message.from_user.first_name, escape=True), + separator=" " # separator separates all strings + ), + parse_mode='MarkdownV2' + ) + + # just a bold text using markdownv2 + bot.send_message( + message.chat.id, + formatting.mbold(message.from_user.first_name, escape=True), + parse_mode='MarkdownV2' + ) + + # html + bot.send_message( + message.chat.id, + formatting.format_text( + formatting.hbold(message.from_user.first_name, escape=True), + formatting.hitalic(message.from_user.first_name, escape=True), + formatting.hunderline(message.from_user.first_name, escape=True), + formatting.hstrikethrough(message.from_user.first_name, escape=True), + formatting.hcode(message.from_user.first_name, escape=True), + separator=" " + ), + parse_mode='HTML' + ) + + # just a bold text in html + bot.send_message( + message.chat.id, + formatting.hbold(message.from_user.first_name, escape=True), + parse_mode='HTML' + ) + +bot.infinity_polling() \ No newline at end of file diff --git a/telebot/__init__.py b/telebot/__init__.py index 1a67667..d6b98da 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -645,7 +645,7 @@ class TeleBot: else: handled = False if not handled: - logger.error(e) + logger.error(traceback.format_exc()) if not non_stop: self.__stop_polling.set() logger.info("Exception occurred. Stopping.") diff --git a/telebot/formatting.py b/telebot/formatting.py new file mode 100644 index 0000000..fc003c1 --- /dev/null +++ b/telebot/formatting.py @@ -0,0 +1,201 @@ +""" +Markdown & HTML formatting functions. + +.. versionadded:: 4.5.1 +""" + +import html +import re + + +def format_text(*args, separator="\n"): + """ + Formats a list of strings into a single string. + + .. code:: python + + format_text( # just an example + mbold('Hello'), + mitalic('World') + ) + + :param args: Strings to format. + :param separator: The separator to use between each string. + """ + return separator.join(args) + + + +def escape_html(content: str) -> str: + """ + Escapes HTML characters in a string of HTML. + + :param content: The string of HTML to escape. + """ + return html.escape(content) + + +def escape_markdown(content: str) -> str: + """ + Escapes Markdown characters in a string of Markdown. + + Credits: simonsmh + + :param content: The string of Markdown to escape. + """ + + parse = re.sub(r"([_*\[\]()~`>\#\+\-=|\.!])", r"\\\1", content) + reparse = re.sub(r"\\\\([_*\[\]()~`>\#\+\-=|\.!])", r"\1", parse) + return reparse + + +def mbold(content: str, escape: bool=False) -> str: + """ + Returns a Markdown-formatted bold string. + + :param content: The string to bold. + :param escape: True if you need to escape special characters. + """ + return '*{}*'.format(escape_markdown(content) if escape else content) + + +def hbold(content: str, escape: bool=False) -> str: + """ + Returns an HTML-formatted bold string. + + :param content: The string to bold. + :param escape: True if you need to escape special characters. + """ + return '{}'.format(escape_html(content) if escape else content) + + +def mitalic(content: str, escape: bool=False) -> str: + """ + Returns a Markdown-formatted italic string. + + :param content: The string to italicize. + :param escape: True if you need to escape special characters. + """ + return '_{}_\r'.format(escape_markdown(content) if escape else content) + + +def hitalic(content: str, escape: bool=False) -> str: + """ + Returns an HTML-formatted italic string. + + :param content: The string to italicize. + :param escape: True if you need to escape special characters. + """ + return '{}'.format(escape_html(content) if escape else content) + + +def munderline(content: str, escape: bool=False) -> str: + """ + Returns a Markdown-formatted underline string. + + :param content: The string to underline. + :param escape: True if you need to escape special characters. + """ + return '__{}__'.format(escape_markdown(content) if escape else content) + + +def hunderline(content: str, escape: bool=False) -> str: + """ + Returns an HTML-formatted underline string. + + :param content: The string to underline. + :param escape: True if you need to escape special characters. + """ + return '{}'.format(escape_html(content) if escape else content) + + +def mstrikethrough(content: str, escape: bool=False) -> str: + """ + Returns a Markdown-formatted strikethrough string. + + :param content: The string to strikethrough. + :param escape: True if you need to escape special characters. + """ + return '~{}~'.format(escape_markdown(content) if escape else content) + + +def hstrikethrough(content: str, escape: bool=False) -> str: + """ + Returns an HTML-formatted strikethrough string. + + :param content: The string to strikethrough. + :param escape: True if you need to escape special characters. + """ + return '{}'.format(escape_html(content) if escape else content) + + +def mspoiler(content: str, escape: bool=False) -> str: + """ + Returns a Markdown-formatted spoiler string. + + :param content: The string to spoiler. + :param escape: True if you need to escape special characters. + """ + return '||{}||'.format(escape_markdown(content) if escape else content) + + +def hspoiler(content: str, escape: bool=False) -> str: + """ + Returns an HTML-formatted spoiler string. + + :param content: The string to spoiler. + :param escape: True if you need to escape special characters. + """ + return '{}'.format(escape_html(content) if escape else content) + + +def mlink(content: str, url: str, escape: bool=False) -> str: + """ + Returns a Markdown-formatted link string. + + :param content: The string to link. + :param url: The URL to link to. + :param escape: True if you need to escape special characters. + """ + return '[{}]({})'.format(escape_markdown(content), escape_markdown(url) if escape else content) + + +def hlink(content: str, url: str, escape: bool=False) -> str: + """ + Returns an HTML-formatted link string. + + :param content: The string to link. + :param url: The URL to link to. + :param escape: True if you need to escape special characters. + """ + return '{}'.format(escape_html(url), escape_html(content) if escape else content) + + +def mcode(content: str, language: str="", escape: bool=False) -> str: + """ + Returns a Markdown-formatted code string. + + :param content: The string to code. + :param escape: True if you need to escape special characters. + """ + return '```{}\n{}```'.format(language, escape_markdown(content) if escape else content) + + +def hcode(content: str, escape: bool=False) -> str: + """ + Returns an HTML-formatted code string. + + :param content: The string to code. + :param escape: True if you need to escape special characters. + """ + return '{}'.format(escape_html(content) if escape else content) + + +def hpre(content: str, escape: bool=False, language: str="") -> str: + """ + Returns an HTML-formatted preformatted string. + + :param content: The string to preformatted. + :param escape: True if you need to escape special characters. + """ + return '
{}
'.format(language, escape_html(content) if escape else content) \ No newline at end of file