Allow to send media groups

This commit is contained in:
jrootjunior 2019-11-14 11:58:44 +02:00
parent 5797ab6c99
commit dd0ee7124b
10 changed files with 116 additions and 78 deletions

View file

@ -95,7 +95,6 @@ from ..types import (
WebhookInfo,
)
from .base import BaseBot
from ...utils.mixins import ContextInstanceMixin
class Bot(ContextInstanceMixin, BaseBot):
@ -135,7 +134,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:rtype: :obj:`List[Update]`
"""
call = GetUpdates(
offset=offset, limit=limit, timeout=timeout, allowed_updates=allowed_updates,
offset=offset, limit=limit, timeout=timeout, allowed_updates=allowed_updates
)
return await self.emit(call)
@ -966,7 +965,7 @@ class Bot(ContextInstanceMixin, BaseBot):
)
return await self.emit(call)
async def send_chat_action(self, chat_id: Union[int, str], action: str,) -> bool:
async def send_chat_action(self, chat_id: Union[int, str], action: str) -> bool:
"""
Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). Returns True on success.
Example: The ImageBot needs some time to process a request and upload the image. Instead of sending a text message along the lines of 'Retrieving image, please wait…', the bot may use sendChatAction with action = upload_photo. The user will see a 'sending photo' status for the bot.
@ -981,11 +980,11 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = SendChatAction(chat_id=chat_id, action=action,)
call = SendChatAction(chat_id=chat_id, action=action)
return await self.emit(call)
async def get_user_profile_photos(
self, user_id: int, offset: Optional[int] = None, limit: Optional[int] = None,
self, user_id: int, offset: Optional[int] = None, limit: Optional[int] = None
) -> UserProfilePhotos:
"""
Use this method to get a list of profile pictures for a user. Returns a UserProfilePhotos object.
@ -1001,10 +1000,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns a UserProfilePhotos object.
:rtype: :obj:`UserProfilePhotos`
"""
call = GetUserProfilePhotos(user_id=user_id, offset=offset, limit=limit,)
call = GetUserProfilePhotos(user_id=user_id, offset=offset, limit=limit)
return await self.emit(call)
async def get_file(self, file_id: str,) -> File:
async def get_file(self, file_id: str) -> File:
"""
Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download files of up to 20MB in size. On success, a File object is returned. The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>, where <file_path> is taken from the response. It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can be requested by calling getFile again.
Note: This function may not preserve the original file name and MIME type. You should save the file's MIME type and name (if available) when the File object is received.
@ -1016,11 +1015,11 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: On success, a File object is returned.
:rtype: :obj:`File`
"""
call = GetFile(file_id=file_id,)
call = GetFile(file_id=file_id)
return await self.emit(call)
async def kick_chat_member(
self, chat_id: Union[int, str], user_id: int, until_date: Optional[int] = None,
self, chat_id: Union[int, str], user_id: int, until_date: Optional[int] = None
) -> bool:
"""
Use this method to kick a user from a group, a supergroup or a channel. In the case of supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
@ -1036,10 +1035,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: In the case of supergroups and channels, the user will not be able to return to the group on their own using invite links, etc. Returns True on success.
:rtype: :obj:`bool`
"""
call = KickChatMember(chat_id=chat_id, user_id=user_id, until_date=until_date,)
call = KickChatMember(chat_id=chat_id, user_id=user_id, until_date=until_date)
return await self.emit(call)
async def unban_chat_member(self, chat_id: Union[int, str], user_id: int,) -> bool:
async def unban_chat_member(self, chat_id: Union[int, str], user_id: int) -> bool:
"""
Use this method to unban a previously kicked user in a supergroup or channel. The user will not return to the group or channel automatically, but will be able to join via link, etc. The bot must be an administrator for this to work. Returns True on success.
@ -1052,7 +1051,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: The user will not return to the group or channel automatically, but will be able to join via link, etc. Returns True on success.
:rtype: :obj:`bool`
"""
call = UnbanChatMember(chat_id=chat_id, user_id=user_id,)
call = UnbanChatMember(chat_id=chat_id, user_id=user_id)
return await self.emit(call)
async def restrict_chat_member(
@ -1079,7 +1078,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:rtype: :obj:`bool`
"""
call = RestrictChatMember(
chat_id=chat_id, user_id=user_id, permissions=permissions, until_date=until_date,
chat_id=chat_id, user_id=user_id, permissions=permissions, until_date=until_date
)
return await self.emit(call)
@ -1139,7 +1138,7 @@ class Bot(ContextInstanceMixin, BaseBot):
return await self.emit(call)
async def set_chat_permissions(
self, chat_id: Union[int, str], permissions: ChatPermissions,
self, chat_id: Union[int, str], permissions: ChatPermissions
) -> bool:
"""
Use this method to set default chat permissions for all members. The bot must be an administrator in the group or a supergroup for this to work and must have the can_restrict_members admin rights. Returns True on success.
@ -1153,10 +1152,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = SetChatPermissions(chat_id=chat_id, permissions=permissions,)
call = SetChatPermissions(chat_id=chat_id, permissions=permissions)
return await self.emit(call)
async def export_chat_invite_link(self, chat_id: Union[int, str],) -> str:
async def export_chat_invite_link(self, chat_id: Union[int, str]) -> str:
"""
Use this method to generate a new invite link for a chat; any previously generated link is revoked. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns the new invite link as String on success.
Note: Each administrator in a chat generates their own invite links. Bots can't use invite links generated by other administrators. If you want your bot to work with invite links, it will need to generate its own link using exportChatInviteLink after this the link will become available to the bot via the getChat method. If your bot needs to generate a new invite link replacing its previous one, use exportChatInviteLink again.
@ -1168,10 +1167,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns the new invite link as String on success.
:rtype: :obj:`str`
"""
call = ExportChatInviteLink(chat_id=chat_id,)
call = ExportChatInviteLink(chat_id=chat_id)
return await self.emit(call)
async def set_chat_photo(self, chat_id: Union[int, str], photo: InputFile,) -> bool:
async def set_chat_photo(self, chat_id: Union[int, str], photo: InputFile) -> bool:
"""
Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
@ -1184,10 +1183,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = SetChatPhoto(chat_id=chat_id, photo=photo,)
call = SetChatPhoto(chat_id=chat_id, photo=photo)
return await self.emit(call)
async def delete_chat_photo(self, chat_id: Union[int, str],) -> bool:
async def delete_chat_photo(self, chat_id: Union[int, str]) -> bool:
"""
Use this method to delete a chat photo. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
@ -1198,10 +1197,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = DeleteChatPhoto(chat_id=chat_id,)
call = DeleteChatPhoto(chat_id=chat_id)
return await self.emit(call)
async def set_chat_title(self, chat_id: Union[int, str], title: str,) -> bool:
async def set_chat_title(self, chat_id: Union[int, str], title: str) -> bool:
"""
Use this method to change the title of a chat. Titles can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
@ -1214,11 +1213,11 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = SetChatTitle(chat_id=chat_id, title=title,)
call = SetChatTitle(chat_id=chat_id, title=title)
return await self.emit(call)
async def set_chat_description(
self, chat_id: Union[int, str], description: Optional[str] = None,
self, chat_id: Union[int, str], description: Optional[str] = None
) -> bool:
"""
Use this method to change the description of a group, a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
@ -1232,7 +1231,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = SetChatDescription(chat_id=chat_id, description=description,)
call = SetChatDescription(chat_id=chat_id, description=description)
return await self.emit(call)
async def pin_chat_message(
@ -1256,11 +1255,11 @@ class Bot(ContextInstanceMixin, BaseBot):
:rtype: :obj:`bool`
"""
call = PinChatMessage(
chat_id=chat_id, message_id=message_id, disable_notification=disable_notification,
chat_id=chat_id, message_id=message_id, disable_notification=disable_notification
)
return await self.emit(call)
async def unpin_chat_message(self, chat_id: Union[int, str],) -> bool:
async def unpin_chat_message(self, chat_id: Union[int, str]) -> bool:
"""
Use this method to unpin a message in a group, a supergroup, or a channel. The bot must be an administrator in the chat for this to work and must have the can_pin_messages admin right in the supergroup or can_edit_messages admin right in the channel. Returns True on success.
@ -1271,10 +1270,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = UnpinChatMessage(chat_id=chat_id,)
call = UnpinChatMessage(chat_id=chat_id)
return await self.emit(call)
async def leave_chat(self, chat_id: Union[int, str],) -> bool:
async def leave_chat(self, chat_id: Union[int, str]) -> bool:
"""
Use this method for your bot to leave a group, supergroup or channel. Returns True on success.
@ -1285,10 +1284,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = LeaveChat(chat_id=chat_id,)
call = LeaveChat(chat_id=chat_id)
return await self.emit(call)
async def get_chat(self, chat_id: Union[int, str],) -> Chat:
async def get_chat(self, chat_id: Union[int, str]) -> Chat:
"""
Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). Returns a Chat object on success.
@ -1299,10 +1298,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns a Chat object on success.
:rtype: :obj:`Chat`
"""
call = GetChat(chat_id=chat_id,)
call = GetChat(chat_id=chat_id)
return await self.emit(call)
async def get_chat_administrators(self, chat_id: Union[int, str],) -> List[ChatMember]:
async def get_chat_administrators(self, chat_id: Union[int, str]) -> List[ChatMember]:
"""
Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned.
@ -1313,10 +1312,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned.
:rtype: :obj:`List[ChatMember]`
"""
call = GetChatAdministrators(chat_id=chat_id,)
call = GetChatAdministrators(chat_id=chat_id)
return await self.emit(call)
async def get_chat_members_count(self, chat_id: Union[int, str],) -> int:
async def get_chat_members_count(self, chat_id: Union[int, str]) -> int:
"""
Use this method to get the number of members in a chat. Returns Int on success.
@ -1327,10 +1326,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns Int on success.
:rtype: :obj:`int`
"""
call = GetChatMembersCount(chat_id=chat_id,)
call = GetChatMembersCount(chat_id=chat_id)
return await self.emit(call)
async def get_chat_member(self, chat_id: Union[int, str], user_id: int,) -> ChatMember:
async def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> ChatMember:
"""
Use this method to get information about a member of a chat. Returns a ChatMember object on success.
@ -1343,10 +1342,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns a ChatMember object on success.
:rtype: :obj:`ChatMember`
"""
call = GetChatMember(chat_id=chat_id, user_id=user_id,)
call = GetChatMember(chat_id=chat_id, user_id=user_id)
return await self.emit(call)
async def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str,) -> bool:
async def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str) -> bool:
"""
Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success.
@ -1359,10 +1358,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success.
:rtype: :obj:`bool`
"""
call = SetChatStickerSet(chat_id=chat_id, sticker_set_name=sticker_set_name,)
call = SetChatStickerSet(chat_id=chat_id, sticker_set_name=sticker_set_name)
return await self.emit(call)
async def delete_chat_sticker_set(self, chat_id: Union[int, str],) -> bool:
async def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool:
"""
Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success.
@ -1373,7 +1372,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success.
:rtype: :obj:`bool`
"""
call = DeleteChatStickerSet(chat_id=chat_id,)
call = DeleteChatStickerSet(chat_id=chat_id)
return await self.emit(call)
async def answer_callback_query(
@ -1585,10 +1584,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: On success, the stopped Poll with the final results is returned.
:rtype: :obj:`Poll`
"""
call = StopPoll(chat_id=chat_id, message_id=message_id, reply_markup=reply_markup,)
call = StopPoll(chat_id=chat_id, message_id=message_id, reply_markup=reply_markup)
return await self.emit(call)
async def delete_message(self, chat_id: Union[int, str], message_id: int,) -> bool:
async def delete_message(self, chat_id: Union[int, str], message_id: int) -> bool:
"""
Use this method to delete a message, including service messages, with the following limitations:
- A message can only be deleted if it was sent less than 48 hours ago.
@ -1608,7 +1607,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = DeleteMessage(chat_id=chat_id, message_id=message_id,)
call = DeleteMessage(chat_id=chat_id, message_id=message_id)
return await self.emit(call)
# =============================================================================================
@ -1653,7 +1652,7 @@ class Bot(ContextInstanceMixin, BaseBot):
)
return await self.emit(call)
async def get_sticker_set(self, name: str,) -> StickerSet:
async def get_sticker_set(self, name: str) -> StickerSet:
"""
Use this method to get a sticker set. On success, a StickerSet object is returned.
@ -1664,10 +1663,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: On success, a StickerSet object is returned.
:rtype: :obj:`StickerSet`
"""
call = GetStickerSet(name=name,)
call = GetStickerSet(name=name)
return await self.emit(call)
async def upload_sticker_file(self, user_id: int, png_sticker: InputFile,) -> File:
async def upload_sticker_file(self, user_id: int, png_sticker: InputFile) -> File:
"""
Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success.
@ -1680,7 +1679,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns the uploaded File on success.
:rtype: :obj:`File`
"""
call = UploadStickerFile(user_id=user_id, png_sticker=png_sticker,)
call = UploadStickerFile(user_id=user_id, png_sticker=png_sticker)
return await self.emit(call)
async def create_new_sticker_set(
@ -1761,7 +1760,7 @@ class Bot(ContextInstanceMixin, BaseBot):
)
return await self.emit(call)
async def set_sticker_position_in_set(self, sticker: str, position: int,) -> bool:
async def set_sticker_position_in_set(self, sticker: str, position: int) -> bool:
"""
Use this method to move a sticker in a set created by the bot to a specific position . Returns True on success.
@ -1774,10 +1773,10 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = SetStickerPositionInSet(sticker=sticker, position=position,)
call = SetStickerPositionInSet(sticker=sticker, position=position)
return await self.emit(call)
async def delete_sticker_from_set(self, sticker: str,) -> bool:
async def delete_sticker_from_set(self, sticker: str) -> bool:
"""
Use this method to delete a sticker from a set created by the bot. Returns True on success.
@ -1788,7 +1787,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: Returns True on success.
:rtype: :obj:`bool`
"""
call = DeleteStickerFromSet(sticker=sticker,)
call = DeleteStickerFromSet(sticker=sticker)
return await self.emit(call)
# =============================================================================================
@ -1984,7 +1983,7 @@ class Bot(ContextInstanceMixin, BaseBot):
return await self.emit(call)
async def answer_pre_checkout_query(
self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str] = None,
self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str] = None
) -> bool:
"""
Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the field pre_checkout_query. Use this method to respond to such pre-checkout queries. On success, True is returned. Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
@ -2001,7 +2000,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:rtype: :obj:`bool`
"""
call = AnswerPreCheckoutQuery(
pre_checkout_query_id=pre_checkout_query_id, ok=ok, error_message=error_message,
pre_checkout_query_id=pre_checkout_query_id, ok=ok, error_message=error_message
)
return await self.emit(call)
@ -2011,7 +2010,7 @@ class Bot(ContextInstanceMixin, BaseBot):
# =============================================================================================
async def set_passport_data_errors(
self, user_id: int, errors: List[PassportElementError],
self, user_id: int, errors: List[PassportElementError]
) -> bool:
"""
Informs a user that some of the Telegram Passport elements they provided contains errors. The user will not be able to re-submit their Passport to you until the errors are fixed (the contents of the field for which you returned the error must change). Returns True on success.
@ -2026,7 +2025,7 @@ class Bot(ContextInstanceMixin, BaseBot):
:return: The user will not be able to re-submit their Passport to you until the errors are fixed (the contents of the field for which you returned the error must change). Returns True on success.
:rtype: :obj:`bool`
"""
call = SetPassportDataErrors(user_id=user_id, errors=errors,)
call = SetPassportDataErrors(user_id=user_id, errors=errors)
return await self.emit(call)
# =============================================================================================

View file

@ -1,7 +1,8 @@
import secrets
from typing import Any, Dict, List, Optional, Union
from .base import Request, TelegramMethod
from ..types import InputMediaPhoto, InputMediaVideo, Message
from ..types import InputMediaPhoto, InputMediaVideo, Message, InputFile
class SendMediaGroup(TelegramMethod[List[Message]]):
@ -26,6 +27,22 @@ class SendMediaGroup(TelegramMethod[List[Message]]):
"""If the messages are a reply, ID of the original message"""
def build_request(self) -> Request:
data: Dict[str, Any] = self.dict(exclude_unset=True, exclude={})
data: Dict[str, Any] = self.dict()
files: Dict[str, InputFile] = {}
return Request(method="sendMediaGroup", data=data)
self.prepare_input_media(data, files)
return Request(method="sendMediaGroup", data=data, files=files)
def prepare_input_media(self, data: Dict[str, Any], files: Dict[str, InputFile]):
if not self.media:
return
for input_media in data.get("media", []): # type: Dict[str, Union[str, InputFile]]
if (
"media" in input_media
and input_media["media"]
and isinstance(input_media["media"], InputFile)
):
tag = secrets.token_urlsafe(10)
files[tag] = input_media.pop("media")
input_media["media"] = f"attach://{tag}"

View file

@ -1,3 +1,4 @@
import json
from typing import Optional, TypeVar
from aiohttp import ClientSession, FormData
@ -26,12 +27,10 @@ class AiohttpSession(BaseSession):
for key, value in request.data.items():
if value is None:
continue
if isinstance(value, bool):
form.add_field(key, value)
else:
form.add_field(key, str(value))
for key, value in request.files.items():
form.add_field(key, value, filename=value.filename or key)
form.add_field(key, self.prepare_value(value))
if request.files:
for key, value in request.files.items():
form.add_field(key, value, filename=value.filename or key)
return form
async def make_request(self, token: str, call: TelegramMethod[T]) -> T:

View file

@ -26,7 +26,7 @@ PRODUCTION = TelegramAPIServer(
)
class BaseSession(abc.ABC, Generic[T]):
class BaseSession(abc.ABC):
def __init__(self, api: TelegramAPIServer = PRODUCTION):
self.api = api
@ -53,3 +53,18 @@ class BaseSession(abc.ABC, Generic[T]):
loop.run_until_complete(self.close())
return
loop.create_task(self.close())
def prepare_value(self, value: Any) -> Union[str, int, bool]:
if isinstance(value, (bool, str, int)):
return value
if isinstance(value, (list, dict)):
return json.dumps(self.clean_json(value))
else:
return str(value)
def clean_json(self, value: Union[List, Dict]):
if isinstance(value, list):
return [self.clean_json(v) for v in value if v is not None]
elif isinstance(value, dict):
return {k: self.clean_json(v) for k, v in value.items() if v is not None}
return value

View file

@ -23,9 +23,11 @@ from .inline_query_result import InlineQueryResult
from .inline_query_result_article import InlineQueryResultArticle
from .inline_query_result_audio import InlineQueryResultAudio
from .inline_query_result_cached_audio import InlineQueryResultCachedAudio
from .inline_query_result_cached_document import InlineQueryResultCachedDocument
from .inline_query_result_cached_document import \
InlineQueryResultCachedDocument
from .inline_query_result_cached_gif import InlineQueryResultCachedGif
from .inline_query_result_cached_mpeg4_gif import InlineQueryResultCachedMpeg4Gif
from .inline_query_result_cached_mpeg4_gif import \
InlineQueryResultCachedMpeg4Gif
from .inline_query_result_cached_photo import InlineQueryResultCachedPhoto
from .inline_query_result_cached_sticker import InlineQueryResultCachedSticker
from .inline_query_result_cached_video import InlineQueryResultCachedVideo
@ -67,10 +69,13 @@ from .passport_element_error_data_field import PassportElementErrorDataField
from .passport_element_error_file import PassportElementErrorFile
from .passport_element_error_files import PassportElementErrorFiles
from .passport_element_error_front_side import PassportElementErrorFrontSide
from .passport_element_error_reverse_side import PassportElementErrorReverseSide
from .passport_element_error_reverse_side import \
PassportElementErrorReverseSide
from .passport_element_error_selfie import PassportElementErrorSelfie
from .passport_element_error_translation_file import PassportElementErrorTranslationFile
from .passport_element_error_translation_files import PassportElementErrorTranslationFiles
from .passport_element_error_translation_file import \
PassportElementErrorTranslationFile
from .passport_element_error_translation_files import \
PassportElementErrorTranslationFiles
from .passport_element_error_unspecified import PassportElementErrorUnspecified
from .passport_file import PassportFile
from .photo_size import PhotoSize

