Merge pull request #1663 from coder2020official/master

Bot API 6.2
This commit is contained in:
Badiboy 2022-08-13 12:44:33 +03:00 committed by GitHub
commit c8d1dac61e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 111 additions and 23 deletions

View File

@ -11,7 +11,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#june-20-2022">6.1</a>!
## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#august-12-2022">6.2</a>!
<h2><a href='https://pytba.readthedocs.io/en/latest/index.html'>Official documentation</a></h2>

View File

@ -4190,6 +4190,20 @@ class TeleBot:
result = apihelper.get_sticker_set(self.token, name)
return types.StickerSet.de_json(result)
def get_custom_emoji_stickers(self, custom_emoji_ids: List[str]) -> List[types.Sticker]:
"""
Use this method to get information about custom emoji stickers by their identifiers.
Returns an Array of Sticker objects.
:param custom_emoji_ids: List of custom emoji identifiers. At most 200 custom emoji identifiers can be specified.
:type custom_emoji_ids: :obj:`list` of :obj:`str`
:return: Returns an Array of Sticker objects.
:rtype: :obj:`list` of :class:`telebot.types.Sticker`
"""
result = apihelper.get_custom_emoji_stickers(self.token, custom_emoji_ids)
return [types.Sticker.de_json(sticker) for sticker in result]
def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]) -> types.File:
"""
Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet
@ -4217,6 +4231,7 @@ class TeleBot:
tgs_sticker: Union[Any, str]=None,
webm_sticker: Union[Any, str]=None,
contains_masks: Optional[bool]=None,
sticker_type: Optional[str]=None,
mask_position: Optional[types.MaskPosition]=None) -> bool:
"""
Use this method to create new sticker set owned by a user.
@ -4250,18 +4265,28 @@ class TeleBot:
:param webm_sticker: WebM animation with the sticker, uploaded using multipart/form-data.
:type webm_sticker: :obj:`str`
:param contains_masks: Pass True, if a set of mask stickers should be created
:param contains_masks: Pass True, if a set of mask stickers should be created. Deprecated since Bot API 6.2,
use sticker_type instead.
:type contains_masks: :obj:`bool`
:param sticker_type: Optional, Type of stickers in the set, pass regular or mask. Custom emoji sticker sets can't be created
via the Bot API at the moment. By default, a regular sticker set is created.
:type sticker_type: :obj:`str`
:param mask_position: A JSON-serialized object for position where the mask should be placed on faces
:type mask_position: :class:`telebot.types.MaskPosition`
:return: On success, True is returned.
:rtype: :obj:`bool`
"""
if contains_masks is not None:
logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type" instead')
if sticker_type is None:
sticker_type = 'mask' if contains_masks else 'regular'
return apihelper.create_new_sticker_set(
self.token, user_id, name, title, emojis, png_sticker, tgs_sticker,
contains_masks, mask_position, webm_sticker)
mask_position, webm_sticker, sticker_type)
def add_sticker_to_set(
self, user_id: int, name: str, emojis: str,

View File

@ -1561,7 +1561,10 @@ def get_sticker_set(token, name):
method_url = 'getStickerSet'
return _make_request(token, method_url, params={'name': name})
def get_custom_emoji_stickers(token, custom_emoji_ids):
method_url = r'getCustomEmojiStickers'
return _make_request(token, method_url, params={'custom_emoji_ids': custom_emoji_ids})
def upload_sticker_file(token, user_id, png_sticker):
method_url = 'uploadStickerFile'
payload = {'user_id': user_id}
@ -1571,7 +1574,7 @@ def upload_sticker_file(token, user_id, png_sticker):
def create_new_sticker_set(
token, user_id, name, title, emojis, png_sticker, tgs_sticker,
contains_masks=None, mask_position=None, webm_sticker=None):
mask_position=None, webm_sticker=None, sticker_type=None):
method_url = 'createNewStickerSet'
payload = {'user_id': user_id, 'name': name, 'title': title, 'emojis': emojis}
if png_sticker:
@ -1586,12 +1589,12 @@ def create_new_sticker_set(
files = {stype: sticker}
else:
payload[stype] = sticker
if contains_masks is not None:
payload['contains_masks'] = contains_masks
if mask_position:
payload['mask_position'] = mask_position.to_json()
if webm_sticker:
payload['webm_sticker'] = webm_sticker
if sticker_type:
payload['sticker_type'] = sticker_type
return _make_request(token, method_url, params=payload, files=files, method='post')

View File

@ -5028,6 +5028,20 @@ class AsyncTeleBot:
result = await asyncio_helper.get_sticker_set(self.token, name)
return types.StickerSet.de_json(result)
async def get_custom_emoji_stickers(self, custom_emoji_ids: List[str]) -> List[types.Sticker]:
"""
Use this method to get information about custom emoji stickers by their identifiers.
Returns an Array of Sticker objects.
:param custom_emoji_ids: List of custom emoji identifiers. At most 200 custom emoji identifiers can be specified.
:type custom_emoji_ids: :obj:`list` of :obj:`str`
:return: Returns an Array of Sticker objects.
:rtype: :obj:`list` of :class:`telebot.types.Sticker`
"""
result = asyncio_helper.get_custom_emoji_stickers(self.token, custom_emoji_ids)
return [types.Sticker.de_json(sticker) for sticker in result]
async def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]) -> types.File:
"""
Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet
@ -5055,6 +5069,7 @@ class AsyncTeleBot:
tgs_sticker: Union[Any, str]=None,
webm_sticker: Union[Any, str]=None,
contains_masks: Optional[bool]=None,
sticker_type: Optional[str]=None,
mask_position: Optional[types.MaskPosition]=None) -> bool:
"""
Use this method to create new sticker set owned by a user.
@ -5088,18 +5103,28 @@ class AsyncTeleBot:
:param webm_sticker: WebM animation with the sticker, uploaded using multipart/form-data.
:type webm_sticker: :obj:`str`
:param contains_masks: Pass True, if a set of mask stickers should be created
:param contains_masks: Pass True, if a set of mask stickers should be created. Deprecated since Bot API 6.2,
use sticker_type instead.
:type contains_masks: :obj:`bool`
:param sticker_type: Optional, Type of stickers in the set, pass regular or mask. Custom emoji sticker sets can't be created
via the Bot API at the moment. By default, a regular sticker set is created.
:type sticker_type: :obj:`str`
:param mask_position: A JSON-serialized object for position where the mask should be placed on faces
:type mask_position: :class:`telebot.types.MaskPosition`
:return: On success, True is returned.
:rtype: :obj:`bool`
"""
if contains_masks is not None:
logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type" instead')
if sticker_type is None:
sticker_type = 'mask' if contains_masks else 'regular'
return await asyncio_helper.create_new_sticker_set(
self.token, user_id, name, title, emojis, png_sticker, tgs_sticker,
contains_masks, mask_position, webm_sticker)
mask_position, webm_sticker, sticker_type)
async def add_sticker_to_set(

View File

@ -1532,6 +1532,9 @@ async def get_sticker_set(token, name):
method_url = 'getStickerSet'
return await _process_request(token, method_url, params={'name': name})
async def get_custom_emoji_stickers(token, custom_emoji_ids):
method_url = r'getCustomEmojiStickers'
return _process_request(token, method_url, params={'custom_emoji_ids': custom_emoji_ids})
async def upload_sticker_file(token, user_id, png_sticker):
method_url = 'uploadStickerFile'
@ -1542,7 +1545,7 @@ async def upload_sticker_file(token, user_id, png_sticker):
async def create_new_sticker_set(
token, user_id, name, title, emojis, png_sticker, tgs_sticker,
contains_masks=None, mask_position=None, webm_sticker=None):
mask_position=None, webm_sticker=None, sticker_type=None):
method_url = 'createNewStickerSet'
payload = {'user_id': user_id, 'name': name, 'title': title, 'emojis': emojis}
if png_sticker:
@ -1557,12 +1560,12 @@ async def create_new_sticker_set(
files = {stype: sticker}
else:
payload[stype] = sticker
if contains_masks is not None:
payload['contains_masks'] = contains_masks
if mask_position:
payload['mask_position'] = mask_position.to_json()
if webm_sticker:
payload['webm_sticker'] = webm_sticker
if sticker_type:
payload['sticker_type'] = sticker_type
return await _process_request(token, method_url, params=payload, files=files, method='post')

View File

@ -525,6 +525,10 @@ class Chat(JsonDeserializable):
allows to use tg://user?id=<user_id> links only in chats with the user. Returned only in getChat.
:type has_private_forwards: :obj:`bool`
:param has_restricted_voice_and_video_messages: Optional. True, if the privacy settings of the other party restrict sending voice and video note messages
in the private chat. Returned only in getChat.
:type :obj:`bool`
:param join_to_send_messages: Optional. :obj:`bool`, if users need to join the supergroup before they can send
messages. Returned only in getChat.
:type join_to_send_messages: :obj:`bool`
@ -599,7 +603,7 @@ class Chat(JsonDeserializable):
permissions=None, slow_mode_delay=None,
message_auto_delete_time=None, has_protected_content=None, sticker_set_name=None,
can_set_sticker_set=None, linked_chat_id=None, location=None,
join_to_send_messages=None, join_by_request=None, **kwargs):
join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, **kwargs):
self.id: int = id
self.type: str = type
self.title: str = title
@ -611,6 +615,7 @@ class Chat(JsonDeserializable):
self.join_to_send_messages: bool = join_to_send_messages
self.join_by_request: bool = join_by_request
self.has_private_forwards: bool = has_private_forwards
self.has_restricted_voice_and_video_messages: bool = has_restricted_voice_and_video_messages
self.description: str = description
self.invite_link: str = invite_link
self.pinned_message: Message = pinned_message
@ -1251,7 +1256,7 @@ class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable):
(do-not-reply@telegram.org), phone_number (+1-212-555-0123), bold (bold text), italic (italic text),
underline (underlined text), strikethrough (strikethrough text), spoiler (spoiler message), code
(monowidth string), pre (monowidth block), text_link (for clickable text URLs), text_mention (for users
without usernames)
without usernames), custom_emoji (for inline custom emoji stickers)
:type type: :obj:`str`
:param offset: Offset in UTF-16 code units to the start of the entity
@ -1269,6 +1274,10 @@ class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable):
:param language: Optional. For pre only, the programming language of the entity text
:type language: :obj:`str`
:param custom_emoji_id: Optional. For custom_emoji only, unique identifier of the custom emoji.
Use get_custom_emoji_stickers to get full information about the sticker.
:type custom_emoji_id: :obj:`str`
:return: Instance of the class
:rtype: :class:`telebot.types.MessageEntity`
"""
@ -1290,13 +1299,14 @@ class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable):
obj['user'] = User.de_json(obj['user'])
return cls(**obj)
def __init__(self, type, offset, length, url=None, user=None, language=None, **kwargs):
def __init__(self, type, offset, length, url=None, user=None, language=None, custom_emoji_id=None, **kwargs):
self.type: str = type
self.offset: int = offset
self.length: int = length
self.url: str = url
self.user: User = user
self.language: str = language
self.custom_emoji_id: str = custom_emoji_id
def to_json(self):
return json.dumps(self.to_dict())
@ -1307,7 +1317,8 @@ class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable):
"length": self.length,
"url": self.url,
"user": self.user,
"language": self.language}
"language": self.language,
"custom_emoji_id": self.custom_emoji_id}
class Dice(JsonSerializable, Dictionaryable, JsonDeserializable):
@ -5439,13 +5450,17 @@ class StickerSet(JsonDeserializable):
:param title: Sticker set title
:type title: :obj:`str`
:param sticker_type: Type of stickers in the set, currently one of regular, mask, custom_emoji
:type sticker_type: :obj:`str`
:param is_animated: True, if the sticker set contains animated stickers
:type is_animated: :obj:`bool`
:param is_video: True, if the sticker set contains video stickers
:type is_video: :obj:`bool`
:param contains_masks: True, if the sticker set contains masks
:param contains_masks: True, if the sticker set contains masks. Deprecated since Bot API 6.2,
use sticker_type instead.
:type contains_masks: :obj:`bool`
:param stickers: List of all set stickers
@ -5471,15 +5486,23 @@ class StickerSet(JsonDeserializable):
obj['thumb'] = None
return cls(**obj)
def __init__(self, name, title, is_animated, is_video, contains_masks, stickers, thumb=None, **kwargs):
def __init__(self, name, title, sticker_type, is_animated, is_video, stickers, thumb=None, **kwargs):
self.name: str = name
self.title: str = title
self.sticker_type: str = sticker_type
self.is_animated: bool = is_animated
self.is_video: bool = is_video
self.contains_masks: bool = contains_masks
self.stickers: List[Sticker] = stickers
self.thumb: PhotoSize = thumb
@property
def contains_masks(self):
"""
Deprecated since Bot API 6.2, use sticker_type instead.
"""
logger.warning("contains_masks is deprecated, use sticker_type instead")
return self.sticker_type == 'mask'
class Sticker(JsonDeserializable):
"""
@ -5494,6 +5517,10 @@ class Sticker(JsonDeserializable):
bots. Can't be used to download or reuse the file.
:type file_unique_id: :obj:`str`
:param type: Type of the sticker, currently one of regular, mask, custom_emoji. The type of the sticker is
independent from its format, which is determined by the fields is_animated and is_video.
:type type: :obj:`str`
:param width: Sticker width
:type width: :obj:`int`
@ -5521,6 +5548,9 @@ class Sticker(JsonDeserializable):
:param mask_position: Optional. For mask stickers, the position where the mask should be placed
:type mask_position: :class:`telebot.types.MaskPosition`
:param custom_emoji_id: Optional. For custom emoji stickers, unique identifier of the custom emoji
:type custom_emoji_id: :obj:`str`
:param file_size: Optional. File size in bytes
:type file_size: :obj:`int`
@ -5542,11 +5572,12 @@ class Sticker(JsonDeserializable):
obj['premium_animation'] = File.de_json(obj['premium_animation'])
return cls(**obj)
def __init__(self, file_id, file_unique_id, width, height, is_animated,
def __init__(self, file_id, file_unique_id, type, width, height, is_animated,
is_video, thumb=None, emoji=None, set_name=None, mask_position=None, file_size=None,
premium_animation=None, **kwargs):
premium_animation=None, custom_emoji_id=None, **kwargs):
self.file_id: str = file_id
self.file_unique_id: str = file_unique_id
self.type: str = type
self.width: int = width
self.height: int = height
self.is_animated: bool = is_animated
@ -5557,6 +5588,7 @@ class Sticker(JsonDeserializable):
self.mask_position: MaskPosition = mask_position
self.file_size: int = file_size
self.premium_animation: File = premium_animation
self.custom_emoji_id: int = custom_emoji_id

View File

@ -83,7 +83,7 @@ def test_json_Message_Audio():
def test_json_Message_Sticker():
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "thumb": {"file_id": "AAMCBAADHQJOFL7mAAJUMF8Dj62hpmDhpRAYvkc8CtIqipolAAJ8AAPA-8cF9yxjgjkLS97A0D4iXQARtQAHbQADHy4AAhoE", "file_unique_id": "AQADwNA-Il0AAx8uAAI", "file_size": 7776, "width": 60, "height": 60}, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"type": "regular", "width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "thumb": {"file_id": "AAMCBAADHQJOFL7mAAJUMF8Dj62hpmDhpRAYvkc8CtIqipolAAJ8AAPA-8cF9yxjgjkLS97A0D4iXQARtQAHbQADHy4AAhoE", "file_unique_id": "AQADwNA-Il0AAx8uAAI", "file_size": 7776, "width": 60, "height": 60}, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
msg = types.Message.de_json(json_string)
assert msg.sticker.height == 368
assert msg.sticker.thumb.height == 60
@ -91,7 +91,7 @@ def test_json_Message_Sticker():
def test_json_Message_Sticker_without_thumb():
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"type": "regular", "width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
msg = types.Message.de_json(json_string)
assert msg.sticker.height == 368
assert msg.sticker.thumb is None