Refactoring.

This commit is contained in:
Alex Root Junior 2017-06-02 03:01:28 +03:00
parent 62e7bd1cbe
commit 07c7c1f32a
38 changed files with 313 additions and 243 deletions

View file

@ -4,15 +4,7 @@ import json
import aiohttp import aiohttp
from . import api from . import api
from .api import ApiMethods from . import types
from .types.chat import Chat
from .types.chat_member import ChatMember
from .types.file import File
from .types.message import Message
from .types.update import Update
from .types.user import User
from .types.user_profile_photos import UserProfilePhotos
from .types.webhook_info import WebhookInfo
from .utils.payload import generate_payload from .utils.payload import generate_payload
@ -45,7 +37,7 @@ class AIOGramBot:
return obj return obj
@property @property
async def me(self) -> User: async def me(self) -> types.User:
if not hasattr(self, '_me'): if not hasattr(self, '_me'):
setattr(self, '_me', await self.get_me()) setattr(self, '_me', await self.get_me())
return getattr(self, '_me') return getattr(self, '_me')
@ -55,13 +47,13 @@ class AIOGramBot:
async def _send_file(self, file_type, file, payload): async def _send_file(self, file_type, file, payload):
methods = { methods = {
'photo': ApiMethods.SEND_PHOTO, 'photo': api.ApiMethods.SEND_PHOTO,
'audio': ApiMethods.SEND_AUDIO, 'audio': api.ApiMethods.SEND_AUDIO,
'document': ApiMethods.SEND_DOCUMENT, 'document': api.ApiMethods.SEND_DOCUMENT,
'sticker': ApiMethods.SEND_STICKER, 'sticker': api.ApiMethods.SEND_STICKER,
'video': ApiMethods.SEND_VIDEO, 'video': api.ApiMethods.SEND_VIDEO,
'voice': ApiMethods.SEND_VOICE, 'voice': api.ApiMethods.SEND_VOICE,
'video_note': ApiMethods.SEND_VIDEO_NOTE 'video_note': api.ApiMethods.SEND_VIDEO_NOTE
} }
method = methods[file_type] method = methods[file_type]
@ -70,41 +62,41 @@ class AIOGramBot:
req = self.request(method, payload) req = self.request(method, payload)
else: else:
data = {file_type: file} data = {file_type: file}
req = self.request(ApiMethods.SEND_PHOTO, payload, data) req = self.request(api.ApiMethods.SEND_PHOTO, payload, data)
return self.prepare_object(Message.de_json(await req)) return self.prepare_object(types.Message.de_json(await req))
async def get_me(self) -> User: async def get_me(self) -> types.User:
raw = await self.request(ApiMethods.GET_ME) raw = await self.request(api.ApiMethods.GET_ME)
return self.prepare_object(User.de_json(raw)) return self.prepare_object(types.User.de_json(raw))
async def get_updates(self, offset=None, limit=None, timeout=None, allowed_updates=None): async def get_updates(self, offset=None, limit=None, timeout=None, allowed_updates=None) -> [types.Update]:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
raw = await self.request(ApiMethods.GET_UPDATES, payload) raw = await self.request(api.ApiMethods.GET_UPDATES, payload)
return [self.prepare_object(Update.de_json(raw_update)) for raw_update in raw] return [self.prepare_object(types.Update.de_json(raw_update)) for raw_update in raw]
async def set_webhook(self, url, certificate=None, max_connections=None, allowed_updates=None): async def set_webhook(self, url, certificate=None, max_connections=None, allowed_updates=None) -> types.WebhookInfo:
payload = generate_payload(**locals(), exclude='certificate') payload = generate_payload(**locals(), exclude='certificate')
if certificate: if certificate:
cert = {'certificate': certificate} cert = {'certificate': certificate}
req = self.request(ApiMethods.SET_WEBHOOK, payload, cert) req = self.request(api.ApiMethods.SET_WEBHOOK, payload, cert)
else: else:
req = self.request(ApiMethods.SET_WEBHOOK, payload) req = self.request(api.ApiMethods.SET_WEBHOOK, payload)
return self.prepare_object(WebhookInfo.de_json(await req)) return self.prepare_object(types.WebhookInfo.de_json(await req))
async def delete_webhook(self): async def delete_webhook(self) -> bool:
payload = {} payload = {}
await self.request(ApiMethods.DELETE_WEBHOOK, payload) await self.request(api.ApiMethods.DELETE_WEBHOOK, payload)
return True return True
async def get_webhook_info(self): async def get_webhook_info(self) -> types.WebhookInfo:
payload = {} payload = {}
webhook_info = await self.request(ApiMethods.GET_WEBHOOK_INFO, payload) webhook_info = await self.request(api.ApiMethods.GET_WEBHOOK_INFO, payload)
return self.prepare_object(webhook_info) return self.prepare_object(webhook_info)
async def send_message(self, chat_id, text, parse_mode=None, disable_web_page_preview=None, async def send_message(self, chat_id, text, parse_mode=None, disable_web_page_preview=None,
disable_notification=None, reply_to_message_id=None, reply_markup=None): disable_notification=None, reply_to_message_id=None, reply_markup=None) -> types.Message:
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -112,16 +104,16 @@ class AIOGramBot:
reply_to_message_id = reply_to_message_id.message_id reply_to_message_id = reply_to_message_id.message_id
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.SEND_MESSAGE, payload) message = await self.request(api.ApiMethods.SEND_MESSAGE, payload)
return self.prepare_object(Message.de_json(message)) return self.prepare_object(types.Message.de_json(message))
async def forward_message(self, chat_id, from_chat_id, message_id, disable_notification=None): async def forward_message(self, chat_id, from_chat_id, message_id, disable_notification=None) -> types.Message:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.FORWARD_MESSAGE, payload) message = await self.request(api.ApiMethods.FORWARD_MESSAGE, payload)
return self.prepare_object(Message.de_json(message)) return self.prepare_object(types.Message.de_json(message))
async def send_photo(self, chat_id, photo, caption=None, disable_notification=None, reply_to_message_id=None, async def send_photo(self, chat_id, photo, caption=None, disable_notification=None, reply_to_message_id=None,
reply_markup=None) -> Message: reply_markup=None) -> types.Message:
_message_type = 'photo' _message_type = 'photo'
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -133,7 +125,7 @@ class AIOGramBot:
return await self._send_file(_message_type, photo, payload) return await self._send_file(_message_type, photo, payload)
async def send_audio(self, chat_id, audio, caption=None, duration=None, performer=None, title=None, async def send_audio(self, chat_id, audio, caption=None, duration=None, performer=None, title=None,
disable_notification=None, reply_to_message_id=None, reply_markup=None) -> Message: disable_notification=None, reply_to_message_id=None, reply_markup=None) -> types.Message:
_message_type = 'audio' _message_type = 'audio'
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -145,7 +137,7 @@ class AIOGramBot:
return await self._send_file(_message_type, audio, payload) return await self._send_file(_message_type, audio, payload)
async def send_document(self, chat_id, document, caption=None, disable_notification=None, reply_to_message_id=None, async def send_document(self, chat_id, document, caption=None, disable_notification=None, reply_to_message_id=None,
reply_markup=None): reply_markup=None) -> types.Message:
_message_type = 'document' _message_type = 'document'
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -157,7 +149,7 @@ class AIOGramBot:
return await self._send_file(_message_type, document, payload) return await self._send_file(_message_type, document, payload)
async def send_sticker(self, chat_id, sticker, disable_notification=None, reply_to_message_id=None, async def send_sticker(self, chat_id, sticker, disable_notification=None, reply_to_message_id=None,
reply_markup=None) -> Message: reply_markup=None) -> types.Message:
_METHOD = 'sticker' _METHOD = 'sticker'
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -169,7 +161,7 @@ class AIOGramBot:
return await self._send_file(_METHOD, sticker, payload) return await self._send_file(_METHOD, sticker, payload)
async def send_video(self, chat_id, video, duration=None, width=None, height=None, caption=None, async def send_video(self, chat_id, video, duration=None, width=None, height=None, caption=None,
disable_notification=None, reply_to_message_id=None, reply_markup=None) -> Message: disable_notification=None, reply_to_message_id=None, reply_markup=None) -> types.Message:
_message_type = 'video' _message_type = 'video'
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -181,7 +173,7 @@ class AIOGramBot:
return await self._send_file(_message_type, video, payload) return await self._send_file(_message_type, video, payload)
async def send_voice(self, chat_id, voice, caption=None, duration=None, disable_notification=None, async def send_voice(self, chat_id, voice, caption=None, duration=None, disable_notification=None,
reply_to_message_id=None, reply_markup=None) -> Message: reply_to_message_id=None, reply_markup=None) -> types.Message:
_message_type = 'voice' _message_type = 'voice'
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -193,7 +185,7 @@ class AIOGramBot:
return await self._send_file(_message_type, voice, payload) return await self._send_file(_message_type, voice, payload)
async def send_video_note(self, chat_id, video_note, duration=None, length=None, disable_notification=None, async def send_video_note(self, chat_id, video_note, duration=None, length=None, disable_notification=None,
reply_to_message_id=None, reply_markup=None) -> Message: reply_to_message_id=None, reply_markup=None) -> types.Message:
_message_type = 'video_note' _message_type = 'video_note'
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -205,7 +197,7 @@ class AIOGramBot:
return await self._send_file(_message_type, video_note, payload) return await self._send_file(_message_type, video_note, payload)
async def send_location(self, chat_id, latitude, longitude, disable_notification=None, reply_to_message_id=None, async def send_location(self, chat_id, latitude, longitude, disable_notification=None, reply_to_message_id=None,
reply_markup=None): reply_markup=None) -> types.Message:
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -213,11 +205,11 @@ class AIOGramBot:
reply_to_message_id = reply_to_message_id.message_id reply_to_message_id = reply_to_message_id.message_id
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.SEND_LOCATION, payload) message = await self.request(api.ApiMethods.SEND_LOCATION, payload)
return self.prepare_object(Message.de_json(message)) return self.prepare_object(types.Message.de_json(message))
async def send_venue(self, chat_id, latitude, longitude, title, address, foursquare_id, disable_notification=None, async def send_venue(self, chat_id, latitude, longitude, title, address, foursquare_id, disable_notification=None,
reply_to_message_id=None, reply_markup=None): reply_to_message_id=None, reply_markup=None) -> types.Message:
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -225,11 +217,11 @@ class AIOGramBot:
reply_to_message_id = reply_to_message_id.message_id reply_to_message_id = reply_to_message_id.message_id
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.SEND_VENUE, payload) message = await self.request(api.ApiMethods.SEND_VENUE, payload)
return self.prepare_object(Message.de_json(message)) return self.prepare_object(types.Message.de_json(message))
async def send_contact(self, chat_id, phone_number, first_name, last_name=None, disable_notification=None, async def send_contact(self, chat_id, phone_number, first_name, last_name=None, disable_notification=None,
reply_to_message_id=None, reply_markup=None): reply_to_message_id=None, reply_markup=None) -> types.Message:
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -237,61 +229,61 @@ class AIOGramBot:
reply_to_message_id = reply_to_message_id.message_id reply_to_message_id = reply_to_message_id.message_id
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.SEND_CONTACT, payload) message = await self.request(api.ApiMethods.SEND_CONTACT, payload)
return self.prepare_object(Message.de_json(message)) return self.prepare_object(types.Message.de_json(message))
async def send_chat_action(self, chat_id, action): async def send_chat_action(self, chat_id, action) -> bool:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.SEND_CHAT_ACTION, payload) return await self.request(api.ApiMethods.SEND_CHAT_ACTION, payload)
return self.prepare_object(Message.de_json(message))
async def get_user_profile_photos(self, user_id, offset=None, limit=None): async def get_user_profile_photos(self, user_id, offset=None, limit=None) -> types.UserProfilePhotos:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.GET_USER_PROFILE_PHOTOS, payload) message = await self.request(api.ApiMethods.GET_USER_PROFILE_PHOTOS, payload)
return self.prepare_object(UserProfilePhotos.de_json(message)) return self.prepare_object(types.UserProfilePhotos.de_json(message))
async def get_file(self, file_id): async def get_file(self, file_id) -> types.File:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
message = await self.request(ApiMethods.GET_FILE, payload) message = await self.request(api.ApiMethods.GET_FILE, payload)
return self.prepare_object(File.de_json(message)) return self.prepare_object(types.File.de_json(message))
async def kick_chat_user(self, chat_id, user_id): async def kick_chat_user(self, chat_id, user_id) -> bool:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
return await self.request(ApiMethods.KICK_CHAT_MEMBER, payload) return await self.request(api.ApiMethods.KICK_CHAT_MEMBER, payload)
async def unban_chat_member(self, chat_id, user_id): async def unban_chat_member(self, chat_id, user_id) -> bool:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
return await self.request(ApiMethods.UNBAN_CHAT_MEMBER, payload) return await self.request(api.ApiMethods.UNBAN_CHAT_MEMBER, payload)
async def leave_chat(self, chat_id): async def leave_chat(self, chat_id) -> bool:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
return await self.request(ApiMethods.LEAVE_CHAT, payload) return await self.request(api.ApiMethods.LEAVE_CHAT, payload)
async def get_chat(self, chat_id) -> Chat: async def get_chat(self, chat_id) -> types.Chat:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
raw = await self.request(ApiMethods.GET_CHAT, payload) raw = await self.request(api.ApiMethods.GET_CHAT, payload)
return self.prepare_object(Chat.de_json(raw)) return self.prepare_object(types.Chat.de_json(raw))
async def get_chat_administrators(self, chat_id): async def get_chat_administrators(self, chat_id) -> [types.ChatMember]:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
raw = await self.request(ApiMethods.GET_CHAT_ADMINISTRATORS, payload) raw = await self.request(api.ApiMethods.GET_CHAT_ADMINISTRATORS, payload)
return [self.prepare_object(ChatMember.de_json(raw_chat_member)) for raw_chat_member in raw] return [self.prepare_object(types.ChatMember.de_json(raw_chat_member)) for raw_chat_member in raw]
async def get_chat_members_count(self, chat_id): async def get_chat_members_count(self, chat_id) -> int:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
return await self.request(ApiMethods.GET_CHAT_MEMBERS_COUNT, payload) return await self.request(api.ApiMethods.GET_CHAT_MEMBERS_COUNT, payload)
async def get_chat_member(self, chat_id, user_id): async def get_chat_member(self, chat_id, user_id) -> types.ChatMember:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
raw = await self.request(ApiMethods.GET_CHAT_MEMBER, payload) raw = await self.request(api.ApiMethods.GET_CHAT_MEMBER, payload)
return self.prepare_object(ChatMember.de_json(raw)) return self.prepare_object(types.ChatMember.de_json(raw))
async def answer_callback_query(self, callback_query_id, text=None, show_alert=None, url=None, cache_time=None): async def answer_callback_query(self, callback_query_id, text=None, show_alert=None, url=None,
cache_time=None) -> bool:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
return await self.request(ApiMethods.LEAVE_CHAT, payload) return await self.request(api.ApiMethods.LEAVE_CHAT, payload)
async def edit_message_text(self, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, async def edit_message_text(self, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None,
disable_web_page_preview=None, reply_markup=None): disable_web_page_preview=None, reply_markup=None) -> types.Message or bool:
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -302,13 +294,13 @@ class AIOGramBot:
inline_message_id = inline_message_id.message_id inline_message_id = inline_message_id.message_id
payload = generate_payload(**locals()) payload = generate_payload(**locals())
raw = await self.request(ApiMethods.EDIT_MESSAGE_TEXT, payload) raw = await self.request(api.ApiMethods.EDIT_MESSAGE_TEXT, payload)
if raw is True: if raw is True:
return raw return raw
return self.prepare_object(Message.de_json(raw)) return self.prepare_object(types.Message.de_json(raw))
async def edit_message_caption(self, chat_id=None, message_id=None, inline_message_id=None, caption=None, async def edit_message_caption(self, chat_id=None, message_id=None, inline_message_id=None, caption=None,
reply_markup=None): reply_markup=None) -> types.Message or bool:
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -319,12 +311,13 @@ class AIOGramBot:
inline_message_id = inline_message_id.message_id inline_message_id = inline_message_id.message_id
payload = generate_payload(**locals()) payload = generate_payload(**locals())
raw = await self.request(ApiMethods.EDIT_MESSAGE_TEXT, payload) raw = await self.request(api.ApiMethods.EDIT_MESSAGE_TEXT, payload)
if raw is True: if raw is True:
return raw return raw
return self.prepare_object(Message.de_json(raw)) return self.prepare_object(types.Message.de_json(raw))
async def edit_message_reply_markup(self, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None): async def edit_message_reply_markup(self, chat_id=None, message_id=None, inline_message_id=None,
reply_markup=None) -> types.Message or bool:
if reply_markup and hasattr(reply_markup, 'to_json'): if reply_markup and hasattr(reply_markup, 'to_json'):
reply_markup = json.dumps(reply_markup.to_json()) reply_markup = json.dumps(reply_markup.to_json())
@ -335,13 +328,13 @@ class AIOGramBot:
inline_message_id = inline_message_id.message_id inline_message_id = inline_message_id.message_id
payload = generate_payload(**locals()) payload = generate_payload(**locals())
raw = await self.request(ApiMethods.EDIT_MESSAGE_TEXT, payload) raw = await self.request(api.ApiMethods.EDIT_MESSAGE_TEXT, payload)
if raw is True: if raw is True:
return raw return raw
return self.prepare_object(Message.de_json(raw)) return self.prepare_object(types.Message.de_json(raw))
async def delete_message(self, chat_id, message_id): async def delete_message(self, chat_id, message_id) -> bool:
payload = generate_payload(**locals()) payload = generate_payload(**locals())
await self.request(ApiMethods.DELETE_MESSAGE, payload) await self.request(api.ApiMethods.DELETE_MESSAGE, payload)
return True return True

View file

@ -5,7 +5,7 @@ class ValidationError(Exception):
class TelegramAPIError(Exception): class TelegramAPIError(Exception):
def __init__(self, message, method, status, body): def __init__(self, message, method, status, body):
super(TelegramAPIError, self).__init__( super(TelegramAPIError, self).__init__(
f"A request to the Telegram API was unsuccessful (Status code: {status}). {message}") f"A request to the Telegram API was unsuccessful.\n{message}")
self.method = method self.method = method
self.status = status self.status = status
self.body = body self.body = body

View file

@ -1,107 +1,75 @@
import datetime from .animation import Animation
import json from .audio import Audio
import time from .callback_query import CallbackQuery
from .chat import Chat
from .chat_member import ChatMember
from .chosen_inline_result import ChosenInlineResult
from .contact import Contact
from .document import Document
from .file import File
from .force_reply import ForceReply
from .game import Game
from .game_high_score import GameHighScore
from .inline_keyboard import InlineKeyboardButton, InlineKeyboardMarkup
from .inline_query import InlineQuery
from .invoice import Invoice
from .location import Location
from .message import Message
from .message_entity import MessageEntity
from .order_info import OrderInfo
from .photo_size import PhotoSize
from .pre_checkout_query import PreCheckoutQuery
from .reply_keyboard import KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
from .shipping_address import ShippingAddress
from .shipping_query import ShippingQuery
from .sticker import Sticker
from .successful_payment import SuccessfulPayment
from .update import Update
from .user import User
from .user_profile_photos import UserProfilePhotos
from .venue import Venue
from .video import Video
from .video_note import VideoNote
from .voice import Voice
from .webhook_info import WebhookInfo
__all__ = [
def deserialize(deserializable, data): 'Animation',
if data: 'Audio',
return deserializable.de_json(data) 'Base',
'CallbackQuery',
'Chat',
def deserialize_array(deserializable, array): 'ChatMember',
if array: 'ChosenInlineResult',
return [deserialize(deserializable, item) for item in array] 'Contact',
'Document',
'File',
class Serializable: 'ForceReply',
def to_json(self): 'Game',
""" 'GameHighScore',
Returns a JSON string representation of this class. 'InlineKeyboardButton',
'InlineKeyboardMarkup',
This function must be overridden by subclasses. 'InlineQuery',
:return: a JSON formatted string. 'Invoice',
""" 'Location',
raise NotImplementedError 'Message',
'MessageEntity',
'OrderInfo',
class Deserializable: 'PhotoSize',
""" 'PreCheckoutQuery',
Subclasses of this class are guaranteed to be able to be created from a json-style dict or json formatted string. 'KeyboardButton',
All subclasses of this class must override de_json. 'ReplyKeyboardMarkup',
""" 'ReplyKeyboardRemove',
'ShippingAddress',
def to_json(self): 'ShippingQuery',
result = {} 'Sticker',
for name, attr in self.__dict__.items(): 'SuccessfulPayment',
if not attr or name == '_bot': 'Update',
continue 'User',
if hasattr(attr, 'to_json'): 'UserProfilePhotos',
attr = getattr(attr, 'to_json')() 'Venue',
elif isinstance(attr, datetime.datetime): 'Video',
attr = int(time.mktime(attr.timetuple())) 'VideoNote',
result[name] = attr 'Voice',
return result 'WebhookInfo'
]
@property
def bot(self):
if not hasattr(self, '_bot'):
raise AttributeError(f"{self.__class__.__name__} is not configured.")
return getattr(self, '_bot')
@bot.setter
def bot(self, bot):
setattr(self, '_bot', bot)
for name, attr in self.__dict__.items():
if hasattr(attr, 'de_json'):
attr.bot = bot
@property
def parent(self):
return getattr(self, '_parent', None)
@parent.setter
def parent(self, value):
setattr(self, '_parent', value)
for name, attr in self.__dict__.items():
if name.startswith('_'):
continue
if hasattr(attr, 'de_json'):
attr.parent = self
@classmethod
def de_json(cls, raw_data):
"""
Returns an instance of this class from the given json dict or string.
This function must be overridden by subclasses.
:return: an instance of this class created from the given json dict or string.
"""
raise NotImplementedError
@staticmethod
def check_json(raw_data) -> dict:
"""
Checks whether json_type is a dict or a string. If it is already a dict, it is returned as-is.
If it is not, it is converted to a dict by means of json.loads(json_type)
:param raw_data:
:return:
"""
if isinstance(raw_data, dict):
return raw_data
elif isinstance(raw_data, str):
return json.loads(raw_data)
else:
raise ValueError("data should be a json dict or string.")
def __str__(self):
return json.dumps(self.to_json())
def __repr__(self):
return str(self)
@classmethod
def deserialize(cls, obj):
if isinstance(obj, list):
return deserialize_array(cls, obj)
return deserialize(cls, obj)

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .photo_size import PhotoSize from .photo_size import PhotoSize

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class Audio(Deserializable): class Audio(Deserializable):