View file

@ -19,7 +19,7 @@ class InputMediaAnimation(InputMedia):
type: str = Field("animation", const=True)
"""Type of the result, must be animation"""
media: str
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name."""
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using multipart/form-data under <file_attach_name>."""

View file

@ -19,7 +19,7 @@ class InputMediaAudio(InputMedia):
type: str = Field("audio", const=True)
"""Type of the result, must be audio"""
media: str
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name."""
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using multipart/form-data under <file_attach_name>."""

View file

@ -19,7 +19,7 @@ class InputMediaDocument(InputMedia):
type: str = Field("document", const=True)
"""Type of the result, must be document"""
media: str
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name."""
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using multipart/form-data under <file_attach_name>."""

View file

@ -1,11 +1,14 @@
from __future__ import annotations
from typing import Optional
from typing import TYPE_CHECKING, Optional, Union
from pydantic import Field
from .input_media import InputMedia
if TYPE_CHECKING:
from .input_file import InputFile
class InputMediaPhoto(InputMedia):
"""
@ -16,7 +19,7 @@ class InputMediaPhoto(InputMedia):
type: str = Field("photo", const=True)
"""Type of the result, must be photo"""
media: str
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name."""
caption: Optional[str] = None
"""Caption of the photo to be sent, 0-1024 characters"""

View file

@ -19,7 +19,7 @@ class InputMediaVideo(InputMedia):
type: str = Field("video", const=True)
"""Type of the result, must be video"""
media: str
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name."""
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using multipart/form-data under <file_attach_name>."""