mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2025-01-03 17:52:31 +01:00
Refactor Handling of Message VS Update Filters (#2032)
* Refactor handling of message vs update filters * address review
This commit is contained in:
parent
7daddfb54d
commit
3842846b2d
6 changed files with 163 additions and 117 deletions
|
@ -29,7 +29,7 @@ from .updater import Updater
|
|||
from .callbackqueryhandler import CallbackQueryHandler
|
||||
from .choseninlineresulthandler import ChosenInlineResultHandler
|
||||
from .inlinequeryhandler import InlineQueryHandler
|
||||
from .filters import BaseFilter, Filters
|
||||
from .filters import BaseFilter, MessageFilter, UpdateFilter, Filters
|
||||
from .messagehandler import MessageHandler
|
||||
from .commandhandler import CommandHandler, PrefixHandler
|
||||
from .regexhandler import RegexHandler
|
||||
|
@ -47,9 +47,9 @@ from .defaults import Defaults
|
|||
|
||||
__all__ = ('Dispatcher', 'JobQueue', 'Job', 'Updater', 'CallbackQueryHandler',
|
||||
'ChosenInlineResultHandler', 'CommandHandler', 'Handler', 'InlineQueryHandler',
|
||||
'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler',
|
||||
'StringRegexHandler', 'TypeHandler', 'ConversationHandler',
|
||||
'PreCheckoutQueryHandler', 'ShippingQueryHandler', 'MessageQueue', 'DelayQueue',
|
||||
'DispatcherHandlerStop', 'run_async', 'CallbackContext', 'BasePersistence',
|
||||
'PicklePersistence', 'DictPersistence', 'PrefixHandler', 'PollAnswerHandler',
|
||||
'PollHandler', 'Defaults')
|
||||
'MessageHandler', 'BaseFilter', 'MessageFilter', 'UpdateFilter', 'Filters',
|
||||
'RegexHandler', 'StringCommandHandler', 'StringRegexHandler', 'TypeHandler',
|
||||
'ConversationHandler', 'PreCheckoutQueryHandler', 'ShippingQueryHandler',
|
||||
'MessageQueue', 'DelayQueue', 'DispatcherHandlerStop', 'run_async', 'CallbackContext',
|
||||
'BasePersistence', 'PicklePersistence', 'DictPersistence', 'PrefixHandler',
|
||||
'PollAnswerHandler', 'PollHandler', 'Defaults')
|
||||
|
|
|
@ -25,13 +25,14 @@ from threading import Lock
|
|||
|
||||
from telegram import Chat, Update, MessageEntity
|
||||
|
||||
__all__ = ['Filters', 'BaseFilter', 'InvertedFilter', 'MergedFilter']
|
||||
__all__ = ['Filters', 'BaseFilter', 'MessageFilter', 'UpdateFilter', 'InvertedFilter',
|
||||
'MergedFilter']
|
||||
|
||||
|
||||
class BaseFilter(ABC):
|
||||
"""Base class for all Message Filters.
|
||||
"""Base class for all Filters.
|
||||
|
||||
Subclassing from this class filters to be combined using bitwise operators:
|
||||
Filters subclassing from this class can combined using bitwise operators:
|
||||
|
||||
And:
|
||||
|
||||
|
@ -56,14 +57,17 @@ class BaseFilter(ABC):
|
|||
|
||||
>>> Filters.regex(r'(a?x)') | Filters.regex(r'(b?x)')
|
||||
|
||||
With a message.text of `x`, will only ever return the matches for the first filter,
|
||||
With ``message.text == x``, will only ever return the matches for the first filter,
|
||||
since the second one is never evaluated.
|
||||
|
||||
|
||||
If you want to create your own filters create a class inheriting from this class and implement
|
||||
a :meth:`filter` method that returns a boolean: :obj:`True` if the message should be
|
||||
handled, :obj:`False` otherwise. Note that the filters work only as class instances, not
|
||||
actual class objects (so remember to initialize your filter classes).
|
||||
If you want to create your own filters create a class inheriting from either
|
||||
:class:`MessageFilter` or :class:`UpdateFilter` and implement a :meth:``filter`` method that
|
||||
returns a boolean: :obj:`True` if the message should be
|
||||
handled, :obj:`False` otherwise.
|
||||
Note that the filters work only as class instances, not
|
||||
actual class objects (so remember to
|
||||
initialize your filter classes).
|
||||
|
||||
By default the filters name (what will get printed when converted to a string for display)
|
||||
will be the class name. If you want to overwrite this assign a better name to the :attr:`name`
|
||||
|
@ -71,8 +75,6 @@ class BaseFilter(ABC):
|
|||
|
||||
Attributes:
|
||||
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
|
||||
update_filter (:obj:`bool`): Whether this filter should work on update. If :obj:`False` it
|
||||
will run the filter on :attr:`update.effective_message`. Default is :obj:`False`.
|
||||
data_filter (:obj:`bool`): Whether this filter is a data filter. A data filter should
|
||||
return a dict with lists. The dict will be merged with
|
||||
:class:`telegram.ext.CallbackContext`'s internal dict in most cases
|
||||
|
@ -80,14 +82,11 @@ class BaseFilter(ABC):
|
|||
"""
|
||||
|
||||
name = None
|
||||
update_filter = False
|
||||
data_filter = False
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, update):
|
||||
if self.update_filter:
|
||||
return self.filter(update)
|
||||
else:
|
||||
return self.filter(update.effective_message)
|
||||
pass
|
||||
|
||||
def __and__(self, other):
|
||||
return MergedFilter(self, and_filter=other)
|
||||
|
@ -104,14 +103,59 @@ class BaseFilter(ABC):
|
|||
self.name = self.__class__.__name__
|
||||
return self.name
|
||||
|
||||
|
||||
class MessageFilter(BaseFilter, ABC):
|
||||
"""Base class for all Message Filters. In contrast to :class:`UpdateFilter`, the object passed
|
||||
to :meth:`filter` is ``update.effective_message``.
|
||||
|
||||
Please see :class:`telegram.ext.BaseFilter` for details on how to create custom filters.
|
||||
|
||||
Attributes:
|
||||
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
|
||||
data_filter (:obj:`bool`): Whether this filter is a data filter. A data filter should
|
||||
return a dict with lists. The dict will be merged with
|
||||
:class:`telegram.ext.CallbackContext`'s internal dict in most cases
|
||||
(depends on the handler).
|
||||
|
||||
"""
|
||||
def __call__(self, update):
|
||||
return self.filter(update.effective_message)
|
||||
|
||||
@abstractmethod
|
||||
def filter(self, message):
|
||||
"""This method must be overwritten.
|
||||
|
||||
Args:
|
||||
message (:class:`telegram.Message`): The message that is tested.
|
||||
|
||||
Returns:
|
||||
:obj:`dict` or :obj:`bool`
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class UpdateFilter(BaseFilter, ABC):
|
||||
"""Base class for all Update Filters. In contrast to :class:`UpdateFilter`, the object
|
||||
passed to :meth:`filter` is ``update``, which allows to create filters like
|
||||
:attr:`Filters.update.edited_message`.
|
||||
|
||||
Please see :class:`telegram.ext.BaseFilter` for details on how to create custom filters.
|
||||
|
||||
Attributes:
|
||||
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
|
||||
data_filter (:obj:`bool`): Whether this filter is a data filter. A data filter should
|
||||
return a dict with lists. The dict will be merged with
|
||||
:class:`telegram.ext.CallbackContext`'s internal dict in most cases
|
||||
(depends on the handler).
|
||||
|
||||
"""
|
||||
def __call__(self, update):
|
||||
return self.filter(update)
|
||||
|
||||
@abstractmethod
|
||||
def filter(self, update):
|
||||
"""This method must be overwritten.
|
||||
|
||||
Note:
|
||||
If :attr:`update_filter` is :obj:`False` then the first argument is `message` and of
|
||||
type :class:`telegram.Message`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): The update that is tested.
|
||||
|
||||
|
@ -121,15 +165,13 @@ class BaseFilter(ABC):
|
|||
"""
|
||||
|
||||
|
||||
class InvertedFilter(BaseFilter):
|
||||
class InvertedFilter(UpdateFilter):
|
||||
"""Represents a filter that has been inverted.
|
||||
|
||||
Args:
|
||||
f: The filter to invert.
|
||||
|
||||
"""
|
||||
update_filter = True
|
||||
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
|
||||
|
@ -140,7 +182,7 @@ class InvertedFilter(BaseFilter):
|
|||
return "<inverted {}>".format(self.f)
|
||||
|
||||
|
||||
class MergedFilter(BaseFilter):
|
||||
class MergedFilter(UpdateFilter):
|
||||
"""Represents a filter consisting of two other filters.
|
||||
|
||||
Args:
|
||||
|
@ -149,8 +191,6 @@ class MergedFilter(BaseFilter):
|
|||
or_filter: Optional filter to "or" with base_filter. Mutually exclusive with and_filter.
|
||||
|
||||
"""
|
||||
update_filter = True
|
||||
|
||||
def __init__(self, base_filter, and_filter=None, or_filter=None):
|
||||
self.base_filter = base_filter
|
||||
if self.base_filter.data_filter:
|
||||
|
@ -215,13 +255,13 @@ class MergedFilter(BaseFilter):
|
|||
self.and_filter or self.or_filter)
|
||||
|
||||
|
||||
class _DiceEmoji(BaseFilter):
|
||||
class _DiceEmoji(MessageFilter):
|
||||
|
||||
def __init__(self, emoji=None, name=None):
|
||||
self.name = 'Filters.dice.{}'.format(name) if name else 'Filters.dice'
|
||||
self.emoji = emoji
|
||||
|
||||
class _DiceValues(BaseFilter):
|
||||
class _DiceValues(MessageFilter):
|
||||
|
||||
def __init__(self, values, name, emoji=None):
|
||||
self.values = [values] if isinstance(values, int) else values
|
||||
|
@ -248,7 +288,8 @@ class _DiceEmoji(BaseFilter):
|
|||
|
||||
|
||||
class Filters:
|
||||
"""Predefined filters for use as the `filter` argument of :class:`telegram.ext.MessageHandler`.
|
||||
"""Predefined filters for use as the ``filter`` argument of
|
||||
:class:`telegram.ext.MessageHandler`.
|
||||
|
||||
Examples:
|
||||
Use ``MessageHandler(Filters.video, callback_method)`` to filter all video
|
||||
|
@ -256,7 +297,7 @@ class Filters:
|
|||
|
||||
"""
|
||||
|
||||
class _All(BaseFilter):
|
||||
class _All(MessageFilter):
|
||||
name = 'Filters.all'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -265,10 +306,10 @@ class Filters:
|
|||
all = _All()
|
||||
"""All Messages."""
|
||||
|
||||
class _Text(BaseFilter):
|
||||
class _Text(MessageFilter):
|
||||
name = 'Filters.text'
|
||||
|
||||
class _TextStrings(BaseFilter):
|
||||
class _TextStrings(MessageFilter):
|
||||
|
||||
def __init__(self, strings):
|
||||
self.strings = strings
|
||||
|
@ -316,10 +357,10 @@ class Filters:
|
|||
exact matches are allowed. If not specified, will allow any text message.
|
||||
"""
|
||||
|
||||
class _Caption(BaseFilter):
|
||||
class _Caption(MessageFilter):
|
||||
name = 'Filters.caption'
|
||||
|
||||
class _CaptionStrings(BaseFilter):
|
||||
class _CaptionStrings(MessageFilter):
|
||||
|
||||
def __init__(self, strings):
|
||||
self.strings = strings
|
||||
|
@ -351,10 +392,10 @@ class Filters:
|
|||
exact matches are allowed. If not specified, will allow any message with a caption.
|
||||
"""
|
||||
|
||||
class _Command(BaseFilter):
|
||||
class _Command(MessageFilter):
|
||||
name = 'Filters.command'
|
||||
|
||||
class _CommandOnlyStart(BaseFilter):
|
||||
class _CommandOnlyStart(MessageFilter):
|
||||
|
||||
def __init__(self, only_start):
|
||||
self.only_start = only_start
|
||||
|
@ -393,7 +434,7 @@ class Filters:
|
|||
command. Defaults to :obj:`True`.
|
||||
"""
|
||||
|
||||
class regex(BaseFilter):
|
||||
class regex(MessageFilter):
|
||||
"""
|
||||
Filters updates by searching for an occurrence of ``pattern`` in the message text.
|
||||
The ``re.search()`` function is used to determine whether an update should be filtered.
|
||||
|
@ -438,7 +479,7 @@ class Filters:
|
|||
return {'matches': [match]}
|
||||
return {}
|
||||
|
||||
class _Reply(BaseFilter):
|
||||
class _Reply(MessageFilter):
|
||||
name = 'Filters.reply'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -447,7 +488,7 @@ class Filters:
|
|||
reply = _Reply()
|
||||
"""Messages that are a reply to another message."""
|
||||
|
||||
class _Audio(BaseFilter):
|
||||
class _Audio(MessageFilter):
|
||||
name = 'Filters.audio'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -456,10 +497,10 @@ class Filters:
|
|||
audio = _Audio()
|
||||
"""Messages that contain :class:`telegram.Audio`."""
|
||||
|
||||
class _Document(BaseFilter):
|
||||
class _Document(MessageFilter):
|
||||
name = 'Filters.document'
|
||||
|
||||
class category(BaseFilter):
|
||||
class category(MessageFilter):
|
||||
"""Filters documents by their category in the mime-type attribute.
|
||||
|
||||
Note:
|
||||
|
@ -492,7 +533,7 @@ class Filters:
|
|||
video = category('video/')
|
||||
text = category('text/')
|
||||
|
||||
class mime_type(BaseFilter):
|
||||
class mime_type(MessageFilter):
|
||||
"""This Filter filters documents by their mime-type attribute
|
||||
|
||||
Note:
|
||||
|
@ -592,7 +633,7 @@ officedocument.wordprocessingml.document")``-
|
|||
zip: Same as ``Filters.document.mime_type("application/zip")``-
|
||||
"""
|
||||
|
||||
class _Animation(BaseFilter):
|
||||
class _Animation(MessageFilter):
|
||||
name = 'Filters.animation'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -601,7 +642,7 @@ officedocument.wordprocessingml.document")``-
|
|||
animation = _Animation()
|
||||
"""Messages that contain :class:`telegram.Animation`."""
|
||||
|
||||
class _Photo(BaseFilter):
|
||||
class _Photo(MessageFilter):
|
||||
name = 'Filters.photo'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -610,7 +651,7 @@ officedocument.wordprocessingml.document")``-
|
|||
photo = _Photo()
|
||||
"""Messages that contain :class:`telegram.PhotoSize`."""
|
||||
|
||||
class _Sticker(BaseFilter):
|
||||
class _Sticker(MessageFilter):
|
||||
name = 'Filters.sticker'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -619,7 +660,7 @@ officedocument.wordprocessingml.document")``-
|
|||
sticker = _Sticker()
|
||||
"""Messages that contain :class:`telegram.Sticker`."""
|
||||
|
||||
class _Video(BaseFilter):
|
||||
class _Video(MessageFilter):
|
||||
name = 'Filters.video'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -628,7 +669,7 @@ officedocument.wordprocessingml.document")``-
|
|||
video = _Video()
|
||||
"""Messages that contain :class:`telegram.Video`."""
|
||||
|
||||
class _Voice(BaseFilter):
|
||||
class _Voice(MessageFilter):
|
||||
name = 'Filters.voice'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -637,7 +678,7 @@ officedocument.wordprocessingml.document")``-
|
|||
voice = _Voice()
|
||||
"""Messages that contain :class:`telegram.Voice`."""
|
||||
|
||||
class _VideoNote(BaseFilter):
|
||||
class _VideoNote(MessageFilter):
|
||||
name = 'Filters.video_note'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -646,7 +687,7 @@ officedocument.wordprocessingml.document")``-
|
|||
video_note = _VideoNote()
|
||||
"""Messages that contain :class:`telegram.VideoNote`."""
|
||||
|
||||
class _Contact(BaseFilter):
|
||||
class _Contact(MessageFilter):
|
||||
name = 'Filters.contact'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -655,7 +696,7 @@ officedocument.wordprocessingml.document")``-
|
|||
contact = _Contact()
|
||||
"""Messages that contain :class:`telegram.Contact`."""
|
||||
|
||||
class _Location(BaseFilter):
|
||||
class _Location(MessageFilter):
|
||||
name = 'Filters.location'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -664,7 +705,7 @@ officedocument.wordprocessingml.document")``-
|
|||
location = _Location()
|
||||
"""Messages that contain :class:`telegram.Location`."""
|
||||
|
||||
class _Venue(BaseFilter):
|
||||
class _Venue(MessageFilter):
|
||||
name = 'Filters.venue'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -673,7 +714,7 @@ officedocument.wordprocessingml.document")``-
|
|||
venue = _Venue()
|
||||
"""Messages that contain :class:`telegram.Venue`."""
|
||||
|
||||
class _StatusUpdate(BaseFilter):
|
||||
class _StatusUpdate(UpdateFilter):
|
||||
"""Subset for messages containing a status update.
|
||||
|
||||
Examples:
|
||||
|
@ -681,9 +722,7 @@ officedocument.wordprocessingml.document")``-
|
|||
``Filters.status_update`` for all status update messages.
|
||||
|
||||
"""
|
||||
update_filter = True
|
||||
|
||||
class _NewChatMembers(BaseFilter):
|
||||
class _NewChatMembers(MessageFilter):
|
||||
name = 'Filters.status_update.new_chat_members'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -692,7 +731,7 @@ officedocument.wordprocessingml.document")``-
|
|||
new_chat_members = _NewChatMembers()
|
||||
"""Messages that contain :attr:`telegram.Message.new_chat_members`."""
|
||||
|
||||
class _LeftChatMember(BaseFilter):
|
||||
class _LeftChatMember(MessageFilter):
|
||||
name = 'Filters.status_update.left_chat_member'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -701,7 +740,7 @@ officedocument.wordprocessingml.document")``-
|
|||
left_chat_member = _LeftChatMember()
|
||||
"""Messages that contain :attr:`telegram.Message.left_chat_member`."""
|
||||
|
||||
class _NewChatTitle(BaseFilter):
|
||||
class _NewChatTitle(MessageFilter):
|
||||
name = 'Filters.status_update.new_chat_title'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -710,7 +749,7 @@ officedocument.wordprocessingml.document")``-
|
|||
new_chat_title = _NewChatTitle()
|
||||
"""Messages that contain :attr:`telegram.Message.new_chat_title`."""
|
||||
|
||||
class _NewChatPhoto(BaseFilter):
|
||||
class _NewChatPhoto(MessageFilter):
|
||||
name = 'Filters.status_update.new_chat_photo'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -719,7 +758,7 @@ officedocument.wordprocessingml.document")``-
|
|||
new_chat_photo = _NewChatPhoto()
|
||||
"""Messages that contain :attr:`telegram.Message.new_chat_photo`."""
|
||||
|
||||
class _DeleteChatPhoto(BaseFilter):
|
||||
class _DeleteChatPhoto(MessageFilter):
|
||||
name = 'Filters.status_update.delete_chat_photo'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -728,7 +767,7 @@ officedocument.wordprocessingml.document")``-
|
|||
delete_chat_photo = _DeleteChatPhoto()
|
||||
"""Messages that contain :attr:`telegram.Message.delete_chat_photo`."""
|
||||
|
||||
class _ChatCreated(BaseFilter):
|
||||
class _ChatCreated(MessageFilter):
|
||||
name = 'Filters.status_update.chat_created'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -740,7 +779,7 @@ officedocument.wordprocessingml.document")``-
|
|||
:attr: `telegram.Message.supergroup_chat_created` or
|
||||
:attr: `telegram.Message.channel_chat_created`."""
|
||||
|
||||
class _Migrate(BaseFilter):
|
||||
class _Migrate(MessageFilter):
|
||||
name = 'Filters.status_update.migrate'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -750,7 +789,7 @@ officedocument.wordprocessingml.document")``-
|
|||
"""Messages that contain :attr:`telegram.Message.migrate_from_chat_id` or
|
||||
:attr:`telegram.Message.migrate_to_chat_id`."""
|
||||
|
||||
class _PinnedMessage(BaseFilter):
|
||||
class _PinnedMessage(MessageFilter):
|
||||
name = 'Filters.status_update.pinned_message'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -759,7 +798,7 @@ officedocument.wordprocessingml.document")``-
|
|||
pinned_message = _PinnedMessage()
|
||||
"""Messages that contain :attr:`telegram.Message.pinned_message`."""
|
||||
|
||||
class _ConnectedWebsite(BaseFilter):
|
||||
class _ConnectedWebsite(MessageFilter):
|
||||
name = 'Filters.status_update.connected_website'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -806,7 +845,7 @@ officedocument.wordprocessingml.document")``-
|
|||
:attr:`telegram.Message.pinned_message`.
|
||||
"""
|
||||
|
||||
class _Forwarded(BaseFilter):
|
||||
class _Forwarded(MessageFilter):
|
||||
name = 'Filters.forwarded'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -815,7 +854,7 @@ officedocument.wordprocessingml.document")``-
|
|||
forwarded = _Forwarded()
|
||||
"""Messages that are forwarded."""
|
||||
|
||||
class _Game(BaseFilter):
|
||||
class _Game(MessageFilter):
|
||||
name = 'Filters.game'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -824,7 +863,7 @@ officedocument.wordprocessingml.document")``-
|
|||
game = _Game()
|
||||
"""Messages that contain :class:`telegram.Game`."""
|
||||
|
||||
class entity(BaseFilter):
|
||||
class entity(MessageFilter):
|
||||
"""
|
||||
Filters messages to only allow those which have a :class:`telegram.MessageEntity`
|
||||
where their `type` matches `entity_type`.
|
||||
|
@ -846,7 +885,7 @@ officedocument.wordprocessingml.document")``-
|
|||
"""""" # remove method from docs
|
||||
return any(entity.type == self.entity_type for entity in message.entities)
|
||||
|
||||
class caption_entity(BaseFilter):
|
||||
class caption_entity(MessageFilter):
|
||||
"""
|
||||
Filters media messages to only allow those which have a :class:`telegram.MessageEntity`
|
||||
where their `type` matches `entity_type`.
|
||||
|
@ -868,7 +907,7 @@ officedocument.wordprocessingml.document")``-
|
|||
"""""" # remove method from docs
|
||||
return any(entity.type == self.entity_type for entity in message.caption_entities)
|
||||
|
||||
class _Private(BaseFilter):
|
||||
class _Private(MessageFilter):
|
||||
name = 'Filters.private'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -877,7 +916,7 @@ officedocument.wordprocessingml.document")``-
|
|||
private = _Private()
|
||||
"""Messages sent in a private chat."""
|
||||
|
||||
class _Group(BaseFilter):
|
||||
class _Group(MessageFilter):
|
||||
name = 'Filters.group'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -886,7 +925,7 @@ officedocument.wordprocessingml.document")``-
|
|||
group = _Group()
|
||||
"""Messages sent in a group chat."""
|
||||
|
||||
class user(BaseFilter):
|
||||
class user(MessageFilter):
|
||||
"""Filters messages to allow only those which are from specified user ID(s) or
|
||||
username(s).
|
||||
|
||||
|
@ -1053,7 +1092,7 @@ officedocument.wordprocessingml.document")``-
|
|||
return self.allow_empty
|
||||
return False
|
||||
|
||||
class via_bot(BaseFilter):
|
||||
class via_bot(MessageFilter):
|
||||
"""Filters messages to allow only those which are from specified via_bot ID(s) or
|
||||
username(s).
|
||||
|
||||
|
@ -1220,7 +1259,7 @@ officedocument.wordprocessingml.document")``-
|
|||
return self.allow_empty
|
||||
return False
|
||||
|
||||
class chat(BaseFilter):
|
||||
class chat(MessageFilter):
|
||||
"""Filters messages to allow only those which are from a specified chat ID or username.
|
||||
|
||||
Examples:
|
||||
|
@ -1387,7 +1426,7 @@ officedocument.wordprocessingml.document")``-
|
|||
return self.allow_empty
|
||||
return False
|
||||
|
||||
class _Invoice(BaseFilter):
|
||||
class _Invoice(MessageFilter):
|
||||
name = 'Filters.invoice'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -1396,7 +1435,7 @@ officedocument.wordprocessingml.document")``-
|
|||
invoice = _Invoice()
|
||||
"""Messages that contain :class:`telegram.Invoice`."""
|
||||
|
||||
class _SuccessfulPayment(BaseFilter):
|
||||
class _SuccessfulPayment(MessageFilter):
|
||||
name = 'Filters.successful_payment'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -1405,7 +1444,7 @@ officedocument.wordprocessingml.document")``-
|
|||
successful_payment = _SuccessfulPayment()
|
||||
"""Messages that confirm a :class:`telegram.SuccessfulPayment`."""
|
||||
|
||||
class _PassportData(BaseFilter):
|
||||
class _PassportData(MessageFilter):
|
||||
name = 'Filters.passport_data'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -1414,7 +1453,7 @@ officedocument.wordprocessingml.document")``-
|
|||
passport_data = _PassportData()
|
||||
"""Messages that contain a :class:`telegram.PassportData`"""
|
||||
|
||||
class _Poll(BaseFilter):
|
||||
class _Poll(MessageFilter):
|
||||
name = 'Filters.poll'
|
||||
|
||||
def filter(self, message):
|
||||
|
@ -1457,7 +1496,7 @@ officedocument.wordprocessingml.document")``-
|
|||
as for :attr:`Filters.dice`.
|
||||
"""
|
||||
|
||||
class language(BaseFilter):
|
||||
class language(MessageFilter):
|
||||
"""Filters messages to only allow those which are from users with a certain language code.
|
||||
|
||||
Note:
|
||||
|
@ -1486,48 +1525,42 @@ officedocument.wordprocessingml.document")``-
|
|||
return message.from_user.language_code and any(
|
||||
[message.from_user.language_code.startswith(x) for x in self.lang])
|
||||
|
||||
class _UpdateType(BaseFilter):
|
||||
update_filter = True
|
||||
class _UpdateType(UpdateFilter):
|
||||
name = 'Filters.update'
|
||||
|
||||
class _Message(BaseFilter):
|
||||
class _Message(UpdateFilter):
|
||||
name = 'Filters.update.message'
|
||||
update_filter = True
|
||||
|
||||
def filter(self, update):
|
||||
return update.message is not None
|
||||
|
||||
message = _Message()
|
||||
|
||||
class _EditedMessage(BaseFilter):
|
||||
class _EditedMessage(UpdateFilter):
|
||||
name = 'Filters.update.edited_message'
|
||||
update_filter = True
|
||||
|
||||
def filter(self, update):
|
||||
return update.edited_message is not None
|
||||
|
||||
edited_message = _EditedMessage()
|
||||
|
||||
class _Messages(BaseFilter):
|
||||
class _Messages(UpdateFilter):
|
||||
name = 'Filters.update.messages'
|
||||
update_filter = True
|
||||
|
||||
def filter(self, update):
|
||||
return update.message is not None or update.edited_message is not None
|
||||
|
||||
messages = _Messages()
|
||||
|
||||
class _ChannelPost(BaseFilter):
|
||||
class _ChannelPost(UpdateFilter):
|
||||
name = 'Filters.update.channel_post'
|
||||
update_filter = True
|
||||
|
||||
def filter(self, update):
|
||||
return update.channel_post is not None
|
||||
|
||||
channel_post = _ChannelPost()
|
||||
|
||||
class _EditedChannelPost(BaseFilter):
|
||||
update_filter = True
|
||||
class _EditedChannelPost(UpdateFilter):
|
||||
name = 'Filters.update.edited_channel_post'
|
||||
|
||||
def filter(self, update):
|
||||
|
@ -1535,8 +1568,7 @@ officedocument.wordprocessingml.document")``-
|
|||
|
||||
edited_channel_post = _EditedChannelPost()
|
||||
|
||||
class _ChannelPosts(BaseFilter):
|
||||
update_filter = True
|
||||
class _ChannelPosts(UpdateFilter):
|
||||
name = 'Filters.update.channel_posts'
|
||||
|
||||
def filter(self, update):
|
||||
|
|
|
@ -25,7 +25,7 @@ class Venue(TelegramObject):
|
|||
"""This object represents a venue.
|
||||
|
||||
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||
considered equal, if their :attr:`location` and :attr:`title`are equal.
|
||||
considered equal, if their :attr:`location` and :attr:`title` are equal.
|
||||
|
||||
Attributes:
|
||||
location (:class:`telegram.Location`): Venue location.
|
||||
|
|
|
@ -30,7 +30,7 @@ import pytz
|
|||
from telegram import (Bot, Message, User, Chat, MessageEntity, Update,
|
||||
InlineQuery, CallbackQuery, ShippingQuery, PreCheckoutQuery,
|
||||
ChosenInlineResult)
|
||||
from telegram.ext import Dispatcher, JobQueue, Updater, BaseFilter, Defaults
|
||||
from telegram.ext import Dispatcher, JobQueue, Updater, MessageFilter, Defaults, UpdateFilter
|
||||
from telegram.error import BadRequest
|
||||
from tests.bots import get_bot
|
||||
|
||||
|
@ -239,13 +239,18 @@ def make_command_update(message, edited=False, **kwargs):
|
|||
return make_message_update(message, make_command_message, edited, **kwargs)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_filter():
|
||||
class MockFilter(BaseFilter):
|
||||
@pytest.fixture(scope='class',
|
||||
params=[
|
||||
{'class': MessageFilter},
|
||||
{'class': UpdateFilter}
|
||||
],
|
||||
ids=['MessageFilter', 'UpdateFilter'])
|
||||
def mock_filter(request):
|
||||
class MockFilter(request.param['class']):
|
||||
def __init__(self):
|
||||
self.tested = False
|
||||
|
||||
def filter(self, message):
|
||||
def filter(self, _):
|
||||
self.tested = True
|
||||
|
||||
return MockFilter()
|
||||
|
|
|
@ -21,7 +21,7 @@ import datetime
|
|||
import pytest
|
||||
|
||||
from telegram import Message, User, Chat, MessageEntity, Document, Update, Dice
|
||||
from telegram.ext import Filters, BaseFilter
|
||||
from telegram.ext import Filters, BaseFilter, MessageFilter, UpdateFilter
|
||||
import re
|
||||
|
||||
|
||||
|
@ -37,6 +37,16 @@ def message_entity(request):
|
|||
return MessageEntity(request.param, 0, 0, url='', user='')
|
||||
|
||||
|
||||
@pytest.fixture(scope='class',
|
||||
params=[
|
||||
{'class': MessageFilter},
|
||||
{'class': UpdateFilter}
|
||||
],
|
||||
ids=['MessageFilter', 'UpdateFilter'])
|
||||
def base_class(request):
|
||||
return request.param['class']
|
||||
|
||||
|
||||
class TestFilters:
|
||||
def test_filters_all(self, update):
|
||||
assert Filters.all(update)
|
||||
|
@ -962,8 +972,8 @@ class TestFilters:
|
|||
with pytest.raises(TypeError, match='Can\'t instantiate abstract class _CustomFilter'):
|
||||
_CustomFilter()
|
||||
|
||||
def test_custom_unnamed_filter(self, update):
|
||||
class Unnamed(BaseFilter):
|
||||
def test_custom_unnamed_filter(self, update, base_class):
|
||||
class Unnamed(base_class):
|
||||
def filter(self, mes):
|
||||
return True
|
||||
|
||||
|
@ -1009,14 +1019,14 @@ class TestFilters:
|
|||
assert Filters.update.channel_posts(update)
|
||||
assert Filters.update(update)
|
||||
|
||||
def test_merged_short_circuit_and(self, update):
|
||||
def test_merged_short_circuit_and(self, update, base_class):
|
||||
update.message.text = '/test'
|
||||
update.message.entities = [MessageEntity(MessageEntity.BOT_COMMAND, 0, 5)]
|
||||
|
||||
class TestException(Exception):
|
||||
pass
|
||||
|
||||
class RaisingFilter(BaseFilter):
|
||||
class RaisingFilter(base_class):
|
||||
def filter(self, _):
|
||||
raise TestException
|
||||
|
||||
|
@ -1029,13 +1039,13 @@ class TestFilters:
|
|||
update.message.entities = []
|
||||
(Filters.command & raising_filter)(update)
|
||||
|
||||
def test_merged_short_circuit_or(self, update):
|
||||
def test_merged_short_circuit_or(self, update, base_class):
|
||||
update.message.text = 'test'
|
||||
|
||||
class TestException(Exception):
|
||||
pass
|
||||
|
||||
class RaisingFilter(BaseFilter):
|
||||
class RaisingFilter(base_class):
|
||||
def filter(self, _):
|
||||
raise TestException
|
||||
|
||||
|
@ -1048,11 +1058,11 @@ class TestFilters:
|
|||
update.message.entities = [MessageEntity(MessageEntity.BOT_COMMAND, 0, 5)]
|
||||
(Filters.command | raising_filter)(update)
|
||||
|
||||
def test_merged_data_merging_and(self, update):
|
||||
def test_merged_data_merging_and(self, update, base_class):
|
||||
update.message.text = '/test'
|
||||
update.message.entities = [MessageEntity(MessageEntity.BOT_COMMAND, 0, 5)]
|
||||
|
||||
class DataFilter(BaseFilter):
|
||||
class DataFilter(base_class):
|
||||
data_filter = True
|
||||
|
||||
def __init__(self, data):
|
||||
|
@ -1072,10 +1082,10 @@ class TestFilters:
|
|||
result = (Filters.command & DataFilter('blah'))(update)
|
||||
assert not result
|
||||
|
||||
def test_merged_data_merging_or(self, update):
|
||||
def test_merged_data_merging_or(self, update, base_class):
|
||||
update.message.text = '/test'
|
||||
|
||||
class DataFilter(BaseFilter):
|
||||
class DataFilter(base_class):
|
||||
data_filter = True
|
||||
|
||||
def __init__(self, data):
|
||||
|
|
|
@ -24,7 +24,7 @@ from telegram.utils.deprecate import TelegramDeprecationWarning
|
|||
|
||||
from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery,
|
||||
ChosenInlineResult, ShippingQuery, PreCheckoutQuery)
|
||||
from telegram.ext import Filters, MessageHandler, CallbackContext, JobQueue, BaseFilter
|
||||
from telegram.ext import Filters, MessageHandler, CallbackContext, JobQueue, UpdateFilter
|
||||
|
||||
message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text')
|
||||
|
||||
|
@ -163,8 +163,7 @@ class TestMessageHandler:
|
|||
|
||||
def test_callback_query_with_filter(self, message):
|
||||
|
||||
class TestFilter(BaseFilter):
|
||||
update_filter = True
|
||||
class TestFilter(UpdateFilter):
|
||||
flag = False
|
||||
|
||||
def filter(self, u):
|
||||
|
|
Loading…
Reference in a new issue