mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Merge pull request #1969 from coder2020official/botapi6.7
Bot API 6.7 - Not much to do, just minor improvements
This commit is contained in:
commit
abec3dc60e
@ -10,7 +10,7 @@
|
|||||||
<p align="center">A simple, but extensible Python implementation for the <a href="https://core.telegram.org/bots/api">Telegram Bot API</a>.</p>
|
<p align="center">A simple, but extensible Python implementation for the <a href="https://core.telegram.org/bots/api">Telegram Bot API</a>.</p>
|
||||||
<p align="center">Both synchronous and asynchronous.</p>
|
<p align="center">Both synchronous and asynchronous.</p>
|
||||||
|
|
||||||
## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#march-9-2023">6.6</a>!
|
## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#april-21-2023">6.7</a>!
|
||||||
|
|
||||||
<h2><a href='https://pytba.readthedocs.io/en/latest/index.html'>Official documentation</a></h2>
|
<h2><a href='https://pytba.readthedocs.io/en/latest/index.html'>Official documentation</a></h2>
|
||||||
<h2><a href='https://pytba.readthedocs.io/ru/latest/index.html'>Official ru documentation</a></h2>
|
<h2><a href='https://pytba.readthedocs.io/ru/latest/index.html'>Official ru documentation</a></h2>
|
||||||
|
@ -3443,6 +3443,40 @@ class TeleBot:
|
|||||||
"""
|
"""
|
||||||
result = apihelper.get_my_commands(self.token, scope, language_code)
|
result = apihelper.get_my_commands(self.token, scope, language_code)
|
||||||
return [types.BotCommand.de_json(cmd) for cmd in result]
|
return [types.BotCommand.de_json(cmd) for cmd in result]
|
||||||
|
|
||||||
|
def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=None):
|
||||||
|
"""
|
||||||
|
Use this method to change the bot's name. Returns True on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#setmyname
|
||||||
|
|
||||||
|
:param name: Optional. New bot name; 0-64 characters. Pass an empty string to remove the dedicated name for the given language.
|
||||||
|
:type name: :obj:`str`
|
||||||
|
|
||||||
|
:param language_code: Optional. A two-letter ISO 639-1 language code. If empty, the name will be shown to all users for whose
|
||||||
|
language there is no dedicated name.
|
||||||
|
:type language_code: :obj:`str`
|
||||||
|
|
||||||
|
:return: True on success.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return apihelper.set_my_name(self.token, name, language_code)
|
||||||
|
|
||||||
|
def get_my_name(self, language_code: Optional[str]=None):
|
||||||
|
"""
|
||||||
|
Use this method to get the current bot name for the given user language.
|
||||||
|
Returns BotName on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#getmyname
|
||||||
|
|
||||||
|
:param language_code: Optional. A two-letter ISO 639-1 language code or an empty string
|
||||||
|
:type language_code: :obj:`str`
|
||||||
|
|
||||||
|
:return: :class:`telebot.types.BotName`
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = apihelper.get_my_name(self.token, language_code)
|
||||||
|
return types.BotName.de_json(result)
|
||||||
|
|
||||||
def set_my_description(self, description: Optional[str]=None, language_code: Optional[str]=None):
|
def set_my_description(self, description: Optional[str]=None, language_code: Optional[str]=None):
|
||||||
"""
|
"""
|
||||||
@ -3450,6 +3484,8 @@ class TeleBot:
|
|||||||
the chat with the bot if the chat is empty.
|
the chat with the bot if the chat is empty.
|
||||||
Returns True on success.
|
Returns True on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#setmydescription
|
||||||
|
|
||||||
:param description: New bot description; 0-512 characters. Pass an empty string to remove the dedicated description for the given language.
|
:param description: New bot description; 0-512 characters. Pass an empty string to remove the dedicated description for the given language.
|
||||||
:type description: :obj:`str`
|
:type description: :obj:`str`
|
||||||
|
|
||||||
@ -3467,6 +3503,8 @@ class TeleBot:
|
|||||||
Use this method to get the current bot description for the given user language.
|
Use this method to get the current bot description for the given user language.
|
||||||
Returns BotDescription on success.
|
Returns BotDescription on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#getmydescription
|
||||||
|
|
||||||
:param language_code: A two-letter ISO 639-1 language code or an empty string
|
:param language_code: A two-letter ISO 639-1 language code or an empty string
|
||||||
:type language_code: :obj:`str`
|
:type language_code: :obj:`str`
|
||||||
|
|
||||||
@ -3481,6 +3519,8 @@ class TeleBot:
|
|||||||
is sent together with the link when users share the bot.
|
is sent together with the link when users share the bot.
|
||||||
Returns True on success.
|
Returns True on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#setmyshortdescription
|
||||||
|
|
||||||
:param short_description: New short description for the bot; 0-120 characters. Pass an empty string to remove the dedicated short description for the given language.
|
:param short_description: New short description for the bot; 0-120 characters. Pass an empty string to remove the dedicated short description for the given language.
|
||||||
:type short_description: :obj:`str`
|
:type short_description: :obj:`str`
|
||||||
|
|
||||||
@ -3498,6 +3538,8 @@ class TeleBot:
|
|||||||
Use this method to get the current bot short description for the given user language.
|
Use this method to get the current bot short description for the given user language.
|
||||||
Returns BotShortDescription on success.
|
Returns BotShortDescription on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#getmyshortdescription
|
||||||
|
|
||||||
:param language_code: A two-letter ISO 639-1 language code or an empty string
|
:param language_code: A two-letter ISO 639-1 language code or an empty string
|
||||||
:type language_code: :obj:`str`
|
:type language_code: :obj:`str`
|
||||||
|
|
||||||
@ -4479,7 +4521,8 @@ class TeleBot:
|
|||||||
is_personal: Optional[bool]=None,
|
is_personal: Optional[bool]=None,
|
||||||
next_offset: Optional[str]=None,
|
next_offset: Optional[str]=None,
|
||||||
switch_pm_text: Optional[str]=None,
|
switch_pm_text: Optional[str]=None,
|
||||||
switch_pm_parameter: Optional[str]=None) -> bool:
|
switch_pm_parameter: Optional[str]=None,
|
||||||
|
button: Optional[types.InlineQueryResultsButton]=None) -> bool:
|
||||||
"""
|
"""
|
||||||
Use this method to send answers to an inline query. On success, True is returned.
|
Use this method to send answers to an inline query. On success, True is returned.
|
||||||
No more than 50 results per query are allowed.
|
No more than 50 results per query are allowed.
|
||||||
@ -4515,11 +4558,18 @@ class TeleBot:
|
|||||||
:param switch_pm_text: Parameter for the start message sent to the bot when user presses the switch button
|
:param switch_pm_text: Parameter for the start message sent to the bot when user presses the switch button
|
||||||
:type switch_pm_text: :obj:`str`
|
:type switch_pm_text: :obj:`str`
|
||||||
|
|
||||||
|
:param button: A JSON-serialized object describing a button to be shown above inline query results
|
||||||
|
:type button: :obj:`types.InlineQueryResultsButton`
|
||||||
|
|
||||||
:return: On success, True is returned.
|
:return: On success, True is returned.
|
||||||
:rtype: :obj:`bool`
|
:rtype: :obj:`bool`
|
||||||
"""
|
"""
|
||||||
|
if not button and (switch_pm_text or switch_pm_parameter):
|
||||||
|
logger.warning("switch_pm_text and switch_pm_parameter are deprecated for answer_inline_query. Use button instead.")
|
||||||
|
button = types.InlineQueryResultsButton(text=switch_pm_text, start_parameter=switch_pm_parameter)
|
||||||
|
|
||||||
return apihelper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset,
|
return apihelper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset,
|
||||||
switch_pm_text, switch_pm_parameter)
|
button)
|
||||||
|
|
||||||
def answer_callback_query(
|
def answer_callback_query(
|
||||||
self, callback_query_id: int,
|
self, callback_query_id: int,
|
||||||
|
@ -1196,6 +1196,22 @@ def get_my_commands(token, scope=None, language_code=None):
|
|||||||
payload['language_code'] = language_code
|
payload['language_code'] = language_code
|
||||||
return _make_request(token, method_url, params=payload)
|
return _make_request(token, method_url, params=payload)
|
||||||
|
|
||||||
|
def set_my_name(token, name=None, language_code=None):
|
||||||
|
method_url = r'setMyName'
|
||||||
|
payload = {}
|
||||||
|
if name is not None:
|
||||||
|
payload['name'] = name
|
||||||
|
if language_code is not None:
|
||||||
|
payload['language_code'] = language_code
|
||||||
|
return _make_request(token, method_url, params=payload, method='post')
|
||||||
|
|
||||||
|
def get_my_name(token, language_code=None):
|
||||||
|
method_url = r'getMyName'
|
||||||
|
payload = {}
|
||||||
|
if language_code is not None:
|
||||||
|
payload['language_code'] = language_code
|
||||||
|
return _make_request(token, method_url, params=payload)
|
||||||
|
|
||||||
def set_chat_menu_button(token, chat_id=None, menu_button=None):
|
def set_chat_menu_button(token, chat_id=None, menu_button=None):
|
||||||
method_url = r'setChatMenuButton'
|
method_url = r'setChatMenuButton'
|
||||||
payload = {}
|
payload = {}
|
||||||
@ -1598,7 +1614,7 @@ def answer_callback_query(token, callback_query_id, text=None, show_alert=None,
|
|||||||
|
|
||||||
|
|
||||||
def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
|
def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
|
||||||
switch_pm_text=None, switch_pm_parameter=None):
|
button=None):
|
||||||
method_url = 'answerInlineQuery'
|
method_url = 'answerInlineQuery'
|
||||||
payload = {'inline_query_id': inline_query_id, 'results': _convert_list_json_serializable(results)}
|
payload = {'inline_query_id': inline_query_id, 'results': _convert_list_json_serializable(results)}
|
||||||
if cache_time is not None:
|
if cache_time is not None:
|
||||||
@ -1607,10 +1623,8 @@ def answer_inline_query(token, inline_query_id, results, cache_time=None, is_per
|
|||||||
payload['is_personal'] = is_personal
|
payload['is_personal'] = is_personal
|
||||||
if next_offset is not None:
|
if next_offset is not None:
|
||||||
payload['next_offset'] = next_offset
|
payload['next_offset'] = next_offset
|
||||||
if switch_pm_text:
|
if button is not None:
|
||||||
payload['switch_pm_text'] = switch_pm_text
|
payload["button"] = button.to_json()
|
||||||
if switch_pm_parameter:
|
|
||||||
payload['switch_pm_parameter'] = switch_pm_parameter
|
|
||||||
return _make_request(token, method_url, params=payload, method='post')
|
return _make_request(token, method_url, params=payload, method='post')
|
||||||
|
|
||||||
|
|
||||||
|
@ -4361,6 +4361,40 @@ class AsyncTeleBot:
|
|||||||
result = await asyncio_helper.get_my_commands(self.token, scope, language_code)
|
result = await asyncio_helper.get_my_commands(self.token, scope, language_code)
|
||||||
return [types.BotCommand.de_json(cmd) for cmd in result]
|
return [types.BotCommand.de_json(cmd) for cmd in result]
|
||||||
|
|
||||||
|
async def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=None):
|
||||||
|
"""
|
||||||
|
Use this method to change the bot's name. Returns True on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#setmyname
|
||||||
|
|
||||||
|
:param name: Optional. New bot name; 0-64 characters. Pass an empty string to remove the dedicated name for the given language.
|
||||||
|
:type name: :obj:`str`
|
||||||
|
|
||||||
|
:param language_code: Optional. A two-letter ISO 639-1 language code. If empty, the name will be shown to all users for whose
|
||||||
|
language there is no dedicated name.
|
||||||
|
:type language_code: :obj:`str`
|
||||||
|
|
||||||
|
:return: True on success.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return await asyncio_helper.set_my_name(self.token, name, language_code)
|
||||||
|
|
||||||
|
async def get_my_name(self, language_code: Optional[str]=None):
|
||||||
|
"""
|
||||||
|
Use this method to get the current bot name for the given user language.
|
||||||
|
Returns BotName on success.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#getmyname
|
||||||
|
|
||||||
|
:param language_code: Optional. A two-letter ISO 639-1 language code or an empty string
|
||||||
|
:type language_code: :obj:`str`
|
||||||
|
|
||||||
|
:return: :class:`telebot.types.BotName`
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = await asyncio_helper.get_my_name(self.token, language_code)
|
||||||
|
return types.BotName.de_json(result)
|
||||||
|
|
||||||
async def set_chat_menu_button(self, chat_id: Union[int, str]=None,
|
async def set_chat_menu_button(self, chat_id: Union[int, str]=None,
|
||||||
menu_button: types.MenuButton=None) -> bool:
|
menu_button: types.MenuButton=None) -> bool:
|
||||||
"""
|
"""
|
||||||
@ -5337,7 +5371,8 @@ class AsyncTeleBot:
|
|||||||
is_personal: Optional[bool]=None,
|
is_personal: Optional[bool]=None,
|
||||||
next_offset: Optional[str]=None,
|
next_offset: Optional[str]=None,
|
||||||
switch_pm_text: Optional[str]=None,
|
switch_pm_text: Optional[str]=None,
|
||||||
switch_pm_parameter: Optional[str]=None) -> bool:
|
switch_pm_parameter: Optional[str]=None,
|
||||||
|
button: Optional[types.InlineQueryResultsButton]=None) -> bool:
|
||||||
"""
|
"""
|
||||||
Use this method to send answers to an inline query. On success, True is returned.
|
Use this method to send answers to an inline query. On success, True is returned.
|
||||||
No more than 50 results per query are allowed.
|
No more than 50 results per query are allowed.
|
||||||
@ -5373,11 +5408,18 @@ class AsyncTeleBot:
|
|||||||
:param switch_pm_text: Parameter for the start message sent to the bot when user presses the switch button
|
:param switch_pm_text: Parameter for the start message sent to the bot when user presses the switch button
|
||||||
:type switch_pm_text: :obj:`str`
|
:type switch_pm_text: :obj:`str`
|
||||||
|
|
||||||
|
:param button: A JSON-serialized object describing a button to be shown above inline query results
|
||||||
|
:type button: :obj:`types.InlineQueryResultsButton`
|
||||||
|
|
||||||
:return: On success, True is returned.
|
:return: On success, True is returned.
|
||||||
:rtype: :obj:`bool`
|
:rtype: :obj:`bool`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if not button and (switch_pm_text or switch_pm_parameter):
|
||||||
|
logger.warning("switch_pm_text and switch_pm_parameter are deprecated for answer_inline_query. Use button instead.")
|
||||||
|
button = types.InlineQueryResultsButton(text=switch_pm_text, start_parameter=switch_pm_parameter)
|
||||||
return await asyncio_helper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset,
|
return await asyncio_helper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset,
|
||||||
switch_pm_text, switch_pm_parameter)
|
button)
|
||||||
|
|
||||||
async def answer_callback_query(
|
async def answer_callback_query(
|
||||||
self, callback_query_id: int,
|
self, callback_query_id: int,
|
||||||
|
@ -1183,6 +1183,23 @@ async def get_my_commands(token, scope=None, language_code=None):
|
|||||||
payload['language_code'] = language_code
|
payload['language_code'] = language_code
|
||||||
return await _process_request(token, method_url, params=payload)
|
return await _process_request(token, method_url, params=payload)
|
||||||
|
|
||||||
|
|
||||||
|
async def set_my_name(token, name=None, language_code=None):
|
||||||
|
method_url = r'setMyName'
|
||||||
|
payload = {}
|
||||||
|
if name is not None:
|
||||||
|
payload['name'] = name
|
||||||
|
if language_code is not None:
|
||||||
|
payload['language_code'] = language_code
|
||||||
|
return await _process_request(token, method_url, params=payload, method='post')
|
||||||
|
|
||||||
|
async def get_my_name(token, language_code=None):
|
||||||
|
method_url = r'getMyName'
|
||||||
|
payload = {}
|
||||||
|
if language_code is not None:
|
||||||
|
payload['language_code'] = language_code
|
||||||
|
return await _process_request(token, method_url, params=payload)
|
||||||
|
|
||||||
async def set_chat_menu_button(token, chat_id=None, menu_button=None):
|
async def set_chat_menu_button(token, chat_id=None, menu_button=None):
|
||||||
method_url = r'setChatMenuButton'
|
method_url = r'setChatMenuButton'
|
||||||
payload = {}
|
payload = {}
|
||||||
@ -1587,7 +1604,7 @@ async def answer_callback_query(token, callback_query_id, text=None, show_alert=
|
|||||||
|
|
||||||
|
|
||||||
async def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
|
async def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
|
||||||
switch_pm_text=None, switch_pm_parameter=None):
|
button=None):
|
||||||
method_url = 'answerInlineQuery'
|
method_url = 'answerInlineQuery'
|
||||||
payload = {'inline_query_id': inline_query_id, 'results': await _convert_list_json_serializable(results)}
|
payload = {'inline_query_id': inline_query_id, 'results': await _convert_list_json_serializable(results)}
|
||||||
if cache_time is not None:
|
if cache_time is not None:
|
||||||
@ -1596,10 +1613,10 @@ async def answer_inline_query(token, inline_query_id, results, cache_time=None,
|
|||||||
payload['is_personal'] = is_personal
|
payload['is_personal'] = is_personal
|
||||||
if next_offset is not None:
|
if next_offset is not None:
|
||||||
payload['next_offset'] = next_offset
|
payload['next_offset'] = next_offset
|
||||||
if switch_pm_text:
|
if button is not None:
|
||||||
payload['switch_pm_text'] = switch_pm_text
|
payload["button"] = button.to_json()
|
||||||
if switch_pm_parameter:
|
|
||||||
payload['switch_pm_parameter'] = switch_pm_parameter
|
|
||||||
return await _process_request(token, method_url, params=payload, method='post')
|
return await _process_request(token, method_url, params=payload, method='post')
|
||||||
|
|
||||||
|
|
||||||
|
198
telebot/types.py
198
telebot/types.py
@ -237,6 +237,9 @@ class ChatMemberUpdated(JsonDeserializable):
|
|||||||
link events only.
|
link events only.
|
||||||
:type invite_link: :class:`telebot.types.ChatInviteLink`
|
:type invite_link: :class:`telebot.types.ChatInviteLink`
|
||||||
|
|
||||||
|
:param via_chat_folder_invite_link: Optional. True, if the user joined the chat via a chat folder invite link
|
||||||
|
:type via_chat_folder_invite_link: :obj:`bool`
|
||||||
|
|
||||||
:return: Instance of the class
|
:return: Instance of the class
|
||||||
:rtype: :class:`telebot.types.ChatMemberUpdated`
|
:rtype: :class:`telebot.types.ChatMemberUpdated`
|
||||||
"""
|
"""
|
||||||
@ -251,13 +254,15 @@ class ChatMemberUpdated(JsonDeserializable):
|
|||||||
obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link'))
|
obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link'))
|
||||||
return cls(**obj)
|
return cls(**obj)
|
||||||
|
|
||||||
def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, **kwargs):
|
def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, via_chat_folder_invite_link=None,
|
||||||
|
**kwargs):
|
||||||
self.chat: Chat = chat
|
self.chat: Chat = chat
|
||||||
self.from_user: User = from_user
|
self.from_user: User = from_user
|
||||||
self.date: int = date
|
self.date: int = date
|
||||||
self.old_chat_member: ChatMember = old_chat_member
|
self.old_chat_member: ChatMember = old_chat_member
|
||||||
self.new_chat_member: ChatMember = new_chat_member
|
self.new_chat_member: ChatMember = new_chat_member
|
||||||
self.invite_link: Optional[ChatInviteLink] = invite_link
|
self.invite_link: Optional[ChatInviteLink] = invite_link
|
||||||
|
self.via_chat_folder_invite_link: Optional[bool] = via_chat_folder_invite_link
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def difference(self) -> Dict[str, List]:
|
def difference(self) -> Dict[str, List]:
|
||||||
@ -1308,6 +1313,7 @@ class Message(JsonDeserializable):
|
|||||||
"strikethrough": "<s>{text}</s>",
|
"strikethrough": "<s>{text}</s>",
|
||||||
"underline": "<u>{text}</u>",
|
"underline": "<u>{text}</u>",
|
||||||
"spoiler": "<span class=\"tg-spoiler\">{text}</span>",
|
"spoiler": "<span class=\"tg-spoiler\">{text}</span>",
|
||||||
|
"custom_emoji": "<tg-emoji emoji-id=\"{custom_emoji_id}\">{text}</tg-emoji>"
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasattr(self, "custom_subs"):
|
if hasattr(self, "custom_subs"):
|
||||||
@ -1316,7 +1322,7 @@ class Message(JsonDeserializable):
|
|||||||
utf16_text = text.encode("utf-16-le")
|
utf16_text = text.encode("utf-16-le")
|
||||||
html_text = ""
|
html_text = ""
|
||||||
|
|
||||||
def func(upd_text, subst_type=None, url=None, user=None):
|
def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None):
|
||||||
upd_text = upd_text.decode("utf-16-le")
|
upd_text = upd_text.decode("utf-16-le")
|
||||||
if subst_type == "text_mention":
|
if subst_type == "text_mention":
|
||||||
subst_type = "text_link"
|
subst_type = "text_link"
|
||||||
@ -1327,30 +1333,41 @@ class Message(JsonDeserializable):
|
|||||||
if not subst_type or not _subs.get(subst_type):
|
if not subst_type or not _subs.get(subst_type):
|
||||||
return upd_text
|
return upd_text
|
||||||
subs = _subs.get(subst_type)
|
subs = _subs.get(subst_type)
|
||||||
|
if subst_type == "custom_emoji":
|
||||||
|
return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id)
|
||||||
return subs.format(text=upd_text, url=url)
|
return subs.format(text=upd_text, url=url)
|
||||||
|
|
||||||
offset = 0
|
offset = 0
|
||||||
|
start_index = 0
|
||||||
|
end_index = 0
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
if entity.offset > offset:
|
if entity.offset > offset:
|
||||||
|
# when the offset is not 0: for example, a __b__
|
||||||
|
# we need to add the text before the entity to the html_text
|
||||||
html_text += func(utf16_text[offset * 2 : entity.offset * 2])
|
html_text += func(utf16_text[offset * 2 : entity.offset * 2])
|
||||||
offset = entity.offset
|
offset = entity.offset
|
||||||
html_text += func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user)
|
|
||||||
|
new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user, entity.custom_emoji_id)
|
||||||
|
start_index = len(html_text)
|
||||||
|
html_text += new_string
|
||||||
offset += entity.length
|
offset += entity.length
|
||||||
|
end_index = len(html_text)
|
||||||
elif entity.offset == offset:
|
elif entity.offset == offset:
|
||||||
html_text += func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user)
|
new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user, entity.custom_emoji_id)
|
||||||
|
start_index = len(html_text)
|
||||||
|
html_text += new_string
|
||||||
|
end_index = len(html_text)
|
||||||
offset += entity.length
|
offset += entity.length
|
||||||
else:
|
else:
|
||||||
# Here we are processing nested entities.
|
# Here we are processing nested entities.
|
||||||
# We shouldn't update offset, because they are the same as entity before.
|
# We shouldn't update offset, because they are the same as entity before.
|
||||||
# And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered,
|
# And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered,
|
||||||
# And we don't change it).
|
# And we don't change it).
|
||||||
entity_string = utf16_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
|
entity_string = html_text[start_index : end_index].encode("utf-16-le")
|
||||||
formatted_string = func(entity_string, entity.type, entity.url, entity.user)
|
formatted_string = func(entity_string, entity.type, entity.url, entity.user, entity.custom_emoji_id).replace("&", "&").replace("<", "<").replace(">",">")
|
||||||
entity_string_decoded = entity_string.decode("utf-16-le")
|
html_text = html_text[:start_index] + formatted_string + html_text[end_index:]
|
||||||
last_occurence = html_text.rfind(entity_string_decoded)
|
end_index = len(html_text)
|
||||||
string_length = len(entity_string_decoded)
|
|
||||||
#html_text = html_text.replace(html_text[last_occurence:last_occurence+string_length], formatted_string)
|
|
||||||
html_text = html_text[:last_occurence] + formatted_string + html_text[last_occurence+string_length:]
|
|
||||||
if offset * 2 < len(utf16_text):
|
if offset * 2 < len(utf16_text):
|
||||||
html_text += func(utf16_text[offset * 2:])
|
html_text += func(utf16_text[offset * 2:])
|
||||||
|
|
||||||
@ -2592,6 +2609,10 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable)
|
|||||||
something from multiple options.
|
something from multiple options.
|
||||||
:type switch_inline_query_current_chat: :obj:`str`
|
:type switch_inline_query_current_chat: :obj:`str`
|
||||||
|
|
||||||
|
:param switch_inline_query_chosen_chat: Optional. If set, pressing the button will prompt the user to select one of their chats of the
|
||||||
|
specified type, open that chat and insert the bot's username and the specified inline query in the input field
|
||||||
|
:type switch_inline_query_chosen_chat: :class:`telebot.types.SwitchInlineQueryChosenChat`
|
||||||
|
|
||||||
:param callback_game: Optional. Description of the game that will be launched when the user presses the
|
:param callback_game: Optional. Description of the game that will be launched when the user presses the
|
||||||
button. NOTE: This type of button must always be the first button in the first row.
|
button. NOTE: This type of button must always be the first button in the first row.
|
||||||
:type callback_game: :class:`telebot.types.CallbackGame`
|
:type callback_game: :class:`telebot.types.CallbackGame`
|
||||||
@ -2611,17 +2632,20 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable)
|
|||||||
obj['login_url'] = LoginUrl.de_json(obj.get('login_url'))
|
obj['login_url'] = LoginUrl.de_json(obj.get('login_url'))
|
||||||
if 'web_app' in obj:
|
if 'web_app' in obj:
|
||||||
obj['web_app'] = WebAppInfo.de_json(obj.get('web_app'))
|
obj['web_app'] = WebAppInfo.de_json(obj.get('web_app'))
|
||||||
|
if 'switch_inline_query_chosen_chat' in obj:
|
||||||
|
obj['switch_inline_query_chosen_chat'] = SwitchInlineQueryChosenChat.de_json(obj.get('switch_inline_query_chosen_chat'))
|
||||||
|
|
||||||
return cls(**obj)
|
return cls(**obj)
|
||||||
|
|
||||||
def __init__(self, text, url=None, callback_data=None, web_app=None, switch_inline_query=None,
|
def __init__(self, text, url=None, callback_data=None, web_app=None, switch_inline_query=None,
|
||||||
switch_inline_query_current_chat=None, callback_game=None, pay=None, login_url=None, **kwargs):
|
switch_inline_query_current_chat=None, switch_inline_query_chosen_chat=None, callback_game=None, pay=None, login_url=None, **kwargs):
|
||||||
self.text: str = text
|
self.text: str = text
|
||||||
self.url: str = url
|
self.url: str = url
|
||||||
self.callback_data: str = callback_data
|
self.callback_data: str = callback_data
|
||||||
self.web_app: WebAppInfo = web_app
|
self.web_app: WebAppInfo = web_app
|
||||||
self.switch_inline_query: str = switch_inline_query
|
self.switch_inline_query: str = switch_inline_query
|
||||||
self.switch_inline_query_current_chat: str = switch_inline_query_current_chat
|
self.switch_inline_query_current_chat: str = switch_inline_query_current_chat
|
||||||
|
self.switch_inline_query_chosen_chat: SwitchInlineQueryChosenChat = switch_inline_query_chosen_chat
|
||||||
self.callback_game = callback_game # Not Implemented
|
self.callback_game = callback_game # Not Implemented
|
||||||
self.pay: bool = pay
|
self.pay: bool = pay
|
||||||
self.login_url: LoginUrl = login_url
|
self.login_url: LoginUrl = login_url
|
||||||
@ -2647,6 +2671,8 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable)
|
|||||||
json_dict['pay'] = self.pay
|
json_dict['pay'] = self.pay
|
||||||
if self.login_url is not None:
|
if self.login_url is not None:
|
||||||
json_dict['login_url'] = self.login_url.to_dict()
|
json_dict['login_url'] = self.login_url.to_dict()
|
||||||
|
if self.switch_inline_query_chosen_chat is not None:
|
||||||
|
json_dict['switch_inline_query_chosen_chat'] = self.switch_inline_query_chosen_chat.to_dict()
|
||||||
return json_dict
|
return json_dict
|
||||||
|
|
||||||
|
|
||||||
@ -7396,13 +7422,20 @@ class WriteAccessAllowed(JsonDeserializable):
|
|||||||
Currently holds no information.
|
Currently holds no information.
|
||||||
|
|
||||||
Telegram documentation: https://core.telegram.org/bots/api#writeaccessallowed
|
Telegram documentation: https://core.telegram.org/bots/api#writeaccessallowed
|
||||||
|
|
||||||
|
:param web_app_name: Optional. Name of the Web App which was launched from a link
|
||||||
|
:type web_app_name: :obj:`str`
|
||||||
"""
|
"""
|
||||||
@classmethod
|
@classmethod
|
||||||
def de_json(cls, json_string):
|
def de_json(cls, json_string):
|
||||||
return cls()
|
if json_string is None: return None
|
||||||
|
obj = cls.check_json(json_string)
|
||||||
|
return cls(**obj)
|
||||||
|
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, web_app_name: str) -> None:
|
||||||
pass
|
self.web_app_name: str = web_app_name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserShared(JsonDeserializable):
|
class UserShared(JsonDeserializable):
|
||||||
@ -7576,4 +7609,137 @@ class InputSticker(Dictionaryable, JsonSerializable):
|
|||||||
return self.to_json(), {self._sticker_name: self.sticker}
|
return self.to_json(), {self._sticker_name: self.sticker}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SwitchInlineQueryChosenChat(JsonDeserializable, Dictionaryable, JsonSerializable):
|
||||||
|
"""
|
||||||
|
Represents an inline button that switches the current user to inline mode in a chosen chat,
|
||||||
|
with an optional default inline query.
|
||||||
|
|
||||||
|
Telegram Documentation: https://core.telegram.org/bots/api#inlinekeyboardbutton
|
||||||
|
|
||||||
|
:param query: Optional. The default inline query to be inserted in the input field.
|
||||||
|
If left empty, only the bot's username will be inserted
|
||||||
|
:type query: :obj:`str`
|
||||||
|
|
||||||
|
:param allow_user_chats: Optional. True, if private chats with users can be chosen
|
||||||
|
:type allow_user_chats: :obj:`bool`
|
||||||
|
|
||||||
|
:param allow_bot_chats: Optional. True, if private chats with bots can be chosen
|
||||||
|
:type allow_bot_chats: :obj:`bool`
|
||||||
|
|
||||||
|
:param allow_group_chats: Optional. True, if group and supergroup chats can be chosen
|
||||||
|
:type allow_group_chats: :obj:`bool`
|
||||||
|
|
||||||
|
:param allow_channel_chats: Optional. True, if channel chats can be chosen
|
||||||
|
:type allow_channel_chats: :obj:`bool`
|
||||||
|
|
||||||
|
:return: Instance of the class
|
||||||
|
:rtype: :class:`SwitchInlineQueryChosenChat`
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def de_json(cls, json_string):
|
||||||
|
if json_string is None:
|
||||||
|
return None
|
||||||
|
obj = cls.check_json(json_string)
|
||||||
|
return cls(**obj)
|
||||||
|
|
||||||
|
def __init__(self, query=None, allow_user_chats=None, allow_bot_chats=None, allow_group_chats=None,
|
||||||
|
allow_channel_chats=None):
|
||||||
|
self.query: str = query
|
||||||
|
self.allow_user_chats: bool = allow_user_chats
|
||||||
|
self.allow_bot_chats: bool = allow_bot_chats
|
||||||
|
self.allow_group_chats: bool = allow_group_chats
|
||||||
|
self.allow_channel_chats: bool = allow_channel_chats
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
json_dict = {}
|
||||||
|
|
||||||
|
if self.query is not None:
|
||||||
|
json_dict['query'] = self.query
|
||||||
|
if self.allow_user_chats is not None:
|
||||||
|
json_dict['allow_user_chats'] = self.allow_user_chats
|
||||||
|
if self.allow_bot_chats is not None:
|
||||||
|
json_dict['allow_bot_chats'] = self.allow_bot_chats
|
||||||
|
if self.allow_group_chats is not None:
|
||||||
|
json_dict['allow_group_chats'] = self.allow_group_chats
|
||||||
|
if self.allow_channel_chats is not None:
|
||||||
|
json_dict['allow_channel_chats'] = self.allow_channel_chats
|
||||||
|
|
||||||
|
return json_dict
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
return json.dumps(self.to_dict())
|
||||||
|
|
||||||
|
|
||||||
|
class BotName(JsonDeserializable):
|
||||||
|
"""
|
||||||
|
This object represents a bot name.
|
||||||
|
|
||||||
|
Telegram Documentation: https://core.telegram.org/bots/api#botname
|
||||||
|
|
||||||
|
:param name: The bot name
|
||||||
|
:type name: :obj:`str`
|
||||||
|
|
||||||
|
:return: Instance of the class
|
||||||
|
:rtype: :class:`BotName`
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def de_json(cls, json_string):
|
||||||
|
if json_string is None:
|
||||||
|
return None
|
||||||
|
obj = cls.check_json(json_string)
|
||||||
|
return cls(**obj)
|
||||||
|
|
||||||
|
def __init__(self, name: str):
|
||||||
|
self.name: str = name
|
||||||
|
|
||||||
|
|
||||||
|
class InlineQueryResultsButton(JsonSerializable, Dictionaryable):
|
||||||
|
"""
|
||||||
|
This object represents a button to be shown above inline query results.
|
||||||
|
You must use exactly one of the optional fields.
|
||||||
|
|
||||||
|
Telegram documentation: https://core.telegram.org/bots/api#inlinequeryresultsbutton
|
||||||
|
|
||||||
|
:param text: Label text on the button
|
||||||
|
:type text: :obj:`str`
|
||||||
|
|
||||||
|
:param web_app: Optional. Description of the Web App that will be launched when the user presses the button.
|
||||||
|
The Web App will be able to switch back to the inline mode using the method web_app_switch_inline_query inside the Web App.
|
||||||
|
:type web_app: :class:`telebot.types.WebAppInfo`
|
||||||
|
|
||||||
|
:param start_parameter: Optional. Deep-linking parameter for the /start message sent to the bot when a user presses the button.
|
||||||
|
1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed.
|
||||||
|
Example: An inline bot that sends YouTube videos can ask the user to connect the bot to their YouTube account to adapt search
|
||||||
|
results accordingly. To do this, it displays a 'Connect your YouTube account' button above the results, or even before showing
|
||||||
|
any. The user presses the button, switches to a private chat with the bot and, in doing so, passes a start parameter that instructs
|
||||||
|
the bot to return an OAuth link. Once done, the bot can offer a switch_inline button so that the user can easily return to the chat
|
||||||
|
where they wanted to use the bot's inline capabilities.
|
||||||
|
:type start_parameter: :obj:`str`
|
||||||
|
|
||||||
|
:return: Instance of the class
|
||||||
|
:rtype: :class:`InlineQueryResultsButton`
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, text: str, web_app: Optional[WebAppInfo]=None, start_parameter: Optional[str]=None) -> None:
|
||||||
|
self.text: str = text
|
||||||
|
self.web_app: Optional[WebAppInfo] = web_app
|
||||||
|
self.start_parameter: Optional[str] = start_parameter
|
||||||
|
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
json_dict = {
|
||||||
|
'text': self.text
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.web_app is not None:
|
||||||
|
json_dict['web_app'] = self.web_app.to_dict()
|
||||||
|
if self.start_parameter is not None:
|
||||||
|
json_dict['start_parameter'] = self.start_parameter
|
||||||
|
|
||||||
|
return json_dict
|
||||||
|
|
||||||
|
def to_json(self) -> str:
|
||||||
|
return json.dumps(self.to_dict())
|
@ -271,5 +271,33 @@ def test_sent_web_app_message():
|
|||||||
assert sent_web_app_message.inline_message_id == '29430'
|
assert sent_web_app_message.inline_message_id == '29430'
|
||||||
|
|
||||||
|
|
||||||
|
def test_message_entity():
|
||||||
|
# TODO: Add support for nesting entities
|
||||||
|
|
||||||
|
|
||||||
|
sample_string_1 = r'{"update_id":934522126,"message":{"message_id":1374510,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682177590,"text":"b b b","entities":[{"offset":0,"length":2,"type":"bold"},{"offset":0,"length":1,"type":"italic"},{"offset":2,"length":2,"type":"bold"},{"offset":2,"length":1,"type":"italic"},{"offset":4,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}'
|
||||||
|
update = types.Update.de_json(sample_string_1)
|
||||||
|
message: types.Message = update.message
|
||||||
|
assert message.html_text == "<i><b>b </b></i><i><b>b </b></i><i><b>b</b></i>"
|
||||||
|
|
||||||
|
sample_string_2 = r'{"update_id":934522166,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"text":"b b b","entities":[{"offset":0,"length":1,"type":"bold"},{"offset":2,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}'
|
||||||
|
message_2 = types.Update.de_json(sample_string_2).message
|
||||||
|
assert message_2.html_text == "<b>b</b> <b>b</b> <i>b</i>"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sample_string_3 = r'{"update_id":934522172,"message":{"message_id":1374530,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179968,"text":"This is a bold text with a nested italic and bold text.","entities":[{"offset":10,"length":4,"type":"bold"},{"offset":27,"length":7,"type":"italic"},{"offset":34,"length":15,"type":"bold"},{"offset":34,"length":15,"type":"italic"}]}}'
|
||||||
|
message_3 = types.Update.de_json(sample_string_3).message
|
||||||
|
assert message_3.html_text == "This is a <b>bold</b> text with a <i>nested </i><i><b>italic and bold</b></i> text."
|
||||||
|
|
||||||
|
|
||||||
|
sample_string_4 = r'{"update_id":934522437,"message":{"message_id":1374619,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682189507,"forward_from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"forward_date":1682189124,"text":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa😋😋","entities":[{"offset":0,"length":76,"type":"bold"},{"offset":0,"length":76,"type":"italic"},{"offset":0,"length":76,"type":"underline"},{"offset":0,"length":76,"type":"strikethrough"},{"offset":76,"length":2,"type":"custom_emoji","custom_emoji_id":"5456188142006575553"},{"offset":78,"length":2,"type":"custom_emoji","custom_emoji_id":"5456188142006575553"}]}}'
|
||||||
|
message_4 = types.Update.de_json(sample_string_4).message
|
||||||
|
assert message_4.html_text == '<s><u><i><b>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</b></i></u></s><tg-emoji emoji-id="5456188142006575553">😋</tg-emoji><tg-emoji emoji-id="5456188142006575553">😋</tg-emoji>'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user