Files
youtube-dl/lib/support/telepot2/namedtuple.py
flaskfarm 4b72b7dc65 update
2022-10-06 14:40:55 +09:00

866 lines
30 KiB
Python

import collections
import warnings
import sys
class _Field(object):
def __init__(self, name, constructor=None, default=None):
self.name = name
self.constructor = constructor
self.default = default
# Function to produce namedtuple classes.
def _create_class(typename, fields):
# extract field names
field_names = [e.name if type(e) is _Field else e for e in fields]
# Some dictionary keys are Python keywords and cannot be used as field names, e.g. `from`.
# Get around by appending a '_', e.g. dict['from'] => namedtuple.from_
keymap = [(k.rstrip('_'), k) for k in filter(lambda e: e in ['from_'], field_names)]
# extract (non-simple) fields that need conversions
conversions = [(e.name, e.constructor) for e in fields if type(e) is _Field and e.constructor is not None]
# extract default values
defaults = [e.default if type(e) is _Field else None for e in fields]
# Create the base tuple class, with defaults.
base = collections.namedtuple(typename, field_names)
base.__new__.__defaults__ = tuple(defaults)
class sub(base):
def __new__(cls, **kwargs):
# Map keys.
for oldkey, newkey in keymap:
if oldkey in kwargs:
kwargs[newkey] = kwargs[oldkey]
del kwargs[oldkey]
# Any unexpected arguments?
unexpected = set(kwargs.keys()) - set(super(sub, cls)._fields)
# Remove unexpected arguments and issue warning.
if unexpected:
for k in unexpected:
del kwargs[k]
s = ('Unexpected fields: ' + ', '.join(unexpected) + ''
'\nBot API seems to have added new fields to the returned data.'
' This version of namedtuple is not able to capture them.'
'\n\nPlease upgrade telepot by:'
'\n sudo pip install telepot --upgrade'
'\n\nIf you still see this message after upgrade, that means I am still working to bring the code up-to-date.'
' Please try upgrade again a few days later.'
' In the meantime, you can access the new fields the old-fashioned way, through the raw dictionary.')
warnings.warn(s, UserWarning)
# Convert non-simple values to namedtuples.
for key, func in conversions:
if key in kwargs:
if type(kwargs[key]) is dict:
kwargs[key] = func(**kwargs[key])
elif type(kwargs[key]) is list:
kwargs[key] = func(kwargs[key])
else:
raise RuntimeError('Can only convert dict or list')
return super(sub, cls).__new__(cls, **kwargs)
# https://bugs.python.org/issue24931
# Python 3.4 bug: namedtuple subclass does not inherit __dict__ properly.
# Fix it manually.
if sys.version_info >= (3,4):
def _asdict(self):
return collections.OrderedDict(zip(self._fields, self))
sub._asdict = _asdict
sub.__name__ = typename
return sub
"""
Different treatments for incoming and outgoing namedtuples:
- Incoming ones require type declarations for certain fields for deeper parsing.
- Outgoing ones need no such declarations because users are expected to put the correct object in place.
"""
# Namedtuple class will reference other namedtuple classes. Due to circular
# dependencies, it is impossible to have all class definitions ready at
# compile time. We have to dynamically obtain class reference at runtime.
# For example, the following function acts like a constructor for `Message`
# so any class can reference the Message namedtuple even before the Message
# namedtuple is defined.
def _Message(**kwargs):
return getattr(sys.modules[__name__], 'Message')(**kwargs)
# incoming
User = _create_class('User', [
'id',
'is_bot',
'first_name',
'last_name',
'username',
'language_code'
])
def UserArray(data):
return [User(**p) for p in data]
# incoming
ChatPhoto = _create_class('ChatPhoto', [
'small_file_id',
'big_file_id',
])
# incoming
Chat = _create_class('Chat', [
'id',
'type',
'title',
'username',
'first_name',
'last_name',
'all_members_are_administrators',
_Field('photo', constructor=ChatPhoto),
'description',
'invite_link',
_Field('pinned_message', constructor=_Message),
'sticker_set_name',
'can_set_sticker_set',
])
# incoming
PhotoSize = _create_class('PhotoSize', [
'file_id',
'width',
'height',
'file_size',
'file_path', # undocumented
])
# incoming
Audio = _create_class('Audio', [
'file_id',
'duration',
'performer',
'title',
'mime_type',
'file_size'
])
# incoming
Document = _create_class('Document', [
'file_id',
_Field('thumb', constructor=PhotoSize),
'file_name',
'mime_type',
'file_size',
'file_path', # undocumented
])
# incoming and outgoing
MaskPosition = _create_class('MaskPosition', [
'point',
'x_shift',
'y_shift',
'scale',
])
# incoming
Sticker = _create_class('Sticker', [
'file_id',
'width',
'height',
_Field('thumb', constructor=PhotoSize),
'emoji',
'set_name',
_Field('mask_position', constructor=MaskPosition),
'file_size',
])
def StickerArray(data):
return [Sticker(**p) for p in data]
# incoming
StickerSet = _create_class('StickerSet', [
'name',
'title',
'contains_masks',
_Field('stickers', constructor=StickerArray),
])
# incoming
Video = _create_class('Video', [
'file_id',
'width',
'height',
'duration',
_Field('thumb', constructor=PhotoSize),
'mime_type',
'file_size',
'file_path', # undocumented
])
# incoming
Voice = _create_class('Voice', [
'file_id',
'duration',
'mime_type',
'file_size'
])
# incoming
VideoNote = _create_class('VideoNote', [
'file_id',
'length',
'duration',
_Field('thumb', constructor=PhotoSize),
'file_size'
])
# incoming
Contact = _create_class('Contact', [
'phone_number',
'first_name',
'last_name',
'user_id'
])
# incoming
Location = _create_class('Location', [
'longitude',
'latitude'
])
# incoming
Venue = _create_class('Venue', [
_Field('location', constructor=Location),
'title',
'address',
'foursquare_id',
])
# incoming
File = _create_class('File', [
'file_id',
'file_size',
'file_path'
])
def PhotoSizeArray(data):
return [PhotoSize(**p) for p in data]
def PhotoSizeArrayArray(data):
return [[PhotoSize(**p) for p in array] for array in data]
# incoming
UserProfilePhotos = _create_class('UserProfilePhotos', [
'total_count',
_Field('photos', constructor=PhotoSizeArrayArray)
])
# incoming
ChatMember = _create_class('ChatMember', [
_Field('user', constructor=User),
'status',
'until_date',
'can_be_edited',
'can_change_info',
'can_post_messages',
'can_edit_messages',
'can_delete_messages',
'can_invite_users',
'can_restrict_members',
'can_pin_messages',
'can_promote_members',
'can_send_messages',
'can_send_media_messages',
'can_send_other_messages',
'can_add_web_page_previews',
])
def ChatMemberArray(data):
return [ChatMember(**p) for p in data]
# outgoing
ReplyKeyboardMarkup = _create_class('ReplyKeyboardMarkup', [
'keyboard',
'resize_keyboard',
'one_time_keyboard',
'selective',
])
# outgoing
KeyboardButton = _create_class('KeyboardButton', [
'text',
'request_contact',
'request_location',
])
# outgoing
ReplyKeyboardRemove = _create_class('ReplyKeyboardRemove', [
_Field('remove_keyboard', default=True),
'selective',
])
# outgoing
ForceReply = _create_class('ForceReply', [
_Field('force_reply', default=True),
'selective',
])
# outgoing
InlineKeyboardButton = _create_class('InlineKeyboardButton', [
'text',
'url',
'callback_data',
'switch_inline_query',
'switch_inline_query_current_chat',
'callback_game',
'pay',
])
# outgoing
InlineKeyboardMarkup = _create_class('InlineKeyboardMarkup', [
'inline_keyboard',
])
# incoming
MessageEntity = _create_class('MessageEntity', [
'type',
'offset',
'length',
'url',
_Field('user', constructor=User),
])
# incoming
def MessageEntityArray(data):
return [MessageEntity(**p) for p in data]
# incoming
GameHighScore = _create_class('GameHighScore', [
'position',
_Field('user', constructor=User),
'score',
])
# incoming
Animation = _create_class('Animation', [
'file_id',
_Field('thumb', constructor=PhotoSize),
'file_name',
'mime_type',
'file_size',
])
# incoming
Game = _create_class('Game', [
'title',
'description',
_Field('photo', constructor=PhotoSizeArray),
'text',
_Field('text_entities', constructor=MessageEntityArray),
_Field('animation', constructor=Animation),
])
# incoming
Invoice = _create_class('Invoice', [
'title',
'description',
'start_parameter',
'currency',
'total_amount',
])
# outgoing
LabeledPrice = _create_class('LabeledPrice', [
'label',
'amount',
])
# outgoing
ShippingOption = _create_class('ShippingOption', [
'id',
'title',
'prices',
])
# incoming
ShippingAddress = _create_class('ShippingAddress', [
'country_code',
'state',
'city',
'street_line1',
'street_line2',
'post_code',
])
# incoming
OrderInfo = _create_class('OrderInfo', [
'name',
'phone_number',
'email',
_Field('shipping_address', constructor=ShippingAddress),
])
# incoming
ShippingQuery = _create_class('ShippingQuery', [
'id',
_Field('from_', constructor=User),
'invoice_payload',
_Field('shipping_address', constructor=ShippingAddress),
])
# incoming
PreCheckoutQuery = _create_class('PreCheckoutQuery', [
'id',
_Field('from_', constructor=User),
'currency',
'total_amount',
'invoice_payload',
'shipping_option_id',
_Field('order_info', constructor=OrderInfo),
])
# incoming
SuccessfulPayment = _create_class('SuccessfulPayment', [
'currency',
'total_amount',
'invoice_payload',
'shipping_option_id',
_Field('order_info', constructor=OrderInfo),
'telegram_payment_charge_id',
'provider_payment_charge_id',
])
# incoming
Message = _create_class('Message', [
'message_id',
_Field('from_', constructor=User),
'date',
_Field('chat', constructor=Chat),
_Field('forward_from', constructor=User),
_Field('forward_from_chat', constructor=Chat),
'forward_from_message_id',
'forward_signature',
'forward_date',
_Field('reply_to_message', constructor=_Message),
'edit_date',
'author_signature',
'text',
_Field('entities', constructor=MessageEntityArray),
_Field('caption_entities', constructor=MessageEntityArray),
_Field('audio', constructor=Audio),
_Field('document', constructor=Document),
_Field('game', constructor=Game),
_Field('photo', constructor=PhotoSizeArray),
_Field('sticker', constructor=Sticker),
_Field('video', constructor=Video),
_Field('voice', constructor=Voice),
_Field('video_note', constructor=VideoNote),
_Field('new_chat_members', constructor=UserArray),
'caption',
_Field('contact', constructor=Contact),
_Field('location', constructor=Location),
_Field('venue', constructor=Venue),
_Field('new_chat_member', constructor=User),
_Field('left_chat_member', constructor=User),
'new_chat_title',
_Field('new_chat_photo', constructor=PhotoSizeArray),
'delete_chat_photo',
'group_chat_created',
'supergroup_chat_created',
'channel_chat_created',
'migrate_to_chat_id',
'migrate_from_chat_id',
_Field('pinned_message', constructor=_Message),
_Field('invoice', constructor=Invoice),
_Field('successful_payment', constructor=SuccessfulPayment),
'connected_website',
])
# incoming
InlineQuery = _create_class('InlineQuery', [
'id',
_Field('from_', constructor=User),
_Field('location', constructor=Location),
'query',
'offset',
])
# incoming
ChosenInlineResult = _create_class('ChosenInlineResult', [
'result_id',
_Field('from_', constructor=User),
_Field('location', constructor=Location),
'inline_message_id',
'query',
])
# incoming
CallbackQuery = _create_class('CallbackQuery', [
'id',
_Field('from_', constructor=User),
_Field('message', constructor=Message),
'inline_message_id',
'chat_instance',
'data',
'game_short_name',
])
# incoming
Update = _create_class('Update', [
'update_id',
_Field('message', constructor=Message),
_Field('edited_message', constructor=Message),
_Field('channel_post', constructor=Message),
_Field('edited_channel_post', constructor=Message),
_Field('inline_query', constructor=InlineQuery),
_Field('chosen_inline_result', constructor=ChosenInlineResult),
_Field('callback_query', constructor=CallbackQuery),
])
# incoming
def UpdateArray(data):
return [Update(**u) for u in data]
# incoming
WebhookInfo = _create_class('WebhookInfo', [
'url',
'has_custom_certificate',
'pending_update_count',
'last_error_date',
'last_error_message',
])
# outgoing
InputTextMessageContent = _create_class('InputTextMessageContent', [
'message_text',
'parse_mode',
'disable_web_page_preview',
])
# outgoing
InputLocationMessageContent = _create_class('InputLocationMessageContent', [
'latitude',
'longitude',
'live_period',
])
# outgoing
InputVenueMessageContent = _create_class('InputVenueMessageContent', [
'latitude',
'longitude',
'title',
'address',
'foursquare_id',
])
# outgoing
InputContactMessageContent = _create_class('InputContactMessageContent', [
'phone_number',
'first_name',
'last_name',
])
# outgoing
InlineQueryResultArticle = _create_class('InlineQueryResultArticle', [
_Field('type', default='article'),
'id',
'title',
'input_message_content',
'reply_markup',
'url',
'hide_url',
'description',
'thumb_url',
'thumb_width',
'thumb_height',
])
# outgoing
InlineQueryResultPhoto = _create_class('InlineQueryResultPhoto', [
_Field('type', default='photo'),
'id',
'photo_url',
'thumb_url',
'photo_width',
'photo_height',
'title',
'description',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultGif = _create_class('InlineQueryResultGif', [
_Field('type', default='gif'),
'id',
'gif_url',
'gif_width',
'gif_height',
'gif_duration',
'thumb_url',
'title',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultMpeg4Gif = _create_class('InlineQueryResultMpeg4Gif', [
_Field('type', default='mpeg4_gif'),
'id',
'mpeg4_url',
'mpeg4_width',
'mpeg4_height',
'mpeg4_duration',
'thumb_url',
'title',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultVideo = _create_class('InlineQueryResultVideo', [
_Field('type', default='video'),
'id',
'video_url',
'mime_type',
'thumb_url',
'title',
'caption',
'parse_mode',
'video_width',
'video_height',
'video_duration',
'description',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultAudio = _create_class('InlineQueryResultAudio', [
_Field('type', default='audio'),
'id',
'audio_url',
'title',
'caption',
'parse_mode',
'performer',
'audio_duration',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultVoice = _create_class('InlineQueryResultVoice', [
_Field('type', default='voice'),
'id',
'voice_url',
'title',
'caption',
'parse_mode',
'voice_duration',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultDocument = _create_class('InlineQueryResultDocument', [
_Field('type', default='document'),
'id',
'title',
'caption',
'parse_mode',
'document_url',
'mime_type',
'description',
'reply_markup',
'input_message_content',
'thumb_url',
'thumb_width',
'thumb_height',
])
# outgoing
InlineQueryResultLocation = _create_class('InlineQueryResultLocation', [
_Field('type', default='location'),
'id',
'latitude',
'longitude',
'title',
'live_period',
'reply_markup',
'input_message_content',
'thumb_url',
'thumb_width',
'thumb_height',
])
# outgoing
InlineQueryResultVenue = _create_class('InlineQueryResultVenue', [
_Field('type', default='venue'),
'id',
'latitude',
'longitude',
'title',
'address',
'foursquare_id',
'reply_markup',
'input_message_content',
'thumb_url',
'thumb_width',
'thumb_height',
])
# outgoing
InlineQueryResultContact = _create_class('InlineQueryResultContact', [
_Field('type', default='contact'),
'id',
'phone_number',
'first_name',
'last_name',
'reply_markup',
'input_message_content',
'thumb_url',
'thumb_width',
'thumb_height',
])
# outgoing
InlineQueryResultGame = _create_class('InlineQueryResultGame', [
_Field('type', default='game'),
'id',
'game_short_name',
'reply_markup',
])
# outgoing
InlineQueryResultCachedPhoto = _create_class('InlineQueryResultCachedPhoto', [
_Field('type', default='photo'),
'id',
'photo_file_id',
'title',
'description',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultCachedGif = _create_class('InlineQueryResultCachedGif', [
_Field('type', default='gif'),
'id',
'gif_file_id',
'title',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultCachedMpeg4Gif = _create_class('InlineQueryResultCachedMpeg4Gif', [
_Field('type', default='mpeg4_gif'),
'id',
'mpeg4_file_id',
'title',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultCachedSticker = _create_class('InlineQueryResultCachedSticker', [
_Field('type', default='sticker'),
'id',
'sticker_file_id',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultCachedDocument = _create_class('InlineQueryResultCachedDocument', [
_Field('type', default='document'),
'id',
'title',
'document_file_id',
'description',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultCachedVideo = _create_class('InlineQueryResultCachedVideo', [
_Field('type', default='video'),
'id',
'video_file_id',
'title',
'description',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultCachedVoice = _create_class('InlineQueryResultCachedVoice', [
_Field('type', default='voice'),
'id',
'voice_file_id',
'title',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InlineQueryResultCachedAudio = _create_class('InlineQueryResultCachedAudio', [
_Field('type', default='audio'),
'id',
'audio_file_id',
'caption',
'parse_mode',
'reply_markup',
'input_message_content',
])
# outgoing
InputMediaPhoto = _create_class('InputMediaPhoto', [
_Field('type', default='photo'),
'media',
'caption',
'parse_mode',
])
# outgoing
InputMediaVideo = _create_class('InputMediaVideo', [
_Field('type', default='video'),
'media',
'caption',
'parse_mode',
'width',
'height',
'duration',
'supports_streaming',
])
# incoming
ResponseParameters = _create_class('ResponseParameters', [
'migrate_to_chat_id',
'retry_after',
])