107
aiogram/types/base.py Normal file
View file

@ -0,0 +1,107 @@
import datetime
import json
import time
def deserialize(deserializable, data):
if data:
return deserializable.de_json(data)
def deserialize_array(deserializable, array):
if array:
return [deserialize(deserializable, item) for item in array]
class Serializable:
def to_json(self):
"""
Returns a JSON string representation of this class.
This function must be overridden by subclasses.
:return: a JSON formatted string.
"""
raise NotImplementedError
class Deserializable:
"""
Subclasses of this class are guaranteed to be able to be created from a json-style dict or json formatted string.
All subclasses of this class must override de_json.
"""
def to_json(self):
result = {}
for name, attr in self.__dict__.items():
if not attr or name == '_bot':
continue
if hasattr(attr, 'to_json'):
attr = getattr(attr, 'to_json')()
elif isinstance(attr, datetime.datetime):
attr = int(time.mktime(attr.timetuple()))
result[name] = attr
return result
@property
def bot(self):
if not hasattr(self, '_bot'):
raise AttributeError(f"{self.__class__.__name__} is not configured.")
return getattr(self, '_bot')
@bot.setter
def bot(self, bot):
setattr(self, '_bot', bot)
for name, attr in self.__dict__.items():
if hasattr(attr, 'de_json'):
attr.bot = bot
@property
def parent(self):
return getattr(self, '_parent', None)
@parent.setter
def parent(self, value):
setattr(self, '_parent', value)
for name, attr in self.__dict__.items():
if name.startswith('_'):
continue
if hasattr(attr, 'de_json'):
attr.parent = self
@classmethod
def de_json(cls, raw_data):
"""
Returns an instance of this class from the given json dict or string.
This function must be overridden by subclasses.
:return: an instance of this class created from the given json dict or string.
"""
raise NotImplementedError
@staticmethod
def check_json(raw_data) -> dict:
"""
Checks whether json_type is a dict or a string. If it is already a dict, it is returned as-is.
If it is not, it is converted to a dict by means of json.loads(json_type)
:param raw_data:
:return:
"""
if isinstance(raw_data, dict):
return raw_data
elif isinstance(raw_data, str):
return json.loads(raw_data)
else:
raise ValueError("data should be a json dict or string.")
def __str__(self):
return json.dumps(self.to_json())
def __repr__(self):
return str(self)
@classmethod
def deserialize(cls, obj):
if isinstance(obj, list):
return deserialize_array(cls, obj)
return deserialize(cls, obj)

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .message import Message from .message import Message
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class Chat(Deserializable): class Chat(Deserializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .location import Location from .location import Location
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class Contact(Deserializable): class Contact(Deserializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .photo_size import PhotoSize from .photo_size import PhotoSize

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class File(Deserializable): class File(Deserializable):

View file

@ -1,4 +1,4 @@
from aiogram.types import Serializable from .base import Serializable
class ForceReply(Serializable): class ForceReply(Serializable):

View file

@ -1,5 +1,5 @@
from . import Deserializable
from .animation import Animation from .animation import Animation
from .base import Deserializable
from .message_entity import MessageEntity from .message_entity import MessageEntity
from .photo_size import PhotoSize from .photo_size import PhotoSize

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Serializable from .base import Serializable
class InlineKeyboardMarkup(Serializable): class InlineKeyboardMarkup(Serializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .location import Location from .location import Location
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class Invoice(Deserializable): class Invoice(Deserializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class Location(Deserializable): class Location(Deserializable):

View file

@ -1,8 +1,7 @@
import datetime import datetime
from aiogram.exceptions import TelegramAPIError
from . import Deserializable
from .audio import Audio from .audio import Audio
from .base import Deserializable
from .chat import Chat from .chat import Chat
from .contact import Contact from .contact import Contact
from .document import Document from .document import Document
@ -18,6 +17,7 @@ from .venue import Venue
from .video import Video from .video import Video
from .video_note import VideoNote from .video_note import VideoNote
from .voice import Voice from .voice import Voice
from ..exceptions import TelegramAPIError
class Message(Deserializable): class Message(Deserializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .shipping_address import ShippingAddress from .shipping_address import ShippingAddress

View file

@ -1,4 +1,4 @@
from . import Deserializable, deserialize from .base import deserialize, Deserializable
class PhotoSize(Deserializable): class PhotoSize(Deserializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .order_info import OrderInfo from .order_info import OrderInfo
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Serializable from .base import Serializable
class ReplyKeyboardMarkup(Serializable): class ReplyKeyboardMarkup(Serializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class ShippingAddress(Deserializable): class ShippingAddress(Deserializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .shipping_address import ShippingAddress from .shipping_address import ShippingAddress
from .user import User from .user import User

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .photo_size import PhotoSize from .photo_size import PhotoSize

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .order_info import OrderInfo from .order_info import OrderInfo

View file

@ -1,10 +1,10 @@
from aiogram.types.callback_query import CallbackQuery from .base import Deserializable
from aiogram.types.chosen_inline_result import ChosenInlineResult from .callback_query import CallbackQuery
from aiogram.types.inline_query import InlineQuery from .chosen_inline_result import ChosenInlineResult
from aiogram.types.pre_checkout_query import PreCheckoutQuery from .inline_query import InlineQuery
from aiogram.types.shipping_query import ShippingQuery
from . import Deserializable
from .message import Message from .message import Message
from .pre_checkout_query import PreCheckoutQuery
from .shipping_query import ShippingQuery
class Update(Deserializable): class Update(Deserializable):

View file

@ -1,6 +1,6 @@
import babel import babel
from . import Deserializable from .base import Deserializable
class User(Deserializable): class User(Deserializable):

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .photo_size import PhotoSize from .photo_size import PhotoSize

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .location import Location from .location import Location

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .photo_size import PhotoSize from .photo_size import PhotoSize

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
from .photo_size import PhotoSize from .photo_size import PhotoSize

View file

@ -1,4 +1,4 @@
from . import Deserializable from .base import Deserializable
class Voice(Deserializable): class Voice(Deserializable):

View file

@ -1,10 +1,11 @@
import datetime import datetime
from . import Deserializable from .base import Deserializable
class WebhookInfo(Deserializable): class WebhookInfo(Deserializable):
def __init__(self, url, has_custom_certificate, pending_update_count, last_error_date, last_error_message, max_connections, allowed_updates): def __init__(self, url, has_custom_certificate, pending_update_count, last_error_date, last_error_message,
max_connections, allowed_updates):
self.url: str = url self.url: str = url
self.has_custom_certificate: bool = has_custom_certificate self.has_custom_certificate: bool = has_custom_certificate
self.pending_update_count: int = pending_update_count self.pending_update_count: int = pending_update_count
@ -29,4 +30,5 @@ class WebhookInfo(Deserializable):
max_connections = raw_data.get('max_connections') max_connections = raw_data.get('max_connections')
allowed_updates = raw_data.get('allowed_updates') allowed_updates = raw_data.get('allowed_updates')
return WebhookInfo(url, has_custom_certificate, pending_update_count, last_error_date, last_error_message, max_connections, allowed_updates) return WebhookInfo(url, has_custom_certificate, pending_update_count, last_error_date, last_error_message,
max_connections, allowed_updates)