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.
This commit is contained in:
parent
a3b28bc1d6
commit
a343e095e8
@ -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.9.12"
|
||||
__version__ = "2.10.1"
|
||||
__maintainer__ = "Davide Testa"
|
||||
__contact__ = "t.me/davte"
|
||||
|
||||
|
@ -7,6 +7,7 @@ A simple aiohttp asynchronous web client is used to make requests.
|
||||
# Standard library modules
|
||||
import asyncio
|
||||
import datetime
|
||||
import inspect
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
@ -349,6 +350,104 @@ class InlineQueryResultsButton(dict):
|
||||
return
|
||||
|
||||
|
||||
class DictToDump(dict):
|
||||
def dumps(self):
|
||||
parameters = {key: value for key, value in self.items() if value}
|
||||
return json.dumps(parameters, separators=(',', ':'))
|
||||
|
||||
|
||||
class ReplyParameters(DictToDump):
|
||||
def __init__(self, message_id: int,
|
||||
chat_id: Union[int, str] = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
quote: str = None,
|
||||
quote_parse_mode: str = None,
|
||||
quote_entities: list = None,
|
||||
quote_position: int = None):
|
||||
super().__init__(self)
|
||||
self['message_id'] = message_id
|
||||
self['chat_id'] = chat_id
|
||||
self['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
self['quote'] = quote
|
||||
self['quote_parse_mode'] = quote_parse_mode
|
||||
self['quote_entities'] = quote_entities
|
||||
self['quote_position'] = quote_position
|
||||
|
||||
|
||||
class LinkPreviewOptions(DictToDump):
|
||||
def __init__(self,
|
||||
is_disabled: bool = None,
|
||||
url: str = None,
|
||||
prefer_small_media: bool = None,
|
||||
prefer_large_media: bool = None,
|
||||
show_above_text: bool = None):
|
||||
super().__init__(self)
|
||||
self['is_disabled'] = is_disabled
|
||||
self['url'] = url
|
||||
self['prefer_small_media'] = prefer_small_media
|
||||
self['prefer_large_media'] = prefer_large_media
|
||||
self['show_above_text'] = show_above_text
|
||||
|
||||
|
||||
class ReactionType(DictToDump):
|
||||
def __init__(self,
|
||||
type_: str,
|
||||
emoji: str = None,
|
||||
custom_emoji_id: str = None):
|
||||
super().__init__(self)
|
||||
if type_ not in ('emoji', 'custom_emoji'):
|
||||
raise TypeError(
|
||||
f"ReactionType must be `emoji` or `custom_emoji`.\n"
|
||||
f"Unknown type {type_}"
|
||||
)
|
||||
self['type'] = type_
|
||||
if emoji and custom_emoji_id:
|
||||
raise TypeError(
|
||||
"One and only one of the two fields `emoji` or `custom_emoji` "
|
||||
"may be not None."
|
||||
)
|
||||
elif emoji:
|
||||
self['emoji'] = emoji
|
||||
elif custom_emoji_id:
|
||||
self['custom_emoji_id'] = custom_emoji_id
|
||||
else:
|
||||
raise TypeError(
|
||||
"At least one of the two fields `emoji` or `custom_emoji` "
|
||||
"must be provided and not None."
|
||||
)
|
||||
|
||||
|
||||
def handle_deprecated_disable_web_page_preview(parameters: dict,
|
||||
kwargs: dict):
|
||||
if 'disable_web_page_preview' in kwargs:
|
||||
if parameters['link_preview_options'] is None:
|
||||
parameters['link_preview_options'] = LinkPreviewOptions()
|
||||
parameters['link_preview_options']['is_disabled'] = True
|
||||
logging.error("DEPRECATION WARNING: `disable_web_page_preview` "
|
||||
f"parameter of function `{inspect.stack()[2][3]}` has been "
|
||||
"deprecated since Bot API 7.0. "
|
||||
"Use `link_preview_options` instead.")
|
||||
return parameters
|
||||
|
||||
|
||||
def handle_deprecated_reply_parameters(parameters: dict,
|
||||
kwargs: dict):
|
||||
if 'reply_to_message_id' in kwargs and kwargs['reply_to_message_id']:
|
||||
if parameters['reply_parameters'] is None:
|
||||
parameters['reply_parameters'] = ReplyParameters(
|
||||
message_id=kwargs['reply_to_message_id']
|
||||
)
|
||||
parameters['reply_parameters']['message_id'] = kwargs['reply_to_message_id']
|
||||
if 'allow_sending_without_reply' in kwargs:
|
||||
parameters['reply_parameters'][
|
||||
'allow_sending_without_reply'
|
||||
] = kwargs['allow_sending_without_reply']
|
||||
logging.error(f"DEPRECATION WARNING: `reply_to_message_id` and "
|
||||
f"`allow_sending_without_reply` parameters of function "
|
||||
f"`{inspect.stack()[2][3]}` have been deprecated since "
|
||||
f"Bot API 7.0. Use `reply_parameters` instead.")
|
||||
return parameters
|
||||
|
||||
|
||||
# This class needs to mirror Telegram API, so camelCase method are needed
|
||||
# noinspection PyPep8Naming
|
||||
@ -491,6 +590,8 @@ class TelegramBot:
|
||||
if (type(value) in (int, list,)
|
||||
or (type(value) is dict and 'file' not in value)):
|
||||
value = json.dumps(value, separators=(',', ':'))
|
||||
elif isinstance(value, DictToDump):
|
||||
value = value.dumps()
|
||||
data.add_field(key, value)
|
||||
return data
|
||||
|
||||
@ -757,19 +858,27 @@ class TelegramBot:
|
||||
message_thread_id: int = None,
|
||||
parse_mode: str = None,
|
||||
entities: List[dict] = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
link_preview_options: LinkPreviewOptions = None,
|
||||
disable_notification: bool = None,
|
||||
protect_content: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a text message. On success, return it.
|
||||
|
||||
See https://core.telegram.org/bots/api#sendmessage for details.
|
||||
"""
|
||||
parameters = handle_deprecated_disable_web_page_preview(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=parameters,
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendMessage',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def forwardMessage(self, chat_id: Union[int, str],
|
||||
@ -794,17 +903,21 @@ class TelegramBot:
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
has_spoiler: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a photo from file_id, HTTP url or file.
|
||||
|
||||
See https://core.telegram.org/bots/api#sendphoto for details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendPhoto',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendAudio(self, chat_id: Union[int, str], audio,
|
||||
@ -816,10 +929,9 @@ class TelegramBot:
|
||||
title: str = None,
|
||||
thumbnail=None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send an audio file from file_id, HTTP url or file.
|
||||
@ -831,9 +943,13 @@ class TelegramBot:
|
||||
logging.error("DEPRECATION WARNING: `thumb` parameter of function"
|
||||
"`sendAudio` has been deprecated since Bot API 6.6. "
|
||||
"Use `thumbnail` instead.")
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendAudio',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendDocument(self, chat_id: Union[int, str], document,
|
||||
@ -843,10 +959,9 @@ class TelegramBot:
|
||||
caption_entities: List[dict] = None,
|
||||
disable_content_type_detection: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a document from file_id, HTTP url or file.
|
||||
@ -858,9 +973,13 @@ class TelegramBot:
|
||||
logging.error("DEPRECATION WARNING: `thumb` parameter of function"
|
||||
"`sendDocument` has been deprecated since Bot API 6.6. "
|
||||
"Use `thumbnail` instead.")
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendDocument',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendVideo(self, chat_id: Union[int, str], video,
|
||||
@ -873,11 +992,10 @@ class TelegramBot:
|
||||
caption_entities: List[dict] = None,
|
||||
supports_streaming: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
has_spoiler: bool = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a video from file_id, HTTP url or file.
|
||||
@ -889,9 +1007,13 @@ class TelegramBot:
|
||||
logging.error("DEPRECATION WARNING: `thumb` parameter of function"
|
||||
"`sendVideo` has been deprecated since Bot API 6.6. "
|
||||
"Use `thumbnail` instead.")
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendVideo',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendAnimation(self, chat_id: Union[int, str], animation,
|
||||
@ -903,11 +1025,10 @@ class TelegramBot:
|
||||
parse_mode: str = None,
|
||||
caption_entities: List[dict] = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
has_spoiler: bool = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send animation files (GIF or H.264/MPEG-4 AVC video without sound).
|
||||
@ -919,9 +1040,13 @@ class TelegramBot:
|
||||
logging.error("DEPRECATION WARNING: `thumb` parameter of function"
|
||||
"`sendAnimation` has been deprecated since Bot API 6.6. "
|
||||
"Use `thumbnail` instead.")
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendAnimation',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendVoice(self, chat_id: Union[int, str], voice,
|
||||
@ -930,19 +1055,23 @@ class TelegramBot:
|
||||
caption_entities: List[dict] = None,
|
||||
duration: int = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send an audio file to be displayed as playable voice message.
|
||||
|
||||
`voice` must be in an .ogg file encoded with OPUS.
|
||||
See https://core.telegram.org/bots/api#sendvoice for details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendVoice',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendVideoNote(self, chat_id: Union[int, str], video_note,
|
||||
@ -950,10 +1079,9 @@ class TelegramBot:
|
||||
length: int = None,
|
||||
thumbnail=None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a rounded square mp4 video message of up to 1 minute long.
|
||||
@ -965,26 +1093,34 @@ class TelegramBot:
|
||||
logging.error("DEPRECATION WARNING: `thumb` parameter of function"
|
||||
"`sendVideoNote` has been deprecated since Bot API 6.6. "
|
||||
"Use `thumbnail` instead.")
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendVideoNote',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendMediaGroup(self, chat_id: Union[int, str], media: list,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
allow_sending_without_reply: bool = None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
**kwargs):
|
||||
"""Send a group of photos or videos as an album.
|
||||
|
||||
`media` must be a list of `InputMediaPhoto` and/or `InputMediaVideo`
|
||||
objects.
|
||||
See https://core.telegram.org/bots/api#sendmediagroup for details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendMediaGroup',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendLocation(self, chat_id: Union[int, str],
|
||||
@ -994,11 +1130,11 @@ class TelegramBot:
|
||||
heading: int = None,
|
||||
proximity_alert_radius: int = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a point on the map. May be kept updated for a `live_period`.
|
||||
|
||||
See https://core.telegram.org/bots/api#sendlocation for details.
|
||||
@ -1011,9 +1147,13 @@ class TelegramBot:
|
||||
heading = max(1, min(heading, 360))
|
||||
if proximity_alert_radius: # Distance 1-100000 m
|
||||
proximity_alert_radius = max(1, min(proximity_alert_radius, 100000))
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendLocation',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def editMessageLiveLocation(self, latitude: float, longitude: float,
|
||||
@ -1072,19 +1212,23 @@ class TelegramBot:
|
||||
google_place_id: str = None,
|
||||
google_place_type: str = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send information about a venue.
|
||||
|
||||
Integrated with FourSquare.
|
||||
See https://core.telegram.org/bots/api#sendvenue for details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendVenue',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendContact(self, chat_id: Union[int, str],
|
||||
@ -1093,18 +1237,22 @@ class TelegramBot:
|
||||
last_name: str = None,
|
||||
vcard: str = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a phone contact.
|
||||
|
||||
See https://core.telegram.org/bots/api#sendcontact for details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendContact',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def sendPoll(self,
|
||||
@ -1122,11 +1270,11 @@ class TelegramBot:
|
||||
close_date: Union[int, datetime.datetime] = None,
|
||||
is_closed: bool = None,
|
||||
disable_notification: bool = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a native poll in a group, a supergroup or channel.
|
||||
|
||||
See https://core.telegram.org/bots/api#sendpoll for details.
|
||||
@ -1150,6 +1298,10 @@ class TelegramBot:
|
||||
parameters = locals().copy()
|
||||
parameters['type'] = parameters['type_']
|
||||
del parameters['type_']
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=parameters,
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendPoll',
|
||||
parameters=parameters
|
||||
@ -1497,17 +1649,22 @@ class TelegramBot:
|
||||
inline_message_id: str = None,
|
||||
parse_mode: str = None,
|
||||
entities: List[dict] = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
reply_markup=None):
|
||||
link_preview_options: LinkPreviewOptions = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Edit text and game messages.
|
||||
|
||||
On success, if edited message is sent by the bot, the edited Message
|
||||
is returned, otherwise True is returned.
|
||||
See https://core.telegram.org/bots/api#editmessagetext for details.
|
||||
"""
|
||||
parameters = handle_deprecated_disable_web_page_preview(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'editMessageText',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def editMessageCaption(self,
|
||||
@ -1604,15 +1761,28 @@ class TelegramBot:
|
||||
parameters=locals()
|
||||
)
|
||||
|
||||
async def deleteMessages(self, chat_id: Union[int, str],
|
||||
message_ids: List[int]):
|
||||
"""Delete multiple messages simultaneously.
|
||||
|
||||
If some of the specified messages can't be found, they are skipped.
|
||||
Returns True on success.
|
||||
See https://core.telegram.org/bots/api#deletemessages for details.
|
||||
"""
|
||||
return await self.api_request(
|
||||
'deleteMessages',
|
||||
parameters=locals()
|
||||
)
|
||||
|
||||
async def sendSticker(self, chat_id: Union[int, str],
|
||||
sticker: Union[str, dict, IO],
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
emoji: str = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send `.webp` stickers.
|
||||
|
||||
`sticker` must be a file path, a URL, a file handle or a dict
|
||||
@ -1624,9 +1794,13 @@ class TelegramBot:
|
||||
if sticker is None:
|
||||
logging.error("Invalid sticker provided!")
|
||||
return
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
result = await self.api_request(
|
||||
'sendSticker',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
if type(sticker) is dict: # Close sticker file, if it was open
|
||||
sticker['file'].close()
|
||||
@ -1715,7 +1889,7 @@ class TelegramBot:
|
||||
raise TypeError(f"Unknown sticker type `{sticker_type}`.")
|
||||
result = await self.api_request(
|
||||
'createNewStickerSet',
|
||||
parameters=locals(),
|
||||
parameters=locals().copy(),
|
||||
exclude=['old_sticker_format']
|
||||
)
|
||||
return result
|
||||
@ -1749,7 +1923,7 @@ class TelegramBot:
|
||||
return
|
||||
result = await self.api_request(
|
||||
'addStickerToSet',
|
||||
parameters=locals(),
|
||||
parameters=locals().copy(),
|
||||
exclude=['old_sticker_format']
|
||||
)
|
||||
return result
|
||||
@ -1821,17 +1995,21 @@ class TelegramBot:
|
||||
send_email_to_provider: bool = None,
|
||||
is_flexible: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send an invoice.
|
||||
|
||||
On success, the sent Message is returned.
|
||||
See https://core.telegram.org/bots/api#sendinvoice for details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendInvoice',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def answerShippingQuery(self, shipping_query_id, ok,
|
||||
@ -1895,18 +2073,22 @@ class TelegramBot:
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
allow_sending_without_reply: bool = None):
|
||||
**kwargs):
|
||||
"""Send a game.
|
||||
|
||||
On success, the sent Message is returned.
|
||||
See https://core.telegram.org/bots/api#sendgame for
|
||||
details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendGame',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def setGameScore(self, user_id: int, score: int,
|
||||
@ -1954,11 +2136,11 @@ class TelegramBot:
|
||||
chat_id: Union[int, str] = None,
|
||||
emoji: str = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
message_thread_id: int = None,
|
||||
protect_content: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Send a dice.
|
||||
|
||||
Use this method to send a dice, which will have a random value from 1
|
||||
@ -1969,9 +2151,13 @@ class TelegramBot:
|
||||
See https://core.telegram.org/bots/api#senddice for
|
||||
details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'sendDice',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def setChatAdministratorCustomTitle(self,
|
||||
@ -2100,9 +2286,9 @@ class TelegramBot:
|
||||
parse_mode: str = None,
|
||||
caption_entities: list = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_markup=None):
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None,
|
||||
**kwargs):
|
||||
"""Use this method to copy messages of any kind.
|
||||
|
||||
The method is analogous to the method forwardMessages, but the copied
|
||||
@ -2110,9 +2296,13 @@ class TelegramBot:
|
||||
Returns the MessageId of the sent message on success.
|
||||
See https://core.telegram.org/bots/api#copymessage for details.
|
||||
"""
|
||||
parameters = handle_deprecated_reply_parameters(
|
||||
parameters=locals().copy(),
|
||||
kwargs=kwargs
|
||||
)
|
||||
return await self.api_request(
|
||||
'copyMessage',
|
||||
parameters=locals()
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def unpinAllChatMessages(self, chat_id: Union[int, str]):
|
||||
@ -2700,3 +2890,79 @@ class TelegramBot:
|
||||
'unpinAllGeneralForumTopicMessages',
|
||||
parameters=locals()
|
||||
)
|
||||
|
||||
async def getUserChatBoosts(self, chat_id: Union[int, str], user_id: int):
|
||||
"""Get the list of boosts added to a chat by a user.
|
||||
|
||||
Requires administrator rights in the chat.
|
||||
Returns a UserChatBoosts object.
|
||||
See https://core.telegram.org/bots/api#getuserchatboosts for details.
|
||||
"""
|
||||
return await self.api_request(
|
||||
'getUserChatBoosts',
|
||||
parameters=locals()
|
||||
)
|
||||
|
||||
async def forwardMessages(self, chat_id: Union[int, str],
|
||||
from_chat_id: Union[int, str],
|
||||
message_ids: List[int],
|
||||
message_thread_id: int = None,
|
||||
disable_notification: bool = None,
|
||||
protect_content: bool = None):
|
||||
"""Forward multiple messages of any kind.
|
||||
|
||||
If some of the specified messages can't be found or forwarded, they are
|
||||
skipped.
|
||||
Service messages and messages with protected content can't be
|
||||
forwarded.
|
||||
Album grouping is kept for forwarded messages.
|
||||
On success, an array of MessageId of the sent messages is returned.
|
||||
See https://core.telegram.org/bots/api#forwardmessages for details.
|
||||
"""
|
||||
return await self.api_request(
|
||||
'forwardMessages',
|
||||
parameters=locals()
|
||||
)
|
||||
|
||||
async def copyMessages(self, chat_id: Union[int, str],
|
||||
from_chat_id: Union[int, str],
|
||||
message_ids: List[int],
|
||||
message_thread_id: int = None,
|
||||
disable_notification: bool = None,
|
||||
protect_content: bool = None,
|
||||
remove_caption: bool = None):
|
||||
"""Copy messages of any kind.
|
||||
|
||||
If some of the specified messages can't be found or copied, they are
|
||||
skipped.
|
||||
Service messages, giveaway messages, giveaway winners messages, and
|
||||
invoice messages can't be copied.
|
||||
A quiz poll can be copied only if the value of the field
|
||||
correct_option_id is known to the bot.
|
||||
The method is analogous to the method forwardMessages, but the copied
|
||||
messages don't have a link to the original message.
|
||||
Album grouping is kept for copied messages.
|
||||
On success, an array of MessageId of the sent messages is returned.
|
||||
See https://core.telegram.org/bots/api#copymessages for details.
|
||||
"""
|
||||
return await self.api_request(
|
||||
'copyMessages',
|
||||
parameters=locals()
|
||||
)
|
||||
|
||||
async def setMessageReaction(self, chat_id: Union[int, str],
|
||||
message_id: int,
|
||||
reaction: List[ReactionType] = None,
|
||||
is_big: bool = None):
|
||||
"""Change the chosen reactions on a message.
|
||||
|
||||
Service messages can't be reacted to.
|
||||
Automatically forwarded messages from a channel to its discussion group
|
||||
have the same available reactions as messages in the channel.
|
||||
Returns True on success.
|
||||
See https://core.telegram.org/bots/api#setmessagereaction for details.
|
||||
"""
|
||||
return await self.api_request(
|
||||
'setMessageReaction',
|
||||
parameters=locals()
|
||||
)
|
||||
|
@ -2,34 +2,6 @@
|
||||
|
||||
camelCase methods mirror API directly, while snake_case ones act as middleware
|
||||
someway.
|
||||
|
||||
Usage
|
||||
```
|
||||
import sys
|
||||
|
||||
from davtelepot.bot import Bot
|
||||
|
||||
from data.passwords import my_token, my_other_token
|
||||
|
||||
long_polling_bot = Bot(token=my_token, database_url='my_db')
|
||||
webhook_bot = Bot(token=my_other_token, hostname='example.com',
|
||||
certificate='path/to/certificate.pem',
|
||||
database_url='my_other_db')
|
||||
|
||||
@long_polling_bot.command('/foo')
|
||||
async def foo_command(bot, update, user_record, language):
|
||||
return "Bar!"
|
||||
|
||||
@webhook_bot.command('/bar')
|
||||
async def bar_command(bot, update, user_record, language):
|
||||
return "Foo!"
|
||||
|
||||
exit_state = Bot.run(
|
||||
local_host='127.0.0.5',
|
||||
port=8552
|
||||
)
|
||||
sys.exit(exit_state)
|
||||
```
|
||||
"""
|
||||
|
||||
# Standard library modules
|
||||
@ -49,7 +21,9 @@ from typing import Callable, List, Union, Dict
|
||||
import aiohttp.web
|
||||
|
||||
# Project modules
|
||||
from davtelepot.api import TelegramBot, TelegramError
|
||||
from davtelepot.api import (
|
||||
LinkPreviewOptions, ReplyParameters, TelegramBot, TelegramError
|
||||
)
|
||||
from davtelepot.database import ObjectWithDatabase
|
||||
from davtelepot.languages import MultiLanguageObject
|
||||
from davtelepot.messages import davtelepot_messages
|
||||
@ -1319,19 +1293,21 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
|
||||
async def send_message(self, chat_id: Union[int, str] = None,
|
||||
text: str = None,
|
||||
message_thread_id: int = None,
|
||||
entities: List[dict] = None,
|
||||
parse_mode: str = 'HTML',
|
||||
message_thread_id: int = None,
|
||||
link_preview_options: LinkPreviewOptions = None,
|
||||
disable_notification: bool = None,
|
||||
protect_content: bool = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
send_default_keyboard: bool = True,
|
||||
user_record: OrderedDict = None):
|
||||
user_record: OrderedDict = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None):
|
||||
"""Send text via message(s).
|
||||
|
||||
This method wraps lower-level `TelegramBot.sendMessage` method.
|
||||
@ -1352,6 +1328,10 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
user_record = self.db['users'].find_one(telegram_id=chat_id)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if disable_web_page_preview:
|
||||
if link_preview_options is None:
|
||||
link_preview_options = LinkPreviewOptions()
|
||||
link_preview_options['is_disabled'] = True
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@ -1395,19 +1375,27 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
limit=self.__class__.TELEGRAM_MESSAGES_MAX_LEN - 100,
|
||||
parse_mode=parse_mode
|
||||
)
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
for text_chunk, is_last in text_chunks:
|
||||
_reply_markup = (reply_markup if is_last else None)
|
||||
sent_message_update = await self.sendMessage(
|
||||
chat_id=chat_id,
|
||||
text=text_chunk,
|
||||
message_thread_id=message_thread_id,
|
||||
parse_mode=parse_mode,
|
||||
entities=entities,
|
||||
message_thread_id=message_thread_id,
|
||||
protect_content=protect_content,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
link_preview_options=link_preview_options,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
protect_content=protect_content,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=_reply_markup
|
||||
)
|
||||
return sent_message_update
|
||||
@ -1431,6 +1419,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
parse_mode: str = 'HTML',
|
||||
entities: List[dict] = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
link_preview_options: LinkPreviewOptions = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_markup=None,
|
||||
update: dict = None):
|
||||
@ -1463,6 +1452,10 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
)
|
||||
):
|
||||
if i == 0:
|
||||
if disable_web_page_preview:
|
||||
if link_preview_options is None:
|
||||
link_preview_options = LinkPreviewOptions()
|
||||
link_preview_options['is_disabled'] = True
|
||||
edited_message = await self.editMessageText(
|
||||
text=text_chunk,
|
||||
chat_id=chat_id,
|
||||
@ -1470,7 +1463,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
inline_message_id=inline_message_id,
|
||||
parse_mode=parse_mode,
|
||||
entities=entities,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
link_preview_options=link_preview_options,
|
||||
reply_markup=(reply_markup if is_last else None)
|
||||
)
|
||||
if chat_id is None:
|
||||
@ -1576,6 +1569,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = True):
|
||||
"""Send photos.
|
||||
@ -1599,6 +1593,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
chat_id = self.get_chat_id(update)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@ -1652,8 +1655,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@ -1701,6 +1703,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = True):
|
||||
"""Send audio files.
|
||||
@ -1724,6 +1727,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
chat_id = self.get_chat_id(update)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@ -1781,8 +1793,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
title=title,
|
||||
thumbnail=thumbnail,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@ -1826,6 +1837,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = True):
|
||||
"""Send voice messages.
|
||||
@ -1849,6 +1861,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
chat_id = self.get_chat_id(update)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@ -1903,8 +1924,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
caption_entities=caption_entities,
|
||||
duration=duration,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@ -1951,6 +1971,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
document_name: str = None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = False):
|
||||
"""Send a document.
|
||||
@ -1983,6 +2004,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
return
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if chat_id > 0:
|
||||
user_record = self.db['users'].find_one(telegram_id=chat_id)
|
||||
language = self.get_language(update=update, user_record=user_record)
|
||||
@ -2061,7 +2091,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
caption=caption,
|
||||
parse_mode=parse_mode,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup,
|
||||
update=update,
|
||||
reply_to_update=reply_to_update,
|
||||
@ -2092,8 +2122,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
caption_entities=caption_entities,
|
||||
disable_content_type_detection=disable_content_type_detection,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@ -3505,7 +3534,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
Each bot will receive updates via long polling or webhook according to
|
||||
its initialization parameters.
|
||||
A single aiohttp.web.Application instance will be run (cls.app) on
|
||||
local_host:port and it may serve custom-defined routes as well.
|
||||
local_host:port, and it may serve custom-defined routes as well.
|
||||
"""
|
||||
if local_host is not None:
|
||||
cls.local_host = local_host
|
||||
|
Loading…
x
Reference in New Issue
Block a user