Skip to content

Commit

Permalink
Merge pull request #2395 from coder2020official/botapi-710
Browse files Browse the repository at this point in the history
bot API 7.10
  • Loading branch information
Badiboy authored Sep 18, 2024
2 parents 290b8d3 + 3759a95 commit 6aab790
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 47 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<p align="center">A simple, but extensible Python implementation for the <a href="https://core.telegram.org/bots/api">Telegram Bot API</a>.</p>
<p align="center">Both synchronous and asynchronous.</p>

## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#august-14-2024"><img src="https://img.shields.io/badge/Bot%20API-7.9-blue?logo=telegram" alt="Supported Bot API version"></a>
## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#september-6-2024"><img src="https://img.shields.io/badge/Bot%20API-7.10-blue?logo=telegram" alt="Supported Bot API version"></a>

<h2><a href='https://pytba.readthedocs.io/en/latest/index.html'>Official documentation</a></h2>
<h2><a href='https://pytba.readthedocs.io/ru/latest/index.html'>Official ru documentation</a></h2>
Expand Down
73 changes: 68 additions & 5 deletions telebot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ def __init__(
self.business_message_handlers = []
self.edited_business_message_handlers = []
self.deleted_business_messages_handlers = []
self.purchased_paid_media_handlers = []

self.custom_filters = {}
self.state_handlers = []
Expand Down Expand Up @@ -724,6 +725,7 @@ def process_new_updates(self, updates: List[types.Update]):
new_business_messages = None
new_edited_business_messages = None
new_deleted_business_messages = None
new_purchased_paid_media = None

for update in updates:
if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares:
Expand Down Expand Up @@ -805,8 +807,10 @@ def process_new_updates(self, updates: List[types.Update]):
if update.deleted_business_messages:
if new_deleted_business_messages is None: new_deleted_business_messages = []
new_deleted_business_messages.append(update.deleted_business_messages)


if update.purchased_paid_media:
if new_purchased_paid_media is None: new_purchased_paid_media = []
new_purchased_paid_media.append(update.purchased_paid_media)

if new_messages:
self.process_new_messages(new_messages)
if new_edited_messages:
Expand Down Expand Up @@ -851,6 +855,8 @@ def process_new_updates(self, updates: List[types.Update]):
self.process_new_edited_business_message(new_edited_business_messages)
if new_deleted_business_messages:
self.process_new_deleted_business_messages(new_deleted_business_messages)
if new_purchased_paid_media:
self.process_new_purchased_paid_media(new_purchased_paid_media)

def process_new_messages(self, new_messages):
"""
Expand Down Expand Up @@ -987,8 +993,11 @@ def process_new_deleted_business_messages(self, new_deleted_business_messages):
"""
self._notify_command_handlers(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages')



def process_new_purchased_paid_media(self, new_purchased_paid_media):
"""
:meta private:
"""
self._notify_command_handlers(self.purchased_paid_media_handlers, new_purchased_paid_media, 'purchased_paid_media')

def process_middlewares(self, update):
"""
Expand Down Expand Up @@ -3137,6 +3146,7 @@ def send_paid_media(
show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None,
payload: Optional[str]=None
) -> types.Message:
"""
Use this method to send paid media to channel chats. On success, the sent Message is returned.
Expand Down Expand Up @@ -3179,6 +3189,9 @@ def send_paid_media(
:param business_connection_id: Identifier of a business connection, in which the message will be sent
:type business_connection_id: :obj:`str`
:param payload: Bot-defined paid media payload, 0-128 bytes. This will not be displayed to the user, use it for your internal processes.
:type payload: :obj:`str`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
Expand All @@ -3187,7 +3200,8 @@ def send_paid_media(
self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode,
caption_entities=caption_entities, show_caption_above_media=show_caption_above_media,
disable_notification=disable_notification, protect_content=protect_content,
reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id)
reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id,
payload=payload)
)


Expand Down Expand Up @@ -8035,6 +8049,55 @@ def register_pre_checkout_query_handler(self, callback: Callable, func: Callable
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
self.add_pre_checkout_query_handler(handler_dict)

def purchased_paid_media_handler(self, func=None, **kwargs):
"""
Handles new incoming purchased paid media.
:param func: Function executed as a filter
:type func: :obj:`function`
:param kwargs: Optional keyword arguments(custom filters)
:return: None
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_purchased_paid_media_handler(handler_dict)
return handler

return decorator

def add_purchased_paid_media_handler(self, handler_dict):
"""
Adds a purchased paid media handler
Note that you should use register_purchased_paid_media_handler to add purchased_paid_media_handler to the bot.
:meta private:
:param handler_dict:
:return:
"""
self.purchased_paid_media_handlers.append(handler_dict)

def register_purchased_paid_media_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs):
"""
Registers purchased paid media handler.
:param callback: function to be called
:type callback: :obj:`function`
:param func: Function executed as a filter
:type func: :obj:`function`
: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)
self.add_purchased_paid_media_handler(handler_dict)

def poll_handler(self, func, **kwargs):
"""
Expand Down
26 changes: 14 additions & 12 deletions telebot/apihelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,30 +530,32 @@ def send_paid_media(
token, chat_id, star_count, media,
caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None,
disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None,
business_connection_id=None):
business_connection_id=None, payload=None):
method_url = r'sendPaidMedia'
media_json, files = convert_input_media_array(media)
payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json}
_payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json}
if caption:
payload['caption'] = caption
_payload['caption'] = caption
if parse_mode:
payload['parse_mode'] = parse_mode
_payload['parse_mode'] = parse_mode
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
_payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
if show_caption_above_media is not None:
payload['show_caption_above_media'] = show_caption_above_media
_payload['show_caption_above_media'] = show_caption_above_media
if disable_notification is not None:
payload['disable_notification'] = disable_notification
_payload['disable_notification'] = disable_notification
if protect_content is not None:
payload['protect_content'] = protect_content
_payload['protect_content'] = protect_content
if reply_parameters is not None:
payload['reply_parameters'] = reply_parameters.to_json()
_payload['reply_parameters'] = reply_parameters.to_json()
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
_payload['reply_markup'] = _convert_markup(reply_markup)
if business_connection_id:
payload['business_connection_id'] = business_connection_id
_payload['business_connection_id'] = business_connection_id
if payload:
_payload['payload'] = payload
return _make_request(
token, method_url, params=payload,
token, method_url, params=_payload,
method='post' if files else 'get',
files=files if files else None)

Expand Down
72 changes: 70 additions & 2 deletions telebot/async_telebot.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[
self.business_message_handlers = []
self.edited_business_message_handlers = []
self.deleted_business_messages_handlers = []
self.purchased_paid_media_handlers = []

self.custom_filters = {}
self.state_handlers = []
Expand Down Expand Up @@ -636,6 +637,7 @@ async def process_new_updates(self, updates: List[types.Update]):
new_business_messages = None
new_edited_business_messages = None
new_deleted_business_messages = None
new_purchased_paid_media = None


for update in updates:
Expand Down Expand Up @@ -706,6 +708,9 @@ async def process_new_updates(self, updates: List[types.Update]):
if update.deleted_business_messages:
if new_deleted_business_messages is None: new_deleted_business_messages = []
new_deleted_business_messages.append(update.deleted_business_messages)
if update.purchased_paid_media:
if new_purchased_paid_media is None: new_purchased_paid_media = []
new_purchased_paid_media.append(update.purchased_paid_media)


if new_messages:
Expand Down Expand Up @@ -750,6 +755,8 @@ async def process_new_updates(self, updates: List[types.Update]):
await self.process_new_edited_business_message(new_edited_business_messages)
if new_deleted_business_messages:
await self.process_new_deleted_business_messages(new_deleted_business_messages)
if new_purchased_paid_media:
await self.process_new_purchased_paid_media(new_purchased_paid_media)

async def process_new_messages(self, new_messages):
"""
Expand Down Expand Up @@ -884,6 +891,12 @@ async def process_new_deleted_business_messages(self, new_deleted_business_messa
"""
await self._process_updates(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages')

async def process_new_purchased_paid_media(self, new_purchased_paid_media):
"""
:meta private:
"""
await self._process_updates(self.purchased_paid_media_handlers, new_purchased_paid_media, 'purchased_paid_media')

async def _get_middlewares(self, update_type):
"""
:meta private:
Expand Down Expand Up @@ -1867,6 +1880,56 @@ def register_pre_checkout_query_handler(self, callback: Callable[[Any], Awaitabl
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
self.add_pre_checkout_query_handler(handler_dict)

def purchased_paid_media_handler(self, func=None, **kwargs):
"""
Handles new incoming purchased paid media.
:param func: Function executed as a filter
:type func: :obj:`function`
:param kwargs: Optional keyword arguments(custom filters)
:return: None
"""
def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_purchased_paid_media_handler(handler_dict)
return handler

return decorator

def add_purchased_paid_media_handler(self, handler_dict):
"""
Adds a purchased paid media handler
Note that you should use register_purchased_paid_media_handler to add purchased_paid_media_handler to the bot.
:meta private:
:param handler_dict:
:return:
"""
self.purchased_paid_media_handlers.append(handler_dict)

def register_purchased_paid_media_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs):
"""
Registers purchased paid media handler.
:param callback: function to be called
:type callback: :obj:`function`
:param func: Function executed as a filter
:type func: :obj:`function`
: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)
self.add_purchased_paid_media_handler(handler_dict)

def poll_handler(self, func, **kwargs):
"""
Handles new state of a poll. Bots receive only updates about stopped polls and polls, which are sent by the bot
Expand Down Expand Up @@ -4564,7 +4627,8 @@ async def send_paid_media(
caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None,
show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None) -> types.Message:
reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None,
payload: Optional[str]=None) -> types.Message:
"""
Use this method to send paid media to channel chats. On success, the sent Message is returned.
Expand Down Expand Up @@ -4606,6 +4670,9 @@ async def send_paid_media(
:param business_connection_id: Identifier of a business connection, in which the message will be sent
:type business_connection_id: :obj:`str`
:param payload: Bot-defined paid media payload, 0-128 bytes. This will not be displayed to the user, use it for your internal processes.
:type payload: :obj:`str`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
Expand All @@ -4614,7 +4681,8 @@ async def send_paid_media(
self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode,
caption_entities=caption_entities, show_caption_above_media=show_caption_above_media,
disable_notification=disable_notification, protect_content=protect_content,
reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id))
reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id,
payload=payload))

async def send_media_group(
self, chat_id: Union[int, str],
Expand Down
28 changes: 16 additions & 12 deletions telebot/asyncio_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,30 +520,34 @@ async def send_paid_media(
token, chat_id, star_count, media,
caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None,
disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None,
business_connection_id=None):
business_connection_id=None, payload=None):
method_url = r'sendPaidMedia'
media_json, files = convert_input_media_array(media)
payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json}
_payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json}
# USE _payload for request payload
if caption:
payload['caption'] = caption
_payload['caption'] = caption
if parse_mode:
payload['parse_mode'] = parse_mode
_payload['parse_mode'] = parse_mode
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
_payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
if show_caption_above_media is not None:
payload['show_caption_above_media'] = show_caption_above_media
_payload['show_caption_above_media'] = show_caption_above_media
if disable_notification is not None:
payload['disable_notification'] = disable_notification
_payload['disable_notification'] = disable_notification
if protect_content is not None:
payload['protect_content'] = protect_content
_payload['protect_content'] = protect_content
if reply_parameters is not None:
payload['reply_parameters'] = reply_parameters.to_json()
_payload['reply_parameters'] = reply_parameters.to_json()
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
_payload['reply_markup'] = _convert_markup(reply_markup)
if business_connection_id:
payload['business_connection_id'] = business_connection_id
_payload['business_connection_id'] = business_connection_id
if payload:
_payload['payload'] = payload

return await _process_request(
token, method_url, params=payload,
token, method_url, params=_payload,
method='post' if files else 'get',
files=files if files else None)

Expand Down
Loading

0 comments on commit 6aab790

Please sign in to comment.