Some refactor

This commit is contained in:
Suren Khorenyan 2019-07-22 00:11:06 +03:00
parent cabb10bc06
commit ad7238fda8
7 changed files with 106 additions and 93 deletions

View file

@ -97,22 +97,22 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
filters_factory.bind(Text, event_handlers=[ filters_factory.bind(Text, event_handlers=[
self.message_handlers, self.edited_message_handlers, self.message_handlers, self.edited_message_handlers,
self.channel_post_handlers, self.edited_channel_post_handlers, self.channel_post_handlers, self.edited_channel_post_handlers,
self.callback_query_handlers, self.poll_handlers, self.inline_query_handlers self.callback_query_handlers, self.poll_handlers, self.inline_query_handlers,
]) ])
filters_factory.bind(HashTag, event_handlers=[ filters_factory.bind(HashTag, event_handlers=[
self.message_handlers, self.edited_message_handlers, self.message_handlers, self.edited_message_handlers,
self.channel_post_handlers, self.edited_channel_post_handlers self.channel_post_handlers, self.edited_channel_post_handlers,
]) ])
filters_factory.bind(Regexp, event_handlers=[ filters_factory.bind(Regexp, event_handlers=[
self.message_handlers, self.edited_message_handlers, self.message_handlers, self.edited_message_handlers,
self.channel_post_handlers, self.edited_channel_post_handlers, self.channel_post_handlers, self.edited_channel_post_handlers,
self.callback_query_handlers, self.poll_handlers, self.inline_query_handlers self.callback_query_handlers, self.poll_handlers, self.inline_query_handlers,
]) ])
filters_factory.bind(RegexpCommandsFilter, event_handlers=[ filters_factory.bind(RegexpCommandsFilter, event_handlers=[
self.message_handlers, self.edited_message_handlers self.message_handlers, self.edited_message_handlers,
]) ])
filters_factory.bind(ExceptionsFilter, event_handlers=[ filters_factory.bind(ExceptionsFilter, event_handlers=[
self.errors_handlers self.errors_handlers,
]) ])
filters_factory.bind(IdFilter, event_handlers=[ filters_factory.bind(IdFilter, event_handlers=[
self.message_handlers, self.edited_message_handlers, self.message_handlers, self.edited_message_handlers,

View file

@ -205,6 +205,13 @@ class Text(Filter):
Simple text filter Simple text filter
""" """
_default_params = (
('text', 'equals'),
('text_contains', 'contains'),
('text_startswith', 'startswith'),
('text_endswith', 'endswith'),
)
def __init__(self, def __init__(self,
equals: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None, equals: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None,
contains: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None, contains: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None,
@ -244,14 +251,9 @@ class Text(Filter):
@classmethod @classmethod
def validate(cls, full_config: Dict[str, Any]): def validate(cls, full_config: Dict[str, Any]):
if 'text' in full_config: for param, key in cls._default_params:
return {'equals': full_config.pop('text')} if param in full_config:
elif 'text_contains' in full_config: return {key: full_config.pop(param)}
return {'contains': full_config.pop('text_contains')}
elif 'text_startswith' in full_config:
return {'startswith': full_config.pop('text_startswith')}
elif 'text_endswith' in full_config:
return {'endswith': full_config.pop('text_endswith')}
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery, Poll]): async def check(self, obj: Union[Message, CallbackQuery, InlineQuery, Poll]):
if isinstance(obj, Message): if isinstance(obj, Message):

View file

@ -25,17 +25,17 @@ class State:
@property @property
def state(self): def state(self):
if self._state is None: if self._state is None or self._state == '*':
return None
elif self._state == '*':
return self._state return self._state
elif self._group_name is None and self._group:
if self._group_name is None and self._group:
group = self._group.__full_group_name__ group = self._group.__full_group_name__
elif self._group_name: elif self._group_name:
group = self._group_name group = self._group_name
else: else:
group = '@' group = '@'
return f"{group}:{self._state}"
return f'{group}:{self._state}'
def set_parent(self, group): def set_parent(self, group):
if not issubclass(group, StatesGroup): if not issubclass(group, StatesGroup):
@ -73,7 +73,6 @@ class StatesGroupMeta(type):
elif inspect.isclass(prop) and issubclass(prop, StatesGroup): elif inspect.isclass(prop) and issubclass(prop, StatesGroup):
childs.append(prop) childs.append(prop)
prop._parent = cls prop._parent = cls
# continue
cls._parent = None cls._parent = None
cls._childs = tuple(childs) cls._childs = tuple(childs)
@ -83,13 +82,13 @@ class StatesGroupMeta(type):
return cls return cls
@property @property
def __group_name__(cls): def __group_name__(cls) -> str:
return cls._group_name return cls._group_name
@property @property
def __full_group_name__(cls): def __full_group_name__(cls) -> str:
if cls._parent: if cls._parent:
return cls._parent.__full_group_name__ + '.' + cls._group_name return '.'.join((cls._parent.__full_group_name__, cls._group_name))
return cls._group_name return cls._group_name
@property @property
@ -97,7 +96,7 @@ class StatesGroupMeta(type):
return cls._states return cls._states
@property @property
def childs(cls): def childs(cls) -> tuple:
return cls._childs return cls._childs
@property @property
@ -130,9 +129,9 @@ class StatesGroupMeta(type):
def __contains__(cls, item): def __contains__(cls, item):
if isinstance(item, str): if isinstance(item, str):
return item in cls.all_states_names return item in cls.all_states_names
elif isinstance(item, State): if isinstance(item, State):
return item in cls.all_states return item in cls.all_states
elif isinstance(item, StatesGroup): if isinstance(item, StatesGroup):
return item in cls.all_childs return item in cls.all_childs
return False return False

View file

@ -31,7 +31,7 @@ T = TypeVar('T')
class ContextInstanceMixin: class ContextInstanceMixin:
def __init_subclass__(cls, **kwargs): def __init_subclass__(cls, **kwargs):
cls.__context_instance = contextvars.ContextVar('instance_' + cls.__name__) cls.__context_instance = contextvars.ContextVar(f'instance_{cls.__name__}')
return cls return cls
@classmethod @classmethod
@ -43,5 +43,5 @@ class ContextInstanceMixin:
@classmethod @classmethod
def set_current(cls: Type[T], value: T): def set_current(cls: Type[T], value: T):
if not isinstance(value, cls): if not isinstance(value, cls):
raise TypeError(f"Value should be instance of '{cls.__name__}' not '{type(value).__name__}'") raise TypeError(f'Value should be instance of {cls.__name__!r} not {type(value).__name__!r}')
cls.__context_instance.set(value) cls.__context_instance.set(value)

View file

@ -15,3 +15,4 @@ sphinx-rtd-theme>=0.4.3
sphinxcontrib-programoutput>=0.14 sphinxcontrib-programoutput>=0.14
aiohttp-socks>=0.2.2 aiohttp-socks>=0.2.2
rethinkdb>=2.4.1 rethinkdb>=2.4.1
coverage==4.5.3

View file

@ -1,16 +1,19 @@
import asyncio import logging
from typing import Optional
import aiogram.utils.markdown as md import aiogram.utils.markdown as md
from aiogram import Bot, Dispatcher, types from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Text
from aiogram.dispatcher.filters.state import State, StatesGroup from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.types import ParseMode from aiogram.types import ParseMode
from aiogram.utils import executor from aiogram.utils import executor
logging.basicConfig(level=logging.INFO)
API_TOKEN = 'BOT TOKEN HERE' API_TOKEN = 'BOT TOKEN HERE'
bot = Bot(token=API_TOKEN) bot = Bot(token=API_TOKEN)
# For example use simple MemoryStorage for Dispatcher. # For example use simple MemoryStorage for Dispatcher.
@ -25,7 +28,7 @@ class Form(StatesGroup):
gender = State() # Will be represented in storage as 'Form:gender' gender = State() # Will be represented in storage as 'Form:gender'
@dp.message_handler(commands=['start']) @dp.message_handler(commands='start')
async def cmd_start(message: types.Message): async def cmd_start(message: types.Message):
""" """
Conversation's entry point Conversation's entry point
@ -37,19 +40,21 @@ async def cmd_start(message: types.Message):
# You can use state '*' if you need to handle all states # You can use state '*' if you need to handle all states
@dp.message_handler(state='*', commands=['cancel']) @dp.message_handler(state='*', commands='cancel')
@dp.message_handler(lambda message: message.text.lower() == 'cancel', state='*') @dp.message_handler(Text(equals='cancel', ignore_case=True), state='*')
async def cancel_handler(message: types.Message, state: FSMContext, raw_state: Optional[str] = None): async def cancel_handler(message: types.Message, state: FSMContext):
""" """
Allow user to cancel any action Allow user to cancel any action
""" """
if raw_state is None: current_state = await state.get_state()
if current_state is None:
return return
logging.info('Cancelling state %r', current_state)
# Cancel state and inform user about it # Cancel state and inform user about it
await state.finish() await state.finish()
# And remove keyboard (just in case) # And remove keyboard (just in case)
await message.reply('Canceled.', reply_markup=types.ReplyKeyboardRemove()) await message.reply('Cancelled.', reply_markup=types.ReplyKeyboardRemove())
@dp.message_handler(state=Form.name) @dp.message_handler(state=Form.name)
@ -66,7 +71,7 @@ async def process_name(message: types.Message, state: FSMContext):
# Check age. Age gotta be digit # Check age. Age gotta be digit
@dp.message_handler(lambda message: not message.text.isdigit(), state=Form.age) @dp.message_handler(lambda message: not message.text.isdigit(), state=Form.age)
async def failed_process_age(message: types.Message): async def process_age_invalid(message: types.Message):
""" """
If age is invalid If age is invalid
""" """
@ -88,11 +93,11 @@ async def process_age(message: types.Message, state: FSMContext):
@dp.message_handler(lambda message: message.text not in ["Male", "Female", "Other"], state=Form.gender) @dp.message_handler(lambda message: message.text not in ["Male", "Female", "Other"], state=Form.gender)
async def failed_process_gender(message: types.Message): async def process_gender_invalid(message: types.Message):
""" """
In this example gender has to be one of: Male, Female, Other. In this example gender has to be one of: Male, Female, Other.
""" """
return await message.reply("Bad gender name. Choose you gender from keyboard.") return await message.reply("Bad gender name. Choose your gender from the keyboard.")
@dp.message_handler(state=Form.gender) @dp.message_handler(state=Form.gender)
@ -104,11 +109,17 @@ async def process_gender(message: types.Message, state: FSMContext):
markup = types.ReplyKeyboardRemove() markup = types.ReplyKeyboardRemove()
# And send message # And send message
await bot.send_message(message.chat.id, md.text( await bot.send_message(
md.text('Hi! Nice to meet you,', md.bold(data['name'])), message.chat.id,
md.text('Age:', data['age']), md.text(
md.text('Gender:', data['gender']), md.text('Hi! Nice to meet you,', md.bold(data['name'])),
sep='\n'), reply_markup=markup, parse_mode=ParseMode.MARKDOWN) md.text('Age:', md.code(data['age'])),
md.text('Gender:', data['gender']),
sep='\n',
),
reply_markup=markup,
parse_mode=ParseMode.MARKDOWN,
)
# Finish conversation # Finish conversation
await state.finish() await state.finish()

View file

@ -8,7 +8,7 @@ USER = {
"first_name": "FirstName", "first_name": "FirstName",
"last_name": "LastName", "last_name": "LastName",
"username": "username", "username": "username",
"language_code": "ru" "language_code": "ru",
} }
CHAT = { CHAT = {
@ -16,14 +16,14 @@ CHAT = {
"first_name": "FirstName", "first_name": "FirstName",
"last_name": "LastName", "last_name": "LastName",
"username": "username", "username": "username",
"type": "private" "type": "private",
} }
PHOTO = { PHOTO = {
"file_id": "AgADBAADFak0G88YZAf8OAug7bHyS9x2ZxkABHVfpJywcloRAAGAAQABAg", "file_id": "AgADBAADFak0G88YZAf8OAug7bHyS9x2ZxkABHVfpJywcloRAAGAAQABAg",
"file_size": 1101, "file_size": 1101,
"width": 90, "width": 90,
"height": 51 "height": 51,
} }
AUDIO = { AUDIO = {
@ -32,7 +32,7 @@ AUDIO = {
"title": "The Best Song", "title": "The Best Song",
"performer": "The Best Singer", "performer": "The Best Singer",
"file_id": "CQADAgADbQEAAsnrIUpNoRRNsH7_hAI", "file_id": "CQADAgADbQEAAsnrIUpNoRRNsH7_hAI",
"file_size": 9507774 "file_size": 9507774,
} }
CHAT_MEMBER = { CHAT_MEMBER = {
@ -44,7 +44,7 @@ CHAT_MEMBER = {
"can_invite_users": True, "can_invite_users": True,
"can_restrict_members": True, "can_restrict_members": True,
"can_pin_messages": True, "can_pin_messages": True,
"can_promote_members": False "can_promote_members": False,
} }
CONTACT = { CONTACT = {
@ -57,7 +57,7 @@ DOCUMENT = {
"file_name": "test.docx", "file_name": "test.docx",
"mime_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "mime_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"file_id": "BQADAgADpgADy_JxS66XQTBRHFleAg", "file_id": "BQADAgADpgADy_JxS66XQTBRHFleAg",
"file_size": 21331 "file_size": 21331,
} }
ANIMATION = { ANIMATION = {
@ -65,51 +65,51 @@ ANIMATION = {
"mime_type": "video/mp4", "mime_type": "video/mp4",
"thumb": PHOTO, "thumb": PHOTO,
"file_id": "CgADBAAD4DUAAoceZAe2WiE9y0crrAI", "file_id": "CgADBAAD4DUAAoceZAe2WiE9y0crrAI",
"file_size": 65837 "file_size": 65837,
} }
ENTITY_BOLD = { ENTITY_BOLD = {
"offset": 5, "offset": 5,
"length": 2, "length": 2,
"type": "bold" "type": "bold",
} }
ENTITY_ITALIC = { ENTITY_ITALIC = {
"offset": 8, "offset": 8,
"length": 1, "length": 1,
"type": "italic" "type": "italic",
} }
ENTITY_LINK = { ENTITY_LINK = {
"offset": 10, "offset": 10,
"length": 6, "length": 6,
"type": "text_link", "type": "text_link",
"url": "http://google.com/" "url": "http://google.com/",
} }
ENTITY_CODE = { ENTITY_CODE = {
"offset": 17, "offset": 17,
"length": 7, "length": 7,
"type": "code" "type": "code",
} }
ENTITY_PRE = { ENTITY_PRE = {
"offset": 30, "offset": 30,
"length": 4, "length": 4,
"type": "pre" "type": "pre",
} }
ENTITY_MENTION = { ENTITY_MENTION = {
"offset": 47, "offset": 47,
"length": 9, "length": 9,
"type": "mention" "type": "mention",
} }
GAME = { GAME = {
"title": "Karate Kido", "title": "Karate Kido",
"description": "No trees were harmed in the making of this game :)", "description": "No trees were harmed in the making of this game :)",
"photo": [PHOTO, PHOTO, PHOTO], "photo": [PHOTO, PHOTO, PHOTO],
"animation": ANIMATION "animation": ANIMATION,
} }
INVOICE = { INVOICE = {
@ -120,19 +120,19 @@ INVOICE = {
"Order our Working Time Machine today!", "Order our Working Time Machine today!",
"start_parameter": "time-machine-example", "start_parameter": "time-machine-example",
"currency": "USD", "currency": "USD",
"total_amount": 6250 "total_amount": 6250,
} }
LOCATION = { LOCATION = {
"latitude": 50.693416, "latitude": 50.693416,
"longitude": 30.624605 "longitude": 30.624605,
} }
VENUE = { VENUE = {
"location": LOCATION, "location": LOCATION,
"title": "Venue Name", "title": "Venue Name",
"address": "Venue Address", "address": "Venue Address",
"foursquare_id": "4e6f2cec483bad563d150f98" "foursquare_id": "4e6f2cec483bad563d150f98",
} }
SHIPPING_ADDRESS = { SHIPPING_ADDRESS = {
@ -141,7 +141,7 @@ SHIPPING_ADDRESS = {
"city": "DefaultCity", "city": "DefaultCity",
"street_line1": "Central", "street_line1": "Central",
"street_line2": "Middle", "street_line2": "Middle",
"post_code": "424242" "post_code": "424242",
} }
STICKER = { STICKER = {
@ -156,7 +156,7 @@ STICKER = {
"height": 128 "height": 128
}, },
"file_id": "AAbbCCddEEffGGhh1234567890", "file_id": "AAbbCCddEEffGGhh1234567890",
"file_size": 12345 "file_size": 12345,
} }
SUCCESSFUL_PAYMENT = { SUCCESSFUL_PAYMENT = {
@ -164,7 +164,7 @@ SUCCESSFUL_PAYMENT = {
"total_amount": 6250, "total_amount": 6250,
"invoice_payload": "HAPPY FRIDAYS COUPON", "invoice_payload": "HAPPY FRIDAYS COUPON",
"telegram_payment_charge_id": "_", "telegram_payment_charge_id": "_",
"provider_payment_charge_id": "12345678901234_test" "provider_payment_charge_id": "12345678901234_test",
} }
VIDEO = { VIDEO = {
@ -174,7 +174,7 @@ VIDEO = {
"mime_type": "video/quicktime", "mime_type": "video/quicktime",
"thumb": PHOTO, "thumb": PHOTO,
"file_id": "BAADAgpAADdawy_JxS72kRvV3cortAg", "file_id": "BAADAgpAADdawy_JxS72kRvV3cortAg",
"file_size": 10099782 "file_size": 10099782,
} }
VIDEO_NOTE = { VIDEO_NOTE = {
@ -182,14 +182,14 @@ VIDEO_NOTE = {
"length": 240, "length": 240,
"thumb": PHOTO, "thumb": PHOTO,
"file_id": "AbCdEfGhIjKlMnOpQrStUvWxYz", "file_id": "AbCdEfGhIjKlMnOpQrStUvWxYz",
"file_size": 186562 "file_size": 186562,
} }
VOICE = { VOICE = {
"duration": 1, "duration": 1,
"mime_type": "audio/ogg", "mime_type": "audio/ogg",
"file_id": "AwADawAgADADy_JxS2gopIVIIxlhAg", "file_id": "AwADawAgADADy_JxS2gopIVIIxlhAg",
"file_size": 4321 "file_size": 4321,
} }
CALLBACK_QUERY = {} CALLBACK_QUERY = {}
@ -206,7 +206,7 @@ EDITED_MESSAGE = {
"chat": CHAT, "chat": CHAT,
"date": 1508825372, "date": 1508825372,
"edit_date": 1508825379, "edit_date": 1508825379,
"text": "hi there (edited)" "text": "hi there (edited)",
} }
FORWARDED_MESSAGE = { FORWARDED_MESSAGE = {
@ -219,7 +219,7 @@ FORWARDED_MESSAGE = {
"forward_date": 1522749037, "forward_date": 1522749037,
"text": "Forwarded text with entities from public channel ", "text": "Forwarded text with entities from public channel ",
"entities": [ENTITY_BOLD, ENTITY_CODE, ENTITY_ITALIC, ENTITY_LINK, "entities": [ENTITY_BOLD, ENTITY_CODE, ENTITY_ITALIC, ENTITY_LINK,
ENTITY_LINK, ENTITY_MENTION, ENTITY_PRE] ENTITY_LINK, ENTITY_MENTION, ENTITY_PRE],
} }
INLINE_QUERY = {} INLINE_QUERY = {}
@ -229,7 +229,7 @@ MESSAGE = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1508709711, "date": 1508709711,
"text": "Hi, world!" "text": "Hi, world!",
} }
MESSAGE_WITH_AUDIO = { MESSAGE_WITH_AUDIO = {
@ -238,7 +238,7 @@ MESSAGE_WITH_AUDIO = {
"chat": CHAT, "chat": CHAT,
"date": 1508739776, "date": 1508739776,
"audio": AUDIO, "audio": AUDIO,
"caption": "This is my favourite song" "caption": "This is my favourite song",
} }
MESSAGE_WITH_AUTHOR_SIGNATURE = {} MESSAGE_WITH_AUTHOR_SIGNATURE = {}
@ -250,7 +250,7 @@ MESSAGE_WITH_CONTACT = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1522850298, "date": 1522850298,
"contact": CONTACT "contact": CONTACT,
} }
MESSAGE_WITH_DELETE_CHAT_PHOTO = {} MESSAGE_WITH_DELETE_CHAT_PHOTO = {}
@ -261,7 +261,7 @@ MESSAGE_WITH_DOCUMENT = {
"chat": CHAT, "chat": CHAT,
"date": 1508768012, "date": 1508768012,
"document": DOCUMENT, "document": DOCUMENT,
"caption": "Read my document" "caption": "Read my document",
} }
MESSAGE_WITH_EDIT_DATE = {} MESSAGE_WITH_EDIT_DATE = {}
@ -273,7 +273,7 @@ MESSAGE_WITH_GAME = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1508824810, "date": 1508824810,
"game": GAME "game": GAME,
} }
MESSAGE_WITH_GROUP_CHAT_CREATED = {} MESSAGE_WITH_GROUP_CHAT_CREATED = {}
@ -283,7 +283,7 @@ MESSAGE_WITH_INVOICE = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1508761719, "date": 1508761719,
"invoice": INVOICE "invoice": INVOICE,
} }
MESSAGE_WITH_LEFT_CHAT_MEMBER = {} MESSAGE_WITH_LEFT_CHAT_MEMBER = {}
@ -293,7 +293,7 @@ MESSAGE_WITH_LOCATION = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1508755473, "date": 1508755473,
"location": LOCATION "location": LOCATION,
} }
MESSAGE_WITH_MIGRATE_TO_CHAT_ID = { MESSAGE_WITH_MIGRATE_TO_CHAT_ID = {
@ -301,7 +301,7 @@ MESSAGE_WITH_MIGRATE_TO_CHAT_ID = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1526943253, "date": 1526943253,
"migrate_to_chat_id": -1234567890987 "migrate_to_chat_id": -1234567890987,
} }
MESSAGE_WITH_MIGRATE_FROM_CHAT_ID = { MESSAGE_WITH_MIGRATE_FROM_CHAT_ID = {
@ -309,7 +309,7 @@ MESSAGE_WITH_MIGRATE_FROM_CHAT_ID = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1526943253, "date": 1526943253,
"migrate_from_chat_id": -123456789 "migrate_from_chat_id": -123456789,
} }
MESSAGE_WITH_NEW_CHAT_MEMBERS = {} MESSAGE_WITH_NEW_CHAT_MEMBERS = {}
@ -324,7 +324,7 @@ MESSAGE_WITH_PHOTO = {
"chat": CHAT, "chat": CHAT,
"date": 1508825154, "date": 1508825154,
"photo": [PHOTO, PHOTO, PHOTO, PHOTO], "photo": [PHOTO, PHOTO, PHOTO, PHOTO],
"caption": "photo description" "caption": "photo description",
} }
MESSAGE_WITH_MEDIA_GROUP = { MESSAGE_WITH_MEDIA_GROUP = {
@ -333,7 +333,7 @@ MESSAGE_WITH_MEDIA_GROUP = {
"chat": CHAT, "chat": CHAT,
"date": 1522843665, "date": 1522843665,
"media_group_id": "12182749320567362", "media_group_id": "12182749320567362",
"photo": [PHOTO, PHOTO, PHOTO, PHOTO] "photo": [PHOTO, PHOTO, PHOTO, PHOTO],
} }
MESSAGE_WITH_PINNED_MESSAGE = {} MESSAGE_WITH_PINNED_MESSAGE = {}
@ -345,7 +345,7 @@ MESSAGE_WITH_STICKER = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1508771450, "date": 1508771450,
"sticker": STICKER "sticker": STICKER,
} }
MESSAGE_WITH_SUCCESSFUL_PAYMENT = { MESSAGE_WITH_SUCCESSFUL_PAYMENT = {
@ -353,7 +353,7 @@ MESSAGE_WITH_SUCCESSFUL_PAYMENT = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1508761169, "date": 1508761169,
"successful_payment": SUCCESSFUL_PAYMENT "successful_payment": SUCCESSFUL_PAYMENT,
} }
MESSAGE_WITH_SUPERGROUP_CHAT_CREATED = {} MESSAGE_WITH_SUPERGROUP_CHAT_CREATED = {}
@ -364,7 +364,7 @@ MESSAGE_WITH_VENUE = {
"chat": CHAT, "chat": CHAT,
"date": 1522849819, "date": 1522849819,
"location": LOCATION, "location": LOCATION,
"venue": VENUE "venue": VENUE,
} }
MESSAGE_WITH_VIDEO = { MESSAGE_WITH_VIDEO = {
@ -373,7 +373,7 @@ MESSAGE_WITH_VIDEO = {
"chat": CHAT, "chat": CHAT,
"date": 1508756494, "date": 1508756494,
"video": VIDEO, "video": VIDEO,
"caption": "description" "caption": "description",
} }
MESSAGE_WITH_VIDEO_NOTE = { MESSAGE_WITH_VIDEO_NOTE = {
@ -381,7 +381,7 @@ MESSAGE_WITH_VIDEO_NOTE = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1522835890, "date": 1522835890,
"video_note": VIDEO_NOTE "video_note": VIDEO_NOTE,
} }
MESSAGE_WITH_VOICE = { MESSAGE_WITH_VOICE = {
@ -389,7 +389,7 @@ MESSAGE_WITH_VOICE = {
"from": USER, "from": USER,
"chat": CHAT, "chat": CHAT,
"date": 1508768403, "date": 1508768403,
"voice": VOICE "voice": VOICE,
} }
PRE_CHECKOUT_QUERY = { PRE_CHECKOUT_QUERY = {
@ -397,7 +397,7 @@ PRE_CHECKOUT_QUERY = {
"from": USER, "from": USER,
"currency": "USD", "currency": "USD",
"total_amount": 6250, "total_amount": 6250,
"invoice_payload": "HAPPY FRIDAYS COUPON" "invoice_payload": "HAPPY FRIDAYS COUPON",
} }
REPLY_MESSAGE = { REPLY_MESSAGE = {
@ -406,37 +406,37 @@ REPLY_MESSAGE = {
"chat": CHAT, "chat": CHAT,
"date": 1508751866, "date": 1508751866,
"reply_to_message": MESSAGE, "reply_to_message": MESSAGE,
"text": "Reply to quoted message" "text": "Reply to quoted message",
} }
SHIPPING_QUERY = { SHIPPING_QUERY = {
"id": "262181558684397422", "id": "262181558684397422",
"from": USER, "from": USER,
"invoice_payload": "HAPPY FRIDAYS COUPON", "invoice_payload": "HAPPY FRIDAYS COUPON",
"shipping_address": SHIPPING_ADDRESS "shipping_address": SHIPPING_ADDRESS,
} }
USER_PROFILE_PHOTOS = { USER_PROFILE_PHOTOS = {
"total_count": 1, "photos": [ "total_count": 1, "photos": [
[PHOTO, PHOTO, PHOTO] [PHOTO, PHOTO, PHOTO],
] ],
} }
FILE = { FILE = {
"file_id": "XXXYYYZZZ", "file_id": "XXXYYYZZZ",
"file_size": 5254, "file_size": 5254,
"file_path": "voice\/file_8" "file_path": "voice/file_8",
} }
INVITE_LINK = 'https://t.me/joinchat/AbCdEfjKILDADwdd123' INVITE_LINK = 'https://t.me/joinchat/AbCdEfjKILDADwdd123'
UPDATE = { UPDATE = {
"update_id": 123456789, "update_id": 123456789,
"message": MESSAGE "message": MESSAGE,
} }
WEBHOOK_INFO = { WEBHOOK_INFO = {
"url": "", "url": "",
"has_custom_certificate": False, "has_custom_certificate": False,
"pending_update_count": 0 "pending_update_count": 0,
} }