mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Completed docstrings for all files except types.py
This commit is contained in:
parent
7c12162576
commit
b0e06253ff
@ -84,10 +84,13 @@ class TeleBot:
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python3
|
||||
:caption: Creating instance of TeleBot
|
||||
|
||||
from telebot import TeleBot
|
||||
bot = TeleBot('token') # get token from @BotFather
|
||||
# now you can register other handlers/update listeners,
|
||||
# and use bot methods.
|
||||
|
||||
See more examples in examples/ directory:
|
||||
https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples
|
||||
@ -243,7 +246,7 @@ class TeleBot:
|
||||
Enable saving states (by default saving disabled)
|
||||
|
||||
.. note::
|
||||
It is recommended to pass a :class:`~telebot.storage.StateMemoryStorage` instance as state_storage
|
||||
It is recommended to pass a :class:`~telebot.storage.StatePickleStorage` instance as state_storage
|
||||
to TeleBot class.
|
||||
|
||||
:param filename: Filename of saving file, defaults to "./.state-save/states.pkl"
|
||||
@ -547,8 +550,6 @@ class TeleBot:
|
||||
|
||||
Telegram documentation: https://core.telegram.org/bots/api#getupdates
|
||||
|
||||
:param allowed_updates: Array of string. List the types of updates you want your bot to receive.
|
||||
:type allowed_updates: :obj:`list`, optional
|
||||
|
||||
:param offset: Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates.
|
||||
By default, updates starting with the earliest unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset
|
||||
@ -562,6 +563,9 @@ class TeleBot:
|
||||
:param timeout: Request connection timeout
|
||||
:type timeout: :obj:`int`, optional
|
||||
|
||||
:param allowed_updates: Array of string. List the types of updates you want your bot to receive.
|
||||
:type allowed_updates: :obj:`list`, optional
|
||||
|
||||
:param long_polling_timeout: Timeout in seconds for long polling.
|
||||
:type long_polling_timeout: :obj:`int`, optional
|
||||
|
||||
@ -604,6 +608,9 @@ class TeleBot:
|
||||
Processes new updates. Just pass list of subclasses of Update to this method.
|
||||
|
||||
:param updates: List of :class:`telebot.types.Update` objects.
|
||||
:type updates: :obj:`list` of :class:`telebot.types.Update`
|
||||
|
||||
:return None:
|
||||
"""
|
||||
upd_count = len(updates)
|
||||
logger.debug('Received {0} new updates'.format(upd_count))
|
||||
@ -885,11 +892,11 @@ class TeleBot:
|
||||
none_stop: Optional[bool]=None):
|
||||
"""
|
||||
This function creates a new Thread that calls an internal __retrieve_updates function.
|
||||
This allows the bot to retrieve Updates automagically and notify listeners and message handlers accordingly.
|
||||
This allows the bot to retrieve Updates automatically and notify listeners and message handlers accordingly.
|
||||
|
||||
Warning: Do not call this function more than once!
|
||||
|
||||
Always get updates.
|
||||
Always gets updates.
|
||||
|
||||
.. deprecated:: 4.1.1
|
||||
Use :meth:`infinity_polling` instead.
|
||||
@ -921,7 +928,7 @@ class TeleBot:
|
||||
|
||||
Please note that this parameter doesn't affect updates created before the call to the get_updates,
|
||||
so unwanted updates may be received for a short period of time.
|
||||
:type allowed_updates: :obj:`list`] of :obj:`str`
|
||||
:type allowed_updates: :obj:`list` of :obj:`str`
|
||||
|
||||
:param none_stop: Deprecated, use non_stop. Old typo, kept for backward compatibility.
|
||||
:type none_stop: :obj:`bool`
|
||||
@ -1104,6 +1111,8 @@ class TeleBot:
|
||||
def stop_polling(self):
|
||||
"""
|
||||
Stops polling.
|
||||
|
||||
Does not accept any arguments.
|
||||
"""
|
||||
self.__stop_polling.set()
|
||||
|
||||
@ -1170,6 +1179,15 @@ class TeleBot:
|
||||
|
||||
|
||||
def download_file(self, file_path: str) -> bytes:
|
||||
"""
|
||||
Downloads file.
|
||||
|
||||
:param file_path: Path where the file should be downloaded.
|
||||
:type file_path: str
|
||||
|
||||
:return: bytes
|
||||
:rtype: :obj:`bytes`
|
||||
"""
|
||||
return apihelper.download_file(self.token, file_path)
|
||||
|
||||
|
||||
@ -1209,7 +1227,7 @@ class TeleBot:
|
||||
limit: Optional[int]=None) -> types.UserProfilePhotos:
|
||||
"""
|
||||
Use this method to get a list of profile pictures for a user.
|
||||
Returns a UserProfilePhotos object.
|
||||
Returns a :class:`telebot.types.UserProfilePhotos` object.
|
||||
|
||||
Telegram documentation: https://core.telegram.org/bots/api#getuserprofilephotos
|
||||
|
||||
@ -1240,7 +1258,7 @@ class TeleBot:
|
||||
:param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
|
||||
:type chat_id: :obj:`int` or :obj:`str`
|
||||
|
||||
:return: :class:`telebot.types.Chat`
|
||||
:return: Chat information
|
||||
:rtype: :class:`telebot.types.Chat`
|
||||
"""
|
||||
result = apihelper.get_chat(self.token, chat_id)
|
||||
@ -1384,8 +1402,8 @@ class TeleBot:
|
||||
"""
|
||||
Use this method to send text messages.
|
||||
|
||||
Warning: Do not send more than about 4000 characters each message, otherwise you'll risk an HTTP 414 error.
|
||||
If you must send more than 4000 characters,
|
||||
Warning: Do not send more than about 4096 characters each message, otherwise you'll risk an HTTP 414 error.
|
||||
If you must send more than 4096 characters,
|
||||
use the `split_string` or `smart_split` function in util.py.
|
||||
|
||||
Telegram documentation: https://core.telegram.org/bots/api#sendmessage
|
||||
@ -3552,7 +3570,12 @@ class TeleBot:
|
||||
message_id: Optional[int]=None,
|
||||
inline_message_id: Optional[str]=None) -> List[types.GameHighScore]:
|
||||
"""
|
||||
Gets top points and game play.
|
||||
Use this method to get data for high score tables. Will return the score of the specified user and several of
|
||||
their neighbors in a game. On success, returns an Array of GameHighScore objects.
|
||||
|
||||
This method will currently return scores for the target user, plus two of their closest neighbors on each side.
|
||||
Will also return the top three users if the user and their neighbors are not among them.
|
||||
Please note that this behavior is subject to change.
|
||||
|
||||
Telegram documentation: https://core.telegram.org/bots/api#getgamehighscores
|
||||
|
||||
@ -4430,10 +4453,16 @@ class TeleBot:
|
||||
|
||||
self.middlewares.append(middleware)
|
||||
|
||||
def set_state(self, user_id: int, state: Union[int, str, State], chat_id: int=None) -> None:
|
||||
def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Optional[int]=None) -> None:
|
||||
"""
|
||||
Sets a new state of a user.
|
||||
|
||||
.. note::
|
||||
|
||||
You should set both user id and chat id in order to set state for a user in a chat.
|
||||
Otherwise, if you only set user_id, chat_id will equal to user_id, this means that
|
||||
state will be set for the user in his private chat with a bot.
|
||||
|
||||
:param user_id: User's identifier
|
||||
:type user_id: :obj:`int`
|
||||
|
||||
@ -4449,7 +4478,7 @@ class TeleBot:
|
||||
chat_id = user_id
|
||||
self.current_states.set_state(chat_id, user_id, state)
|
||||
|
||||
def reset_data(self, user_id: int, chat_id: int=None):
|
||||
def reset_data(self, user_id: int, chat_id: Optional[int]=None):
|
||||
"""
|
||||
Reset data for a user in chat.
|
||||
|
||||
@ -4465,7 +4494,7 @@ class TeleBot:
|
||||
chat_id = user_id
|
||||
self.current_states.reset_data(chat_id, user_id)
|
||||
|
||||
def delete_state(self, user_id: int, chat_id: int=None) -> None:
|
||||
def delete_state(self, user_id: int, chat_id: Optional[int]=None) -> None:
|
||||
"""
|
||||
Delete the current state of a user.
|
||||
|
||||
@ -4481,12 +4510,24 @@ class TeleBot:
|
||||
chat_id = user_id
|
||||
self.current_states.delete_state(chat_id, user_id)
|
||||
|
||||
def retrieve_data(self, user_id: int, chat_id: int=None) -> Optional[Any]:
|
||||
def retrieve_data(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Any]:
|
||||
"""
|
||||
Returns context manager with data for a user in chat.
|
||||
|
||||
:param user_id: User identifier
|
||||
:type user_id: int
|
||||
|
||||
:param chat_id: Chat's unique identifier, defaults to user_id
|
||||
:type chat_id: int, optional
|
||||
|
||||
:return: Context manager with data for a user in chat
|
||||
:rtype: Optional[Any]
|
||||
"""
|
||||
if chat_id is None:
|
||||
chat_id = user_id
|
||||
return self.current_states.get_interactive_data(chat_id, user_id)
|
||||
|
||||
def get_state(self, user_id: int, chat_id: int=None) -> Optional[Union[int, str, State]]:
|
||||
def get_state(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Union[int, str, State]]:
|
||||
"""
|
||||
Gets current state of a user.
|
||||
Not recommended to use this method. But it is ok for debugging.
|
||||
@ -4504,7 +4545,7 @@ class TeleBot:
|
||||
chat_id = user_id
|
||||
return self.current_states.get_state(chat_id, user_id)
|
||||
|
||||
def add_data(self, user_id: int, chat_id:int=None, **kwargs):
|
||||
def add_data(self, user_id: int, chat_id: Optional[int]=None, **kwargs):
|
||||
"""
|
||||
Add data to states.
|
||||
|
||||
@ -4635,6 +4676,7 @@ class TeleBot:
|
||||
Example:
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Usage of middleware_handler
|
||||
|
||||
bot = TeleBot('TOKEN')
|
||||
|
||||
@ -4728,13 +4770,14 @@ class TeleBot:
|
||||
def message_handler(self, commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None,
|
||||
content_types: Optional[List[str]]=None, chat_types: Optional[List[str]]=None, **kwargs):
|
||||
"""
|
||||
Message handler decorator.
|
||||
This decorator can be used to decorate functions that must handle certain types of messages.
|
||||
Handles New incoming message of any kind - text, photo, sticker, etc.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.Message` object.
|
||||
All message handlers are tested in the order they were added.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python3
|
||||
:caption: Usage of message_handler
|
||||
|
||||
bot = TeleBot('TOKEN')
|
||||
|
||||
@ -4768,8 +4811,17 @@ class TeleBot:
|
||||
|
||||
:param func: Optional lambda function. The lambda receives the message to test as the first parameter.
|
||||
It must return True if the command should handle the message.
|
||||
:type func: :obj:`lambda`
|
||||
|
||||
:param content_types: Supported message content types. Must be a list. Defaults to ['text'].
|
||||
:type content_types: :obj:`list` of :obj:`str`
|
||||
|
||||
:param chat_types: list of chat types
|
||||
:type chat_types: :obj:`list` of :obj:`str`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: decorated function
|
||||
"""
|
||||
if content_types is None:
|
||||
content_types = ["text"]
|
||||
@ -4871,7 +4923,8 @@ class TeleBot:
|
||||
|
||||
def edited_message_handler(self, commands=None, regexp=None, func=None, content_types=None, chat_types=None, **kwargs):
|
||||
"""
|
||||
Edit message handler decorator
|
||||
Handles new version of a message that is known to the bot and was edited.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.Message` object.
|
||||
|
||||
:param commands: Optional list of strings (commands to handle).
|
||||
:type commands: :obj:`list` of :obj:`str`
|
||||
@ -4889,6 +4942,7 @@ class TeleBot:
|
||||
:type chat_types: :obj:`list` of :obj:`str`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
if content_types is None:
|
||||
@ -4960,6 +5014,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
method_name = "register_edited_message_handler"
|
||||
@ -4988,7 +5044,8 @@ class TeleBot:
|
||||
|
||||
def channel_post_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs):
|
||||
"""
|
||||
Channel post handler decorator.
|
||||
Handles new incoming channel post of any kind - text, photo, sticker, etc.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.Message` object.
|
||||
|
||||
:param commands: Optional list of strings (commands to handle).
|
||||
:type commands: :obj:`list` of :obj:`str`
|
||||
@ -5003,6 +5060,7 @@ class TeleBot:
|
||||
:type content_types: :obj:`list` of :obj:`str`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
if content_types is None:
|
||||
@ -5069,6 +5127,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
method_name = "register_channel_post_handler"
|
||||
@ -5096,7 +5156,8 @@ class TeleBot:
|
||||
|
||||
def edited_channel_post_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs):
|
||||
"""
|
||||
Edit channel post handler decorator
|
||||
Handles new version of a channel post that is known to the bot and was edited.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.Message` object.
|
||||
|
||||
:param commands: Optional list of strings (commands to handle).
|
||||
:type commands: :obj:`list` of :obj:`str`
|
||||
@ -5178,6 +5239,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: decorated function
|
||||
"""
|
||||
method_name = "register_edited_channel_post_handler"
|
||||
@ -5205,7 +5268,8 @@ class TeleBot:
|
||||
|
||||
def inline_handler(self, func, **kwargs):
|
||||
"""
|
||||
Inline call handler decorator
|
||||
Handles new incoming inline query.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.InlineQuery` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5246,6 +5310,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: decorated function
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5253,7 +5319,9 @@ class TeleBot:
|
||||
|
||||
def chosen_inline_handler(self, func, **kwargs):
|
||||
"""
|
||||
Description: The result of an inline query that was chosen by a user and sent to their chat partner.
|
||||
Handles the result of an inline query that was chosen by a user and sent to their chat partner.
|
||||
Please see our documentation on the feedback collecting for details on how to enable these updates for your bot.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.ChosenInlineResult` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5294,6 +5362,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5301,7 +5371,8 @@ class TeleBot:
|
||||
|
||||
def callback_query_handler(self, func, **kwargs):
|
||||
"""
|
||||
Callback request handler decorator
|
||||
Handles new incoming callback query.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.CallbackQuery` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5342,6 +5413,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5349,7 +5422,8 @@ class TeleBot:
|
||||
|
||||
def shipping_query_handler(self, func, **kwargs):
|
||||
"""
|
||||
Shipping request handler
|
||||
Handles new incoming shipping query. Only for invoices with flexible price.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.ShippingQuery` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5390,6 +5464,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5397,7 +5473,8 @@ class TeleBot:
|
||||
|
||||
def pre_checkout_query_handler(self, func, **kwargs):
|
||||
"""
|
||||
Pre-checkout request handler
|
||||
New incoming pre-checkout query. Contains full information about checkout.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.PreCheckoutQuery` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5437,6 +5514,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: decorated function
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5444,7 +5523,8 @@ class TeleBot:
|
||||
|
||||
def poll_handler(self, func, **kwargs):
|
||||
"""
|
||||
Poll request handler
|
||||
Handles new state of a poll. Bots receive only updates about stopped polls and polls, which are sent by the bot
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.Poll` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5484,6 +5564,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5491,7 +5573,9 @@ class TeleBot:
|
||||
|
||||
def poll_answer_handler(self, func=None, **kwargs):
|
||||
"""
|
||||
Poll_answer request handler
|
||||
Handles change of user's answer in a non-anonymous poll(when user changes the vote).
|
||||
Bots receive new votes only in polls that were sent by the bot itself.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.PollAnswer` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5532,6 +5616,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5539,8 +5625,9 @@ class TeleBot:
|
||||
|
||||
def my_chat_member_handler(self, func=None, **kwargs):
|
||||
"""
|
||||
The bot's chat member status was updated in a chat. For private chats,
|
||||
Handles update in a status of a bot. For private chats,
|
||||
this update is received only when the bot is blocked or unblocked by the user.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.ChatMemberUpdated` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5581,6 +5668,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5588,8 +5677,10 @@ class TeleBot:
|
||||
|
||||
def chat_member_handler(self, func=None, **kwargs):
|
||||
"""
|
||||
A chat member's status was updated in a chat. The bot must be an administrator
|
||||
in the chat and must explicitly specify “chat_member” in the list of allowed_updates to receive these updates.
|
||||
Handles update in a status of a user in a chat.
|
||||
The bot must be an administrator in the chat and must explicitly specify “chat_member”
|
||||
in the list of allowed_updates to receive these updates.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.ChatMemberUpdated` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5639,8 +5730,9 @@ class TeleBot:
|
||||
|
||||
def chat_join_request_handler(self, func=None, **kwargs):
|
||||
"""
|
||||
A request to join the chat has been sent. The bot must have the can_invite_users
|
||||
Handles a request to join the chat has been sent. The bot must have the can_invite_users
|
||||
administrator right in the chat to receive these updates.
|
||||
As a parameter to the decorator function, it passes :class:`telebot.types.ChatJoinRequest` object.
|
||||
|
||||
:param func: Function executed as a filter
|
||||
:type func: :obj:`function`
|
||||
@ -5681,6 +5773,8 @@ class TeleBot:
|
||||
:param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
|
||||
:type pass_bot: :obj:`bool`
|
||||
|
||||
:param kwargs: Optional keyword arguments(custom filters)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
|
||||
@ -5707,6 +5801,15 @@ class TeleBot:
|
||||
"""
|
||||
Create custom filter.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example on checking the text of a message
|
||||
|
||||
class TextMatchFilter(AdvancedCustomFilter):
|
||||
key = 'text'
|
||||
|
||||
async def check(self, message, text):
|
||||
return text == message.text
|
||||
|
||||
:param custom_filter: Class with check(message) method.
|
||||
:param custom_filter: Custom filter class with key.
|
||||
"""
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,17 @@ class SimpleCustomFilter(ABC):
|
||||
Accepts only message, returns bool value, that is compared with given in handler.
|
||||
|
||||
Child classes should have .key property.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example on creating a simple custom filter.
|
||||
|
||||
class ForwardFilter(SimpleCustomFilter):
|
||||
# Check whether message was forwarded from channel or group.
|
||||
key = 'is_forwarded'
|
||||
|
||||
def check(self, message):
|
||||
return message.forward_date is not None
|
||||
|
||||
"""
|
||||
|
||||
key: str = None
|
||||
@ -25,13 +36,23 @@ class SimpleCustomFilter(ABC):
|
||||
|
||||
class AdvancedCustomFilter(ABC):
|
||||
"""
|
||||
Simple Custom Filter base class.
|
||||
Advanced Custom Filter base class.
|
||||
Create child class with check() method.
|
||||
Accepts two parameters, returns bool: True - filter passed, False - filter failed.
|
||||
message: Message class
|
||||
text: Filter value given in handler
|
||||
|
||||
Child classes should have .key property.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example on creating an advanced custom filter.
|
||||
|
||||
class TextStartsFilter(AdvancedCustomFilter):
|
||||
# Filter to check whether message starts with some text.
|
||||
key = 'text_startswith'
|
||||
|
||||
def check(self, message, text):
|
||||
return message.text.startswith(text)
|
||||
"""
|
||||
|
||||
key: str = None
|
||||
@ -48,6 +69,25 @@ class TextFilter:
|
||||
Advanced text filter to check (types.Message, types.CallbackQuery, types.InlineQuery, types.Poll)
|
||||
|
||||
example of usage is in examples/asynchronous_telebot/custom_filters/advanced_text_filter.py
|
||||
|
||||
:param equals: string, True if object's text is equal to passed string
|
||||
:type equals: :obj:`str`
|
||||
|
||||
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
|
||||
:type contains: list[str] or tuple[str]
|
||||
|
||||
:param starts_with: string, True if object's text starts with passed string
|
||||
:type starts_with: :obj:`str`
|
||||
|
||||
:param ends_with: string, True if object's text starts with passed string
|
||||
:type ends_with: :obj:`str`
|
||||
|
||||
:param ignore_case: bool (default False), case insensitive
|
||||
:type ignore_case: :obj:`bool`
|
||||
|
||||
:raises ValueError: if incorrect value for a parameter was supplied
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@ -56,13 +96,25 @@ class TextFilter:
|
||||
starts_with: Optional[Union[str, list, tuple]] = None,
|
||||
ends_with: Optional[Union[str, list, tuple]] = None,
|
||||
ignore_case: bool = False):
|
||||
|
||||
"""
|
||||
:param equals: string, True if object's text is equal to passed string
|
||||
:type equals: :obj:`str`
|
||||
|
||||
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
|
||||
:type contains: list[str] or tuple[str]
|
||||
|
||||
:param starts_with: string, True if object's text starts with passed string
|
||||
:type starts_with: :obj:`str`
|
||||
|
||||
:param ends_with: string, True if object's text starts with passed string
|
||||
:type ends_with: :obj:`str`
|
||||
|
||||
:param ignore_case: bool (default False), case insensitive
|
||||
:type ignore_case: :obj:`bool`
|
||||
|
||||
:raises ValueError: if incorrect value for a parameter was supplied
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
to_check = sum((pattern is not None for pattern in (equals, contains, starts_with, ends_with)))
|
||||
@ -87,7 +139,9 @@ class TextFilter:
|
||||
return iterable
|
||||
|
||||
async def check(self, obj: Union[types.Message, types.CallbackQuery, types.InlineQuery, types.Poll]):
|
||||
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(obj, types.Poll):
|
||||
text = obj.question
|
||||
elif isinstance(obj, types.Message):
|
||||
@ -135,15 +189,20 @@ class TextFilter:
|
||||
class TextMatchFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Filter to check Text message.
|
||||
key: text
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(text=['account'])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'text'
|
||||
|
||||
async def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(text, TextFilter):
|
||||
return await text.check(message)
|
||||
elif type(text) is list:
|
||||
@ -157,14 +216,21 @@ class TextContainsFilter(AdvancedCustomFilter):
|
||||
Filter to check Text message.
|
||||
key: text
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
# Will respond if any message.text contains word 'account'
|
||||
@bot.message_handler(text_contains=['account'])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'text_contains'
|
||||
|
||||
async def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if not isinstance(text, str) and not isinstance(text, list) and not isinstance(text, tuple):
|
||||
raise ValueError("Incorrect text_contains value")
|
||||
elif isinstance(text, str):
|
||||
@ -179,14 +245,20 @@ class TextStartsFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Filter to check whether message starts with some text.
|
||||
|
||||
Example:
|
||||
# Will work if message.text starts with 'Sir'.
|
||||
@bot.message_handler(text_startswith='Sir')
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
# Will work if message.text starts with 'sir'.
|
||||
@bot.message_handler(text_startswith='sir')
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'text_startswith'
|
||||
|
||||
async def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
return message.text.startswith(text)
|
||||
|
||||
|
||||
@ -194,13 +266,19 @@ class ChatFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Check whether chat_id corresponds to given chat_id.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(chat_id=[99999])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'chat_id'
|
||||
|
||||
async def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(message, types.CallbackQuery):
|
||||
return message.message.chat.id in text
|
||||
return message.chat.id in text
|
||||
@ -210,14 +288,19 @@ class ForwardFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether message was forwarded from channel or group.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(is_forwarded=True)
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'is_forwarded'
|
||||
|
||||
async def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
return message.forward_date is not None
|
||||
|
||||
|
||||
@ -225,14 +308,19 @@ class IsReplyFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether message is a reply.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(is_reply=True)
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'is_reply'
|
||||
|
||||
async def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(message, types.CallbackQuery):
|
||||
return message.message.reply_to_message is not None
|
||||
return message.reply_to_message is not None
|
||||
@ -242,14 +330,19 @@ class LanguageFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Check users language_code.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(language_code=['ru'])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'language_code'
|
||||
|
||||
async def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if type(text) is list:
|
||||
return message.from_user.language_code in text
|
||||
else:
|
||||
@ -260,8 +353,11 @@ class IsAdminFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether the user is administrator / owner of the chat.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'is_chat_admin'
|
||||
@ -270,6 +366,9 @@ class IsAdminFilter(SimpleCustomFilter):
|
||||
self._bot = bot
|
||||
|
||||
async def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(message, types.CallbackQuery):
|
||||
result = await self._bot.get_chat_member(message.message.chat.id, message.from_user.id)
|
||||
return result.status ('creator', 'administrator')
|
||||
@ -281,8 +380,11 @@ class StateFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Filter to check state.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(state=1)
|
||||
# your function
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
@ -291,6 +393,9 @@ class StateFilter(AdvancedCustomFilter):
|
||||
key = 'state'
|
||||
|
||||
async def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if text == '*': return True
|
||||
|
||||
# needs to work with callbackquery
|
||||
@ -334,10 +439,16 @@ class IsDigitFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Filter to check whether the string is made up of only digits.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(is_digit=True)
|
||||
# your function
|
||||
"""
|
||||
key = 'is_digit'
|
||||
|
||||
async def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
return message.text.isdigit()
|
||||
|
@ -1,3 +1,10 @@
|
||||
"""
|
||||
File with all middleware classes, states.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
class BaseMiddleware:
|
||||
"""
|
||||
Base class for middleware.
|
||||
@ -9,23 +16,25 @@ class BaseMiddleware:
|
||||
so on. Same applies to post_process.
|
||||
|
||||
.. code-block:: python
|
||||
:caption: Example of class-based middlewares
|
||||
|
||||
class MyMiddleware(BaseMiddleware):
|
||||
def __init__(self):
|
||||
self.update_sensitive = True
|
||||
self.update_types = ['message', 'edited_message']
|
||||
|
||||
def pre_process_message(self, message, data):
|
||||
async def pre_process_message(self, message, data):
|
||||
# only message update here
|
||||
pass
|
||||
|
||||
def post_process_message(self, message, data, exception):
|
||||
async def post_process_message(self, message, data, exception):
|
||||
pass # only message update here for post_process
|
||||
|
||||
def pre_process_edited_message(self, message, data):
|
||||
async def pre_process_edited_message(self, message, data):
|
||||
# only edited_message update here
|
||||
pass
|
||||
|
||||
def post_process_edited_message(self, message, data, exception):
|
||||
async def post_process_edited_message(self, message, data, exception):
|
||||
pass # only edited_message update here for post_process
|
||||
"""
|
||||
|
||||
@ -42,6 +51,14 @@ class BaseMiddleware:
|
||||
|
||||
|
||||
class State:
|
||||
"""
|
||||
Class representing a state.
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
class MyStates(StatesGroup):
|
||||
my_state = State() # returns my_state:State string.
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
self.name = None
|
||||
|
||||
@ -50,6 +67,14 @@ class State:
|
||||
|
||||
|
||||
class StatesGroup:
|
||||
"""
|
||||
Class representing common states.
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
class MyStates(StatesGroup):
|
||||
my_state = State() # returns my_state:State string.
|
||||
"""
|
||||
def __init_subclass__(cls) -> None:
|
||||
|
||||
for name, value in cls.__dict__.items():
|
||||
|
@ -1,3 +1,7 @@
|
||||
"""
|
||||
Callback data factory's file.
|
||||
"""
|
||||
|
||||
"""
|
||||
Copyright (c) 2017-2018 Alex Root Junior
|
||||
|
||||
@ -29,17 +33,23 @@ import typing
|
||||
|
||||
|
||||
class CallbackDataFilter:
|
||||
"""
|
||||
Filter for CallbackData.
|
||||
"""
|
||||
|
||||
def __init__(self, factory, config: typing.Dict[str, str]):
|
||||
self.config = config
|
||||
self.factory = factory
|
||||
|
||||
def check(self, query):
|
||||
def check(self, query) -> bool:
|
||||
"""
|
||||
Checks if query.data appropriates to specified config
|
||||
|
||||
:param query: telebot.types.CallbackQuery
|
||||
:return: bool
|
||||
:type query: telebot.types.CallbackQuery
|
||||
|
||||
:return: True if query.data appropriates to specified config
|
||||
:rtype: bool
|
||||
"""
|
||||
|
||||
try:
|
||||
@ -135,7 +145,7 @@ class CallbackData:
|
||||
"""
|
||||
Generate filter
|
||||
|
||||
:param config: specified named parameters will be checked with CallbackQury.data
|
||||
:param config: specified named parameters will be checked with CallbackQuery.data
|
||||
:return: CallbackDataFilter class
|
||||
"""
|
||||
|
||||
|
@ -14,6 +14,17 @@ class SimpleCustomFilter(ABC):
|
||||
Accepts only message, returns bool value, that is compared with given in handler.
|
||||
|
||||
Child classes should have .key property.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example on creating a simple custom filter.
|
||||
|
||||
class ForwardFilter(SimpleCustomFilter):
|
||||
# Check whether message was forwarded from channel or group.
|
||||
key = 'is_forwarded'
|
||||
|
||||
def check(self, message):
|
||||
return message.forward_date is not None
|
||||
|
||||
"""
|
||||
|
||||
key: str = None
|
||||
@ -27,13 +38,23 @@ class SimpleCustomFilter(ABC):
|
||||
|
||||
class AdvancedCustomFilter(ABC):
|
||||
"""
|
||||
Simple Custom Filter base class.
|
||||
Advanced Custom Filter base class.
|
||||
Create child class with check() method.
|
||||
Accepts two parameters, returns bool: True - filter passed, False - filter failed.
|
||||
message: Message class
|
||||
text: Filter value given in handler
|
||||
|
||||
Child classes should have .key property.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example on creating an advanced custom filter.
|
||||
|
||||
class TextStartsFilter(AdvancedCustomFilter):
|
||||
# Filter to check whether message starts with some text.
|
||||
key = 'text_startswith'
|
||||
|
||||
def check(self, message, text):
|
||||
return message.text.startswith(text)
|
||||
"""
|
||||
|
||||
key: str = None
|
||||
@ -50,6 +71,25 @@ class TextFilter:
|
||||
Advanced text filter to check (types.Message, types.CallbackQuery, types.InlineQuery, types.Poll)
|
||||
|
||||
example of usage is in examples/custom_filters/advanced_text_filter.py
|
||||
|
||||
:param equals: string, True if object's text is equal to passed string
|
||||
:type equals: :obj:`str`
|
||||
|
||||
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
|
||||
:type contains: list[str] or tuple[str]
|
||||
|
||||
:param starts_with: string, True if object's text starts with passed string
|
||||
:type starts_with: :obj:`str`
|
||||
|
||||
:param ends_with: string, True if object's text starts with passed string
|
||||
:type ends_with: :obj:`str`
|
||||
|
||||
:param ignore_case: bool (default False), case insensitive
|
||||
:type ignore_case: :obj:`bool`
|
||||
|
||||
:raises ValueError: if incorrect value for a parameter was supplied
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@ -58,13 +98,25 @@ class TextFilter:
|
||||
starts_with: Optional[Union[str, list, tuple]] = None,
|
||||
ends_with: Optional[Union[str, list, tuple]] = None,
|
||||
ignore_case: bool = False):
|
||||
|
||||
"""
|
||||
:param equals: string, True if object's text is equal to passed string
|
||||
:type equals: :obj:`str`
|
||||
|
||||
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
|
||||
:type contains: list[str] or tuple[str]
|
||||
|
||||
:param starts_with: string, True if object's text starts with passed string
|
||||
:type starts_with: :obj:`str`
|
||||
|
||||
:param ends_with: string, True if object's text starts with passed string
|
||||
:type ends_with: :obj:`str`
|
||||
|
||||
:param ignore_case: bool (default False), case insensitive
|
||||
:type ignore_case: :obj:`bool`
|
||||
|
||||
:raises ValueError: if incorrect value for a parameter was supplied
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
to_check = sum((pattern is not None for pattern in (equals, contains, starts_with, ends_with)))
|
||||
@ -89,6 +141,9 @@ class TextFilter:
|
||||
return iterable
|
||||
|
||||
def check(self, obj: Union[types.Message, types.CallbackQuery, types.InlineQuery, types.Poll]):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
|
||||
if isinstance(obj, types.Poll):
|
||||
text = obj.question
|
||||
@ -142,15 +197,20 @@ class TextFilter:
|
||||
class TextMatchFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Filter to check Text message.
|
||||
key: text
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(text=['account'])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'text'
|
||||
|
||||
def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(text, TextFilter):
|
||||
return text.check(message)
|
||||
elif type(text) is list:
|
||||
@ -164,14 +224,21 @@ class TextContainsFilter(AdvancedCustomFilter):
|
||||
Filter to check Text message.
|
||||
key: text
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
# Will respond if any message.text contains word 'account'
|
||||
@bot.message_handler(text_contains=['account'])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'text_contains'
|
||||
|
||||
def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if not isinstance(text, str) and not isinstance(text, list) and not isinstance(text, tuple):
|
||||
raise ValueError("Incorrect text_contains value")
|
||||
elif isinstance(text, str):
|
||||
@ -186,14 +253,20 @@ class TextStartsFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Filter to check whether message starts with some text.
|
||||
|
||||
Example:
|
||||
# Will work if message.text starts with 'Sir'.
|
||||
@bot.message_handler(text_startswith='Sir')
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
# Will work if message.text starts with 'sir'.
|
||||
@bot.message_handler(text_startswith='sir')
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'text_startswith'
|
||||
|
||||
def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
return message.text.startswith(text)
|
||||
|
||||
|
||||
@ -201,13 +274,19 @@ class ChatFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Check whether chat_id corresponds to given chat_id.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(chat_id=[99999])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'chat_id'
|
||||
|
||||
def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(message, types.CallbackQuery):
|
||||
return message.message.chat.id in text
|
||||
return message.chat.id in text
|
||||
@ -217,14 +296,19 @@ class ForwardFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether message was forwarded from channel or group.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(is_forwarded=True)
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'is_forwarded'
|
||||
|
||||
def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
return message.forward_date is not None
|
||||
|
||||
|
||||
@ -232,14 +316,19 @@ class IsReplyFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether message is a reply.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(is_reply=True)
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'is_reply'
|
||||
|
||||
def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(message, types.CallbackQuery):
|
||||
return message.message.reply_to_message is not None
|
||||
return message.reply_to_message is not None
|
||||
@ -249,14 +338,19 @@ class LanguageFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Check users language_code.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(language_code=['ru'])
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'language_code'
|
||||
|
||||
def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if type(text) is list:
|
||||
return message.from_user.language_code in text
|
||||
else:
|
||||
@ -267,8 +361,11 @@ class IsAdminFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Check whether the user is administrator / owner of the chat.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
|
||||
# your function
|
||||
"""
|
||||
|
||||
key = 'is_chat_admin'
|
||||
@ -277,6 +374,9 @@ class IsAdminFilter(SimpleCustomFilter):
|
||||
self._bot = bot
|
||||
|
||||
def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if isinstance(message, types.CallbackQuery):
|
||||
return self._bot.get_chat_member(message.message.chat.id, message.from_user.id).status in ['creator', 'administrator']
|
||||
return self._bot.get_chat_member(message.chat.id, message.from_user.id).status in ['creator', 'administrator']
|
||||
@ -286,8 +386,11 @@ class StateFilter(AdvancedCustomFilter):
|
||||
"""
|
||||
Filter to check state.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(state=1)
|
||||
# your function
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
@ -296,6 +399,9 @@ class StateFilter(AdvancedCustomFilter):
|
||||
key = 'state'
|
||||
|
||||
def check(self, message, text):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if text == '*': return True
|
||||
|
||||
# needs to work with callbackquery
|
||||
@ -341,10 +447,16 @@ class IsDigitFilter(SimpleCustomFilter):
|
||||
"""
|
||||
Filter to check whether the string is made up of only digits.
|
||||
|
||||
Example:
|
||||
.. code-block:: python3
|
||||
:caption: Example on using this filter:
|
||||
|
||||
@bot.message_handler(is_digit=True)
|
||||
# your function
|
||||
"""
|
||||
key = 'is_digit'
|
||||
|
||||
def check(self, message):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
return message.text.isdigit()
|
||||
|
@ -34,14 +34,34 @@ class AsyncWebhookListener:
|
||||
"""
|
||||
Aynchronous implementation of webhook listener
|
||||
for asynchronous version of telebot.
|
||||
Not supposed to be used manually by user.
|
||||
Use AsyncTeleBot.run_webhooks() instead.
|
||||
|
||||
:param bot: AsyncTeleBot instance.
|
||||
:type bot: telebot.async_telebot.AsyncTeleBot
|
||||
|
||||
:param bot: TeleBot instance
|
||||
:param secret_token: Telegram secret token
|
||||
:type secret_token: str
|
||||
|
||||
:param host: Webhook host
|
||||
:type host: str
|
||||
|
||||
:param port: Webhook port
|
||||
:type port: int
|
||||
|
||||
:param ssl_context: SSL context
|
||||
:type ssl_context: tuple
|
||||
|
||||
:param url_path: Webhook url path
|
||||
:type url_path: str
|
||||
|
||||
:param debug: Debug mode
|
||||
:type debug: bool
|
||||
|
||||
:raises ImportError: If FastAPI or uvicorn is not installed.
|
||||
:raises ImportError: If Starlette version is too old.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
self._check_dependencies()
|
||||
|
||||
@ -73,6 +93,8 @@ class AsyncWebhookListener:
|
||||
async def process_update(self, request: Request, update: dict):
|
||||
"""
|
||||
Processes updates.
|
||||
|
||||
:meta private:
|
||||
"""
|
||||
# header containsX-Telegram-Bot-Api-Secret-Token
|
||||
if request.headers.get('X-Telegram-Bot-Api-Secret-Token') != self._secret_token:
|
||||
@ -88,7 +110,10 @@ class AsyncWebhookListener:
|
||||
|
||||
async def run_app(self):
|
||||
"""
|
||||
Run app with the given parameters.
|
||||
Run app with the given parameters to init.
|
||||
Not supposed to be used manually by user.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
config = Config(app=self.app,
|
||||
|
@ -1,8 +1,7 @@
|
||||
"""
|
||||
This file is used by TeleBot.run_webhooks() &
|
||||
AsyncTeleBot.run_webhooks() functions.
|
||||
This file is used by TeleBot.run_webhooks() function.
|
||||
|
||||
Flask/fastapi is required to run this script.
|
||||
Fastapi is required to run this script.
|
||||
"""
|
||||
|
||||
# modules required for running this script
|
||||
@ -34,16 +33,36 @@ class SyncWebhookListener:
|
||||
debug: Optional[bool]=False
|
||||
) -> None:
|
||||
"""
|
||||
Synchronous implementation of webhook listener
|
||||
for synchronous version of telebot.
|
||||
Aynchronous implementation of webhook listener
|
||||
for asynchronous version of telebot.
|
||||
Not supposed to be used manually by user.
|
||||
Use AsyncTeleBot.run_webhooks() instead.
|
||||
|
||||
:param bot: AsyncTeleBot instance.
|
||||
:type bot: telebot.async_telebot.AsyncTeleBot
|
||||
|
||||
:param bot: TeleBot instance
|
||||
:param secret_token: Telegram secret token
|
||||
:type secret_token: str
|
||||
|
||||
:param host: Webhook host
|
||||
:type host: str
|
||||
|
||||
:param port: Webhook port
|
||||
:type port: int
|
||||
|
||||
:param ssl_context: SSL context
|
||||
:type ssl_context: tuple
|
||||
|
||||
:param url_path: Webhook url path
|
||||
:type url_path: str
|
||||
|
||||
:param debug: Debug mode
|
||||
:type debug: bool
|
||||
|
||||
:raises ImportError: If FastAPI or uvicorn is not installed.
|
||||
:raises ImportError: If Starlette version is too old.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
self._check_dependencies()
|
||||
|
||||
@ -75,6 +94,8 @@ class SyncWebhookListener:
|
||||
def process_update(self, request: Request, update: dict):
|
||||
"""
|
||||
Processes updates.
|
||||
|
||||
:meta private:
|
||||
"""
|
||||
# header containsX-Telegram-Bot-Api-Secret-Token
|
||||
if request.headers.get('X-Telegram-Bot-Api-Secret-Token') != self._secret_token:
|
||||
@ -89,7 +110,10 @@ class SyncWebhookListener:
|
||||
|
||||
def run_app(self):
|
||||
"""
|
||||
Run app with the given parameters.
|
||||
Run app with the given parameters to init.
|
||||
Not supposed to be used manually by user.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
uvicorn.run(app=self.app,
|
||||
|
@ -5,14 +5,17 @@ Markdown & HTML formatting functions.
|
||||
"""
|
||||
|
||||
import html
|
||||
|
||||
import re
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def format_text(*args, separator="\n"):
|
||||
"""
|
||||
Formats a list of strings into a single string.
|
||||
|
||||
.. code:: python
|
||||
.. code:: python3
|
||||
|
||||
format_text( # just an example
|
||||
mbold('Hello'),
|
||||
@ -20,7 +23,13 @@ def format_text(*args, separator="\n"):
|
||||
)
|
||||
|
||||
:param args: Strings to format.
|
||||
:type args: :obj:`str`
|
||||
|
||||
:param separator: The separator to use between each string.
|
||||
:type separator: :obj:`str`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return separator.join(args)
|
||||
|
||||
@ -31,6 +40,10 @@ def escape_html(content: str) -> str:
|
||||
Escapes HTML characters in a string of HTML.
|
||||
|
||||
:param content: The string of HTML to escape.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:return: The escaped string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return html.escape(content)
|
||||
|
||||
@ -39,9 +52,13 @@ def escape_markdown(content: str) -> str:
|
||||
"""
|
||||
Escapes Markdown characters in a string of Markdown.
|
||||
|
||||
Credits: simonsmh
|
||||
Credits to: simonsmh
|
||||
|
||||
:param content: The string of Markdown to escape.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:return: The escaped string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
|
||||
parse = re.sub(r"([_*\[\]()~`>\#\+\-=|\.!])", r"\\\1", content)
|
||||
@ -49,154 +66,249 @@ def escape_markdown(content: str) -> str:
|
||||
return reparse
|
||||
|
||||
|
||||
def mbold(content: str, escape: bool=True) -> str:
|
||||
def mbold(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns a Markdown-formatted bold string.
|
||||
|
||||
:param content: The string to bold.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '*{}*'.format(escape_markdown(content) if escape else content)
|
||||
|
||||
|
||||
def hbold(content: str, escape: bool=True) -> str:
|
||||
def hbold(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns an HTML-formatted bold string.
|
||||
|
||||
:param content: The string to bold.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '<b>{}</b>'.format(escape_html(content) if escape else content)
|
||||
|
||||
|
||||
def mitalic(content: str, escape: bool=True) -> str:
|
||||
def mitalic(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns a Markdown-formatted italic string.
|
||||
|
||||
:param content: The string to italicize.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '_{}_\r'.format(escape_markdown(content) if escape else content)
|
||||
|
||||
|
||||
def hitalic(content: str, escape: bool=True) -> str:
|
||||
def hitalic(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns an HTML-formatted italic string.
|
||||
|
||||
:param content: The string to italicize.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '<i>{}</i>'.format(escape_html(content) if escape else content)
|
||||
|
||||
|
||||
def munderline(content: str, escape: bool=True) -> str:
|
||||
def munderline(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns a Markdown-formatted underline string.
|
||||
|
||||
:param content: The string to underline.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '__{}__'.format(escape_markdown(content) if escape else content)
|
||||
|
||||
|
||||
def hunderline(content: str, escape: bool=True) -> str:
|
||||
def hunderline(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns an HTML-formatted underline string.
|
||||
|
||||
:param content: The string to underline.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
|
||||
"""
|
||||
return '<u>{}</u>'.format(escape_html(content) if escape else content)
|
||||
|
||||
|
||||
def mstrikethrough(content: str, escape: bool=True) -> str:
|
||||
def mstrikethrough(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns a Markdown-formatted strikethrough string.
|
||||
|
||||
:param content: The string to strikethrough.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '~{}~'.format(escape_markdown(content) if escape else content)
|
||||
|
||||
|
||||
def hstrikethrough(content: str, escape: bool=True) -> str:
|
||||
def hstrikethrough(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns an HTML-formatted strikethrough string.
|
||||
|
||||
:param content: The string to strikethrough.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '<s>{}</s>'.format(escape_html(content) if escape else content)
|
||||
|
||||
|
||||
def mspoiler(content: str, escape: bool=True) -> str:
|
||||
def mspoiler(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns a Markdown-formatted spoiler string.
|
||||
|
||||
:param content: The string to spoiler.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '||{}||'.format(escape_markdown(content) if escape else content)
|
||||
|
||||
|
||||
def hspoiler(content: str, escape: bool=True) -> str:
|
||||
def hspoiler(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns an HTML-formatted spoiler string.
|
||||
|
||||
:param content: The string to spoiler.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '<tg-spoiler>{}</tg-spoiler>'.format(escape_html(content) if escape else content)
|
||||
|
||||
|
||||
def mlink(content: str, url: str, escape: bool=True) -> str:
|
||||
def mlink(content: str, url: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns a Markdown-formatted link string.
|
||||
|
||||
:param content: The string to link.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param url: The URL to link to.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type url: str
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '[{}]({})'.format(escape_markdown(content), escape_markdown(url) if escape else content)
|
||||
|
||||
|
||||
def hlink(content: str, url: str, escape: bool=True) -> str:
|
||||
def hlink(content: str, url: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns an HTML-formatted link string.
|
||||
|
||||
:param content: The string to link.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param url: The URL to link to.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type url: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '<a href="{}">{}</a>'.format(escape_html(url), escape_html(content) if escape else content)
|
||||
|
||||
|
||||
def mcode(content: str, language: str="", escape: bool=True) -> str:
|
||||
def mcode(content: str, language: str="", escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns a Markdown-formatted code string.
|
||||
|
||||
:param content: The string to code.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '```{}\n{}```'.format(language, escape_markdown(content) if escape else content)
|
||||
|
||||
|
||||
def hcode(content: str, escape: bool=True) -> str:
|
||||
def hcode(content: str, escape: Optional[bool]=True) -> str:
|
||||
"""
|
||||
Returns an HTML-formatted code string.
|
||||
|
||||
:param content: The string to code.
|
||||
:param escape: True if you need to escape special characters.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '<code>{}</code>'.format(escape_html(content) if escape else content)
|
||||
|
||||
|
||||
def hpre(content: str, escape: bool=True, language: str="") -> str:
|
||||
def hpre(content: str, escape: Optional[bool]=True, 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.
|
||||
:type content: :obj:`str`
|
||||
|
||||
:param escape: True if you need to escape special characters. Defaults to True.
|
||||
:type escape: :obj:`bool`
|
||||
|
||||
:return: The formatted string.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return '<pre><code class="{}">{}</code></pre>'.format(language, escape_html(content) if escape else content)
|
||||
|
||||
@ -205,7 +317,10 @@ def hide_link(url: str) -> str:
|
||||
"""
|
||||
Hide url of an image.
|
||||
|
||||
:param url:
|
||||
:return: str
|
||||
:param url: The url of the image.
|
||||
:type url: :obj:`str`
|
||||
|
||||
:return: The hidden url.
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return f'<a href="{url}">⁠</a>'
|
@ -12,7 +12,9 @@ except:
|
||||
|
||||
class HandlerBackend(object):
|
||||
"""
|
||||
Class for saving (next step|reply) handlers
|
||||
Class for saving (next step|reply) handlers.
|
||||
|
||||
:meta private:
|
||||
"""
|
||||
def __init__(self, handlers=None):
|
||||
if handlers is None:
|
||||
@ -30,6 +32,9 @@ class HandlerBackend(object):
|
||||
|
||||
|
||||
class MemoryHandlerBackend(HandlerBackend):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
def register_handler(self, handler_group_id, handler):
|
||||
if handler_group_id in self.handlers:
|
||||
self.handlers[handler_group_id].append(handler)
|
||||
@ -47,6 +52,9 @@ class MemoryHandlerBackend(HandlerBackend):
|
||||
|
||||
|
||||
class FileHandlerBackend(HandlerBackend):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
def __init__(self, handlers=None, filename='./.handler-saves/handlers.save', delay=120):
|
||||
super(FileHandlerBackend, self).__init__(handlers)
|
||||
self.filename = filename
|
||||
@ -119,6 +127,9 @@ class FileHandlerBackend(HandlerBackend):
|
||||
|
||||
|
||||
class RedisHandlerBackend(HandlerBackend):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
def __init__(self, handlers=None, host='localhost', port=6379, db=0, prefix='telebot', password=None):
|
||||
super(RedisHandlerBackend, self).__init__(handlers)
|
||||
if not redis_installed:
|
||||
@ -150,6 +161,14 @@ class RedisHandlerBackend(HandlerBackend):
|
||||
|
||||
|
||||
class State:
|
||||
"""
|
||||
Class representing a state.
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
class MyStates(StatesGroup):
|
||||
my_state = State() # returns my_state:State string.
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
self.name = None
|
||||
def __str__(self) -> str:
|
||||
@ -158,6 +177,14 @@ class State:
|
||||
|
||||
|
||||
class StatesGroup:
|
||||
"""
|
||||
Class representing common states.
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
class MyStates(StatesGroup):
|
||||
my_state = State() # returns my_state:State string.
|
||||
"""
|
||||
def __init_subclass__(cls) -> None:
|
||||
for name, value in cls.__dict__.items():
|
||||
if not name.startswith('__') and not callable(value) and isinstance(value, State):
|
||||
@ -179,7 +206,12 @@ class BaseMiddleware:
|
||||
message update, then you will have to create pre_process_message function, and
|
||||
so on. Same applies to post_process.
|
||||
|
||||
.. code-block:: python
|
||||
.. note::
|
||||
If you want to use middleware, you have to set use_class_middlewares=True in your
|
||||
TeleBot instance.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example of class-based middlewares.
|
||||
|
||||
class MyMiddleware(BaseMiddleware):
|
||||
def __init__(self):
|
||||
|
@ -20,6 +20,7 @@ class JsonSerializable(object):
|
||||
"""
|
||||
Subclasses of this class are guaranteed to be able to be converted to JSON format.
|
||||
All subclasses of this class must override to_json.
|
||||
|
||||
"""
|
||||
|
||||
def to_json(self):
|
||||
@ -36,6 +37,7 @@ class Dictionaryable(object):
|
||||
"""
|
||||
Subclasses of this class are guaranteed to be able to be converted to dictionary.
|
||||
All subclasses of this class must override to_dict.
|
||||
|
||||
"""
|
||||
|
||||
def to_dict(self):
|
||||
@ -90,6 +92,65 @@ class JsonDeserializable(object):
|
||||
|
||||
|
||||
class Update(JsonDeserializable):
|
||||
"""
|
||||
This object represents an incoming update.
|
||||
|
||||
https://core.telegram.org/bots/api#update
|
||||
|
||||
:attribute update_id: The update's unique identifier. Update identifiers start from a certain positive number and increase sequentially.
|
||||
This ID becomes especially handy if you're using webhooks, since it allows you to ignore repeated updates or to restore the correct
|
||||
update sequence, should they get out of order. If there are no new updates for at least a week, then identifier of the next update will
|
||||
be chosen randomly instead of sequentially.
|
||||
:type update_id: int
|
||||
|
||||
:attribute message: New incoming message of any kind — text, photo, sticker, etc.
|
||||
:type message: :class:`telebot.types.Message`
|
||||
|
||||
:attribute edited_message: New version of a message that is known to the bot and was edited.
|
||||
:type edited_message: :class:`telebot.types.Message`
|
||||
|
||||
:attribute channel_post: New incoming channel post of any kind — text, photo, sticker, etc.
|
||||
:type channel_post: :class:`telebot.types.Message`
|
||||
|
||||
:attribute edited_channel_post: New version of a channel post that is known to the bot and was edited.
|
||||
:type edited_channel_post: :class:`telebot.types.Message`
|
||||
|
||||
:attribute inline_query: New incoming query from a user, which is answered by a bot and can be further processed.
|
||||
:type inline_query: :class:`telebot.types.InlineQuery`
|
||||
|
||||
:attribute chosen_inline_result: New incoming result of an inline query that was chosen by a user and sent to their chat partner.
|
||||
:type chosen_inline_result: :class:`telebot.types.ChosenInlineResult`
|
||||
|
||||
:attribute callback_query: New incoming callback query from a user.
|
||||
:type callback_query: :class:`telebot.types.CallbackQuery`
|
||||
|
||||
:attribute shipping_query: New incoming shipping query. Only for invoices with flexible price
|
||||
:type shipping_query: :class:`telebot.types.ShippingQuery`
|
||||
|
||||
:attribute pre_checkout_query: New incoming pre-checkout query. Contains full information about checkout
|
||||
:type pre_checkout_query: :class:`telebot.types.PreCheckoutQuery`
|
||||
|
||||
:attribute poll: New poll state. Bots receive only updates about stopped polls and polls, which are sent by the bot
|
||||
:type poll: :class:`telebot.types.Poll`
|
||||
|
||||
:attribute poll_answer: A user changed their answer in a non-anonymous poll. Bots receive new votes only in polls that were sent by the bot itself.
|
||||
:type poll_answer: :class:`telebot.types.PollAnswer`
|
||||
|
||||
:attribute my_chat_member: The bot's chat member status was updated in a chat. For private chats,
|
||||
this update is received only when the bot is blocked or unblocked by the user.
|
||||
:type my_chat_member: :class:`telebot.types.ChatMember`
|
||||
|
||||
:attribute chat_member: A chat member's status was updated in a chat. The bot must be an administrator in the chat and must
|
||||
explicitly specify “chat_member” in the list of allowed_updates to receive these updates.
|
||||
:type chat_member: :class:`telebot.types.ChatMember`
|
||||
|
||||
:attribute chat_join_request: A request to join the chat has been sent. The bot must have the can_invite_users
|
||||
administrator right in the chat to receive these updates.
|
||||
:type chat_join_request: :class:`telebot.types.ChatJoinRequest`
|
||||
|
||||
:return: An Update object.
|
||||
:rtype: :class:`telebot.types.Update`
|
||||
"""
|
||||
@classmethod
|
||||
def de_json(cls, json_string):
|
||||
if json_string is None: return None
|
||||
|
191
telebot/util.py
191
telebot/util.py
@ -35,11 +35,13 @@ logger = logging.getLogger('TeleBot')
|
||||
|
||||
thread_local = threading.local()
|
||||
|
||||
#: Contains all media content types.
|
||||
content_type_media = [
|
||||
'text', 'audio', 'animation', 'document', 'photo', 'sticker', 'video', 'video_note', 'voice', 'contact', 'dice', 'poll',
|
||||
'venue', 'location'
|
||||
]
|
||||
|
||||
#: Contains all service content types such as `User joined the group`.
|
||||
content_type_service = [
|
||||
'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo', 'group_chat_created',
|
||||
'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message',
|
||||
@ -47,6 +49,7 @@ content_type_service = [
|
||||
'video_chat_participants_invited', 'message_auto_delete_timer_changed'
|
||||
]
|
||||
|
||||
#: All update types, should be used for allowed_updates parameter in polling.
|
||||
update_types = [
|
||||
"message", "edited_message", "channel_post", "edited_channel_post", "inline_query",
|
||||
"chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer",
|
||||
@ -55,6 +58,9 @@ update_types = [
|
||||
|
||||
|
||||
class WorkerThread(threading.Thread):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
count = 0
|
||||
|
||||
def __init__(self, exception_callback=None, queue=None, name=None):
|
||||
@ -118,7 +124,9 @@ class WorkerThread(threading.Thread):
|
||||
|
||||
|
||||
class ThreadPool:
|
||||
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
def __init__(self, telebot, num_threads=2):
|
||||
self.telebot = telebot
|
||||
self.tasks = Queue.Queue()
|
||||
@ -156,6 +164,9 @@ class ThreadPool:
|
||||
|
||||
|
||||
class AsyncTask:
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
def __init__(self, target, *args, **kwargs):
|
||||
self.target = target
|
||||
self.args = args
|
||||
@ -182,6 +193,9 @@ class AsyncTask:
|
||||
|
||||
|
||||
class CustomRequestResponse():
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
def __init__(self, json_text, status_code = 200, reason = ""):
|
||||
self.status_code = status_code
|
||||
self.text = json_text
|
||||
@ -192,6 +206,9 @@ class CustomRequestResponse():
|
||||
|
||||
|
||||
def async_dec():
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
def decorator(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
return AsyncTask(fn, *args, **kwargs)
|
||||
@ -201,19 +218,49 @@ def async_dec():
|
||||
return decorator
|
||||
|
||||
|
||||
def is_string(var):
|
||||
def is_string(var) -> bool:
|
||||
"""
|
||||
Returns True if the given object is a string.
|
||||
"""
|
||||
return isinstance(var, str)
|
||||
|
||||
|
||||
def is_dict(var):
|
||||
def is_dict(var) -> bool:
|
||||
"""
|
||||
Returns True if the given object is a dictionary.
|
||||
|
||||
:param var: object to be checked
|
||||
:type var: :obj:`object`
|
||||
|
||||
:return: True if the given object is a dictionary.
|
||||
:rtype: :obj:`bool`
|
||||
"""
|
||||
return isinstance(var, dict)
|
||||
|
||||
|
||||
def is_bytes(var):
|
||||
def is_bytes(var) -> bool:
|
||||
"""
|
||||
Returns True if the given object is a bytes object.
|
||||
|
||||
:param var: object to be checked
|
||||
:type var: :obj:`object`
|
||||
|
||||
:return: True if the given object is a bytes object.
|
||||
:rtype: :obj:`bool`
|
||||
"""
|
||||
return isinstance(var, bytes)
|
||||
|
||||
|
||||
def is_pil_image(var):
|
||||
def is_pil_image(var) -> bool:
|
||||
"""
|
||||
Returns True if the given object is a PIL.Image.Image object.
|
||||
|
||||
:param var: object to be checked
|
||||
:type var: :obj:`object`
|
||||
|
||||
:return: True if the given object is a PIL.Image.Image object.
|
||||
:rtype: :obj:`bool`
|
||||
"""
|
||||
return pil_imported and isinstance(var, Image.Image)
|
||||
|
||||
|
||||
@ -233,7 +280,10 @@ def is_command(text: str) -> bool:
|
||||
Checks if `text` is a command. Telegram chat commands start with the '/' character.
|
||||
|
||||
:param text: Text to check.
|
||||
:type text: :obj:`str`
|
||||
|
||||
:return: True if `text` is a command, else False.
|
||||
:rtype: :obj:`bool`
|
||||
"""
|
||||
if text is None: return False
|
||||
return text.startswith('/')
|
||||
@ -244,30 +294,40 @@ def extract_command(text: str) -> Union[str, None]:
|
||||
Extracts the command from `text` (minus the '/') if `text` is a command (see is_command).
|
||||
If `text` is not a command, this function returns None.
|
||||
|
||||
Examples:
|
||||
.. code-block:: python3
|
||||
:caption: Examples:
|
||||
|
||||
extract_command('/help'): 'help'
|
||||
extract_command('/help@BotName'): 'help'
|
||||
extract_command('/search black eyed peas'): 'search'
|
||||
extract_command('Good day to you'): None
|
||||
|
||||
:param text: String to extract the command from
|
||||
:type text: :obj:`str`
|
||||
|
||||
:return: the command if `text` is a command (according to is_command), else None.
|
||||
:rtype: :obj:`str` or :obj:`None`
|
||||
"""
|
||||
if text is None: return None
|
||||
return text.split()[0].split('@')[0][1:] if is_command(text) else None
|
||||
|
||||
|
||||
def extract_arguments(text: str) -> str:
|
||||
def extract_arguments(text: str) -> str or None:
|
||||
"""
|
||||
Returns the argument after the command.
|
||||
|
||||
Examples:
|
||||
.. code-block:: python3
|
||||
:caption: Examples:
|
||||
|
||||
extract_arguments("/get name"): 'name'
|
||||
extract_arguments("/get"): ''
|
||||
extract_arguments("/get@botName name"): 'name'
|
||||
|
||||
:param text: String to extract the arguments from a command
|
||||
:type text: :obj:`str`
|
||||
|
||||
:return: the arguments if `text` is a command (according to is_command), else None.
|
||||
:rtype: :obj:`str` or :obj:`None`
|
||||
"""
|
||||
regexp = re.compile(r"/\w*(@\w*)*\s*([\s\S]*)", re.IGNORECASE)
|
||||
result = regexp.match(text)
|
||||
@ -280,8 +340,13 @@ def split_string(text: str, chars_per_string: int) -> List[str]:
|
||||
This is very useful for splitting one giant message into multiples.
|
||||
|
||||
:param text: The text to split
|
||||
:type text: :obj:`str`
|
||||
|
||||
:param chars_per_string: The number of characters per line the text is split into.
|
||||
:type chars_per_string: :obj:`int`
|
||||
|
||||
:return: The splitted text as a list of strings.
|
||||
:rtype: :obj:`list` of :obj:`str`
|
||||
"""
|
||||
return [text[i:i + chars_per_string] for i in range(0, len(text), chars_per_string)]
|
||||
|
||||
@ -294,8 +359,13 @@ def smart_split(text: str, chars_per_string: int=MAX_MESSAGE_LENGTH) -> List[str
|
||||
Splits by '\n', '. ' or ' ' in exactly this priority.
|
||||
|
||||
:param text: The text to split
|
||||
:type text: :obj:`str`
|
||||
|
||||
:param chars_per_string: The number of maximum characters per part the text is split to.
|
||||
:type chars_per_string: :obj:`int`
|
||||
|
||||
:return: The splitted text as a list of strings.
|
||||
:rtype: :obj:`list` of :obj:`str`
|
||||
"""
|
||||
|
||||
def _text_before_last(substr: str) -> str:
|
||||
@ -336,12 +406,25 @@ def user_link(user: types.User, include_id: bool=False) -> str:
|
||||
Returns an HTML user link. This is useful for reports.
|
||||
Attention: Don't forget to set parse_mode to 'HTML'!
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example:
|
||||
|
||||
bot.send_message(your_user_id, user_link(message.from_user) + ' started the bot!', parse_mode='HTML')
|
||||
|
||||
.. note::
|
||||
You can use formatting.* for all other formatting options(bold, italic, links, and etc.)
|
||||
This method is kept for backward compatibility, and it is recommended to use formatting.* for
|
||||
more options.
|
||||
|
||||
:param user: the user (not the user_id)
|
||||
:type user: :obj:`telebot.types.User`
|
||||
|
||||
:param include_id: include the user_id
|
||||
:type include_id: :obj:`bool`
|
||||
|
||||
:return: HTML user link
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
name = escape(user.first_name)
|
||||
return (f"<a href='tg://user?id={user.id}'>{name}</a>"
|
||||
@ -355,7 +438,8 @@ def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int=2) -> types.I
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python3
|
||||
:caption: Using quick_markup:
|
||||
|
||||
quick_markup({
|
||||
'Twitter': {'url': 'https://twitter.com'},
|
||||
@ -378,8 +462,13 @@ def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int=2) -> types.I
|
||||
}
|
||||
|
||||
:param values: a dict containing all buttons to create in this format: {text: kwargs} {str:}
|
||||
:type values: :obj:`dict`
|
||||
|
||||
:param row_width: int row width
|
||||
:type row_width: :obj:`int`
|
||||
|
||||
:return: InlineKeyboardMarkup
|
||||
:rtype: :obj:`types.InlineKeyboardMarkup`
|
||||
"""
|
||||
markup = types.InlineKeyboardMarkup(row_width=row_width)
|
||||
buttons = [
|
||||
@ -392,16 +481,25 @@ def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int=2) -> types.I
|
||||
|
||||
# CREDITS TO http://stackoverflow.com/questions/12317940#answer-12320352
|
||||
def or_set(self):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
self._set()
|
||||
self.changed()
|
||||
|
||||
|
||||
def or_clear(self):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
self._clear()
|
||||
self.changed()
|
||||
|
||||
|
||||
def orify(e, changed_callback):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if not hasattr(e, "_set"):
|
||||
e._set = e.set
|
||||
if not hasattr(e, "_clear"):
|
||||
@ -412,6 +510,9 @@ def orify(e, changed_callback):
|
||||
|
||||
|
||||
def OrEvent(*events):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
or_event = threading.Event()
|
||||
|
||||
def changed():
|
||||
@ -435,6 +536,9 @@ def OrEvent(*events):
|
||||
|
||||
|
||||
def per_thread(key, construct_value, reset=False):
|
||||
"""
|
||||
:meta private:
|
||||
"""
|
||||
if reset or not hasattr(thread_local, key):
|
||||
value = construct_value()
|
||||
setattr(thread_local, key, value)
|
||||
@ -449,7 +553,13 @@ def chunks(lst, n):
|
||||
yield lst[i:i + n]
|
||||
|
||||
|
||||
def generate_random_token():
|
||||
def generate_random_token() -> str:
|
||||
"""
|
||||
Generates a random token consisting of letters and digits, 16 characters long.
|
||||
|
||||
:return: a random token
|
||||
:rtype: :obj:`str`
|
||||
"""
|
||||
return ''.join(random.sample(string.ascii_letters, 16))
|
||||
|
||||
|
||||
@ -458,9 +568,18 @@ def deprecated(warn: bool=True, alternative: Optional[Callable]=None, deprecatio
|
||||
Use this decorator to mark functions as deprecated.
|
||||
When the function is used, an info (or warning if `warn` is True) is logged.
|
||||
|
||||
:meta private:
|
||||
|
||||
:param warn: If True a warning is logged else an info
|
||||
:type warn: :obj:`bool`
|
||||
|
||||
:param alternative: The new function to use instead
|
||||
:type alternative: :obj:`Callable`
|
||||
|
||||
:param deprecation_text: Custom deprecation text
|
||||
:type deprecation_text: :obj:`str`
|
||||
|
||||
:return: The decorated function
|
||||
"""
|
||||
def decorator(function):
|
||||
def wrapper(*args, **kwargs):
|
||||
@ -480,7 +599,17 @@ def deprecated(warn: bool=True, alternative: Optional[Callable]=None, deprecatio
|
||||
|
||||
# Cloud helpers
|
||||
def webhook_google_functions(bot, request):
|
||||
"""A webhook endpoint for Google Cloud Functions FaaS."""
|
||||
"""
|
||||
A webhook endpoint for Google Cloud Functions FaaS.
|
||||
|
||||
:param bot: The bot instance
|
||||
:type bot: :obj:`telebot.TeleBot` or :obj:`telebot.async_telebot.AsyncTeleBot`
|
||||
|
||||
:param request: The request object
|
||||
:type request: :obj:`flask.Request`
|
||||
|
||||
:return: The response object
|
||||
"""
|
||||
if request.is_json:
|
||||
try:
|
||||
request_json = request.get_json()
|
||||
@ -494,7 +623,7 @@ def webhook_google_functions(bot, request):
|
||||
return 'Bot ON'
|
||||
|
||||
|
||||
def antiflood(function, *args, **kwargs):
|
||||
def antiflood(function: Callable, *args, **kwargs):
|
||||
"""
|
||||
Use this function inside loops in order to avoid getting TooManyRequests error.
|
||||
Example:
|
||||
@ -505,9 +634,15 @@ def antiflood(function, *args, **kwargs):
|
||||
for chat_id in chat_id_list:
|
||||
msg = antiflood(bot.send_message, chat_id, text)
|
||||
|
||||
:param function:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:param function: The function to call
|
||||
:type function: :obj:`Callable`
|
||||
|
||||
:param args: The arguments to pass to the function
|
||||
:type args: :obj:`tuple`
|
||||
|
||||
:param kwargs: The keyword arguments to pass to the function
|
||||
:type kwargs: :obj:`dict`
|
||||
|
||||
:return: None
|
||||
"""
|
||||
from telebot.apihelper import ApiTelegramException
|
||||
@ -524,6 +659,17 @@ def antiflood(function, *args, **kwargs):
|
||||
|
||||
|
||||
def parse_web_app_data(token: str, raw_init_data: str):
|
||||
"""
|
||||
Parses web app data.
|
||||
|
||||
:param token: The bot token
|
||||
:type token: :obj:`str`
|
||||
|
||||
:param raw_init_data: The raw init data
|
||||
:type raw_init_data: :obj:`str`
|
||||
|
||||
:return: The parsed init data
|
||||
"""
|
||||
is_valid = validate_web_app_data(token, raw_init_data)
|
||||
if not is_valid:
|
||||
return False
|
||||
@ -539,7 +685,18 @@ def parse_web_app_data(token: str, raw_init_data: str):
|
||||
return result
|
||||
|
||||
|
||||
def validate_web_app_data(token, raw_init_data):
|
||||
def validate_web_app_data(token: str, raw_init_data: str):
|
||||
"""
|
||||
Validates web app data.
|
||||
|
||||
:param token: The bot token
|
||||
:type token: :obj:`str`
|
||||
|
||||
:param raw_init_data: The raw init data
|
||||
:type raw_init_data: :obj:`str`
|
||||
|
||||
:return: The parsed init data
|
||||
"""
|
||||
try:
|
||||
parsed_data = dict(parse_qsl(raw_init_data))
|
||||
except ValueError:
|
||||
|
Loading…
Reference in New Issue
Block a user