# -*- coding: utf-8 -*- import logging from typing import Dict, List, Optional, Union from abc import ABC try: import ujson as json except ImportError: import json from telebot import util DISABLE_KEYLEN_ERROR = False logger = logging.getLogger('TeleBot') class JsonSerializable(object): """ Subclasses of this class are guaranteed to be able to be converted to JSON format. All subclasses of this class must override to_json. """ 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 Dictionaryable(object): """ Subclasses of this class are guaranteed to be able to be converted to dictionary. All subclasses of this class must override to_dict. """ def to_dict(self): """ Returns a DICT with class field values This function must be overridden by subclasses. :return: a DICT """ raise NotImplementedError class JsonDeserializable(object): """ 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. """ @classmethod def de_json(cls, json_string): """ 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(json_type, dict_copy = True): """ 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 json_type: input json or parsed dict :param dict_copy: if dict is passed and it is changed outside - should be True! :return: Dictionary parsed from json or original dict """ if util.is_dict(json_type): return json_type.copy() if dict_copy else json_type elif util.is_string(json_type): return json.loads(json_type) else: raise ValueError("json_type should be a json dict or string.") def __str__(self): d = { x: y.__dict__ if hasattr(y, '__dict__') else y for x, y in self.__dict__.items() } return str(d) class Update(JsonDeserializable): """ This object represents an incoming update. https://core.telegram.org/bots/api#update :attribute update_id: The update's unique identifier. Update identifiers start from a certain positive number and increase sequentially. This ID becomes especially handy if you're using webhooks, since it allows you to ignore repeated updates or to restore the correct update sequence, should they get out of order. If there are no new updates for at least a week, then identifier of the next update will be chosen randomly instead of sequentially. :type update_id: int :attribute message: New incoming message of any kind — text, photo, sticker, etc. :type message: :class:`telebot.types.Message` :attribute edited_message: New version of a message that is known to the bot and was edited. :type edited_message: :class:`telebot.types.Message` :attribute channel_post: New incoming channel post of any kind — text, photo, sticker, etc. :type channel_post: :class:`telebot.types.Message` :attribute edited_channel_post: New version of a channel post that is known to the bot and was edited. :type edited_channel_post: :class:`telebot.types.Message` :attribute inline_query: New incoming query from a user, which is answered by a bot and can be further processed. :type inline_query: :class:`telebot.types.InlineQuery` :attribute chosen_inline_result: New incoming result of an inline query that was chosen by a user and sent to their chat partner. :type chosen_inline_result: :class:`telebot.types.ChosenInlineResult` :attribute callback_query: New incoming callback query from a user. :type callback_query: :class:`telebot.types.CallbackQuery` :attribute shipping_query: New incoming shipping query. Only for invoices with flexible price :type shipping_query: :class:`telebot.types.ShippingQuery` :attribute pre_checkout_query: New incoming pre-checkout query. Contains full information about checkout :type pre_checkout_query: :class:`telebot.types.PreCheckoutQuery` :attribute poll: New poll state. Bots receive only updates about stopped polls and polls, which are sent by the bot :type poll: :class:`telebot.types.Poll` :attribute poll_answer: A user changed their answer in a non-anonymous poll. Bots receive new votes only in polls that were sent by the bot itself. :type poll_answer: :class:`telebot.types.PollAnswer` :attribute my_chat_member: The bot's chat member status was updated in a chat. For private chats, this update is received only when the bot is blocked or unblocked by the user. :type my_chat_member: :class:`telebot.types.ChatMember` :attribute chat_member: A chat member's status was updated in a chat. The bot must be an administrator in the chat and must explicitly specify “chat_member” in the list of allowed_updates to receive these updates. :type chat_member: :class:`telebot.types.ChatMember` :attribute chat_join_request: A request to join the chat has been sent. The bot must have the can_invite_users administrator right in the chat to receive these updates. :type chat_join_request: :class:`telebot.types.ChatJoinRequest` :return: An Update object. :rtype: :class:`telebot.types.Update` """ @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) update_id = obj['update_id'] message = Message.de_json(obj.get('message')) edited_message = Message.de_json(obj.get('edited_message')) channel_post = Message.de_json(obj.get('channel_post')) edited_channel_post = Message.de_json(obj.get('edited_channel_post')) inline_query = InlineQuery.de_json(obj.get('inline_query')) chosen_inline_result = ChosenInlineResult.de_json(obj.get('chosen_inline_result')) callback_query = CallbackQuery.de_json(obj.get('callback_query')) shipping_query = ShippingQuery.de_json(obj.get('shipping_query')) pre_checkout_query = PreCheckoutQuery.de_json(obj.get('pre_checkout_query')) poll = Poll.de_json(obj.get('poll')) poll_answer = PollAnswer.de_json(obj.get('poll_answer')) my_chat_member = ChatMemberUpdated.de_json(obj.get('my_chat_member')) chat_member = ChatMemberUpdated.de_json(obj.get('chat_member')) chat_join_request = ChatJoinRequest.de_json(obj.get('chat_join_request')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request): self.update_id = update_id self.message = message self.edited_message = edited_message self.channel_post = channel_post self.edited_channel_post = edited_channel_post self.inline_query = inline_query self.chosen_inline_result = chosen_inline_result self.callback_query = callback_query self.shipping_query = shipping_query self.pre_checkout_query = pre_checkout_query self.poll = poll self.poll_answer = poll_answer self.my_chat_member = my_chat_member self.chat_member = chat_member self.chat_join_request = chat_join_request class ChatMemberUpdated(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) obj['from_user'] = User.de_json(obj.pop('from')) obj['old_chat_member'] = ChatMember.de_json(obj['old_chat_member']) obj['new_chat_member'] = ChatMember.de_json(obj['new_chat_member']) obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link')) return cls(**obj) def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, **kwargs): self.chat: Chat = chat self.from_user: User = from_user self.date: int = date self.old_chat_member: ChatMember = old_chat_member self.new_chat_member: ChatMember = new_chat_member self.invite_link: Optional[ChatInviteLink] = invite_link @property def difference(self) -> Dict[str, List]: """ Get the difference between `old_chat_member` and `new_chat_member` as a dict in the following format {'parameter': [old_value, new_value]} E.g {'status': ['member', 'kicked'], 'until_date': [None, 1625055092]} """ old: Dict = self.old_chat_member.__dict__ new: Dict = self.new_chat_member.__dict__ dif = {} for key in new: if key == 'user': continue if new[key] != old[key]: dif[key] = [old[key], new[key]] return dif class ChatJoinRequest(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) obj['from_user'] = User.de_json(obj['from']) obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link')) return cls(**obj) def __init__(self, chat, from_user, date, bio=None, invite_link=None, **kwargs): self.chat = chat self.from_user = from_user self.date = date self.bio = bio self.invite_link = invite_link class WebhookInfo(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, url, has_custom_certificate, pending_update_count, ip_address=None, last_error_date=None, last_error_message=None, last_synchronization_error_date=None, max_connections=None, allowed_updates=None, **kwargs): self.url = url self.has_custom_certificate = has_custom_certificate self.pending_update_count = pending_update_count self.ip_address = ip_address self.last_error_date = last_error_date self.last_error_message = last_error_message self.last_synchronization_error_date = last_synchronization_error_date self.max_connections = max_connections self.allowed_updates = allowed_updates class User(JsonDeserializable, Dictionaryable, JsonSerializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, id, is_bot, first_name, last_name=None, username=None, language_code=None, can_join_groups=None, can_read_all_group_messages=None, supports_inline_queries=None, is_premium=None, added_to_attachment_menu=None, **kwargs): self.id: int = id self.is_bot: bool = is_bot self.first_name: str = first_name self.username: str = username self.last_name: str = last_name self.language_code: str = language_code self.can_join_groups: bool = can_join_groups self.can_read_all_group_messages: bool = can_read_all_group_messages self.supports_inline_queries: bool = supports_inline_queries self.is_premium: bool = is_premium self.added_to_attachment_menu: bool = added_to_attachment_menu @property def full_name(self): full_name = self.first_name if self.last_name: full_name += ' {0}'.format(self.last_name) return full_name def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return {'id': self.id, 'is_bot': self.is_bot, 'first_name': self.first_name, 'last_name': self.last_name, 'username': self.username, 'language_code': self.language_code, 'can_join_groups': self.can_join_groups, 'can_read_all_group_messages': self.can_read_all_group_messages, 'supports_inline_queries': self.supports_inline_queries} class GroupChat(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, id, title, **kwargs): self.id: int = id self.title: str = title class Chat(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'photo' in obj: obj['photo'] = ChatPhoto.de_json(obj['photo']) if 'pinned_message' in obj: obj['pinned_message'] = Message.de_json(obj['pinned_message']) if 'permissions' in obj: obj['permissions'] = ChatPermissions.de_json(obj['permissions']) if 'location' in obj: obj['location'] = ChatLocation.de_json(obj['location']) return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, last_name=None, photo=None, bio=None, has_private_forwards=None, description=None, invite_link=None, pinned_message=None, permissions=None, slow_mode_delay=None, message_auto_delete_time=None, has_protected_content=None, sticker_set_name=None, can_set_sticker_set=None, linked_chat_id=None, location=None, join_to_send_messages=None, join_by_request=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title self.username: str = username self.first_name: str = first_name self.last_name: str = last_name self.photo: ChatPhoto = photo self.bio: str = bio self.join_to_send_messages: bool = join_to_send_messages self.join_by_request: bool = join_by_request self.has_private_forwards: bool = has_private_forwards self.description: str = description self.invite_link: str = invite_link self.pinned_message: Message = pinned_message self.permissions: ChatPermissions = permissions self.slow_mode_delay: int = slow_mode_delay self.message_auto_delete_time: int = message_auto_delete_time self.has_protected_content: bool = has_protected_content self.sticker_set_name: str = sticker_set_name self.can_set_sticker_set: bool = can_set_sticker_set self.linked_chat_id: int = linked_chat_id self.location: ChatLocation = location class MessageID(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, message_id, **kwargs): self.message_id = message_id class WebAppData(JsonDeserializable): def __init__(self, data, button_text): self.data = data self.button_text = button_text def to_dict(self): return {'data': self.data, 'button_text': self.button_text} @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) class Message(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) message_id = obj['message_id'] from_user = User.de_json(obj.get('from')) date = obj['date'] chat = Chat.de_json(obj['chat']) content_type = None opts = {} if 'sender_chat' in obj: opts['sender_chat'] = Chat.de_json(obj['sender_chat']) if 'forward_from' in obj: opts['forward_from'] = User.de_json(obj['forward_from']) if 'forward_from_chat' in obj: opts['forward_from_chat'] = Chat.de_json(obj['forward_from_chat']) if 'forward_from_message_id' in obj: opts['forward_from_message_id'] = obj.get('forward_from_message_id') if 'forward_signature' in obj: opts['forward_signature'] = obj.get('forward_signature') if 'forward_sender_name' in obj: opts['forward_sender_name'] = obj.get('forward_sender_name') if 'forward_date' in obj: opts['forward_date'] = obj.get('forward_date') if 'is_automatic_forward' in obj: opts['is_automatic_forward'] = obj.get('is_automatic_forward') if 'reply_to_message' in obj: opts['reply_to_message'] = Message.de_json(obj['reply_to_message']) if 'via_bot' in obj: opts['via_bot'] = User.de_json(obj['via_bot']) if 'edit_date' in obj: opts['edit_date'] = obj.get('edit_date') if 'has_protected_content' in obj: opts['has_protected_content'] = obj.get('has_protected_content') if 'media_group_id' in obj: opts['media_group_id'] = obj.get('media_group_id') if 'author_signature' in obj: opts['author_signature'] = obj.get('author_signature') if 'text' in obj: opts['text'] = obj['text'] content_type = 'text' if 'entities' in obj: opts['entities'] = Message.parse_entities(obj['entities']) if 'caption_entities' in obj: opts['caption_entities'] = Message.parse_entities(obj['caption_entities']) if 'audio' in obj: opts['audio'] = Audio.de_json(obj['audio']) content_type = 'audio' if 'document' in obj: opts['document'] = Document.de_json(obj['document']) content_type = 'document' if 'animation' in obj: # Document content type accompanies "animation", # so "animation" should be checked below "document" to override it opts['animation'] = Animation.de_json(obj['animation']) content_type = 'animation' if 'game' in obj: opts['game'] = Game.de_json(obj['game']) content_type = 'game' if 'photo' in obj: opts['photo'] = Message.parse_photo(obj['photo']) content_type = 'photo' if 'sticker' in obj: opts['sticker'] = Sticker.de_json(obj['sticker']) content_type = 'sticker' if 'video' in obj: opts['video'] = Video.de_json(obj['video']) content_type = 'video' if 'video_note' in obj: opts['video_note'] = VideoNote.de_json(obj['video_note']) content_type = 'video_note' if 'voice' in obj: opts['voice'] = Audio.de_json(obj['voice']) content_type = 'voice' if 'caption' in obj: opts['caption'] = obj['caption'] if 'contact' in obj: opts['contact'] = Contact.de_json(json.dumps(obj['contact'])) content_type = 'contact' if 'location' in obj: opts['location'] = Location.de_json(obj['location']) content_type = 'location' if 'venue' in obj: opts['venue'] = Venue.de_json(obj['venue']) content_type = 'venue' if 'dice' in obj: opts['dice'] = Dice.de_json(obj['dice']) content_type = 'dice' if 'new_chat_members' in obj: new_chat_members = [] for member in obj['new_chat_members']: new_chat_members.append(User.de_json(member)) opts['new_chat_members'] = new_chat_members content_type = 'new_chat_members' if 'left_chat_member' in obj: opts['left_chat_member'] = User.de_json(obj['left_chat_member']) content_type = 'left_chat_member' if 'new_chat_title' in obj: opts['new_chat_title'] = obj['new_chat_title'] content_type = 'new_chat_title' if 'new_chat_photo' in obj: opts['new_chat_photo'] = Message.parse_photo(obj['new_chat_photo']) content_type = 'new_chat_photo' if 'delete_chat_photo' in obj: opts['delete_chat_photo'] = obj['delete_chat_photo'] content_type = 'delete_chat_photo' if 'group_chat_created' in obj: opts['group_chat_created'] = obj['group_chat_created'] content_type = 'group_chat_created' if 'supergroup_chat_created' in obj: opts['supergroup_chat_created'] = obj['supergroup_chat_created'] content_type = 'supergroup_chat_created' if 'channel_chat_created' in obj: opts['channel_chat_created'] = obj['channel_chat_created'] content_type = 'channel_chat_created' if 'migrate_to_chat_id' in obj: opts['migrate_to_chat_id'] = obj['migrate_to_chat_id'] content_type = 'migrate_to_chat_id' if 'migrate_from_chat_id' in obj: opts['migrate_from_chat_id'] = obj['migrate_from_chat_id'] content_type = 'migrate_from_chat_id' if 'pinned_message' in obj: opts['pinned_message'] = Message.de_json(obj['pinned_message']) content_type = 'pinned_message' if 'invoice' in obj: opts['invoice'] = Invoice.de_json(obj['invoice']) content_type = 'invoice' if 'successful_payment' in obj: opts['successful_payment'] = SuccessfulPayment.de_json(obj['successful_payment']) content_type = 'successful_payment' if 'connected_website' in obj: opts['connected_website'] = obj['connected_website'] content_type = 'connected_website' if 'poll' in obj: opts['poll'] = Poll.de_json(obj['poll']) content_type = 'poll' if 'passport_data' in obj: opts['passport_data'] = obj['passport_data'] content_type = 'passport_data' if 'proximity_alert_triggered' in obj: opts['proximity_alert_triggered'] = ProximityAlertTriggered.de_json(obj[ 'proximity_alert_triggered']) content_type = 'proximity_alert_triggered' if 'video_chat_scheduled' in obj: opts['video_chat_scheduled'] = VideoChatScheduled.de_json(obj['video_chat_scheduled']) opts['voice_chat_scheduled'] = opts['video_chat_scheduled'] # deprecated, for backward compatibility content_type = 'video_chat_scheduled' if 'video_chat_started' in obj: opts['video_chat_started'] = VideoChatStarted.de_json(obj['video_chat_started']) opts['voice_chat_started'] = opts['video_chat_started'] # deprecated, for backward compatibility content_type = 'video_chat_started' if 'video_chat_ended' in obj: opts['video_chat_ended'] = VideoChatEnded.de_json(obj['video_chat_ended']) opts['voice_chat_ended'] = opts['video_chat_ended'] # deprecated, for backward compatibility content_type = 'video_chat_ended' if 'video_chat_participants_invited' in obj: opts['video_chat_participants_invited'] = VideoChatParticipantsInvited.de_json(obj['video_chat_participants_invited']) opts['voice_chat_participants_invited'] = opts['video_chat_participants_invited'] # deprecated, for backward compatibility content_type = 'video_chat_participants_invited' if 'web_app_data' in obj: opts['web_app_data'] = WebAppData.de_json(obj['web_app_data']) content_type = 'web_app_data' if 'message_auto_delete_timer_changed' in obj: opts['message_auto_delete_timer_changed'] = MessageAutoDeleteTimerChanged.de_json(obj['message_auto_delete_timer_changed']) content_type = 'message_auto_delete_timer_changed' if 'reply_markup' in obj: opts['reply_markup'] = InlineKeyboardMarkup.de_json(obj['reply_markup']) return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod def parse_chat(cls, chat): if 'first_name' not in chat: return GroupChat.de_json(chat) else: return User.de_json(chat) @classmethod def parse_photo(cls, photo_size_array): ret = [] for ps in photo_size_array: ret.append(PhotoSize.de_json(ps)) return ret @classmethod def parse_entities(cls, message_entity_array): ret = [] for me in message_entity_array: ret.append(MessageEntity.de_json(me)) return ret def __init__(self, message_id, from_user, date, chat, content_type, options, json_string): self.content_type: str = content_type self.id: int = message_id # Lets fix the telegram usability ####up with ID in Message :) self.message_id: int = message_id self.from_user: User = from_user self.date: int = date self.chat: Chat = chat self.sender_chat: Optional[Chat] = None self.forward_from: Optional[User] = None self.forward_from_chat: Optional[Chat] = None self.forward_from_message_id: Optional[int] = None self.forward_signature: Optional[str] = None self.forward_sender_name: Optional[str] = None self.forward_date: Optional[int] = None self.is_automatic_forward: Optional[bool] = None self.reply_to_message: Optional[Message] = None self.via_bot: Optional[User] = None self.edit_date: Optional[int] = None self.has_protected_content: Optional[bool] = None self.media_group_id: Optional[str] = None self.author_signature: Optional[str] = None self.text: Optional[str] = None self.entities: Optional[List[MessageEntity]] = None self.caption_entities: Optional[List[MessageEntity]] = None self.audio: Optional[Audio] = None self.document: Optional[Document] = None self.photo: Optional[List[PhotoSize]] = None self.sticker: Optional[Sticker] = None self.video: Optional[Video] = None self.video_note: Optional[VideoNote] = None self.voice: Optional[Voice] = None self.caption: Optional[str] = None self.contact: Optional[Contact] = None self.location: Optional[Location] = None self.venue: Optional[Venue] = None self.animation: Optional[Animation] = None self.dice: Optional[Dice] = None self.new_chat_member: Optional[User] = None # Deprecated since Bot API 3.0. Not processed anymore self.new_chat_members: Optional[List[User]] = None self.left_chat_member: Optional[User] = None self.new_chat_title: Optional[str] = None self.new_chat_photo: Optional[List[PhotoSize]] = None self.delete_chat_photo: Optional[bool] = None self.group_chat_created: Optional[bool] = None self.supergroup_chat_created: Optional[bool] = None self.channel_chat_created: Optional[bool] = None self.migrate_to_chat_id: Optional[int] = None self.migrate_from_chat_id: Optional[int] = None self.pinned_message: Optional[Message] = None self.invoice: Optional[Invoice] = None self.successful_payment: Optional[SuccessfulPayment] = None self.connected_website: Optional[str] = None self.reply_markup: Optional[InlineKeyboardMarkup] = None for key in options: setattr(self, key, options[key]) self.json = json_string def __html_text(self, text, entities): """ Author: @sviat9440 Updaters: @badiboy Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" Example: message.html_text >> "Test parse formatting, url, text_mention and mention @username" Custom subs: You can customize the substitutes. By default, there is no substitute for the entities: hashtag, bot_command, email. You can add or modify substitute an existing entity. Example: message.custom_subs = {"bold": "{text}", "italic": "{text}", "mention": "{text}"} message.html_text >> "Test parse formatting, url and text_mention and mention @username" """ if not entities: return text _subs = { "bold": "{text}", "italic": "{text}", "pre": "
{text}
", "code": "{text}", # "url": "{text}", # @badiboy plain URLs have no text and do not need tags "text_link": "{text}", "strikethrough": "{text}", "underline": "{text}", "spoiler": "{text}", } if hasattr(self, "custom_subs"): for key, value in self.custom_subs.items(): _subs[key] = value utf16_text = text.encode("utf-16-le") html_text = "" def func(upd_text, subst_type=None, url=None, user=None): upd_text = upd_text.decode("utf-16-le") if subst_type == "text_mention": subst_type = "text_link" url = "tg://user?id={0}".format(user.id) elif subst_type == "mention": url = "https://t.me/{0}".format(upd_text[1:]) upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") if not subst_type or not _subs.get(subst_type): return upd_text subs = _subs.get(subst_type) return subs.format(text=upd_text, url=url) offset = 0 for entity in entities: if entity.offset > offset: html_text += func(utf16_text[offset * 2 : entity.offset * 2]) offset = entity.offset html_text += func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user) offset += entity.length elif entity.offset == offset: html_text += func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user) offset += entity.length else: # TODO: process nested entities from Bot API 4.5 # Now ignoring them pass if offset * 2 < len(utf16_text): html_text += func(utf16_text[offset * 2:]) return html_text @property def html_text(self): return self.__html_text(self.text, self.entities) @property def html_caption(self): return self.__html_text(self.caption, self.caption_entities) class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): @staticmethod def to_list_of_dicts(entity_list) -> Union[List[Dict], None]: res = [] for e in entity_list: res.append(MessageEntity.to_dict(e)) return res or None @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'user' in obj: obj['user'] = User.de_json(obj['user']) return cls(**obj) def __init__(self, type, offset, length, url=None, user=None, language=None, **kwargs): self.type: str = type self.offset: int = offset self.length: int = length self.url: str = url self.user: User = user self.language: str = language def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return {"type": self.type, "offset": self.offset, "length": self.length, "url": self.url, "user": self.user, "language": self.language} class Dice(JsonSerializable, Dictionaryable, JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, value, emoji, **kwargs): self.value: int = value self.emoji: str = emoji def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return {'value': self.value, 'emoji': self.emoji} class PhotoSize(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, file_id, file_unique_id, width, height, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.width: int = width self.height: int = height self.file_size: int = file_size class Audio(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'thumb' in obj and 'file_id' in obj['thumb']: obj['thumb'] = PhotoSize.de_json(obj['thumb']) else: obj['thumb'] = None return cls(**obj) def __init__(self, file_id, file_unique_id, duration, performer=None, title=None, file_name=None, mime_type=None, file_size=None, thumb=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.duration: int = duration self.performer: str = performer self.title: str = title self.file_name: str = file_name self.mime_type: str = mime_type self.file_size: int = file_size self.thumb: PhotoSize = thumb class Voice(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, file_id, file_unique_id, duration, mime_type=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.duration: int = duration self.mime_type: str = mime_type self.file_size: int = file_size class Document(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'thumb' in obj and 'file_id' in obj['thumb']: obj['thumb'] = PhotoSize.de_json(obj['thumb']) else: obj['thumb'] = None return cls(**obj) def __init__(self, file_id, file_unique_id, thumb=None, file_name=None, mime_type=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.thumb: PhotoSize = thumb self.file_name: str = file_name self.mime_type: str = mime_type self.file_size: int = file_size class Video(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'thumb' in obj and 'file_id' in obj['thumb']: obj['thumb'] = PhotoSize.de_json(obj['thumb']) return cls(**obj) def __init__(self, file_id, file_unique_id, width, height, duration, thumb=None, file_name=None, mime_type=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.width: int = width self.height: int = height self.duration: int = duration self.thumb: PhotoSize = thumb self.file_name: str = file_name self.mime_type: str = mime_type self.file_size: int = file_size class VideoNote(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'thumb' in obj and 'file_id' in obj['thumb']: obj['thumb'] = PhotoSize.de_json(obj['thumb']) return cls(**obj) def __init__(self, file_id, file_unique_id, length, duration, thumb=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.length: int = length self.duration: int = duration self.thumb: PhotoSize = thumb self.file_size: int = file_size class Contact(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, phone_number, first_name, last_name=None, user_id=None, vcard=None, **kwargs): self.phone_number: str = phone_number self.first_name: str = first_name self.last_name: str = last_name self.user_id: int = user_id self.vcard: str = vcard class Location(JsonDeserializable, JsonSerializable, Dictionaryable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, longitude, latitude, horizontal_accuracy=None, live_period=None, heading=None, proximity_alert_radius=None, **kwargs): self.longitude: float = longitude self.latitude: float = latitude self.horizontal_accuracy: float = horizontal_accuracy self.live_period: int = live_period self.heading: int = heading self.proximity_alert_radius: int = proximity_alert_radius def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return { "longitude": self.longitude, "latitude": self.latitude, "horizontal_accuracy": self.horizontal_accuracy, "live_period": self.live_period, "heading": self.heading, "proximity_alert_radius": self.proximity_alert_radius, } class Venue(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['location'] = Location.de_json(obj['location']) return cls(**obj) def __init__(self, location, title, address, foursquare_id=None, foursquare_type=None, google_place_id=None, google_place_type=None, **kwargs): self.location: Location = location self.title: str = title self.address: str = address self.foursquare_id: str = foursquare_id self.foursquare_type: str = foursquare_type self.google_place_id: str = google_place_id self.google_place_type: str = google_place_type class UserProfilePhotos(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'photos' in obj: photos = [[PhotoSize.de_json(y) for y in x] for x in obj['photos']] obj['photos'] = photos return cls(**obj) def __init__(self, total_count, photos=None, **kwargs): self.total_count: int = total_count self.photos: List[PhotoSize] = photos class File(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, file_id, file_unique_id, file_size=None, file_path=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.file_size: int = file_size self.file_path: str = file_path class ForceReply(JsonSerializable): def __init__(self, selective: Optional[bool]=None, input_field_placeholder: Optional[str]=None): self.selective: bool = selective self.input_field_placeholder: str = input_field_placeholder def to_json(self): json_dict = {'force_reply': True} if self.selective is not None: json_dict['selective'] = self.selective if self.input_field_placeholder: json_dict['input_field_placeholder'] = self.input_field_placeholder return json.dumps(json_dict) class ReplyKeyboardRemove(JsonSerializable): def __init__(self, selective=None): self.selective: bool = selective def to_json(self): json_dict = {'remove_keyboard': True} if self.selective: json_dict['selective'] = self.selective return json.dumps(json_dict) class WebAppInfo(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) def __init__(self, url, **kwargs): self.url: str = url def to_dict(self): return {'url': self.url} class ReplyKeyboardMarkup(JsonSerializable): max_row_keys = 12 def __init__(self, resize_keyboard: Optional[bool]=None, one_time_keyboard: Optional[bool]=None, selective: Optional[bool]=None, row_width: int=3, input_field_placeholder: Optional[str]=None): if row_width > self.max_row_keys: # Todo: Will be replaced with Exception in future releases if not DISABLE_KEYLEN_ERROR: logger.error('Telegram does not support reply keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys self.resize_keyboard: bool = resize_keyboard self.one_time_keyboard: bool = one_time_keyboard self.selective: bool = selective self.row_width: int = row_width self.input_field_placeholder: str = input_field_placeholder self.keyboard: List[List[KeyboardButton]] = [] def add(self, *args, row_width=None): """ This function adds strings to the keyboard, while not exceeding row_width. E.g. ReplyKeyboardMarkup#add("A", "B", "C") yields the json result {keyboard: [["A"], ["B"], ["C"]]} when row_width is set to 1. When row_width is set to 2, the following is the result of this function: {keyboard: [["A", "B"], ["C"]]} See https://core.telegram.org/bots/api#replykeyboardmarkup :param args: KeyboardButton to append to the keyboard :param row_width: width of row :return: self, to allow function chaining. """ if row_width is None: row_width = self.row_width if row_width > self.max_row_keys: # Todo: Will be replaced with Exception in future releases if not DISABLE_KEYLEN_ERROR: logger.error('Telegram does not support reply keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys for row in util.chunks(args, row_width): button_array = [] for button in row: if util.is_string(button): button_array.append({'text': button}) elif util.is_bytes(button): button_array.append({'text': button.decode('utf-8')}) else: button_array.append(button.to_dict()) self.keyboard.append(button_array) return self def row(self, *args): """ Adds a list of KeyboardButton to the keyboard. This function does not consider row_width. ReplyKeyboardMarkup#row("A")#row("B", "C")#to_json() outputs '{keyboard: [["A"], ["B", "C"]]}' See https://core.telegram.org/bots/api#replykeyboardmarkup :param args: strings :return: self, to allow function chaining. """ return self.add(*args, row_width=self.max_row_keys) def to_json(self): """ Converts this object to its json representation following the Telegram API guidelines described here: https://core.telegram.org/bots/api#replykeyboardmarkup :return: """ json_dict = {'keyboard': self.keyboard} if self.one_time_keyboard is not None: json_dict['one_time_keyboard'] = self.one_time_keyboard if self.resize_keyboard is not None: json_dict['resize_keyboard'] = self.resize_keyboard if self.selective is not None: json_dict['selective'] = self.selective if self.input_field_placeholder: json_dict['input_field_placeholder'] = self.input_field_placeholder return json.dumps(json_dict) class KeyboardButtonPollType(Dictionaryable): def __init__(self, type=''): self.type: str = type def to_dict(self): return {'type': self.type} class KeyboardButton(Dictionaryable, JsonSerializable): def __init__(self, text: str, request_contact: Optional[bool]=None, request_location: Optional[bool]=None, request_poll: Optional[KeyboardButtonPollType]=None, web_app: WebAppInfo=None): self.text: str = text self.request_contact: bool = request_contact self.request_location: bool = request_location self.request_poll: KeyboardButtonPollType = request_poll self.web_app: WebAppInfo = web_app def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): json_dict = {'text': self.text} if self.request_contact is not None: json_dict['request_contact'] = self.request_contact if self.request_location is not None: json_dict['request_location'] = self.request_location if self.request_poll is not None: json_dict['request_poll'] = self.request_poll.to_dict() if self.web_app is not None: json_dict['web_app'] = self.web_app.to_dict() return json_dict class InlineKeyboardMarkup(Dictionaryable, JsonSerializable, JsonDeserializable): max_row_keys = 8 @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) keyboard = [[InlineKeyboardButton.de_json(button) for button in row] for row in obj['inline_keyboard']] return cls(keyboard = keyboard) def __init__(self, keyboard=None, row_width=3): """ This object represents an inline keyboard that appears right next to the message it belongs to. :return: None """ if row_width > self.max_row_keys: # Todo: Will be replaced with Exception in future releases logger.error('Telegram does not support inline keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys self.row_width: int = row_width self.keyboard: List[List[InlineKeyboardButton]] = keyboard or [] def add(self, *args, row_width=None): """ This method adds buttons to the keyboard without exceeding row_width. E.g. InlineKeyboardMarkup.add("A", "B", "C") yields the json result: {keyboard: [["A"], ["B"], ["C"]]} when row_width is set to 1. When row_width is set to 2, the result: {keyboard: [["A", "B"], ["C"]]} See https://core.telegram.org/bots/api#inlinekeyboardmarkup :param args: Array of InlineKeyboardButton to append to the keyboard :param row_width: width of row :return: self, to allow function chaining. """ if row_width is None: row_width = self.row_width if row_width > self.max_row_keys: # Todo: Will be replaced with Exception in future releases logger.error('Telegram does not support inline keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys for row in util.chunks(args, row_width): button_array = [button for button in row] self.keyboard.append(button_array) return self def row(self, *args): """ Adds a list of InlineKeyboardButton to the keyboard. This method does not consider row_width. InlineKeyboardMarkup.row("A").row("B", "C").to_json() outputs: '{keyboard: [["A"], ["B", "C"]]}' See https://core.telegram.org/bots/api#inlinekeyboardmarkup :param args: Array of InlineKeyboardButton to append to the keyboard :return: self, to allow function chaining. """ return self.add(*args, row_width=self.max_row_keys) def to_json(self): """ Converts this object to its json representation following the Telegram API guidelines described here: https://core.telegram.org/bots/api#inlinekeyboardmarkup :return: """ return json.dumps(self.to_dict()) def to_dict(self): json_dict = dict() json_dict['inline_keyboard'] = [[button.to_dict() for button in row] for row in self.keyboard] return json_dict class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'login_url' in obj: obj['login_url'] = LoginUrl.de_json(obj.get('login_url')) if 'web_app' in obj: obj['web_app'] = WebAppInfo.de_json(obj.get('web_app')) return cls(**obj) def __init__(self, text, url=None, callback_data=None, web_app=None, switch_inline_query=None, switch_inline_query_current_chat=None, callback_game=None, pay=None, login_url=None, **kwargs): self.text: str = text self.url: str = url self.callback_data: str = callback_data self.web_app: WebAppInfo = web_app self.switch_inline_query: str = switch_inline_query self.switch_inline_query_current_chat: str = switch_inline_query_current_chat self.callback_game = callback_game # Not Implemented self.pay: bool = pay self.login_url: LoginUrl = login_url def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): json_dict = {'text': self.text} if self.url: json_dict['url'] = self.url if self.callback_data: json_dict['callback_data'] = self.callback_data if self.web_app: json_dict['web_app'] = self.web_app.to_dict() if self.switch_inline_query is not None: json_dict['switch_inline_query'] = self.switch_inline_query if self.switch_inline_query_current_chat is not None: json_dict['switch_inline_query_current_chat'] = self.switch_inline_query_current_chat if self.callback_game is not None: json_dict['callback_game'] = self.callback_game if self.pay is not None: json_dict['pay'] = self.pay if self.login_url is not None: json_dict['login_url'] = self.login_url.to_dict() return json_dict class LoginUrl(Dictionaryable, JsonSerializable, JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, url, forward_text=None, bot_username=None, request_write_access=None, **kwargs): self.url: str = url self.forward_text: str = forward_text self.bot_username: str = bot_username self.request_write_access: bool = request_write_access def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): json_dict = {'url': self.url} if self.forward_text: json_dict['forward_text'] = self.forward_text if self.bot_username: json_dict['bot_username'] = self.bot_username if self.request_write_access is not None: json_dict['request_write_access'] = self.request_write_access return json_dict class CallbackQuery(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if not "data" in obj: # "data" field is Optional in the API, but historically is mandatory in the class constructor obj['data'] = None obj['from_user'] = User.de_json(obj.pop('from')) if 'message' in obj: obj['message'] = Message.de_json(obj.get('message')) obj['json_string'] = json_string return cls(**obj) def __init__(self, id, from_user, data, chat_instance, json_string, message=None, inline_message_id=None, game_short_name=None, **kwargs): self.id: int = id self.from_user: User = from_user self.message: Message = message self.inline_message_id: str = inline_message_id self.chat_instance: str = chat_instance self.data: str = data self.game_short_name: str = game_short_name self.json = json_string class ChatPhoto(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, small_file_id, small_file_unique_id, big_file_id, big_file_unique_id, **kwargs): self.small_file_id: str = small_file_id self.small_file_unique_id: str = small_file_unique_id self.big_file_id: str = big_file_id self.big_file_unique_id: str = big_file_unique_id class ChatMember(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) member_type = obj['status'] # Ordered according to estimated appearance frequency. if member_type == "member": return ChatMemberMember(**obj) elif member_type == "left": return ChatMemberLeft(**obj) elif member_type == "kicked": return ChatMemberBanned(**obj) elif member_type == "restricted": return ChatMemberRestricted(**obj) elif member_type == "administrator": return ChatMemberAdministrator(**obj) elif member_type == "creator": return ChatMemberOwner(**obj) else: # Should not be here. For "if something happen" compatibility return cls(**obj) def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_edited=None, can_post_messages=None, can_edit_messages=None, can_delete_messages=None, can_restrict_members=None, can_promote_members=None, can_change_info=None, can_invite_users=None, can_pin_messages=None, is_member=None, can_send_messages=None, can_send_media_messages=None, can_send_polls=None, can_send_other_messages=None, can_add_web_page_previews=None, can_manage_chat=None, can_manage_video_chats=None, until_date=None, **kwargs): self.user: User = user self.status: str = status self.custom_title: str = custom_title self.is_anonymous: bool = is_anonymous self.can_be_edited: bool = can_be_edited self.can_post_messages: bool = can_post_messages self.can_edit_messages: bool = can_edit_messages self.can_delete_messages: bool = can_delete_messages self.can_restrict_members: bool = can_restrict_members self.can_promote_members: bool = can_promote_members self.can_change_info: bool = can_change_info self.can_invite_users: bool = can_invite_users self.can_pin_messages: bool = can_pin_messages self.is_member: bool = is_member self.can_send_messages: bool = can_send_messages self.can_send_media_messages: bool = can_send_media_messages self.can_send_polls: bool = can_send_polls self.can_send_other_messages: bool = can_send_other_messages self.can_add_web_page_previews: bool = can_add_web_page_previews self.can_manage_chat: bool = can_manage_chat self.can_manage_video_chats: bool = can_manage_video_chats self.can_manage_voice_chats: bool = self.can_manage_video_chats # deprecated, for backward compatibility self.until_date: int = until_date class ChatMemberOwner(ChatMember): pass class ChatMemberAdministrator(ChatMember): pass class ChatMemberMember(ChatMember): pass class ChatMemberRestricted(ChatMember): pass class ChatMemberLeft(ChatMember): pass class ChatMemberBanned(ChatMember): pass class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): @classmethod def de_json(cls, json_string): if json_string is None: return json_string obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, can_send_messages=None, can_send_media_messages=None, can_send_polls=None, can_send_other_messages=None, can_add_web_page_previews=None, can_change_info=None, can_invite_users=None, can_pin_messages=None, **kwargs): self.can_send_messages: bool = can_send_messages self.can_send_media_messages: bool = can_send_media_messages self.can_send_polls: bool = can_send_polls self.can_send_other_messages: bool = can_send_other_messages self.can_add_web_page_previews: bool = can_add_web_page_previews self.can_change_info: bool = can_change_info self.can_invite_users: bool = can_invite_users self.can_pin_messages: bool = can_pin_messages def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): json_dict = dict() if self.can_send_messages is not None: json_dict['can_send_messages'] = self.can_send_messages if self.can_send_media_messages is not None: json_dict['can_send_media_messages'] = self.can_send_media_messages if self.can_send_polls is not None: json_dict['can_send_polls'] = self.can_send_polls if self.can_send_other_messages is not None: json_dict['can_send_other_messages'] = self.can_send_other_messages if self.can_add_web_page_previews is not None: json_dict['can_add_web_page_previews'] = self.can_add_web_page_previews if self.can_change_info is not None: json_dict['can_change_info'] = self.can_change_info if self.can_invite_users is not None: json_dict['can_invite_users'] = self.can_invite_users if self.can_pin_messages is not None: json_dict['can_pin_messages'] = self.can_pin_messages return json_dict class BotCommand(JsonSerializable, JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, command, description): """ This object represents a bot command. :param command: Text of the command, 1-32 characters. Can contain only lowercase English letters, digits and underscores. :param description: Description of the command, 3-256 characters. :return: """ self.command: str = command self.description: str = description def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return {'command': self.command, 'description': self.description} # BotCommandScopes class BotCommandScope(ABC, JsonSerializable): def __init__(self, type='default', chat_id=None, user_id=None): """ Abstract class. Use BotCommandScopeX classes to set a specific scope type: BotCommandScopeDefault BotCommandScopeAllPrivateChats BotCommandScopeAllGroupChats BotCommandScopeAllChatAdministrators BotCommandScopeChat BotCommandScopeChatAdministrators BotCommandScopeChatMember """ self.type: str = type self.chat_id: Optional[Union[int, str]] = chat_id self.user_id: Optional[Union[int, str]] = user_id def to_json(self): json_dict = {'type': self.type} if self.chat_id: json_dict['chat_id'] = self.chat_id if self.user_id: json_dict['user_id'] = self.user_id return json.dumps(json_dict) class BotCommandScopeDefault(BotCommandScope): def __init__(self): """ Represents the default scope of bot commands. Default commands are used if no commands with a narrower scope are specified for the user. """ super(BotCommandScopeDefault, self).__init__(type='default') class BotCommandScopeAllPrivateChats(BotCommandScope): def __init__(self): """ Represents the scope of bot commands, covering all private chats. """ super(BotCommandScopeAllPrivateChats, self).__init__(type='all_private_chats') class BotCommandScopeAllGroupChats(BotCommandScope): def __init__(self): """ Represents the scope of bot commands, covering all group and supergroup chats. """ super(BotCommandScopeAllGroupChats, self).__init__(type='all_group_chats') class BotCommandScopeAllChatAdministrators(BotCommandScope): def __init__(self): """ Represents the scope of bot commands, covering all group and supergroup chat administrators. """ super(BotCommandScopeAllChatAdministrators, self).__init__(type='all_chat_administrators') class BotCommandScopeChat(BotCommandScope): def __init__(self, chat_id=None): super(BotCommandScopeChat, self).__init__(type='chat', chat_id=chat_id) class BotCommandScopeChatAdministrators(BotCommandScope): def __init__(self, chat_id=None): """ Represents the scope of bot commands, covering a specific chat. @param chat_id: Unique identifier for the target chat """ super(BotCommandScopeChatAdministrators, self).__init__(type='chat_administrators', chat_id=chat_id) class BotCommandScopeChatMember(BotCommandScope): def __init__(self, chat_id=None, user_id=None): """ Represents the scope of bot commands, covering all administrators of a specific group or supergroup chat @param chat_id: Unique identifier for the target chat @param user_id: Unique identifier of the target user """ super(BotCommandScopeChatMember, self).__init__(type='chat_member', chat_id=chat_id, user_id=user_id) # InlineQuery class InlineQuery(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['from_user'] = User.de_json(obj.pop('from')) if 'location' in obj: obj['location'] = Location.de_json(obj['location']) return cls(**obj) def __init__(self, id, from_user, query, offset, chat_type=None, location=None, **kwargs): """ This object represents an incoming inline query. When the user sends an empty query, your bot could return some default or trending results. :param id: string Unique identifier for this query :param from_user: User Sender :param query: String Text of the query :param chat_type: String Type of the chat, from which the inline query was sent. Can be either “sender” for a private chat with the inline query sender, “private”, “group”, “supergroup”, or “channel”. :param offset: String Offset of the results to be returned, can be controlled by the bot :param location: Sender location, only for bots that request user location :return: InlineQuery Object """ self.id: int = id self.from_user: User = from_user self.query: str = query self.offset: str = offset self.chat_type: str = chat_type self.location: Location = location class InputTextMessageContent(Dictionaryable): def __init__(self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None): self.message_text: str = message_text self.parse_mode: str = parse_mode self.entities: List[MessageEntity] = entities self.disable_web_page_preview: bool = disable_web_page_preview def to_dict(self): json_dict = {'message_text': self.message_text} if self.parse_mode: json_dict['parse_mode'] = self.parse_mode if self.entities: json_dict['entities'] = MessageEntity.to_list_of_dicts(self.entities) if self.disable_web_page_preview is not None: json_dict['disable_web_page_preview'] = self.disable_web_page_preview return json_dict class InputLocationMessageContent(Dictionaryable): def __init__(self, latitude, longitude, horizontal_accuracy=None, live_period=None, heading=None, proximity_alert_radius=None): self.latitude: float = latitude self.longitude: float = longitude self.horizontal_accuracy: float = horizontal_accuracy self.live_period: int = live_period self.heading: int = heading self.proximity_alert_radius: int = proximity_alert_radius def to_dict(self): json_dict = {'latitude': self.latitude, 'longitude': self.longitude} if self.horizontal_accuracy: json_dict['horizontal_accuracy'] = self.horizontal_accuracy if self.live_period: json_dict['live_period'] = self.live_period if self.heading: json_dict['heading'] = self.heading if self.proximity_alert_radius: json_dict['proximity_alert_radius'] = self.proximity_alert_radius return json_dict class InputVenueMessageContent(Dictionaryable): def __init__(self, latitude, longitude, title, address, foursquare_id=None, foursquare_type=None, google_place_id=None, google_place_type=None): self.latitude: float = latitude self.longitude: float = longitude self.title: str = title self.address: str = address self.foursquare_id: str = foursquare_id self.foursquare_type: str = foursquare_type self.google_place_id: str = google_place_id self.google_place_type: str = google_place_type def to_dict(self): json_dict = { 'latitude': self.latitude, 'longitude': self.longitude, 'title': self.title, 'address' : self.address } if self.foursquare_id: json_dict['foursquare_id'] = self.foursquare_id if self.foursquare_type: json_dict['foursquare_type'] = self.foursquare_type if self.google_place_id: json_dict['google_place_id'] = self.google_place_id if self.google_place_type: json_dict['google_place_type'] = self.google_place_type return json_dict class InputContactMessageContent(Dictionaryable): def __init__(self, phone_number, first_name, last_name=None, vcard=None): self.phone_number: str = phone_number self.first_name: str = first_name self.last_name: str = last_name self.vcard: str = vcard def to_dict(self): json_dict = {'phone_number': self.phone_number, 'first_name': self.first_name} if self.last_name: json_dict['last_name'] = self.last_name if self.vcard: json_dict['vcard'] = self.vcard return json_dict class InputInvoiceMessageContent(Dictionaryable): def __init__(self, title, description, payload, provider_token, currency, prices, max_tip_amount=None, suggested_tip_amounts=None, provider_data=None, photo_url=None, photo_size=None, photo_width=None, photo_height=None, need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None, send_phone_number_to_provider=None, send_email_to_provider=None, is_flexible=None): self.title: str = title self.description: str = description self.payload: str = payload self.provider_token: str = provider_token self.currency: str = currency self.prices: List[LabeledPrice] = prices self.max_tip_amount: Optional[int] = max_tip_amount self.suggested_tip_amounts: Optional[List[int]] = suggested_tip_amounts self.provider_data: Optional[str] = provider_data self.photo_url: Optional[str] = photo_url self.photo_size: Optional[int] = photo_size self.photo_width: Optional[int] = photo_width self.photo_height: Optional[int] = photo_height self.need_name: Optional[bool] = need_name self.need_phone_number: Optional[bool] = need_phone_number self.need_email: Optional[bool] = need_email self.need_shipping_address: Optional[bool] = need_shipping_address self.send_phone_number_to_provider: Optional[bool] = send_phone_number_to_provider self.send_email_to_provider: Optional[bool] = send_email_to_provider self.is_flexible: Optional[bool] = is_flexible def to_dict(self): json_dict = { 'title': self.title, 'description': self.description, 'payload': self.payload, 'provider_token': self.provider_token, 'currency': self.currency, 'prices': [LabeledPrice.to_dict(lp) for lp in self.prices] } if self.max_tip_amount: json_dict['max_tip_amount'] = self.max_tip_amount if self.suggested_tip_amounts: json_dict['suggested_tip_amounts'] = self.suggested_tip_amounts if self.provider_data: json_dict['provider_data'] = self.provider_data if self.photo_url: json_dict['photo_url'] = self.photo_url if self.photo_size: json_dict['photo_size'] = self.photo_size if self.photo_width: json_dict['photo_width'] = self.photo_width if self.photo_height: json_dict['photo_height'] = self.photo_height if self.need_name is not None: json_dict['need_name'] = self.need_name if self.need_phone_number is not None: json_dict['need_phone_number'] = self.need_phone_number if self.need_email is not None: json_dict['need_email'] = self.need_email if self.need_shipping_address is not None: json_dict['need_shipping_address'] = self.need_shipping_address if self.send_phone_number_to_provider is not None: json_dict['send_phone_number_to_provider'] = self.send_phone_number_to_provider if self.send_email_to_provider is not None: json_dict['send_email_to_provider'] = self.send_email_to_provider if self.is_flexible is not None: json_dict['is_flexible'] = self.is_flexible return json_dict class ChosenInlineResult(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['from_user'] = User.de_json(obj.pop('from')) if 'location' in obj: obj['location'] = Location.de_json(obj['location']) return cls(**obj) def __init__(self, result_id, from_user, query, location=None, inline_message_id=None, **kwargs): """ This object represents a result of an inline query that was chosen by the user and sent to their chat partner. :param result_id: string The unique identifier for the result that was chosen. :param from_user: User The user that chose the result. :param query: String The query that was used to obtain the result. :return: ChosenInlineResult Object. """ self.result_id: str = result_id self.from_user: User = from_user self.location: Location = location self.inline_message_id: str = inline_message_id self.query: str = query class InlineQueryResultBase(ABC, Dictionaryable, JsonSerializable): # noinspection PyShadowingBuiltins def __init__(self, type, id, title = None, caption = None, input_message_content = None, reply_markup = None, caption_entities = None, parse_mode = None): self.type = type self.id = id self.title = title self.caption = caption self.input_message_content = input_message_content self.reply_markup = reply_markup self.caption_entities = caption_entities self.parse_mode = parse_mode def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): json_dict = { 'type': self.type, 'id': self.id } if self.title: json_dict['title'] = self.title if self.caption: json_dict['caption'] = self.caption if self.input_message_content: json_dict['input_message_content'] = self.input_message_content.to_dict() if self.reply_markup: json_dict['reply_markup'] = self.reply_markup.to_dict() if self.caption_entities: json_dict['caption_entities'] = MessageEntity.to_list_of_dicts(self.caption_entities) if self.parse_mode: json_dict['parse_mode'] = self.parse_mode return json_dict class SentWebAppMessage(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) def __init__(self, inline_message_id=None): self.inline_message_id = inline_message_id def to_dict(self): json_dict = {} if self.inline_message_id: json_dict['inline_message_id'] = self.inline_message_id return json_dict class InlineQueryResultArticle(InlineQueryResultBase): def __init__(self, id, title, input_message_content, reply_markup=None, url=None, hide_url=None, description=None, thumb_url=None, thumb_width=None, thumb_height=None): """ Represents a link to an article or web page. :param id: Unique identifier for this result, 1-64 Bytes. :param title: Title of the result. :param input_message_content: InputMessageContent : Content of the message to be sent :param reply_markup: InlineKeyboardMarkup : Inline keyboard attached to the message :param url: URL of the result. :param hide_url: Pass True, if you don't want the URL to be shown in the message. :param description: Short description of the result. :param thumb_url: Url of the thumbnail for the result. :param thumb_width: Thumbnail width. :param thumb_height: Thumbnail height :return: """ super().__init__('article', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) self.url = url self.hide_url = hide_url self.description = description self.thumb_url = thumb_url self.thumb_width = thumb_width self.thumb_height = thumb_height def to_dict(self): json_dict = super().to_dict() if self.url: json_dict['url'] = self.url if self.hide_url: json_dict['hide_url'] = self.hide_url if self.description: json_dict['description'] = self.description if self.thumb_url: json_dict['thumb_url'] = self.thumb_url if self.thumb_width: json_dict['thumb_width'] = self.thumb_width if self.thumb_height: json_dict['thumb_height'] = self.thumb_height return json_dict class InlineQueryResultPhoto(InlineQueryResultBase): def __init__(self, id, photo_url, thumb_url, photo_width=None, photo_height=None, title=None, description=None, caption=None, caption_entities=None, parse_mode=None, reply_markup=None, input_message_content=None): """ Represents a link to a photo. :param id: Unique identifier for this result, 1-64 bytes :param photo_url: A valid URL of the photo. Photo must be in jpeg format. Photo size must not exceed 5MB :param thumb_url: URL of the thumbnail for the photo :param photo_width: Width of the photo. :param photo_height: Height of the photo. :param title: Title for the result. :param description: Short description of the result. :param caption: Caption of the photo to be sent, 0-200 characters. :param parse_mode: Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. :param reply_markup: InlineKeyboardMarkup : Inline keyboard attached to the message :param input_message_content: InputMessageContent : Content of the message to be sent instead of the photo :return: """ super().__init__('photo', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) self.photo_url = photo_url self.thumb_url = thumb_url self.photo_width = photo_width self.photo_height = photo_height self.description = description def to_dict(self): json_dict = super().to_dict() json_dict['photo_url'] = self.photo_url json_dict['thumb_url'] = self.thumb_url if self.photo_width: json_dict['photo_width'] = self.photo_width if self.photo_height: json_dict['photo_height'] = self.photo_height if self.description: json_dict['description'] = self.description return json_dict class InlineQueryResultGif(InlineQueryResultBase): def __init__(self, id, gif_url, thumb_url, gif_width=None, gif_height=None, title=None, caption=None, caption_entities=None, reply_markup=None, input_message_content=None, gif_duration=None, parse_mode=None, thumb_mime_type=None): """ Represents a link to an animated GIF file. :param id: Unique identifier for this result, 1-64 bytes. :param gif_url: A valid URL for the GIF file. File size must not exceed 1MB :param thumb_url: URL of the static thumbnail (jpeg or gif) for the result. :param gif_width: Width of the GIF. :param gif_height: Height of the GIF. :param title: Title for the result. :param caption: Caption of the GIF file to be sent, 0-200 characters :param reply_markup: InlineKeyboardMarkup : Inline keyboard attached to the message :param input_message_content: InputMessageContent : Content of the message to be sent instead of the photo :return: """ super().__init__('gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) self.gif_url = gif_url self.gif_width = gif_width self.gif_height = gif_height self.thumb_url = thumb_url self.gif_duration = gif_duration self.thumb_mime_type = thumb_mime_type def to_dict(self): json_dict = super().to_dict() json_dict['gif_url'] = self.gif_url if self.gif_width: json_dict['gif_width'] = self.gif_width if self.gif_height: json_dict['gif_height'] = self.gif_height json_dict['thumb_url'] = self.thumb_url if self.gif_duration: json_dict['gif_duration'] = self.gif_duration if self.thumb_mime_type: json_dict['thumb_mime_type'] = self.thumb_mime_type return json_dict class InlineQueryResultMpeg4Gif(InlineQueryResultBase): def __init__(self, id, mpeg4_url, thumb_url, mpeg4_width=None, mpeg4_height=None, title=None, caption=None, caption_entities=None, parse_mode=None, reply_markup=None, input_message_content=None, mpeg4_duration=None, thumb_mime_type=None): """ Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). :param id: Unique identifier for this result, 1-64 bytes :param mpeg4_url: A valid URL for the MP4 file. File size must not exceed 1MB :param thumb_url: URL of the static thumbnail (jpeg or gif) for the result :param mpeg4_width: Video width :param mpeg4_height: Video height :param title: Title for the result :param caption: Caption of the MPEG-4 file to be sent, 0-200 characters :param parse_mode: Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. :param reply_markup: InlineKeyboardMarkup : Inline keyboard attached to the message :param input_message_content: InputMessageContent : Content of the message to be sent instead of the photo :return: """ super().__init__('mpeg4_gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) self.mpeg4_url = mpeg4_url self.mpeg4_width = mpeg4_width self.mpeg4_height = mpeg4_height self.thumb_url = thumb_url self.mpeg4_duration = mpeg4_duration self.thumb_mime_type = thumb_mime_type def to_dict(self): json_dict = super().to_dict() json_dict['mpeg4_url'] = self.mpeg4_url if self.mpeg4_width: json_dict['mpeg4_width'] = self.mpeg4_width if self.mpeg4_height: json_dict['mpeg4_height'] = self.mpeg4_height json_dict['thumb_url'] = self.thumb_url if self.mpeg4_duration: json_dict['mpeg4_duration '] = self.mpeg4_duration if self.thumb_mime_type: json_dict['thumb_mime_type'] = self.thumb_mime_type return json_dict class InlineQueryResultVideo(InlineQueryResultBase): def __init__(self, id, video_url, mime_type, thumb_url, title, caption=None, caption_entities=None, parse_mode=None, video_width=None, video_height=None, video_duration=None, description=None, reply_markup=None, input_message_content=None): """ Represents link to a page containing an embedded video player or a video file. :param id: Unique identifier for this result, 1-64 bytes :param video_url: A valid URL for the embedded video player or video file :param mime_type: Mime type of the content of video url, “text/html” or “video/mp4” :param thumb_url: URL of the thumbnail (jpeg only) for the video :param title: Title for the result :param parse_mode: Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. :param video_width: Video width :param video_height: Video height :param video_duration: Video duration in seconds :param description: Short description of the result :return: """ super().__init__('video', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) self.video_url = video_url self.mime_type = mime_type self.thumb_url = thumb_url self.video_width = video_width self.video_height = video_height self.video_duration = video_duration self.description = description def to_dict(self): json_dict = super().to_dict() json_dict['video_url'] = self.video_url json_dict['mime_type'] = self.mime_type json_dict['thumb_url'] = self.thumb_url if self.video_height: json_dict['video_height'] = self.video_height if self.video_duration: json_dict['video_duration'] = self.video_duration if self.description: json_dict['description'] = self.description return json_dict class InlineQueryResultAudio(InlineQueryResultBase): def __init__(self, id, audio_url, title, caption=None, caption_entities=None, parse_mode=None, performer=None, audio_duration=None, reply_markup=None, input_message_content=None): super().__init__('audio', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) self.audio_url = audio_url self.performer = performer self.audio_duration = audio_duration def to_dict(self): json_dict = super().to_dict() json_dict['audio_url'] = self.audio_url if self.performer: json_dict['performer'] = self.performer if self.audio_duration: json_dict['audio_duration'] = self.audio_duration return json_dict class InlineQueryResultVoice(InlineQueryResultBase): def __init__(self, id, voice_url, title, caption=None, caption_entities=None, parse_mode=None, voice_duration=None, reply_markup=None, input_message_content=None): super().__init__('voice', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) self.voice_url = voice_url self.voice_duration = voice_duration def to_dict(self): json_dict = super().to_dict() json_dict['voice_url'] = self.voice_url if self.voice_duration: json_dict['voice_duration'] = self.voice_duration return json_dict class InlineQueryResultDocument(InlineQueryResultBase): def __init__(self, id, title, document_url, mime_type, caption=None, caption_entities=None, parse_mode=None, description=None, reply_markup=None, input_message_content=None, thumb_url=None, thumb_width=None, thumb_height=None): super().__init__('document', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) self.document_url = document_url self.mime_type = mime_type self.description = description self.thumb_url = thumb_url self.thumb_width = thumb_width self.thumb_height = thumb_height def to_dict(self): json_dict = super().to_dict() json_dict['document_url'] = self.document_url json_dict['mime_type'] = self.mime_type if self.description: json_dict['description'] = self.description if self.thumb_url: json_dict['thumb_url'] = self.thumb_url if self.thumb_width: json_dict['thumb_width'] = self.thumb_width if self.thumb_height: json_dict['thumb_height'] = self.thumb_height return json_dict class InlineQueryResultLocation(InlineQueryResultBase): def __init__(self, id, title, latitude, longitude, horizontal_accuracy, live_period=None, reply_markup=None, input_message_content=None, thumb_url=None, thumb_width=None, thumb_height=None, heading=None, proximity_alert_radius = None): super().__init__('location', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) self.latitude = latitude self.longitude = longitude self.horizontal_accuracy = horizontal_accuracy self.live_period = live_period self.heading: int = heading self.proximity_alert_radius: int = proximity_alert_radius self.thumb_url = thumb_url self.thumb_width = thumb_width self.thumb_height = thumb_height def to_dict(self): json_dict = super().to_dict() json_dict['latitude'] = self.latitude json_dict['longitude'] = self.longitude if self.horizontal_accuracy: json_dict['horizontal_accuracy'] = self.horizontal_accuracy if self.live_period: json_dict['live_period'] = self.live_period if self.heading: json_dict['heading'] = self.heading if self.proximity_alert_radius: json_dict['proximity_alert_radius'] = self.proximity_alert_radius if self.thumb_url: json_dict['thumb_url'] = self.thumb_url if self.thumb_width: json_dict['thumb_width'] = self.thumb_width if self.thumb_height: json_dict['thumb_height'] = self.thumb_height return json_dict class InlineQueryResultVenue(InlineQueryResultBase): def __init__(self, id, title, latitude, longitude, address, foursquare_id=None, foursquare_type=None, reply_markup=None, input_message_content=None, thumb_url=None, thumb_width=None, thumb_height=None, google_place_id=None, google_place_type=None): super().__init__('venue', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) self.latitude = latitude self.longitude = longitude self.address = address self.foursquare_id = foursquare_id self.foursquare_type = foursquare_type self.google_place_id = google_place_id self.google_place_type = google_place_type self.thumb_url = thumb_url self.thumb_width = thumb_width self.thumb_height = thumb_height def to_dict(self): json_dict = super().to_dict() json_dict['latitude'] = self.latitude json_dict['longitude'] = self.longitude json_dict['address'] = self.address if self.foursquare_id: json_dict['foursquare_id'] = self.foursquare_id if self.foursquare_type: json_dict['foursquare_type'] = self.foursquare_type if self.google_place_id: json_dict['google_place_id'] = self.google_place_id if self.google_place_type: json_dict['google_place_type'] = self.google_place_type if self.thumb_url: json_dict['thumb_url'] = self.thumb_url if self.thumb_width: json_dict['thumb_width'] = self.thumb_width if self.thumb_height: json_dict['thumb_height'] = self.thumb_height return json_dict class InlineQueryResultContact(InlineQueryResultBase): def __init__(self, id, phone_number, first_name, last_name=None, vcard=None, reply_markup=None, input_message_content=None, thumb_url=None, thumb_width=None, thumb_height=None): super().__init__('contact', id, input_message_content = input_message_content, reply_markup = reply_markup) self.phone_number = phone_number self.first_name = first_name self.last_name = last_name self.vcard = vcard self.thumb_url = thumb_url self.thumb_width = thumb_width self.thumb_height = thumb_height def to_dict(self): json_dict = super().to_dict() json_dict['phone_number'] = self.phone_number json_dict['first_name'] = self.first_name if self.last_name: json_dict['last_name'] = self.last_name if self.vcard: json_dict['vcard'] = self.vcard if self.thumb_url: json_dict['thumb_url'] = self.thumb_url if self.thumb_width: json_dict['thumb_width'] = self.thumb_width if self.thumb_height: json_dict['thumb_height'] = self.thumb_height return json_dict class InlineQueryResultGame(InlineQueryResultBase): def __init__(self, id, game_short_name, reply_markup=None): super().__init__('game', id, reply_markup = reply_markup) self.game_short_name = game_short_name def to_dict(self): json_dict = super().to_dict() json_dict['game_short_name'] = self.game_short_name return json_dict class InlineQueryResultCachedBase(ABC, JsonSerializable): def __init__(self): self.type = None self.id = None self.title = None self.description = None self.caption = None self.reply_markup = None self.input_message_content = None self.parse_mode = None self.caption_entities = None self.payload_dic = {} def to_json(self): json_dict = self.payload_dic json_dict['type'] = self.type json_dict['id'] = self.id if self.title: json_dict['title'] = self.title if self.description: json_dict['description'] = self.description if self.caption: json_dict['caption'] = self.caption if self.reply_markup: json_dict['reply_markup'] = self.reply_markup.to_dict() if self.input_message_content: json_dict['input_message_content'] = self.input_message_content.to_dict() if self.parse_mode: json_dict['parse_mode'] = self.parse_mode if self.caption_entities: json_dict['caption_entities'] = MessageEntity.to_list_of_dicts(self.caption_entities) return json.dumps(json_dict) class InlineQueryResultCachedPhoto(InlineQueryResultCachedBase): def __init__(self, id, photo_file_id, title=None, description=None, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'photo' self.id = id self.photo_file_id = photo_file_id self.title = title self.description = description self.caption = caption self.caption_entities = caption_entities self.reply_markup = reply_markup self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['photo_file_id'] = photo_file_id class InlineQueryResultCachedGif(InlineQueryResultCachedBase): def __init__(self, id, gif_file_id, title=None, description=None, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'gif' self.id = id self.gif_file_id = gif_file_id self.title = title self.description = description self.caption = caption self.caption_entities = caption_entities self.reply_markup = reply_markup self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['gif_file_id'] = gif_file_id class InlineQueryResultCachedMpeg4Gif(InlineQueryResultCachedBase): def __init__(self, id, mpeg4_file_id, title=None, description=None, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'mpeg4_gif' self.id = id self.mpeg4_file_id = mpeg4_file_id self.title = title self.description = description self.caption = caption self.caption_entities = caption_entities self.reply_markup = reply_markup self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['mpeg4_file_id'] = mpeg4_file_id class InlineQueryResultCachedSticker(InlineQueryResultCachedBase): def __init__(self, id, sticker_file_id, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'sticker' self.id = id self.sticker_file_id = sticker_file_id self.reply_markup = reply_markup self.input_message_content = input_message_content self.payload_dic['sticker_file_id'] = sticker_file_id class InlineQueryResultCachedDocument(InlineQueryResultCachedBase): def __init__(self, id, document_file_id, title, description=None, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'document' self.id = id self.document_file_id = document_file_id self.title = title self.description = description self.caption = caption self.caption_entities = caption_entities self.reply_markup = reply_markup self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['document_file_id'] = document_file_id class InlineQueryResultCachedVideo(InlineQueryResultCachedBase): def __init__(self, id, video_file_id, title, description=None, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'video' self.id = id self.video_file_id = video_file_id self.title = title self.description = description self.caption = caption self.caption_entities = caption_entities self.reply_markup = reply_markup self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['video_file_id'] = video_file_id class InlineQueryResultCachedVoice(InlineQueryResultCachedBase): def __init__(self, id, voice_file_id, title, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'voice' self.id = id self.voice_file_id = voice_file_id self.title = title self.caption = caption self.caption_entities = caption_entities self.reply_markup = reply_markup self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['voice_file_id'] = voice_file_id class InlineQueryResultCachedAudio(InlineQueryResultCachedBase): def __init__(self, id, audio_file_id, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, input_message_content=None): InlineQueryResultCachedBase.__init__(self) self.type = 'audio' self.id = id self.audio_file_id = audio_file_id self.caption = caption self.caption_entities = caption_entities self.reply_markup = reply_markup self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['audio_file_id'] = audio_file_id # Games class Game(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['photo'] = Game.parse_photo(obj['photo']) if 'text_entities' in obj: obj['text_entities'] = Game.parse_entities(obj['text_entities']) if 'animation' in obj: obj['animation'] = Animation.de_json(obj['animation']) return cls(**obj) @classmethod def parse_photo(cls, photo_size_array): ret = [] for ps in photo_size_array: ret.append(PhotoSize.de_json(ps)) return ret @classmethod def parse_entities(cls, message_entity_array): ret = [] for me in message_entity_array: ret.append(MessageEntity.de_json(me)) return ret def __init__(self, title, description, photo, text=None, text_entities=None, animation=None, **kwargs): self.title: str = title self.description: str = description self.photo: List[PhotoSize] = photo self.text: str = text self.text_entities: List[MessageEntity] = text_entities self.animation: Animation = animation class Animation(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) if 'thumb' in obj and 'file_id' in obj['thumb']: obj["thumb"] = PhotoSize.de_json(obj['thumb']) else: obj['thumb'] = None return cls(**obj) def __init__(self, file_id, file_unique_id, width=None, height=None, duration=None, thumb=None, file_name=None, mime_type=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.width: int = width self.height: int = height self.duration: int = duration self.thumb: PhotoSize = thumb self.file_name: str = file_name self.mime_type: str = mime_type self.file_size: int = file_size class GameHighScore(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) return cls(**obj) def __init__(self, position, user, score, **kwargs): self.position: int = position self.user: User = user self.score: int = score # Payments class LabeledPrice(JsonSerializable): def __init__(self, label, amount): self.label: str = label self.amount: int = amount def to_dict(self): return { 'label': self.label, 'amount': self.amount } def to_json(self): return json.dumps(self.to_dict()) class Invoice(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, title, description, start_parameter, currency, total_amount, **kwargs): self.title: str = title self.description: str = description self.start_parameter: str = start_parameter self.currency: str = currency self.total_amount: int = total_amount class ShippingAddress(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, country_code, state, city, street_line1, street_line2, post_code, **kwargs): self.country_code: str = country_code self.state: str = state self.city: str = city self.street_line1: str = street_line1 self.street_line2: str = street_line2 self.post_code: str = post_code class OrderInfo(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['shipping_address'] = ShippingAddress.de_json(obj.get('shipping_address')) return cls(**obj) def __init__(self, name=None, phone_number=None, email=None, shipping_address=None, **kwargs): self.name: str = name self.phone_number: str = phone_number self.email: str = email self.shipping_address: ShippingAddress = shipping_address class ShippingOption(JsonSerializable): def __init__(self, id, title): self.id: str = id self.title: str = title self.prices: List[LabeledPrice] = [] def add_price(self, *args): """ Add LabeledPrice to ShippingOption :param args: LabeledPrices """ for price in args: self.prices.append(price) return self def to_json(self): price_list = [] for p in self.prices: price_list.append(p.to_dict()) json_dict = json.dumps({'id': self.id, 'title': self.title, 'prices': price_list}) return json_dict class SuccessfulPayment(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['order_info'] = OrderInfo.de_json(obj.get('order_info')) return cls(**obj) def __init__(self, currency, total_amount, invoice_payload, shipping_option_id=None, order_info=None, telegram_payment_charge_id=None, provider_payment_charge_id=None, **kwargs): self.currency: str = currency self.total_amount: int = total_amount self.invoice_payload: str = invoice_payload self.shipping_option_id: str = shipping_option_id self.order_info: OrderInfo = order_info self.telegram_payment_charge_id: str = telegram_payment_charge_id self.provider_payment_charge_id: str = provider_payment_charge_id class ShippingQuery(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['from_user'] = User.de_json(obj.pop('from')) obj['shipping_address'] = ShippingAddress.de_json(obj['shipping_address']) return cls(**obj) def __init__(self, id, from_user, invoice_payload, shipping_address, **kwargs): self.id: str = id self.from_user: User = from_user self.invoice_payload: str = invoice_payload self.shipping_address: ShippingAddress = shipping_address class PreCheckoutQuery(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['from_user'] = User.de_json(obj.pop('from')) obj['order_info'] = OrderInfo.de_json(obj.get('order_info')) return cls(**obj) def __init__(self, id, from_user, currency, total_amount, invoice_payload, shipping_option_id=None, order_info=None, **kwargs): self.id: str = id self.from_user: User = from_user self.currency: str = currency self.total_amount: int = total_amount self.invoice_payload: str = invoice_payload self.shipping_option_id: str = shipping_option_id self.order_info: OrderInfo = order_info # Stickers class StickerSet(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) stickers = [] for s in obj['stickers']: stickers.append(Sticker.de_json(s)) obj['stickers'] = stickers if 'thumb' in obj and 'file_id' in obj['thumb']: obj['thumb'] = PhotoSize.de_json(obj['thumb']) else: obj['thumb'] = None return cls(**obj) def __init__(self, name, title, is_animated, is_video, contains_masks, stickers, thumb=None, **kwargs): self.name: str = name self.title: str = title self.is_animated: bool = is_animated self.is_video: bool = is_video self.contains_masks: bool = contains_masks self.stickers: List[Sticker] = stickers self.thumb: PhotoSize = thumb class Sticker(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) if 'thumb' in obj and 'file_id' in obj['thumb']: obj['thumb'] = PhotoSize.de_json(obj['thumb']) else: obj['thumb'] = None if 'mask_position' in obj: obj['mask_position'] = MaskPosition.de_json(obj['mask_position']) if 'premium_animation' in obj: obj['premium_animation'] = File.de_json(obj['premium_animation']) return cls(**obj) def __init__(self, file_id, file_unique_id, width, height, is_animated, is_video, thumb=None, emoji=None, set_name=None, mask_position=None, file_size=None, premium_animation=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.width: int = width self.height: int = height self.is_animated: bool = is_animated self.is_video: bool = is_video self.thumb: PhotoSize = thumb self.emoji: str = emoji self.set_name: str = set_name self.mask_position: MaskPosition = mask_position self.file_size: int = file_size self.premium_animation: File = premium_animation class MaskPosition(Dictionaryable, JsonDeserializable, JsonSerializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, point, x_shift, y_shift, scale, **kwargs): self.point: str = point self.x_shift: float = x_shift self.y_shift: float = y_shift self.scale: float = scale def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return {'point': self.point, 'x_shift': self.x_shift, 'y_shift': self.y_shift, 'scale': self.scale} # InputMedia class InputMedia(Dictionaryable, JsonSerializable): def __init__(self, type, media, caption=None, parse_mode=None, caption_entities=None): self.type: str = type self.media: str = media self.caption: Optional[str] = caption self.parse_mode: Optional[str] = parse_mode self.caption_entities: Optional[List[MessageEntity]] = caption_entities if util.is_string(self.media): self._media_name = '' self._media_dic = self.media else: self._media_name = util.generate_random_token() self._media_dic = 'attach://{0}'.format(self._media_name) def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): json_dict = {'type': self.type, 'media': self._media_dic} if self.caption: json_dict['caption'] = self.caption if self.parse_mode: json_dict['parse_mode'] = self.parse_mode if self.caption_entities: json_dict['caption_entities'] = MessageEntity.to_list_of_dicts(self.caption_entities) return json_dict def convert_input_media(self): if util.is_string(self.media): return self.to_json(), None return self.to_json(), {self._media_name: self.media} class InputMediaPhoto(InputMedia): def __init__(self, media, caption=None, parse_mode=None): if util.is_pil_image(media): media = util.pil_image_to_file(media) super(InputMediaPhoto, self).__init__(type="photo", media=media, caption=caption, parse_mode=parse_mode) def to_dict(self): return super(InputMediaPhoto, self).to_dict() class InputMediaVideo(InputMedia): def __init__(self, media, thumb=None, caption=None, parse_mode=None, width=None, height=None, duration=None, supports_streaming=None): super(InputMediaVideo, self).__init__(type="video", media=media, caption=caption, parse_mode=parse_mode) self.thumb = thumb self.width = width self.height = height self.duration = duration self.supports_streaming = supports_streaming def to_dict(self): ret = super(InputMediaVideo, self).to_dict() if self.thumb: ret['thumb'] = self.thumb if self.width: ret['width'] = self.width if self.height: ret['height'] = self.height if self.duration: ret['duration'] = self.duration if self.supports_streaming: ret['supports_streaming'] = self.supports_streaming return ret class InputMediaAnimation(InputMedia): def __init__(self, media, thumb=None, caption=None, parse_mode=None, width=None, height=None, duration=None): super(InputMediaAnimation, self).__init__(type="animation", media=media, caption=caption, parse_mode=parse_mode) self.thumb = thumb self.width = width self.height = height self.duration = duration def to_dict(self): ret = super(InputMediaAnimation, self).to_dict() if self.thumb: ret['thumb'] = self.thumb if self.width: ret['width'] = self.width if self.height: ret['height'] = self.height if self.duration: ret['duration'] = self.duration return ret class InputMediaAudio(InputMedia): def __init__(self, media, thumb=None, caption=None, parse_mode=None, duration=None, performer=None, title=None): super(InputMediaAudio, self).__init__(type="audio", media=media, caption=caption, parse_mode=parse_mode) self.thumb = thumb self.duration = duration self.performer = performer self.title = title def to_dict(self): ret = super(InputMediaAudio, self).to_dict() if self.thumb: ret['thumb'] = self.thumb if self.duration: ret['duration'] = self.duration if self.performer: ret['performer'] = self.performer if self.title: ret['title'] = self.title return ret class InputMediaDocument(InputMedia): def __init__(self, media, thumb=None, caption=None, parse_mode=None, disable_content_type_detection=None): super(InputMediaDocument, self).__init__(type="document", media=media, caption=caption, parse_mode=parse_mode) self.thumb = thumb self.disable_content_type_detection = disable_content_type_detection def to_dict(self): ret = super(InputMediaDocument, self).to_dict() if self.thumb: ret['thumb'] = self.thumb if self.disable_content_type_detection is not None: ret['disable_content_type_detection'] = self.disable_content_type_detection return ret class PollOption(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, text, voter_count = 0, **kwargs): self.text: str = text self.voter_count: int = voter_count # Converted in _convert_poll_options # def to_json(self): # # send_poll Option is a simple string: https://core.telegram.org/bots/api#sendpoll # return json.dumps(self.text) class Poll(JsonDeserializable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['poll_id'] = obj.pop('id') options = [] for opt in obj['options']: options.append(PollOption.de_json(opt)) obj['options'] = options or None if 'explanation_entities' in obj: obj['explanation_entities'] = Message.parse_entities(obj['explanation_entities']) return cls(**obj) # noinspection PyShadowingBuiltins def __init__( self, question, options, poll_id=None, total_voter_count=None, is_closed=None, is_anonymous=None, type=None, allows_multiple_answers=None, correct_option_id=None, explanation=None, explanation_entities=None, open_period=None, close_date=None, poll_type=None, **kwargs): self.id: str = poll_id self.question: str = question self.options: List[PollOption] = options self.total_voter_count: int = total_voter_count self.is_closed: bool = is_closed self.is_anonymous: bool = is_anonymous self.type: str = type if poll_type is not None: # Wrong param name backward compatibility logger.warning("Poll: poll_type parameter is deprecated. Use type instead.") if type is None: self.type: str = poll_type self.allows_multiple_answers: bool = allows_multiple_answers self.correct_option_id: int = correct_option_id self.explanation: str = explanation self.explanation_entities: List[MessageEntity] = explanation_entities self.open_period: int = open_period self.close_date: int = close_date def add(self, option): if type(option) is PollOption: self.options.append(option) else: self.options.append(PollOption(option)) class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): @classmethod def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) return cls(**obj) def __init__(self, poll_id, user, option_ids, **kwargs): self.poll_id: str = poll_id self.user: User = user self.option_ids: List[int] = option_ids def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return {'poll_id': self.poll_id, 'user': self.user.to_dict(), 'option_ids': self.option_ids} class ChatLocation(JsonSerializable, JsonDeserializable, Dictionaryable): @classmethod def de_json(cls, json_string): if json_string is None: return json_string obj = cls.check_json(json_string) obj['location'] = Location.de_json(obj['location']) return cls(**obj) def __init__(self, location, address, **kwargs): self.location: Location = location self.address: str = address def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return { "location": self.location.to_dict(), "address": self.address } class ChatInviteLink(JsonSerializable, JsonDeserializable, Dictionaryable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['creator'] = User.de_json(obj['creator']) return cls(**obj) def __init__(self, invite_link, creator, creates_join_request , is_primary, is_revoked, name=None, expire_date=None, member_limit=None, pending_join_request_count=None, **kwargs): self.invite_link: str = invite_link self.creator: User = creator self.creates_join_request: bool = creates_join_request self.is_primary: bool = is_primary self.is_revoked: bool = is_revoked self.name: str = name self.expire_date: int = expire_date self.member_limit: int = member_limit self.pending_join_request_count: int = pending_join_request_count def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): json_dict = { "invite_link": self.invite_link, "creator": self.creator.to_dict(), "is_primary": self.is_primary, "is_revoked": self.is_revoked, "creates_join_request": self.creates_join_request } if self.expire_date: json_dict["expire_date"] = self.expire_date if self.member_limit: json_dict["member_limit"] = self.member_limit if self.pending_join_request_count: json_dict["pending_join_request_count"] = self.pending_join_request_count if self.name: json_dict["name"] = self.name return json_dict class ProximityAlertTriggered(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, traveler, watcher, distance, **kwargs): self.traveler: User = traveler self.watcher: User = watcher self.distance: int = distance class VideoChatStarted(JsonDeserializable): @classmethod def de_json(cls, json_string): return cls() def __init__(self): """ This object represents a service message about a voice chat started in the chat. Currently holds no information. """ pass class VoiceChatStarted(VideoChatStarted): def __init__(self): logger.warning('VoiceChatStarted is deprecated. Use VideoChatStarted instead.') super().__init__() class VideoChatScheduled(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, start_date, **kwargs): self.start_date: int = start_date class VoiceChatScheduled(VideoChatScheduled): def __init__(self, *args, **kwargs): logger.warning('VoiceChatScheduled is deprecated. Use VideoChatScheduled instead.') super().__init__(*args, **kwargs) class VideoChatEnded(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, duration, **kwargs): self.duration: int = duration class VoiceChatEnded(VideoChatEnded): def __init__(self, *args, **kwargs): logger.warning('VoiceChatEnded is deprecated. Use VideoChatEnded instead.') super().__init__(*args, **kwargs) class VideoChatParticipantsInvited(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'users' in obj: obj['users'] = [User.de_json(u) for u in obj['users']] return cls(**obj) def __init__(self, users=None, **kwargs): self.users: List[User] = users class VoiceChatParticipantsInvited(VideoChatParticipantsInvited): def __init__(self, *args, **kwargs): logger.warning('VoiceChatParticipantsInvited is deprecated. Use VideoChatParticipantsInvited instead.') super().__init__(*args, **kwargs) class MessageAutoDeleteTimerChanged(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) def __init__(self, message_auto_delete_time, **kwargs): self.message_auto_delete_time = message_auto_delete_time class MenuButton(JsonDeserializable, JsonSerializable): """ Base class for MenuButtons. """ @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) map = { 'commands': MenuButtonCommands, 'web_app': MenuButtonWebApp, 'default': MenuButtonDefault } return map[obj['type']](**obj) def to_json(self): raise NotImplementedError class MenuButtonCommands(MenuButton): def __init__(self, type): self.type = type def to_dict(self): return {'type': self.type} def to_json(self): return json.dumps(self.to_dict()) class MenuButtonWebApp(MenuButton): def __init__(self, type, text, web_app): self.type: str = type self.text: str = text self.web_app: WebAppInfo = web_app def to_dict(self): return {'type': self.type, 'text': self.text, 'web_app': self.web_app.to_dict()} def to_json(self): return json.dumps(self.to_dict()) class MenuButtonDefault(MenuButton): def __init__(self, type): self.type: str = type def to_dict(self): return {'type': self.type} def to_json(self): return json.dumps(self.to_dict()) class ChatAdministratorRights(JsonDeserializable, JsonSerializable): """ Class representation of: https://core.telegram.org/bots/api#chatadministratorrights """ @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) def __init__(self, is_anonymous: bool, can_manage_chat: bool, can_delete_messages: bool, can_manage_video_chats: bool, can_restrict_members: bool, can_promote_members: bool, can_change_info: bool, can_invite_users: bool, can_post_messages: bool=None, can_edit_messages: bool=None, can_pin_messages: bool=None) -> None: self.is_anonymous: bool = is_anonymous self.can_manage_chat: bool = can_manage_chat self.can_delete_messages: bool = can_delete_messages self.can_manage_video_chats: bool = can_manage_video_chats self.can_restrict_members: bool = can_restrict_members self.can_promote_members: bool = can_promote_members self.can_change_info: bool = can_change_info self.can_invite_users: bool = can_invite_users self.can_post_messages: bool = can_post_messages self.can_edit_messages: bool = can_edit_messages self.can_pin_messages: bool = can_pin_messages def to_dict(self): json_dict = { 'is_anonymous': self.is_anonymous, 'can_manage_chat': self.can_manage_chat, 'can_delete_messages': self.can_delete_messages, 'can_manage_video_chats': self.can_manage_video_chats, 'can_restrict_members': self.can_restrict_members, 'can_promote_members': self.can_promote_members, 'can_change_info': self.can_change_info, 'can_invite_users': self.can_invite_users, } if self.can_post_messages is not None: json_dict['can_post_messages'] = self.can_post_messages if self.can_edit_messages is not None: json_dict['can_edit_messages'] = self.can_edit_messages if self.can_pin_messages is not None: json_dict['can_pin_messages'] = self.can_pin_messages return json_dict def to_json(self): return json.dumps(self.to_dict())