mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-08 17:13:56 +00:00
Rewrite file uploading mechanism. Allow to send thumbs (Bot API 4.0).
This commit is contained in:
parent
8109400a0d
commit
4d7555b1c3
7 changed files with 252 additions and 135 deletions
|
|
@ -118,7 +118,7 @@ class BaseBot:
|
|||
url = api.Methods.file_url(token=self.__token, path=file_path)
|
||||
|
||||
dest = destination if isinstance(destination, io.IOBase) else open(destination, 'wb')
|
||||
async with self.session.get(url, timeout=timeout, proxy=self.proxy, proxy_auth=self.proxy_auth) as response:
|
||||
async with self.connector.session.get(url, timeout=timeout) as response:
|
||||
while True:
|
||||
chunk = await response.content.read(chunk_size)
|
||||
if not chunk:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from contextvars import ContextVar
|
|||
from .base import BaseBot, api
|
||||
from .. import types
|
||||
from ..types import base
|
||||
from ..utils.payload import generate_payload, prepare_arg
|
||||
from ..utils.payload import generate_payload, prepare_arg, prepare_attachment, prepare_file
|
||||
|
||||
|
||||
class Bot(BaseBot):
|
||||
|
|
@ -91,8 +91,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
allowed_updates = prepare_arg(allowed_updates)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_UPDATES, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_UPDATES, payload)
|
||||
return [types.Update(**update) for update in result]
|
||||
|
||||
async def set_webhook(self, url: base.String,
|
||||
|
|
@ -121,8 +121,11 @@ class Bot(BaseBot):
|
|||
"""
|
||||
allowed_updates = prepare_arg(allowed_updates)
|
||||
payload = generate_payload(**locals(), exclude=['certificate'])
|
||||
result = await self.send_file('certificate', api.Methods.SET_WEBHOOK, certificate, payload)
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'certificate', certificate)
|
||||
|
||||
result = await self.request(api.Methods.SET_WEBHOOK, payload, files)
|
||||
return result
|
||||
|
||||
async def delete_webhook(self) -> base.Boolean:
|
||||
|
|
@ -136,8 +139,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.DELETE_WEBHOOK, payload)
|
||||
|
||||
result = await self.request(api.Methods.DELETE_WEBHOOK, payload)
|
||||
return result
|
||||
|
||||
async def get_webhook_info(self) -> types.WebhookInfo:
|
||||
|
|
@ -152,8 +155,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.WebhookInfo`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_WEBHOOK_INFO, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_WEBHOOK_INFO, payload)
|
||||
return types.WebhookInfo(**result)
|
||||
|
||||
# === Base methods ===
|
||||
|
|
@ -169,8 +172,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.User`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_ME, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_ME, payload)
|
||||
return types.User(**result)
|
||||
|
||||
async def send_message(self, chat_id: typing.Union[base.Integer, base.String], text: base.String,
|
||||
|
|
@ -212,7 +215,6 @@ class Bot(BaseBot):
|
|||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.request(api.Methods.SEND_MESSAGE, payload)
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def forward_message(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -235,8 +237,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.Message`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.FORWARD_MESSAGE, payload)
|
||||
|
||||
result = await self.request(api.Methods.FORWARD_MESSAGE, payload)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_photo(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -278,8 +280,10 @@ class Bot(BaseBot):
|
|||
if self.parse_mode:
|
||||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.send_file('photo', api.Methods.SEND_PHOTO, photo, payload)
|
||||
files = {}
|
||||
prepare_file(payload, files, 'photo', photo)
|
||||
|
||||
result = await self.request(api.Methods.SEND_PHOTO, payload, files)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_audio(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -336,8 +340,10 @@ class Bot(BaseBot):
|
|||
if self.parse_mode:
|
||||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.send_file('audio', api.Methods.SEND_AUDIO, audio, payload)
|
||||
files = {}
|
||||
prepare_file(payload, files, 'audio', audio)
|
||||
|
||||
result = await self.request(api.Methods.SEND_AUDIO, payload, files)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_document(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -384,8 +390,10 @@ class Bot(BaseBot):
|
|||
if self.parse_mode:
|
||||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.send_file('document', api.Methods.SEND_DOCUMENT, document, payload)
|
||||
files = {}
|
||||
prepare_file(payload, files, 'document', document)
|
||||
|
||||
result = await self.request(api.Methods.SEND_DOCUMENT, payload, document)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_video(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -439,29 +447,33 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.Message`
|
||||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals(), exclude=['video'])
|
||||
payload = generate_payload(**locals(), exclude=['video', 'thumb'])
|
||||
if self.parse_mode:
|
||||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.send_file('video', api.Methods.SEND_VIDEO, video, payload)
|
||||
files = {}
|
||||
prepare_file(payload, files, 'video', video)
|
||||
prepare_attachment(payload, files, 'thumb', thumb)
|
||||
|
||||
result = await self.request(api.Methods.SEND_VIDEO, payload, files)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_animation(self,
|
||||
chat_id: typing.Union[base.Integer, base.String],
|
||||
animation: typing.Union[base.InputFile, base.String],
|
||||
duration: typing.Union[base.Integer, None] = None,
|
||||
width: typing.Union[base.Integer, None] = None,
|
||||
height: typing.Union[base.Integer, None] = None,
|
||||
thumb: typing.Union[typing.Union[base.InputFile, base.String], None] = None,
|
||||
caption: typing.Union[base.String, None] = None,
|
||||
parse_mode: typing.Union[base.String, None] = None,
|
||||
disable_notification: typing.Union[base.Boolean, None] = None,
|
||||
reply_to_message_id: typing.Union[base.Integer, None] = None,
|
||||
reply_markup: typing.Union[typing.Union[types.InlineKeyboardMarkup,
|
||||
types.ReplyKeyboardMarkup,
|
||||
types.ReplyKeyboardRemove,
|
||||
types.ForceReply], None] = None,) -> types.Message:
|
||||
chat_id: typing.Union[base.Integer, base.String],
|
||||
animation: typing.Union[base.InputFile, base.String],
|
||||
duration: typing.Union[base.Integer, None] = None,
|
||||
width: typing.Union[base.Integer, None] = None,
|
||||
height: typing.Union[base.Integer, None] = None,
|
||||
thumb: typing.Union[typing.Union[base.InputFile, base.String], None] = None,
|
||||
caption: typing.Union[base.String, None] = None,
|
||||
parse_mode: typing.Union[base.String, None] = None,
|
||||
disable_notification: typing.Union[base.Boolean, None] = None,
|
||||
reply_to_message_id: typing.Union[base.Integer, None] = None,
|
||||
reply_markup: typing.Union[typing.Union[types.InlineKeyboardMarkup,
|
||||
types.ReplyKeyboardMarkup,
|
||||
types.ReplyKeyboardRemove,
|
||||
types.ForceReply], None] = None
|
||||
) -> types.Message:
|
||||
"""
|
||||
Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound).
|
||||
|
||||
|
|
@ -503,9 +515,13 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.Message`
|
||||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals(), exclude=["animation"])
|
||||
result = await self.send_file("animation", api.Methods.SEND_ANIMATION, thumb, payload)
|
||||
payload = generate_payload(**locals(), exclude=["animation", "thumb"])
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'animation', animation)
|
||||
prepare_attachment(payload, files, 'thumb', thumb)
|
||||
|
||||
result = await self.request(api.Methods.SEND_ANIMATION, payload, files)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_voice(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -554,8 +570,10 @@ class Bot(BaseBot):
|
|||
if self.parse_mode:
|
||||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.send_file('voice', api.Methods.SEND_VOICE, voice, payload)
|
||||
files = {}
|
||||
prepare_file(payload, files, 'voice', voice)
|
||||
|
||||
result = await self.request(api.Methods.SEND_VOICE, payload, files)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_video_note(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -597,8 +615,11 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals(), exclude=['video_note'])
|
||||
result = await self.send_file('video_note', api.Methods.SEND_VIDEO_NOTE, video_note, payload)
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'video_note', video_note)
|
||||
|
||||
result = await self.request(api.Methods.SEND_VIDEO_NOTE, payload, files)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_media_group(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -626,13 +647,12 @@ class Bot(BaseBot):
|
|||
if isinstance(media, list):
|
||||
media = types.MediaGroup(media)
|
||||
|
||||
# Extract files
|
||||
files = media.get_files()
|
||||
files = dict(media.get_files())
|
||||
|
||||
media = prepare_arg(media)
|
||||
payload = generate_payload(**locals(), exclude=['files'])
|
||||
result = await self.request(api.Methods.SEND_MEDIA_GROUP, payload, files)
|
||||
|
||||
result = await self.request(api.Methods.SEND_MEDIA_GROUP, payload, files)
|
||||
return [types.Message(**message) for message in result]
|
||||
|
||||
async def send_location(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -669,8 +689,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SEND_LOCATION, payload)
|
||||
|
||||
result = await self.request(api.Methods.SEND_LOCATION, payload)
|
||||
return types.Message(**result)
|
||||
|
||||
async def edit_message_live_location(self, latitude: base.Float, longitude: base.Float,
|
||||
|
|
@ -704,11 +724,10 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_LIVE_LOCATION, payload)
|
||||
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_LIVE_LOCATION, payload)
|
||||
if isinstance(result, bool):
|
||||
return result
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def stop_message_live_location(self,
|
||||
|
|
@ -737,11 +756,10 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.STOP_MESSAGE_LIVE_LOCATION, payload)
|
||||
|
||||
result = await self.request(api.Methods.STOP_MESSAGE_LIVE_LOCATION, payload)
|
||||
if isinstance(result, bool):
|
||||
return result
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_venue(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -786,8 +804,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SEND_VENUE, payload)
|
||||
|
||||
result = await self.request(api.Methods.SEND_VENUE, payload)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_contact(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -827,8 +845,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SEND_CONTACT, payload)
|
||||
|
||||
result = await self.request(api.Methods.SEND_CONTACT, payload)
|
||||
return types.Message(**result)
|
||||
|
||||
async def send_chat_action(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -851,8 +869,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SEND_CHAT_ACTION, payload)
|
||||
|
||||
result = await self.request(api.Methods.SEND_CHAT_ACTION, payload)
|
||||
return result
|
||||
|
||||
async def get_user_profile_photos(self, user_id: base.Integer, offset: typing.Union[base.Integer, None] = None,
|
||||
|
|
@ -872,8 +890,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.UserProfilePhotos`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_USER_PROFILE_PHOTOS, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_USER_PROFILE_PHOTOS, payload)
|
||||
return types.UserProfilePhotos(**result)
|
||||
|
||||
async def get_file(self, file_id: base.String) -> types.File:
|
||||
|
|
@ -892,8 +910,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.File`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_FILE, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_FILE, payload)
|
||||
return types.File(**result)
|
||||
|
||||
async def kick_chat_member(self, chat_id: typing.Union[base.Integer, base.String], user_id: base.Integer,
|
||||
|
|
@ -922,8 +940,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
until_date = prepare_arg(until_date)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.KICK_CHAT_MEMBER, payload)
|
||||
|
||||
result = await self.request(api.Methods.KICK_CHAT_MEMBER, payload)
|
||||
return result
|
||||
|
||||
async def unban_chat_member(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -944,8 +962,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.UNBAN_CHAT_MEMBER, payload)
|
||||
|
||||
result = await self.request(api.Methods.UNBAN_CHAT_MEMBER, payload)
|
||||
return result
|
||||
|
||||
async def restrict_chat_member(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -984,8 +1002,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
until_date = prepare_arg(until_date)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.RESTRICT_CHAT_MEMBER, payload)
|
||||
|
||||
result = await self.request(api.Methods.RESTRICT_CHAT_MEMBER, payload)
|
||||
return result
|
||||
|
||||
async def promote_chat_member(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -1031,8 +1049,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.PROMOTE_CHAT_MEMBER, payload)
|
||||
|
||||
result = await self.request(api.Methods.PROMOTE_CHAT_MEMBER, payload)
|
||||
return result
|
||||
|
||||
async def export_chat_invite_link(self, chat_id: typing.Union[base.Integer, base.String]) -> base.String:
|
||||
|
|
@ -1048,8 +1066,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.String`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.EXPORT_CHAT_INVITE_LINK, payload)
|
||||
|
||||
result = await self.request(api.Methods.EXPORT_CHAT_INVITE_LINK, payload)
|
||||
return result
|
||||
|
||||
async def set_chat_photo(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -1071,8 +1089,11 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals(), exclude=['photo'])
|
||||
result = await self.send_file('photo', api.Methods.SET_CHAT_PHOTO, photo, payload)
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'photo', photo)
|
||||
|
||||
result = await self.request(api.Methods.SET_CHAT_PHOTO, payload, files)
|
||||
return result
|
||||
|
||||
async def delete_chat_photo(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Boolean:
|
||||
|
|
@ -1091,8 +1112,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.DELETE_CHAT_PHOTO, payload)
|
||||
|
||||
result = await self.request(api.Methods.DELETE_CHAT_PHOTO, payload)
|
||||
return result
|
||||
|
||||
async def set_chat_title(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -1114,8 +1135,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SET_CHAT_TITLE, payload)
|
||||
|
||||
result = await self.request(api.Methods.SET_CHAT_TITLE, payload)
|
||||
return result
|
||||
|
||||
async def set_chat_description(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -1134,8 +1155,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SET_CHAT_DESCRIPTION, payload)
|
||||
|
||||
result = await self.request(api.Methods.SET_CHAT_DESCRIPTION, payload)
|
||||
return result
|
||||
|
||||
async def pin_chat_message(self, chat_id: typing.Union[base.Integer, base.String], message_id: base.Integer,
|
||||
|
|
@ -1157,8 +1178,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.PIN_CHAT_MESSAGE, payload)
|
||||
|
||||
result = await self.request(api.Methods.PIN_CHAT_MESSAGE, payload)
|
||||
return result
|
||||
|
||||
async def unpin_chat_message(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Boolean:
|
||||
|
|
@ -1174,8 +1195,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.UNPIN_CHAT_MESSAGE, payload)
|
||||
|
||||
result = await self.request(api.Methods.UNPIN_CHAT_MESSAGE, payload)
|
||||
return result
|
||||
|
||||
async def leave_chat(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Boolean:
|
||||
|
|
@ -1190,8 +1211,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.LEAVE_CHAT, payload)
|
||||
|
||||
result = await self.request(api.Methods.LEAVE_CHAT, payload)
|
||||
return result
|
||||
|
||||
async def get_chat(self, chat_id: typing.Union[base.Integer, base.String]) -> types.Chat:
|
||||
|
|
@ -1207,8 +1228,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.Chat`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_CHAT, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_CHAT, payload)
|
||||
return types.Chat(**result)
|
||||
|
||||
async def get_chat_administrators(self, chat_id: typing.Union[base.Integer, base.String]
|
||||
|
|
@ -1227,8 +1248,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`typing.List[types.ChatMember]`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_CHAT_ADMINISTRATORS, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_CHAT_ADMINISTRATORS, payload)
|
||||
return [types.ChatMember(**chatmember) for chatmember in result]
|
||||
|
||||
async def get_chat_members_count(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Integer:
|
||||
|
|
@ -1243,8 +1264,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Integer`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_CHAT_MEMBERS_COUNT, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_CHAT_MEMBERS_COUNT, payload)
|
||||
return result
|
||||
|
||||
async def get_chat_member(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -1262,8 +1283,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.ChatMember`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_CHAT_MEMBER, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_CHAT_MEMBER, payload)
|
||||
return types.ChatMember(**result)
|
||||
|
||||
async def set_chat_sticker_set(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -1285,8 +1306,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SET_CHAT_STICKER_SET, payload)
|
||||
|
||||
result = await self.request(api.Methods.SET_CHAT_STICKER_SET, payload)
|
||||
return result
|
||||
|
||||
async def delete_chat_sticker_set(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Boolean:
|
||||
|
|
@ -1305,8 +1326,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.DELETE_CHAT_STICKER_SET, payload)
|
||||
|
||||
result = await self.request(api.Methods.DELETE_CHAT_STICKER_SET, payload)
|
||||
return result
|
||||
|
||||
async def answer_callback_query(self, callback_query_id: base.String,
|
||||
|
|
@ -1340,8 +1361,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.ANSWER_CALLBACK_QUERY, payload)
|
||||
|
||||
result = await self.request(api.Methods.ANSWER_CALLBACK_QUERY, payload)
|
||||
return result
|
||||
|
||||
async def edit_message_text(self, text: base.String,
|
||||
|
|
@ -1383,10 +1404,8 @@ class Bot(BaseBot):
|
|||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_TEXT, payload)
|
||||
|
||||
if isinstance(result, bool):
|
||||
return result
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def edit_message_caption(self, chat_id: typing.Union[base.Integer, base.String, None] = None,
|
||||
|
|
@ -1425,19 +1444,17 @@ class Bot(BaseBot):
|
|||
payload.setdefault('parse_mode', self.parse_mode)
|
||||
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_CAPTION, payload)
|
||||
|
||||
if isinstance(result, bool):
|
||||
return result
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def edit_message_media(self,
|
||||
media: types.InputMedia,
|
||||
chat_id: typing.Union[typing.Union[base.Integer, base.String], None] = None,
|
||||
message_id: typing.Union[base.Integer, None] = None,
|
||||
inline_message_id: typing.Union[base.String, None] = None,
|
||||
reply_markup: typing.Union[types.InlineKeyboardMarkup, None] = None,
|
||||
) -> typing.Union[types.Message, base.Boolean]:
|
||||
media: types.InputMedia,
|
||||
chat_id: typing.Union[typing.Union[base.Integer, base.String], None] = None,
|
||||
message_id: typing.Union[base.Integer, None] = None,
|
||||
inline_message_id: typing.Union[base.String, None] = None,
|
||||
reply_markup: typing.Union[types.InlineKeyboardMarkup, None] = None,
|
||||
) -> typing.Union[types.Message, base.Boolean]:
|
||||
"""
|
||||
Use this method to edit audio, document, photo, or video messages.
|
||||
If a message is a part of a message album, then it can be edited only to a photo or a video.
|
||||
|
|
@ -1464,20 +1481,17 @@ class Bot(BaseBot):
|
|||
otherwise True is returned
|
||||
:rtype: :obj:`typing.Union[types.Message, base.Boolean]`
|
||||
"""
|
||||
|
||||
if isinstance(media, types.InputMedia) and media.file:
|
||||
files = {media.attachment_key: media.file}
|
||||
else:
|
||||
files = None
|
||||
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_MEDIA, payload, files)
|
||||
if isinstance(media, types.InputMedia):
|
||||
files = dict(media.get_files())
|
||||
else:
|
||||
files = None
|
||||
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_MEDIA, payload, files)
|
||||
if isinstance(result, bool):
|
||||
return result
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def edit_message_reply_markup(self,
|
||||
|
|
@ -1506,11 +1520,10 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_REPLY_MARKUP, payload)
|
||||
|
||||
result = await self.request(api.Methods.EDIT_MESSAGE_REPLY_MARKUP, payload)
|
||||
if isinstance(result, bool):
|
||||
return result
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def delete_message(self, chat_id: typing.Union[base.Integer, base.String],
|
||||
|
|
@ -1535,8 +1548,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.DELETE_MESSAGE, payload)
|
||||
|
||||
result = await self.request(api.Methods.DELETE_MESSAGE, payload)
|
||||
return result
|
||||
|
||||
# === Stickers ===
|
||||
|
|
@ -1571,8 +1584,11 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals(), exclude=['sticker'])
|
||||
result = await self.send_file('sticker', api.Methods.SEND_STICKER, sticker, payload)
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'sticker', sticker)
|
||||
|
||||
result = await self.request(api.Methods.SEND_STICKER, payload, files)
|
||||
return types.Message(**result)
|
||||
|
||||
async def get_sticker_set(self, name: base.String) -> types.StickerSet:
|
||||
|
|
@ -1587,8 +1603,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.StickerSet`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.GET_STICKER_SET, payload)
|
||||
|
||||
result = await self.request(api.Methods.GET_STICKER_SET, payload)
|
||||
return types.StickerSet(**result)
|
||||
|
||||
async def upload_sticker_file(self, user_id: base.Integer, png_sticker: base.InputFile) -> types.File:
|
||||
|
|
@ -1607,8 +1623,11 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`types.File`
|
||||
"""
|
||||
payload = generate_payload(**locals(), exclude=['png_sticker'])
|
||||
result = await self.send_file('png_sticker', api.Methods.UPLOAD_STICKER_FILE, png_sticker, payload)
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'png_sticker', png_sticker)
|
||||
|
||||
result = await self.request(api.Methods.UPLOAD_STICKER_FILE, payload, files)
|
||||
return types.File(**result)
|
||||
|
||||
async def create_new_sticker_set(self, user_id: base.Integer, name: base.String, title: base.String,
|
||||
|
|
@ -1640,8 +1659,11 @@ class Bot(BaseBot):
|
|||
"""
|
||||
mask_position = prepare_arg(mask_position)
|
||||
payload = generate_payload(**locals(), exclude=['png_sticker'])
|
||||
result = await self.send_file('png_sticker', api.Methods.CREATE_NEW_STICKER_SET, png_sticker, payload)
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'png_sticker', png_sticker)
|
||||
|
||||
result = await self.request(api.Methods.CREATE_NEW_STICKER_SET, payload, files)
|
||||
return result
|
||||
|
||||
async def add_sticker_to_set(self, user_id: base.Integer, name: base.String,
|
||||
|
|
@ -1668,8 +1690,11 @@ class Bot(BaseBot):
|
|||
"""
|
||||
mask_position = prepare_arg(mask_position)
|
||||
payload = generate_payload(**locals(), exclude=['png_sticker'])
|
||||
result = await self.send_file('png_sticker', api.Methods.ADD_STICKER_TO_SET, png_sticker, payload)
|
||||
|
||||
files = {}
|
||||
prepare_file(payload, files, 'png_sticker', png_sticker)
|
||||
|
||||
result = await self.request(api.Methods.ADD_STICKER_TO_SET, payload, files)
|
||||
return result
|
||||
|
||||
async def set_sticker_position_in_set(self, sticker: base.String, position: base.Integer) -> base.Boolean:
|
||||
|
|
@ -1704,8 +1729,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.DELETE_STICKER_FROM_SET, payload)
|
||||
|
||||
result = await self.request(api.Methods.DELETE_STICKER_FROM_SET, payload)
|
||||
return result
|
||||
|
||||
async def answer_inline_query(self, inline_query_id: base.String,
|
||||
|
|
@ -1748,8 +1773,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
results = prepare_arg(results)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.ANSWER_INLINE_QUERY, payload)
|
||||
|
||||
result = await self.request(api.Methods.ANSWER_INLINE_QUERY, payload)
|
||||
return result
|
||||
|
||||
# === Payments ===
|
||||
|
|
@ -1829,8 +1854,8 @@ class Bot(BaseBot):
|
|||
prices = prepare_arg([price.to_python() if hasattr(price, 'to_python') else price for price in prices])
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload_ = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SEND_INVOICE, payload_)
|
||||
|
||||
result = await self.request(api.Methods.SEND_INVOICE, payload_)
|
||||
return types.Message(**result)
|
||||
|
||||
async def answer_shipping_query(self, shipping_query_id: base.String, ok: base.Boolean,
|
||||
|
|
@ -1863,8 +1888,8 @@ class Bot(BaseBot):
|
|||
else shipping_option
|
||||
for shipping_option in shipping_options])
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.ANSWER_SHIPPING_QUERY, payload)
|
||||
|
||||
result = await self.request(api.Methods.ANSWER_SHIPPING_QUERY, payload)
|
||||
return result
|
||||
|
||||
async def answer_pre_checkout_query(self, pre_checkout_query_id: base.String, ok: base.Boolean,
|
||||
|
|
@ -1891,8 +1916,8 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`base.Boolean`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.ANSWER_PRE_CHECKOUT_QUERY, payload)
|
||||
|
||||
result = await self.request(api.Methods.ANSWER_PRE_CHECKOUT_QUERY, payload)
|
||||
return result
|
||||
|
||||
# === Games ===
|
||||
|
|
@ -1923,8 +1948,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
errors = prepare_arg(errors)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SET_PASSPORT_DATA_ERRORS, payload)
|
||||
|
||||
result = await self.request(api.Methods.SET_PASSPORT_DATA_ERRORS, payload)
|
||||
return result
|
||||
|
||||
# === Games ===
|
||||
|
|
@ -1956,8 +1981,8 @@ class Bot(BaseBot):
|
|||
"""
|
||||
reply_markup = prepare_arg(reply_markup)
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SEND_GAME, payload)
|
||||
|
||||
result = await self.request(api.Methods.SEND_GAME, payload)
|
||||
return types.Message(**result)
|
||||
|
||||
async def set_game_score(self, user_id: base.Integer, score: base.Integer,
|
||||
|
|
@ -1994,11 +2019,10 @@ class Bot(BaseBot):
|
|||
:rtype: :obj:`typing.Union[types.Message, base.Boolean]`
|
||||
"""
|
||||
payload = generate_payload(**locals())
|
||||
result = await self.request(api.Methods.SET_GAME_SCORE, payload)
|
||||
|
||||
result = await self.request(api.Methods.SET_GAME_SCORE, payload)
|
||||
if isinstance(result, bool):
|
||||
return result
|
||||
|
||||
return types.Message(**result)
|
||||
|
||||
async def get_game_high_scores(self, user_id: base.Integer,
|
||||
|
|
|
|||
|
|
@ -955,7 +955,7 @@ class SendMediaGroup(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
self.reply_to_message_id = reply_to_message_id
|
||||
|
||||
def prepare(self):
|
||||
files = self.media.get_files()
|
||||
files = dict(self.media.get_files())
|
||||
if files:
|
||||
raise TypeError('Allowed only file ID or URL\'s')
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class BaseField(metaclass=abc.ABCMeta):
|
|||
Base field (prop)
|
||||
"""
|
||||
|
||||
def __init__(self, *, base=None, default=None, alias=None):
|
||||
def __init__(self, *, base=None, default=None, alias=None, on_change=None):
|
||||
"""
|
||||
Init prop
|
||||
|
||||
|
|
@ -17,10 +17,12 @@ class BaseField(metaclass=abc.ABCMeta):
|
|||
:param default: default value
|
||||
:param alias: alias name (for e.g. field 'from' has to be named 'from_user'
|
||||
as 'from' is a builtin Python keyword
|
||||
:param on_change: callback will be called when value is changed
|
||||
"""
|
||||
self.base_object = base
|
||||
self.default = default
|
||||
self.alias = alias
|
||||
self.on_change = on_change
|
||||
|
||||
def __set_name__(self, owner, name):
|
||||
if self.alias is None:
|
||||
|
|
@ -53,6 +55,13 @@ class BaseField(metaclass=abc.ABCMeta):
|
|||
self.resolve_base(instance)
|
||||
value = self.deserialize(value, parent)
|
||||
instance.values[self.alias] = value
|
||||
self._trigger_changed(instance, value)
|
||||
|
||||
def _trigger_changed(self, instance, value):
|
||||
if not self.on_change and instance is not None:
|
||||
return
|
||||
callback = getattr(instance, self.on_change)
|
||||
callback(value)
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
return self.get_value(instance)
|
||||
|
|
@ -154,7 +163,7 @@ class ListOfLists(Field):
|
|||
return result
|
||||
|
||||
|
||||
class DateTimeField(BaseField):
|
||||
class DateTimeField(Field):
|
||||
"""
|
||||
In this field st_ored datetime
|
||||
|
||||
|
|
@ -167,3 +176,24 @@ class DateTimeField(BaseField):
|
|||
|
||||
def deserialize(self, value, parent=None):
|
||||
return datetime.datetime.fromtimestamp(value)
|
||||
|
||||
|
||||
class TextField(Field):
|
||||
def __init__(self, *, prefix=None, suffix=None, default=None, alias=None):
|
||||
super(TextField, self).__init__(default=default, alias=alias)
|
||||
self.prefix = prefix
|
||||
self.suffix = suffix
|
||||
|
||||
def serialize(self, value):
|
||||
if value is None:
|
||||
return value
|
||||
if self.prefix:
|
||||
value = self.prefix + value
|
||||
if self.suffix:
|
||||
value += self.suffix
|
||||
return value
|
||||
|
||||
def deserialize(self, value, parent=None):
|
||||
if value is not None and not isinstance(value, str):
|
||||
raise TypeError(f"Field '{self.alias}' should be str not {type(value).__name__}")
|
||||
return value
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import io
|
||||
import logging
|
||||
import os
|
||||
import secrets
|
||||
import time
|
||||
|
||||
import aiohttp
|
||||
|
|
@ -45,6 +46,8 @@ class InputFile(base.TelegramObject):
|
|||
|
||||
self._filename = filename
|
||||
|
||||
self.attachment_key = secrets.token_urlsafe(16)
|
||||
|
||||
def __del__(self):
|
||||
"""
|
||||
Close file descriptor
|
||||
|
|
@ -61,6 +64,10 @@ class InputFile(base.TelegramObject):
|
|||
def filename(self, value):
|
||||
self._filename = value
|
||||
|
||||
@property
|
||||
def attach(self):
|
||||
return f"attach://{self.attachment_key}"
|
||||
|
||||
def get_filename(self) -> str:
|
||||
"""
|
||||
Get file name
|
||||
|
|
@ -159,6 +166,9 @@ class InputFile(base.TelegramObject):
|
|||
|
||||
return writer
|
||||
|
||||
def __str__(self):
|
||||
return f"<InputFile 'attach://{self.attachment_key}' with file='{self.file}'>"
|
||||
|
||||
def to_python(self):
|
||||
raise TypeError('Object of this type is not exportable!')
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ ATTACHMENT_PREFIX = 'attach://'
|
|||
class InputMedia(base.TelegramObject):
|
||||
"""
|
||||
This object represents the content of a media message to be sent. It should be one of
|
||||
- InputMediaAnimation
|
||||
- InputMediaDocument
|
||||
- InputMediaAudio
|
||||
- InputMediaPhoto
|
||||
- InputMediaVideo
|
||||
|
||||
|
|
@ -20,36 +23,76 @@ class InputMedia(base.TelegramObject):
|
|||
https://core.telegram.org/bots/api#inputmedia
|
||||
"""
|
||||
type: base.String = fields.Field(default='photo')
|
||||
media: base.String = fields.Field()
|
||||
thumb: typing.Union[base.InputFile, base.String] = fields.Field()
|
||||
media: base.String = fields.Field(alias='media', on_change='_media_changed')
|
||||
thumb: typing.Union[base.InputFile, base.String] = fields.Field(alias='thumb', on_change='_thumb_changed')
|
||||
caption: base.String = fields.Field()
|
||||
parse_mode: base.Boolean = fields.Field()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._thumb_file = None
|
||||
self._media_file = None
|
||||
|
||||
media = kwargs.pop('media', None)
|
||||
if isinstance(media, (io.IOBase, InputFile)):
|
||||
self.file = media
|
||||
elif media is not None:
|
||||
self.media = media
|
||||
|
||||
thumb = kwargs.pop('thumb', None)
|
||||
if isinstance(thumb, (io.IOBase, InputFile)):
|
||||
self.thumb_file = thumb
|
||||
elif thumb is not None:
|
||||
self.thumb = thumb
|
||||
|
||||
super(InputMedia, self).__init__(*args, **kwargs)
|
||||
|
||||
try:
|
||||
if self.parse_mode is None and self.bot.parse_mode:
|
||||
if self.parse_mode is None and self.bot and self.bot.parse_mode:
|
||||
self.parse_mode = self.bot.parse_mode
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
@property
|
||||
def file(self):
|
||||
return getattr(self, '_file', None)
|
||||
return self._media_file
|
||||
|
||||
@file.setter
|
||||
def file(self, file: io.IOBase):
|
||||
setattr(self, '_file', file)
|
||||
attachment_key = self.attachment_key = secrets.token_urlsafe(16)
|
||||
self.media = ATTACHMENT_PREFIX + attachment_key
|
||||
self.media = 'attach://' + secrets.token_urlsafe(16)
|
||||
self._media_file = file
|
||||
|
||||
@file.deleter
|
||||
def file(self):
|
||||
self.media = None
|
||||
self._media_file = None
|
||||
|
||||
def _media_changed(self, value):
|
||||
if value is None or isinstance(value, str) and not value.startswith('attach://'):
|
||||
self._media_file = None
|
||||
|
||||
@property
|
||||
def attachment_key(self):
|
||||
return self.conf.get('attachment_key', None)
|
||||
def thumb_file(self):
|
||||
return self._thumb_file
|
||||
|
||||
@attachment_key.setter
|
||||
def attachment_key(self, value):
|
||||
self.conf['attachment_key'] = value
|
||||
@thumb_file.setter
|
||||
def thumb_file(self, file: io.IOBase):
|
||||
self.thumb = 'attach://' + secrets.token_urlsafe(16)
|
||||
self._thumb_file = file
|
||||
|
||||
@thumb_file.deleter
|
||||
def thumb_file(self):
|
||||
self.thumb = None
|
||||
self._thumb_file = None
|
||||
|
||||
def _thumb_changed(self, value):
|
||||
if value is None or isinstance(value, str) and not value.startswith('attach://'):
|
||||
self._thumb_file = None
|
||||
|
||||
def get_files(self):
|
||||
if self._media_file:
|
||||
yield self.media[9:], self._media_file
|
||||
if self._thumb_file:
|
||||
yield self.thumb[9:], self._thumb_file
|
||||
|
||||
|
||||
class InputMediaAnimation(InputMedia):
|
||||
|
|
@ -72,9 +115,6 @@ class InputMediaAnimation(InputMedia):
|
|||
width=width, height=height, duration=duration,
|
||||
parse_mode=parse_mode, conf=kwargs)
|
||||
|
||||
if isinstance(media, (io.IOBase, InputFile)):
|
||||
self.file = media
|
||||
|
||||
|
||||
class InputMediaDocument(InputMedia):
|
||||
"""
|
||||
|
|
@ -89,9 +129,6 @@ class InputMediaDocument(InputMedia):
|
|||
caption=caption, parse_mode=parse_mode,
|
||||
conf=kwargs)
|
||||
|
||||
if isinstance(media, (io.IOBase, InputFile)):
|
||||
self.file = media
|
||||
|
||||
|
||||
class InputMediaAudio(InputMedia):
|
||||
"""
|
||||
|
|
@ -119,9 +156,6 @@ class InputMediaAudio(InputMedia):
|
|||
performer=performer, title=title,
|
||||
parse_mode=parse_mode, conf=kwargs)
|
||||
|
||||
if isinstance(media, (io.IOBase, InputFile)):
|
||||
self.file = media
|
||||
|
||||
|
||||
class InputMediaPhoto(InputMedia):
|
||||
"""
|
||||
|
|
@ -136,9 +170,6 @@ class InputMediaPhoto(InputMedia):
|
|||
caption=caption, parse_mode=parse_mode,
|
||||
conf=kwargs)
|
||||
|
||||
if isinstance(media, (io.IOBase, InputFile)):
|
||||
self.file = media
|
||||
|
||||
|
||||
class InputMediaVideo(InputMedia):
|
||||
"""
|
||||
|
|
@ -151,18 +182,17 @@ class InputMediaVideo(InputMedia):
|
|||
duration: base.Integer = fields.Field()
|
||||
supports_streaming: base.Boolean = fields.Field()
|
||||
|
||||
def __init__(self, media: base.InputFile, caption: base.String = None,
|
||||
def __init__(self, media: base.InputFile,
|
||||
thumb: typing.Union[base.InputFile, base.String] = None,
|
||||
caption: base.String = None,
|
||||
width: base.Integer = None, height: base.Integer = None, duration: base.Integer = None,
|
||||
parse_mode: base.Boolean = None,
|
||||
supports_streaming: base.Boolean = None, **kwargs):
|
||||
super(InputMediaVideo, self).__init__(type='video', media=media, caption=caption,
|
||||
super(InputMediaVideo, self).__init__(type='video', media=media, thumb=thumb, caption=caption,
|
||||
width=width, height=height, duration=duration,
|
||||
parse_mode=parse_mode,
|
||||
supports_streaming=supports_streaming, conf=kwargs)
|
||||
|
||||
if isinstance(media, (io.IOBase, InputFile)):
|
||||
self.file = media
|
||||
|
||||
|
||||
class MediaGroup(base.TelegramObject):
|
||||
"""
|
||||
|
|
@ -296,6 +326,7 @@ class MediaGroup(base.TelegramObject):
|
|||
self.attach(photo)
|
||||
|
||||
def attach_video(self, video: typing.Union[InputMediaVideo, base.InputFile],
|
||||
thumb: typing.Union[base.InputFile, base.String] = None,
|
||||
caption: base.String = None,
|
||||
width: base.Integer = None, height: base.Integer = None, duration: base.Integer = None):
|
||||
"""
|
||||
|
|
@ -308,7 +339,7 @@ class MediaGroup(base.TelegramObject):
|
|||
:param duration:
|
||||
"""
|
||||
if not isinstance(video, InputMedia):
|
||||
video = InputMediaVideo(media=video, caption=caption,
|
||||
video = InputMediaVideo(media=video, thumb=thumb, caption=caption,
|
||||
width=width, height=height, duration=duration)
|
||||
self.attach(video)
|
||||
|
||||
|
|
@ -327,6 +358,7 @@ class MediaGroup(base.TelegramObject):
|
|||
return result
|
||||
|
||||
def get_files(self):
|
||||
return {inputmedia.attachment_key: inputmedia.file
|
||||
for inputmedia in self.media
|
||||
if isinstance(inputmedia, InputMedia) and inputmedia.file}
|
||||
for inputmedia in self.media:
|
||||
if not isinstance(inputmedia, InputMedia) or not inputmedia.file:
|
||||
continue
|
||||
yield from inputmedia.get_files()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import datetime
|
||||
import secrets
|
||||
|
||||
from aiogram import types
|
||||
from . import json
|
||||
|
||||
DEFAULT_FILTER = ['self', 'cls']
|
||||
|
|
@ -56,3 +58,22 @@ def prepare_arg(value):
|
|||
elif isinstance(value, datetime.datetime):
|
||||
return round(value.timestamp())
|
||||
return value
|
||||
|
||||
|
||||
def prepare_file(payload, files, key, file):
|
||||
if isinstance(file, str):
|
||||
payload[key] = file
|
||||
elif file is not None:
|
||||
files[key] = file
|
||||
|
||||
|
||||
def prepare_attachment(payload, files, key, file):
|
||||
if isinstance(file, str):
|
||||
payload[key] = file
|
||||
elif isinstance(file, types.InputFile):
|
||||
payload[key] = file.attach
|
||||
files[file.attachment_key] = file.file
|
||||
elif file is not None:
|
||||
file_attach_name = secrets.token_urlsafe(16)
|
||||
payload[key] = "attach://" + file_attach_name
|
||||
files[file_attach_name] = file
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue