Compare commits

..

61 Commits

Author SHA1 Message Date
4a79535321 Compliance with bot API 8.02
Also, closed sessions are now removed from Bot.sessions
2025-02-01 16:46:33 +01:00
425902d2ac Compliance with bot API 7.10 2024-09-06 16:01:50 +02:00
6759e5c704 Administrators may be set after administration module initialization
Do not check for administrators until bot has got information about itself. Prevent duplicate calls to bot.get_me() async method
2024-09-01 18:27:28 +02:00
db240ce199 Compliance with bot API 7.9
Implemented a system to get administration privileges if running the bot in absence of administrators (the token is provided through the command line).
2024-08-17 21:12:00 +02:00
02386d69da Get package version from metadata when package has no __version__ attribute 2024-08-04 18:49:41 +02:00
cc4cbbacbd Compliance with bot API 7.8 2024-08-04 18:29:21 +02:00
fd4374f328 Compliance with bot API 7.7 2024-07-07 14:36:58 +02:00
6b489363de Compliance with bot API 7.2
- Included python version in `/version` command
- Added the parameter `business_connection_id` to the methods sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendPoll, sendDice, sendGame, and sendMediaGroup, sendChatAction.
- Moved the parameter `format` to Sticker instead of StickerSet (and related methods)
2024-04-13 11:15:42 +02:00
a343e095e8 Compliance with bot API 7.1
- Added the class ReplyParameters and replaced parameters reply_to_message_id and allow_sending_without_reply in the methods copyMessage, sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendPoll, sendDice, sendInvoice, sendGame, and sendMediaGroup with the field reply_parameters of type ReplyParameters.
- Added the class LinkPreviewOptions and replaced the parameter disable_web_page_preview with link_preview_options in the methods sendMessage and editMessageText.
2024-03-10 20:22:05 +01:00
a3b28bc1d6 Allow to overwrite file when using bot.download_file method 2024-03-05 18:50:03 +01:00
3969794075 download_file behaves differently if a local bot API server is used. Wrong default API url was being used 2024-02-17 15:44:04 +01:00
748ba624a4 Support Local Bot API Server (with custom api_url). 2024-02-17 14:47:09 +01:00
41507067be download_file method updated to handle exceptions and return information about downloaded file 2024-02-14 19:30:35 +01:00
ec747bef1d Specify encoding in send_part_of_text_file function 2023-12-17 10:22:12 +01:00
199fe29cf1 Compliance with bot API 6.8 and 6.9
Added the method `unpinAllGeneralForumTopicMessages` (6.8).

Added the new administrator privileges `can_post_stories`, `can_edit_stories` and `can_delete_stories` to the class `ChatAdministratorRights` and to the method `promoteChatMember` (6.9).
2023-11-12 11:56:16 +01:00
41f38d0b23 Method to add table columns if missing 2023-08-23 18:23:17 +02:00
cf492f0c8b Allow non-null standard output and/or error pipe to be passed to aio_subprocess_shell function 2023-08-23 17:17:26 +02:00
eab81b065d When answering inline queries, prevent invalid InlineQueryResultsButton instantiation 2023-08-07 20:19:09 +02:00
51a77c695b Better variable regex: accept only one decimal separator in float numbers 2023-07-25 18:58:31 +02:00
febe5cee3f Config command implemented, allowing administrators to add variables to configuration files 2023-07-25 16:41:22 +02:00
fb04211e81 Whitespace and type mismatch 2023-04-29 20:56:32 +02:00
3bd1a9b679 Compliance with Telegram Bot API 6.6 and new command line interface to run bot or send a single message 2023-04-29 20:38:33 +02:00
0c3ed2070d Compliance with Telegram Bot API 6.5 2023-02-03 21:38:20 +01:00
5c30dafd4c Compliance with Telegram Bot API 6.4 2023-01-06 10:29:44 +01:00
davte
27f9d62cf9 Make the regex dot match any character at all, including a newline, when cleaning HTML strings (so multiline tag bodies are allowed, as they are in Telegram HTML markdown). 2022-12-26 14:05:33 +01:00
fafa639328 HTML parse_mode check upgraded.
All supported tags permitted, malformed tags replaced with escaped characters
2022-12-12 22:43:44 +01:00
55b47ed1f7 Method to add a table and its columns to and ObjectWithDatabase 2022-12-10 18:46:20 +01:00
881d249256 Compliance with Telegram Bot API 6.3 2022-12-08 16:18:22 +01:00
fc486c60ce When admin A requests profile picture of user B, send B's picture and not A's. 2022-12-06 22:18:51 +01:00
e813d37c8f Browse users via /auth command 2022-12-05 22:10:30 +01:00
21f91fb07c Syntax-breaking typo 2022-10-12 14:12:39 +02:00
50c2f92e8e asyncio get_event_loop method is being deprecated; use new_event_loop / get_running_loop and asyncio.run instead
Major version change because it may not be backward-compatible
2022-10-12 14:08:46 +02:00
d77c416ea6 send_document method should not require a chat_id since it can be passed an update object 2020-12-20 20:30:59 +01:00
e487764aad send_photo method should not require a chat_id since it can be passed an update object 2020-12-11 08:22:16 +01:00
4bf00f0cc5 Avoid relative import statements 2020-11-19 15:18:44 +01:00
ed7e335d4e Items in __all__ must be str, not module 2020-11-19 14:37:25 +01:00
d6a4a1d69a Document can be None if document_path is provided 2020-11-19 12:32:58 +01:00
668822fc21 Do not log chardet INFO and DEBUG levels 2020-11-16 23:05:18 +01:00
135442dcd6 Compliance with Telegram Bot API 5.0 and improved type hinting for API methods. 2020-11-16 22:56:12 +01:00
eb11160a02 Version number 2020-11-15 21:35:38 +01:00
fda4cac348 Import statements refactored 2020-11-15 21:34:18 +01:00
773fe1fdb1 web should not be imported from aiohttp; use aiohttp.web instead 2020-11-15 20:55:43 +01:00
ddf25f8dd1 Store user profile pictures in bot database and show them in authorization panel 2020-10-07 16:32:51 +02:00
17b26ec23e MySQL compatibility: specify VARCHAR length
`db.types.string` becomes now `db.types.string(n)`
`db.types.text` is the wrong type to use (text blobs)
2020-10-07 16:32:50 +02:00
68974c4c40 Pass all information to command handler when using /start 2020-09-26 19:28:18 +02:00
92e39e7ed7 Make general_handler handle photo updates 2020-09-05 10:36:00 +02:00
48b7e1e4a2 Updated examples 2020-08-23 14:21:45 +02:00
b797f3fffe Remove argument parameter from parser decorator 2020-08-23 14:08:06 +02:00
3e19ba4c81 In text message handler, make available both lowered and original text and inspect condition parameters 2020-08-23 14:03:52 +02:00
e29bb08b7b Accept language directly 2020-08-20 15:51:00 +02:00
7233f9e478 General handler implemented and applied to contact updates 2020-08-17 23:51:50 +02:00
e481623a75 Document handlers implemented 2020-08-16 15:18:02 +02:00
Davte
88835955ef Update default help messages with given ones, instead of replacing them 2020-07-17 09:48:39 +02:00
Davte
8c37d00602 In default keyboard, show only buttons for commands the user is authorized to call 2020-07-16 10:06:32 +02:00
Davte
ada375b766 Prevent decoding None objects 2020-07-15 13:15:48 +02:00
Davte
ed05d843bc Async function to run shell commands 2020-07-15 13:11:45 +02:00
Davte
bc51ed109a Split outgoing documents bigger than 50 MB and send chunks 2020-06-22 22:56:21 +02:00
Davte
76204ccd69 Script to merge split files 2020-06-22 22:56:16 +02:00
Davte
293a831958 Typos 2020-06-20 15:43:22 +02:00
Davte
fafc3de090 Send error message if database could not be sent - new version 2020-06-20 15:35:24 +02:00
Davte
5fe875e49c Send error message if database could not be sent 2020-06-20 15:32:37 +02:00
5 changed files with 294 additions and 16 deletions

1
.gitignore vendored
View File

@@ -41,6 +41,7 @@ __pycache__/
# Distribution / packaging
.Python
env/
.venv/
build/
develop-eggs/
dist/

View File

@@ -11,7 +11,7 @@ __author__ = "Davide Testa"
__email__ = "davide@davte.it"
__credits__ = ["Marco Origlia", "Nick Lee @Nickoala"]
__license__ = "GNU General Public License v3.0"
__version__ = "2.10.6"
__version__ = "2.10.9"
__maintainer__ = "Davide Testa"
__contact__ = "t.me/davte"

View File

@@ -1890,6 +1890,8 @@ async def create_promotion_command(bot: Bot):
of the machine running the bot.
"""
await bot.get_me()
if len(bot.administrators) > 0:
return
bot.administration_token = get_secure_key(length=10)
print(f"To become administrator click "
f"https://t.me/{bot.name}?start="
@@ -2132,6 +2134,4 @@ def init(telegram_bot: Bot,
update=update,
user_record=user_record,
language=language)
if len(telegram_bot.administrators) == 0:
asyncio.ensure_future(create_promotion_command(bot=telegram_bot))

View File

@@ -457,6 +457,40 @@ class InputPaidMediaVideo(InputPaidMedia):
self['supports_streaming'] = supports_streaming
class MessageEntity(DictToDump):
def __init__(self,
type_: str,
offset: int,
length: int,
url: str,
user: 'User',
language: str,
custom_emoji_id: str):
super().__init__()
self['type'] = type_
self['offset'] = offset
self['length'] = length
self['url'] = url
self['user'] = user
self['language'] = language
self['custom_emoji_id'] = custom_emoji_id
class PreparedInlineMessage(DictToDump):
"""Describes an inline message to be sent by a user of a Mini App.
Attributes:
id (str): Unique identifier of the prepared message
expiration_date (int): Expiration date of the prepared message,
in Unix time. Expired prepared messages can no longer be used.
"""
def __init__(self,
id: str,
expiration_date: int):
super().__init__()
self['id'] = id
self['expiration_date'] = expiration_date
def handle_deprecated_disable_web_page_preview(parameters: dict,
kwargs: dict):
if 'disable_web_page_preview' in kwargs:
@@ -917,6 +951,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a text message. On success, return it.
@@ -963,6 +998,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a photo from file_id, HTTP url or file.
@@ -992,6 +1028,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send an audio file from file_id, HTTP url or file.
@@ -1024,6 +1061,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a document from file_id, HTTP url or file.
@@ -1061,6 +1099,7 @@ class TelegramBot:
has_spoiler: bool = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a video from file_id, HTTP url or file.
@@ -1097,6 +1136,7 @@ class TelegramBot:
has_spoiler: bool = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send animation files (GIF or H.264/MPEG-4 AVC video without sound).
@@ -1128,6 +1168,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send an audio file to be displayed as playable voice message.
@@ -1154,6 +1195,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a rounded square mp4 video message of up to 1 minute long.
@@ -1180,6 +1222,7 @@ class TelegramBot:
protect_content: bool = None,
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a group of photos or videos as an album.
@@ -1209,6 +1252,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a point on the map. May be kept updated for a `live_period`.
@@ -1296,6 +1340,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send information about a venue.
@@ -1323,6 +1368,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a phone contact.
@@ -1360,6 +1406,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a native poll in a group, a supergroup or channel.
@@ -1881,6 +1928,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send `.webp` stickers.
@@ -2100,6 +2148,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send an invoice.
@@ -2180,6 +2229,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a game.
@@ -2247,6 +2297,7 @@ class TelegramBot:
message_effect_id: str = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Send a dice.
@@ -2396,6 +2447,7 @@ class TelegramBot:
disable_notification: bool = None,
reply_parameters: ReplyParameters = None,
reply_markup=None,
allow_paid_broadcast: bool = None,
**kwargs):
"""Use this method to copy messages of any kind.
@@ -2758,11 +2810,27 @@ class TelegramBot:
need_shipping_address: bool,
send_phone_number_to_provider: bool,
send_email_to_provider: bool,
is_flexible: bool):
is_flexible: bool,
business_connection_id: str = None,
subscription_period: int = None
):
"""Use this method to create a link for an invoice.
Returns the created invoice link as String on success.
See https://core.telegram.org/bots/api#createinvoicelink for details.
Returns the created invoice link as String on success. See
https://core.telegram.org/bots/api#createinvoicelink for details.
Attributes:
business_connection_id (Optional[str]): Unique identifier of the
business connection on behalf of which the link will be created.
For payments in Telegram Stars only.
subscription_period (Optional[int]): The number of seconds the
subscription will be active for before the next payment. The
currency must be set to “XTR” (Telegram Stars) if the parameter
is used. Currently, it must always be 2592000 (30 days) if
specified. Any number of subscriptions can be active for a given
bot at the same time, including multiple concurrent
subscriptions from the same user.
Subscription price must no exceed 2500 Telegram Stars.
"""
return await self.api_request(
'createInvoiceLink',
@@ -3109,6 +3177,7 @@ class TelegramBot:
async def sendPaidMedia(self, chat_id: Union[int, str], star_count: int,
media: List[InputPaidMedia],
payload: str = None,
business_connection_id: str = None,
caption: str = None, parse_mode: str = None,
caption_entities: List[dict] = None,
@@ -3116,6 +3185,7 @@ class TelegramBot:
disable_notification: bool = None,
protect_content: bool = None,
reply_parameters: ReplyParameters = None,
allow_paid_broadcast: bool = None,
reply_markup = None):
"""Send paid media to channel chats.
@@ -3188,3 +3258,146 @@ class TelegramBot:
'editChatSubscriptionInviteLink',
parameters=locals()
)
async def setUserEmojiStatus(self, user_id: int,
emoji_status_custom_emoji_id: str = None,
emoji_status_expiration_date: int = None):
"""Changes the emoji status for a given user that previously allowed the
bot to manage their emoji status via the Mini App method
requestEmojiStatusAccess.
Returns True on success.
See https://core.telegram.org/bots/api#setuseremojistatus for details.
"""
if emoji_status_custom_emoji_id is None:
emoji_status_custom_emoji_id = ''
return await self.api_request(
'setUserEmojiStatus',
parameters=locals()
)
async def getAvailableGifts(self):
"""Returns the list of gifts that can be sent by the bot to users.
Requires no parameters.
Returns a Gifts object.
See https://core.telegram.org/bots/api#getavailablegifts for details.
"""
return await self.api_request(
'getAvailableGifts',
parameters=locals()
)
async def sendGift(self, user_id: int, gift_id: str, pay_for_upgrade: bool,
text: str, text_parse_mode: str,
text_entities: List['MessageEntity']):
"""Sends a gift to the given user.
The gift can't be converted to Telegram Stars by the user.
Returns True on success.
See https://core.telegram.org/bots/api#sendgift for details.
"""
return await self.api_request(
'sendGift',
parameters=locals()
)
async def verifyUser(self, user_id: int,
custom_description: str = None):
"""Verifies a user on behalf of the organization which is represented by
the bot.
Returns True on success.
See https://core.telegram.org/bots/api#verifyuser for details.
"""
if len(custom_description) > 70:
raise TypeError("Parameter `custom_description` is too long "
"(0-70 characters).")
return await self.api_request(
'verifyUser',
parameters=locals()
)
async def verifyChat(self, chat_id: Union[int, str],
custom_description: str = None):
"""Verifies a chat on behalf of the organization which is represented by
the bot.
Returns True on success.
See https://core.telegram.org/bots/api#verifychat for details.
"""
if isinstance(chat_id, str) and chat_id.isnumeric():
chat_id = int(chat_id)
if not (isinstance(chat_id, int) or
(isinstance(chat_id, str) and chat_id.startswith('@'))):
raise TypeError(f"Invalid chat_id: `{chat_id}`")
if len(custom_description) > 70:
raise TypeError("Parameter `custom_description` is too long "
"(0-70 characters).")
return await self.api_request(
'verifyChat',
parameters=locals()
)
async def removeUserVerification(self, user_id: int):
"""Removes verification from a user who is currently verified on behalf
of the organization represented by the bot.
Returns True on success.
See https://core.telegram.org/bots/api#removeuserverification for
details.
"""
return await self.api_request(
'removeUserVerification',
parameters=locals()
)
async def removeChatVerification(self, chat_id: Union[int, str]):
"""Removes verification from a chat that is currently verified on behalf
of the organization represented by the bot.
Returns True on success.
See https://core.telegram.org/bots/api#removechatverification for
details.
"""
if not (isinstance(chat_id, int) or
(isinstance(chat_id, str) and chat_id.startswith('@'))):
raise TypeError(f"Invalid chat_id: `{chat_id}`")
return await self.api_request(
'removeChatVerification',
parameters=locals()
)
async def savePreparedInlineMessage(self,
user_id: int,
result: 'InlineQueryResult',
allow_user_chats: bool = None,
allow_bot_chats: bool = None,
allow_group_chats: bool = None,
allow_channel_chats: bool = None
) -> 'PreparedInlineMessage':
"""Stores a message that can be sent by a user of a Mini App.
Returns a PreparedInlineMessage object.
See https://core.telegram.org/bots/api#savepreparedinlinemessage for
details.
"""
return await self.api_request(
'savePreparedInlineMessage',
parameters=locals()
)
async def editUserStarSubscription(self, user_id: int,
telegram_payment_charge_id: str,
is_canceled: bool):
"""Allows the bot to cancel or re-enable extension of a subscription
paid in Telegram Stars.
Returns True on success.
See https://core.telegram.org/bots/api#edituserstarsubscription for
details.
"""
return await self.api_request(
'editUserStarSubscription',
parameters=locals()
)

View File

@@ -122,12 +122,47 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
'edited_message': self.edited_message_handler,
'channel_post': self.channel_post_handler,
'edited_channel_post': self.edited_channel_post_handler,
'business_connection': self.get_update_handler(
update_type='business_connection'
),
'business_message': self.get_update_handler(
update_type='business_message'
),
'edited_business_message': self.get_update_handler(
update_type='edited_business_message'
),
'deleted_business_messages': self.get_update_handler(
update_type='deleted_business_messages'
),
'message_reaction': self.get_update_handler(
update_type='message_reaction'
),
'message_reaction_count': self.get_update_handler(
update_type='message_reaction_count'
),
'inline_query': self.inline_query_handler,
'chosen_inline_result': self.chosen_inline_result_handler,
'callback_query': self.callback_query_handler,
'shipping_query': self.shipping_query_handler,
'pre_checkout_query': self.pre_checkout_query_handler,
'purchased_paid_media': self.get_update_handler(
update_type='purchased_paid_media'
),
'poll': self.poll_handler,
'poll_answer': self.get_update_handler(
update_type='poll_answer'
),
'my_chat_member': self.get_update_handler(
update_type='my_chat_member'
),
'chat_member': self.get_update_handler( update_type='chat_member' ),
'chat_join_request': self.get_update_handler(
update_type='chat_join_request'
),
'chat_boost': self.get_update_handler( update_type='chat_boost' ),
'removed_chat_boost': self.get_update_handler(
update_type='removed_chat_boost'
),
}
# Different message update types need different handlers
self.message_handlers = {
@@ -221,6 +256,8 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
self.Role = None
self.packages = [sys.modules['davtelepot']]
self._documents_max_dimension = None
self._getting_me = False
self._got_me = False
# Add `users` table with its fields if missing
if 'users' not in self.db.tables:
table = self.db.create_table(
@@ -680,6 +717,18 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
)
return
def get_update_handler(self, update_type: str):
"""Get update handler for `update_type`."""
bot = self
async def handler(update, user_record, language=None):
"""Handle update message of type `update_type`"""
logging.info(
"The following update was received: %s\n"
"However, this `%s` handler does nothing yet.",
update, update_type
)
return handler
async def edited_channel_post_handler(self, update, user_record, language=None):
"""Handle Telegram `edited_channel_post` update."""
logging.info(
@@ -2804,9 +2853,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
"""
if not callable(condition):
raise TypeError(
'Condition {c} is not a callable'.format(
c=condition.__name__
)
f'Condition {condition.__name__} is not a callable'
)
def query_decorator(handler):
@@ -3147,26 +3194,41 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
Restart bots if bot can't be got.
"""
for _ in range(60):
if not self._getting_me:
break
await asyncio.sleep(0.5)
else:
raise TimeoutError("Getting bot information was in progress but "
"did not make it in 30 seconds...")
if self._got_me:
return
self._getting_me = True
try:
me = await self.getMe()
if isinstance(me, Exception):
raise me
elif me is None:
raise Exception('getMe returned None')
if me is None:
raise TypeError('getMe returned None')
self._name = me["username"]
self._telegram_id = me['id']
except Exception as e:
logging.error(
f"API getMe method failed, information about this bot could "
f"not be retrieved. Restarting in 5 minutes...\n\n"
f"Error information:\n{e}"
"API getMe method failed, information about this bot could "
"not be retrieved. Restarting in 5 minutes...\n\n"
"Error information:\n%s", e
)
self._getting_me = False
await asyncio.sleep(5*60)
if self._got_me:
return
self.__class__.stop(
message="Information about this bot could not be retrieved.\n"
"Restarting...",
final_state=65
)
self._getting_me = False
self._got_me = True
def setup(self):
"""Make bot ask for updates and handle responses."""
@@ -3181,9 +3243,11 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
async def close_sessions(self):
"""Close open sessions."""
for session_name, session in self.sessions.items():
for session_name in list(self.sessions.keys()):
session = self.sessions[session_name]
if not session.closed:
await session.close()
del self.sessions[session_name]
async def send_one_message(self, *args, **kwargs):
sent_message = await self.send_message(*args, **kwargs)