mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Merge branch 'dev-2.x' into add_rename_argument_decorator
This commit is contained in:
commit
95f83d7cef
45 changed files with 876 additions and 835 deletions
|
|
@ -97,15 +97,13 @@ class I18nMiddleware(BaseMiddleware):
|
|||
if locale not in self.locales:
|
||||
if n is 1:
|
||||
return singular
|
||||
else:
|
||||
return plural
|
||||
return plural
|
||||
|
||||
translator = self.locales[locale]
|
||||
|
||||
if plural is None:
|
||||
return translator.gettext(singular)
|
||||
else:
|
||||
return translator.ngettext(singular, plural, n)
|
||||
return translator.ngettext(singular, plural, n)
|
||||
|
||||
def lazy_gettext(self, singular, plural=None, n=1, locale=None, enable_cache=True) -> LazyProxy:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -85,39 +85,56 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
|
|||
|
||||
filters_factory.bind(StateFilter, exclude_event_handlers=[
|
||||
self.errors_handlers,
|
||||
self.poll_handlers
|
||||
self.poll_handlers,
|
||||
])
|
||||
filters_factory.bind(ContentTypeFilter, event_handlers=[
|
||||
self.message_handlers, self.edited_message_handlers,
|
||||
self.channel_post_handlers, self.edited_channel_post_handlers,
|
||||
self.message_handlers,
|
||||
self.edited_message_handlers,
|
||||
self.channel_post_handlers,
|
||||
self.edited_channel_post_handlers,
|
||||
]),
|
||||
filters_factory.bind(Command, event_handlers=[
|
||||
self.message_handlers, self.edited_message_handlers
|
||||
self.message_handlers,
|
||||
self.edited_message_handlers
|
||||
])
|
||||
filters_factory.bind(Text, event_handlers=[
|
||||
self.message_handlers, self.edited_message_handlers,
|
||||
self.channel_post_handlers, self.edited_channel_post_handlers,
|
||||
self.callback_query_handlers, self.poll_handlers, self.inline_query_handlers
|
||||
self.message_handlers,
|
||||
self.edited_message_handlers,
|
||||
self.channel_post_handlers,
|
||||
self.edited_channel_post_handlers,
|
||||
self.callback_query_handlers,
|
||||
self.poll_handlers,
|
||||
self.inline_query_handlers,
|
||||
])
|
||||
filters_factory.bind(HashTag, event_handlers=[
|
||||
self.message_handlers, self.edited_message_handlers,
|
||||
self.channel_post_handlers, self.edited_channel_post_handlers
|
||||
self.message_handlers,
|
||||
self.edited_message_handlers,
|
||||
self.channel_post_handlers,
|
||||
self.edited_channel_post_handlers,
|
||||
])
|
||||
filters_factory.bind(Regexp, event_handlers=[
|
||||
self.message_handlers, self.edited_message_handlers,
|
||||
self.channel_post_handlers, self.edited_channel_post_handlers,
|
||||
self.callback_query_handlers, self.poll_handlers, self.inline_query_handlers
|
||||
self.message_handlers,
|
||||
self.edited_message_handlers,
|
||||
self.channel_post_handlers,
|
||||
self.edited_channel_post_handlers,
|
||||
self.callback_query_handlers,
|
||||
self.poll_handlers,
|
||||
self.inline_query_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=[
|
||||
self.errors_handlers
|
||||
self.errors_handlers,
|
||||
])
|
||||
filters_factory.bind(IdFilter, event_handlers=[
|
||||
self.message_handlers, self.edited_message_handlers,
|
||||
self.channel_post_handlers, self.edited_channel_post_handlers,
|
||||
self.callback_query_handlers, self.inline_query_handlers
|
||||
self.message_handlers,
|
||||
self.edited_message_handlers,
|
||||
self.channel_post_handlers,
|
||||
self.edited_channel_post_handlers,
|
||||
self.callback_query_handlers,
|
||||
self.inline_query_handlers,
|
||||
])
|
||||
|
||||
def __del__(self):
|
||||
|
|
|
|||
|
|
@ -27,5 +27,5 @@ __all__ = [
|
|||
'get_filter_spec',
|
||||
'get_filters_spec',
|
||||
'execute_filter',
|
||||
'check_filters'
|
||||
'check_filters',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -84,9 +84,9 @@ class Command(Filter):
|
|||
|
||||
if not ignore_mention and mention and (await message.bot.me).username.lower() != mention.lower():
|
||||
return False
|
||||
elif prefix not in prefixes:
|
||||
if prefix not in prefixes:
|
||||
return False
|
||||
elif (command.lower() if ignore_case else command) not in commands:
|
||||
if (command.lower() if ignore_case else command) not in commands:
|
||||
return False
|
||||
|
||||
return {'command': Command.CommandObj(command=command, prefix=prefix, mention=mention)}
|
||||
|
|
@ -149,7 +149,7 @@ class CommandStart(Command):
|
|||
|
||||
:param deep_link: string or compiled regular expression (by ``re.compile(...)``).
|
||||
"""
|
||||
super(CommandStart, self).__init__(['start'])
|
||||
super().__init__(['start'])
|
||||
self.deep_link = deep_link
|
||||
|
||||
async def check(self, message: types.Message):
|
||||
|
|
@ -159,7 +159,7 @@ class CommandStart(Command):
|
|||
:param message:
|
||||
:return:
|
||||
"""
|
||||
check = await super(CommandStart, self).check(message)
|
||||
check = await super().check(message)
|
||||
|
||||
if check and self.deep_link is not None:
|
||||
if not isinstance(self.deep_link, re.Pattern):
|
||||
|
|
@ -179,7 +179,7 @@ class CommandHelp(Command):
|
|||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(CommandHelp, self).__init__(['help'])
|
||||
super().__init__(['help'])
|
||||
|
||||
|
||||
class CommandSettings(Command):
|
||||
|
|
@ -188,7 +188,7 @@ class CommandSettings(Command):
|
|||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(CommandSettings, self).__init__(['settings'])
|
||||
super().__init__(['settings'])
|
||||
|
||||
|
||||
class CommandPrivacy(Command):
|
||||
|
|
@ -197,7 +197,7 @@ class CommandPrivacy(Command):
|
|||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(CommandPrivacy, self).__init__(['privacy'])
|
||||
super().__init__(['privacy'])
|
||||
|
||||
|
||||
class Text(Filter):
|
||||
|
|
@ -205,6 +205,13 @@ class Text(Filter):
|
|||
Simple text filter
|
||||
"""
|
||||
|
||||
_default_params = (
|
||||
('text', 'equals'),
|
||||
('text_contains', 'contains'),
|
||||
('text_startswith', 'startswith'),
|
||||
('text_endswith', 'endswith'),
|
||||
)
|
||||
|
||||
def __init__(self,
|
||||
equals: 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
|
||||
def validate(cls, full_config: Dict[str, Any]):
|
||||
if 'text' in full_config:
|
||||
return {'equals': full_config.pop('text')}
|
||||
elif 'text_contains' in full_config:
|
||||
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')}
|
||||
for param, key in cls._default_params:
|
||||
if param in full_config:
|
||||
return {key: full_config.pop(param)}
|
||||
|
||||
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery, Poll]):
|
||||
if isinstance(obj, Message):
|
||||
|
|
@ -269,19 +271,26 @@ class Text(Filter):
|
|||
|
||||
if self.ignore_case:
|
||||
text = text.lower()
|
||||
_pre_process_func = lambda s: str(s).lower()
|
||||
else:
|
||||
_pre_process_func = str
|
||||
|
||||
# now check
|
||||
if self.equals is not None:
|
||||
self.equals = list(map(lambda s: str(s).lower() if self.ignore_case else str(s), self.equals))
|
||||
return text in self.equals
|
||||
elif self.contains is not None:
|
||||
self.contains = list(map(lambda s: str(s).lower() if self.ignore_case else str(s), self.contains))
|
||||
return all(map(text.__contains__, self.contains))
|
||||
elif self.startswith is not None:
|
||||
self.startswith = list(map(lambda s: str(s).lower() if self.ignore_case else str(s), self.startswith))
|
||||
return any(map(text.startswith, self.startswith))
|
||||
elif self.endswith is not None:
|
||||
self.endswith = list(map(lambda s: str(s).lower() if self.ignore_case else str(s), self.endswith))
|
||||
return any(map(text.endswith, self.endswith))
|
||||
equals = list(map(_pre_process_func, self.equals))
|
||||
return text in equals
|
||||
|
||||
if self.contains is not None:
|
||||
contains = list(map(_pre_process_func, self.contains))
|
||||
return all(map(text.__contains__, contains))
|
||||
|
||||
if self.startswith is not None:
|
||||
startswith = list(map(_pre_process_func, self.startswith))
|
||||
return any(map(text.startswith, startswith))
|
||||
|
||||
if self.endswith is not None:
|
||||
endswith = list(map(_pre_process_func, self.endswith))
|
||||
return any(map(text.endswith, endswith))
|
||||
|
||||
return False
|
||||
|
||||
|
|
@ -556,9 +565,9 @@ class IdFilter(Filter):
|
|||
|
||||
if self.user_id and self.chat_id:
|
||||
return user_id in self.user_id and chat_id in self.chat_id
|
||||
elif self.user_id:
|
||||
if self.user_id:
|
||||
return user_id in self.user_id
|
||||
elif self.chat_id:
|
||||
if self.chat_id:
|
||||
return chat_id in self.chat_id
|
||||
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -70,4 +70,4 @@ class FiltersFactory:
|
|||
yield filter_
|
||||
|
||||
if full_config:
|
||||
raise NameError('Invalid filter name(s): \'' + '\', '.join(full_config.keys()) + '\'')
|
||||
raise NameError("Invalid filter name(s): '" + "', ".join(full_config.keys()) + "'")
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class FilterRecord:
|
|||
Filters record for factory
|
||||
"""
|
||||
|
||||
def __init__(self, callback: typing.Callable,
|
||||
def __init__(self, callback: typing.Union[typing.Callable, 'AbstractFilter'],
|
||||
validator: typing.Optional[typing.Callable] = None,
|
||||
event_handlers: typing.Optional[typing.Iterable[Handler]] = None,
|
||||
exclude_event_handlers: typing.Optional[typing.Iterable[Handler]] = None):
|
||||
|
|
|
|||
|
|
@ -25,17 +25,17 @@ class State:
|
|||
|
||||
@property
|
||||
def state(self):
|
||||
if self._state is None:
|
||||
return None
|
||||
elif self._state == '*':
|
||||
if self._state is None or 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__
|
||||
elif self._group_name:
|
||||
group = self._group_name
|
||||
else:
|
||||
group = '@'
|
||||
return f"{group}:{self._state}"
|
||||
|
||||
return f'{group}:{self._state}'
|
||||
|
||||
def set_parent(self, group):
|
||||
if not issubclass(group, StatesGroup):
|
||||
|
|
@ -73,7 +73,6 @@ class StatesGroupMeta(type):
|
|||
elif inspect.isclass(prop) and issubclass(prop, StatesGroup):
|
||||
childs.append(prop)
|
||||
prop._parent = cls
|
||||
# continue
|
||||
|
||||
cls._parent = None
|
||||
cls._childs = tuple(childs)
|
||||
|
|
@ -83,13 +82,13 @@ class StatesGroupMeta(type):
|
|||
return cls
|
||||
|
||||
@property
|
||||
def __group_name__(cls):
|
||||
def __group_name__(cls) -> str:
|
||||
return cls._group_name
|
||||
|
||||
@property
|
||||
def __full_group_name__(cls):
|
||||
def __full_group_name__(cls) -> str:
|
||||
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
|
||||
|
||||
@property
|
||||
|
|
@ -97,7 +96,7 @@ class StatesGroupMeta(type):
|
|||
return cls._states
|
||||
|
||||
@property
|
||||
def childs(cls):
|
||||
def childs(cls) -> tuple:
|
||||
return cls._childs
|
||||
|
||||
@property
|
||||
|
|
@ -130,9 +129,9 @@ class StatesGroupMeta(type):
|
|||
def __contains__(cls, item):
|
||||
if isinstance(item, str):
|
||||
return item in cls.all_states_names
|
||||
elif isinstance(item, State):
|
||||
if isinstance(item, State):
|
||||
return item in cls.all_states
|
||||
elif isinstance(item, StatesGroup):
|
||||
if isinstance(item, StatesGroup):
|
||||
return item in cls.all_childs
|
||||
return False
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import inspect
|
||||
from contextvars import ContextVar
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Iterable
|
||||
from typing import Optional, Iterable, List
|
||||
|
||||
ctx_data = ContextVar('ctx_handler_data')
|
||||
current_handler = ContextVar('current_handler')
|
||||
|
|
@ -41,11 +41,10 @@ class Handler:
|
|||
self.dispatcher = dispatcher
|
||||
self.once = once
|
||||
|
||||
self.handlers = []
|
||||
self.handlers: List[Handler.HandlerObj] = []
|
||||
self.middleware_key = middleware_key
|
||||
|
||||
def register(self, handler, filters=None, index=None):
|
||||
from .filters import get_filters_spec
|
||||
"""
|
||||
Register callback
|
||||
|
||||
|
|
@ -55,6 +54,8 @@ class Handler:
|
|||
:param filters: list of filters
|
||||
:param index: you can reorder handlers
|
||||
"""
|
||||
from .filters import get_filters_spec
|
||||
|
||||
spec = _get_spec(handler)
|
||||
|
||||
if filters and not isinstance(filters, (list, tuple, set)):
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ class SendMessage(BaseResponse, ReplyToMixin, ParseModeMixin, DisableNotificatio
|
|||
'disable_web_page_preview': self.disable_web_page_preview,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
def write(self, *text, sep=' '):
|
||||
|
|
@ -642,7 +642,7 @@ class SendPhoto(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'caption': self.caption,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -704,7 +704,7 @@ class SendAudio(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'title': self.title,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -817,7 +817,7 @@ class SendVideo(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'caption': self.caption,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -871,7 +871,7 @@ class SendVoice(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'duration': self.duration,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -924,7 +924,7 @@ class SendVideoNote(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'length': self.length,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1050,7 +1050,7 @@ class SendLocation(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'longitude': self.longitude,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1109,7 +1109,7 @@ class SendVenue(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'foursquare_id': self.foursquare_id,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1160,7 +1160,7 @@ class SendContact(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'last_name': self.last_name,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1220,7 +1220,7 @@ class KickChatMember(BaseResponse):
|
|||
return {
|
||||
'chat_id': self.chat_id,
|
||||
'user_id': self.user_id,
|
||||
'until_date': prepare_arg(self.until_date)
|
||||
'until_date': prepare_arg(self.until_date),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1608,7 +1608,7 @@ class EditMessageText(BaseResponse, ParseModeMixin, DisableWebPagePreviewMixin):
|
|||
'text': self.text,
|
||||
'parse_mode': self.parse_mode,
|
||||
'disable_web_page_preview': self.disable_web_page_preview,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1649,7 +1649,7 @@ class EditMessageCaption(BaseResponse):
|
|||
'message_id': self.message_id,
|
||||
'inline_message_id': self.inline_message_id,
|
||||
'caption': self.caption,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1685,7 +1685,7 @@ class EditMessageReplyMarkup(BaseResponse):
|
|||
'chat_id': self.chat_id,
|
||||
'message_id': self.message_id,
|
||||
'inline_message_id': self.inline_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1756,7 +1756,7 @@ class SendSticker(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'sticker': self.sticker,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1848,7 +1848,7 @@ class AddStickerToSet(BaseResponse):
|
|||
'name': self.name,
|
||||
'png_sticker': self.png_sticker,
|
||||
'emojis': self.emojis,
|
||||
'mask_position': prepare_arg(self.mask_position)
|
||||
'mask_position': prepare_arg(self.mask_position),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2177,5 +2177,5 @@ class SendGame(BaseResponse, ReplyToMixin, DisableNotificationMixin):
|
|||
'game_short_name': self.game_short_name,
|
||||
'disable_notification': self.disable_notification,
|
||||
'reply_to_message_id': self.reply_to_message_id,
|
||||
'reply_markup': prepare_arg(self.reply_markup)
|
||||
'reply_markup': prepare_arg(self.reply_markup),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,60 +94,60 @@ class Message(base.TelegramObject):
|
|||
def content_type(self):
|
||||
if self.text:
|
||||
return ContentType.TEXT
|
||||
elif self.audio:
|
||||
if self.audio:
|
||||
return ContentType.AUDIO
|
||||
elif self.animation:
|
||||
if self.animation:
|
||||
return ContentType.ANIMATION
|
||||
elif self.document:
|
||||
if self.document:
|
||||
return ContentType.DOCUMENT
|
||||
elif self.game:
|
||||
if self.game:
|
||||
return ContentType.GAME
|
||||
elif self.photo:
|
||||
if self.photo:
|
||||
return ContentType.PHOTO
|
||||
elif self.sticker:
|
||||
if self.sticker:
|
||||
return ContentType.STICKER
|
||||
elif self.video:
|
||||
if self.video:
|
||||
return ContentType.VIDEO
|
||||
elif self.video_note:
|
||||
if self.video_note:
|
||||
return ContentType.VIDEO_NOTE
|
||||
elif self.voice:
|
||||
if self.voice:
|
||||
return ContentType.VOICE
|
||||
elif self.contact:
|
||||
if self.contact:
|
||||
return ContentType.CONTACT
|
||||
elif self.venue:
|
||||
if self.venue:
|
||||
return ContentType.VENUE
|
||||
elif self.location:
|
||||
if self.location:
|
||||
return ContentType.LOCATION
|
||||
elif self.new_chat_members:
|
||||
if self.new_chat_members:
|
||||
return ContentType.NEW_CHAT_MEMBERS
|
||||
elif self.left_chat_member:
|
||||
if self.left_chat_member:
|
||||
return ContentType.LEFT_CHAT_MEMBER
|
||||
elif self.invoice:
|
||||
if self.invoice:
|
||||
return ContentType.INVOICE
|
||||
elif self.successful_payment:
|
||||
if self.successful_payment:
|
||||
return ContentType.SUCCESSFUL_PAYMENT
|
||||
elif self.connected_website:
|
||||
if self.connected_website:
|
||||
return ContentType.CONNECTED_WEBSITE
|
||||
elif self.migrate_from_chat_id:
|
||||
if self.migrate_from_chat_id:
|
||||
return ContentType.MIGRATE_FROM_CHAT_ID
|
||||
elif self.migrate_to_chat_id:
|
||||
if self.migrate_to_chat_id:
|
||||
return ContentType.MIGRATE_TO_CHAT_ID
|
||||
elif self.pinned_message:
|
||||
if self.pinned_message:
|
||||
return ContentType.PINNED_MESSAGE
|
||||
elif self.new_chat_title:
|
||||
if self.new_chat_title:
|
||||
return ContentType.NEW_CHAT_TITLE
|
||||
elif self.new_chat_photo:
|
||||
if self.new_chat_photo:
|
||||
return ContentType.NEW_CHAT_PHOTO
|
||||
elif self.delete_chat_photo:
|
||||
if self.delete_chat_photo:
|
||||
return ContentType.DELETE_CHAT_PHOTO
|
||||
elif self.group_chat_created:
|
||||
if self.group_chat_created:
|
||||
return ContentType.GROUP_CHAT_CREATED
|
||||
elif self.passport_data:
|
||||
if self.passport_data:
|
||||
return ContentType.PASSPORT_DATA
|
||||
elif self.poll:
|
||||
if self.poll:
|
||||
return ContentType.POLL
|
||||
else:
|
||||
return ContentType.UNKNOWN
|
||||
|
||||
return ContentType.UNKNOWN
|
||||
|
||||
def is_command(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -49,30 +49,24 @@ class MessageEntity(base.TelegramObject):
|
|||
entity_text = self.get_text(text)
|
||||
|
||||
if self.type == MessageEntityType.BOLD:
|
||||
if as_html:
|
||||
return markdown.hbold(entity_text)
|
||||
return markdown.bold(entity_text)
|
||||
elif self.type == MessageEntityType.ITALIC:
|
||||
if as_html:
|
||||
return markdown.hitalic(entity_text)
|
||||
return markdown.italic(entity_text)
|
||||
elif self.type == MessageEntityType.PRE:
|
||||
if as_html:
|
||||
return markdown.hpre(entity_text)
|
||||
return markdown.pre(entity_text)
|
||||
elif self.type == MessageEntityType.CODE:
|
||||
if as_html:
|
||||
return markdown.hcode(entity_text)
|
||||
return markdown.code(entity_text)
|
||||
elif self.type == MessageEntityType.URL:
|
||||
if as_html:
|
||||
return markdown.hlink(entity_text, entity_text)
|
||||
return markdown.link(entity_text, entity_text)
|
||||
elif self.type == MessageEntityType.TEXT_LINK:
|
||||
if as_html:
|
||||
return markdown.hlink(entity_text, self.url)
|
||||
return markdown.link(entity_text, self.url)
|
||||
elif self.type == MessageEntityType.TEXT_MENTION and self.user:
|
||||
method = markdown.hbold if as_html else markdown.bold
|
||||
return method(entity_text)
|
||||
if self.type == MessageEntityType.ITALIC:
|
||||
method = markdown.hitalic if as_html else markdown.italic
|
||||
return method(entity_text)
|
||||
if self.type == MessageEntityType.PRE:
|
||||
method = markdown.hpre if as_html else markdown.pre
|
||||
return method(entity_text)
|
||||
if self.type == MessageEntityType.CODE:
|
||||
method = markdown.hcode if as_html else markdown.code
|
||||
return method(entity_text)
|
||||
if self.type == MessageEntityType.URL:
|
||||
method = markdown.hlink if as_html else markdown.link
|
||||
return method(entity_text, entity_text)
|
||||
if self.type == MessageEntityType.TEXT_LINK:
|
||||
method = markdown.hlink if as_html else markdown.link
|
||||
return method(entity_text, self.url)
|
||||
if self.type == MessageEntityType.TEXT_MENTION and self.user:
|
||||
return self.user.get_mention(entity_text)
|
||||
return entity_text
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import babel
|
||||
|
||||
from . import base
|
||||
|
|
@ -45,7 +47,7 @@ class User(base.TelegramObject):
|
|||
return self.full_name
|
||||
|
||||
@property
|
||||
def locale(self) -> babel.core.Locale or None:
|
||||
def locale(self) -> Optional[babel.core.Locale]:
|
||||
"""
|
||||
Get user's locale
|
||||
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ class CallbackData:
|
|||
|
||||
def __init__(self, prefix, *parts, sep=':'):
|
||||
if not isinstance(prefix, str):
|
||||
raise TypeError(f"Prefix must be instance of str not {type(prefix).__name__}")
|
||||
elif not prefix:
|
||||
raise ValueError('Prefix can\'t be empty')
|
||||
elif sep in prefix:
|
||||
raise ValueError(f"Separator '{sep}' can't be used in prefix")
|
||||
elif not parts:
|
||||
raise TypeError('Parts is not passed!')
|
||||
raise TypeError(f'Prefix must be instance of str not {type(prefix).__name__}')
|
||||
if not prefix:
|
||||
raise ValueError("Prefix can't be empty")
|
||||
if sep in prefix:
|
||||
raise ValueError(f"Separator {sep!r} can't be used in prefix")
|
||||
if not parts:
|
||||
raise TypeError('Parts were not passed!')
|
||||
|
||||
self.prefix = prefix
|
||||
self.sep = sep
|
||||
|
|
@ -59,20 +59,20 @@ class CallbackData:
|
|||
if args:
|
||||
value = args.pop(0)
|
||||
else:
|
||||
raise ValueError(f"Value for '{part}' is not passed!")
|
||||
raise ValueError(f'Value for {part!r} was not passed!')
|
||||
|
||||
if value is not None and not isinstance(value, str):
|
||||
value = str(value)
|
||||
|
||||
if not value:
|
||||
raise ValueError(f"Value for part {part} can't be empty!'")
|
||||
elif self.sep in value:
|
||||
raise ValueError(f"Symbol defined as separator can't be used in values of parts")
|
||||
raise ValueError(f"Value for part {part!r} can't be empty!'")
|
||||
if self.sep in value:
|
||||
raise ValueError(f"Symbol {self.sep!r} is defined as the separator and can't be used in parts' values")
|
||||
|
||||
data.append(value)
|
||||
|
||||
if args or kwargs:
|
||||
raise TypeError('Too many arguments is passed!')
|
||||
raise TypeError('Too many arguments were passed!')
|
||||
|
||||
callback_data = self.sep.join(data)
|
||||
if len(callback_data) > 64:
|
||||
|
|
@ -106,30 +106,31 @@ class CallbackData:
|
|||
"""
|
||||
for key in config.keys():
|
||||
if key not in self._part_names:
|
||||
raise ValueError(f"Invalid field name '{key}'")
|
||||
raise ValueError(f'Invalid field name {key!r}')
|
||||
return CallbackDataFilter(self, config)
|
||||
|
||||
|
||||
class CallbackDataFilter(Filter):
|
||||
|
||||
def __init__(self, factory: CallbackData, config: typing.Dict[str, str]):
|
||||
self.config = config
|
||||
self.factory = factory
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: typing.Dict[str, typing.Any]):
|
||||
raise ValueError('That filter can\'t be used in filters factory!')
|
||||
raise ValueError("That filter can't be used in filters factory!")
|
||||
|
||||
async def check(self, query: types.CallbackQuery):
|
||||
try:
|
||||
data = self.factory.parse(query.data)
|
||||
except ValueError:
|
||||
return False
|
||||
else:
|
||||
for key, value in self.config.items():
|
||||
if isinstance(value, (list, tuple, set)):
|
||||
if data.get(key) not in value:
|
||||
return False
|
||||
else:
|
||||
if value != data.get(key):
|
||||
return False
|
||||
return {'callback_data': data}
|
||||
|
||||
for key, value in self.config.items():
|
||||
if isinstance(value, (list, tuple, set, frozenset)):
|
||||
if data.get(key) not in value:
|
||||
return False
|
||||
else:
|
||||
if data.get(key) != value:
|
||||
return False
|
||||
return {'callback_data': data}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from ..dispatcher.webhook import BOT_DISPATCHER_KEY, DEFAULT_ROUTE_NAME, Webhook
|
|||
APP_EXECUTOR_KEY = 'APP_EXECUTOR'
|
||||
|
||||
|
||||
def _setup_callbacks(executor, on_startup=None, on_shutdown=None):
|
||||
def _setup_callbacks(executor: 'Executor', on_startup=None, on_shutdown=None):
|
||||
if on_startup is not None:
|
||||
executor.on_startup(on_startup)
|
||||
if on_shutdown is not None:
|
||||
|
|
@ -23,7 +23,7 @@ def _setup_callbacks(executor, on_startup=None, on_shutdown=None):
|
|||
|
||||
|
||||
def start_polling(dispatcher, *, loop=None, skip_updates=False, reset_webhook=True,
|
||||
on_startup=None, on_shutdown=None, timeout=20, fast=True):
|
||||
on_startup=None, on_shutdown=None, timeout=20, relax=0.1, fast=True):
|
||||
"""
|
||||
Start bot in long-polling mode
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ def start_polling(dispatcher, *, loop=None, skip_updates=False, reset_webhook=Tr
|
|||
executor = Executor(dispatcher, skip_updates=skip_updates, loop=loop)
|
||||
_setup_callbacks(executor, on_startup, on_shutdown)
|
||||
|
||||
executor.start_polling(reset_webhook=reset_webhook, timeout=timeout, fast=fast)
|
||||
executor.start_polling(reset_webhook=reset_webhook, timeout=timeout, relax=relax, fast=fast)
|
||||
|
||||
|
||||
def set_webhook(dispatcher: Dispatcher, webhook_path: str, *, loop: Optional[asyncio.AbstractEventLoop] = None,
|
||||
|
|
@ -291,7 +291,7 @@ class Executor:
|
|||
self.set_webhook(webhook_path=webhook_path, request_handler=request_handler, route_name=route_name)
|
||||
self.run_app(**kwargs)
|
||||
|
||||
def start_polling(self, reset_webhook=None, timeout=20, fast=True):
|
||||
def start_polling(self, reset_webhook=None, timeout=20, relax=0.1, fast=True):
|
||||
"""
|
||||
Start bot in long-polling mode
|
||||
|
||||
|
|
@ -303,7 +303,8 @@ class Executor:
|
|||
|
||||
try:
|
||||
loop.run_until_complete(self._startup_polling())
|
||||
loop.create_task(self.dispatcher.start_polling(reset_webhook=reset_webhook, timeout=timeout, fast=fast))
|
||||
loop.create_task(self.dispatcher.start_polling(reset_webhook=reset_webhook, timeout=timeout,
|
||||
relax=relax, fast=fast))
|
||||
loop.run_forever()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
# loop.stop()
|
||||
|
|
@ -339,7 +340,7 @@ class Executor:
|
|||
async def _skip_updates(self):
|
||||
await self.dispatcher.reset_webhook(True)
|
||||
await self.dispatcher.skip_updates()
|
||||
log.warning(f"Updates are skipped successfully.")
|
||||
log.warning(f'Updates were skipped successfully.')
|
||||
|
||||
async def _welcome(self):
|
||||
user = await self.dispatcher.bot.me
|
||||
|
|
|
|||
|
|
@ -120,15 +120,15 @@ class HelperMode(Helper):
|
|||
"""
|
||||
if mode == cls.SCREAMING_SNAKE_CASE:
|
||||
return cls._screaming_snake_case(text)
|
||||
elif mode == cls.snake_case:
|
||||
if mode == cls.snake_case:
|
||||
return cls._snake_case(text)
|
||||
elif mode == cls.lowercase:
|
||||
if mode == cls.lowercase:
|
||||
return cls._snake_case(text).replace('_', '')
|
||||
elif mode == cls.lowerCamelCase:
|
||||
if mode == cls.lowerCamelCase:
|
||||
return cls._camel_case(text)
|
||||
elif mode == cls.CamelCase:
|
||||
if mode == cls.CamelCase:
|
||||
return cls._camel_case(text, True)
|
||||
elif callable(mode):
|
||||
if callable(mode):
|
||||
return mode(text)
|
||||
return text
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ T = TypeVar('T')
|
|||
|
||||
class ContextInstanceMixin:
|
||||
def __init_subclass__(cls, **kwargs):
|
||||
cls.__context_instance = contextvars.ContextVar('instance_' + cls.__name__)
|
||||
cls.__context_instance = contextvars.ContextVar(f'instance_{cls.__name__}')
|
||||
return cls
|
||||
|
||||
@classmethod
|
||||
|
|
@ -43,5 +43,5 @@ class ContextInstanceMixin:
|
|||
@classmethod
|
||||
def set_current(cls: Type[T], value: T):
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -52,14 +52,14 @@ def prepare_arg(value):
|
|||
"""
|
||||
if value is None:
|
||||
return value
|
||||
elif isinstance(value, (list, dict)) or hasattr(value, 'to_python'):
|
||||
if isinstance(value, (list, dict)) or hasattr(value, 'to_python'):
|
||||
return json.dumps(_normalize(value))
|
||||
elif isinstance(value, datetime.timedelta):
|
||||
if isinstance(value, datetime.timedelta):
|
||||
now = datetime.datetime.now()
|
||||
return int((now + value).timestamp())
|
||||
elif isinstance(value, datetime.datetime):
|
||||
if isinstance(value, datetime.datetime):
|
||||
return round(value.timestamp())
|
||||
elif isinstance(value, LazyProxy):
|
||||
if isinstance(value, LazyProxy):
|
||||
return str(value)
|
||||
return value
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue