From 3f28633e7915ebc01f7a6f97cb69ae431e85301f Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Mon, 25 Apr 2016 14:26:52 +0300 Subject: [PATCH] MessageHandler / filters: refactor filters are now functions instead of enum like objects. their definitions were moved to messagehandler.py --- README.rst | 5 +- docs/source/telegram.ext.filters.rst | 7 -- docs/source/telegram.ext.rst | 1 - examples/clibot.py | 4 +- examples/echobot2.py | 4 +- examples/inlinekeyboard_example.py | 4 +- examples/state_machine_bot.py | 4 +- telegram/ext/__init__.py | 4 +- telegram/ext/filters.py | 23 ------ telegram/ext/messagehandler.py | 106 +++++++++++++++++++-------- tests/test_updater.py | 4 +- 11 files changed, 89 insertions(+), 77 deletions(-) delete mode 100644 docs/source/telegram.ext.filters.rst delete mode 100644 telegram/ext/filters.py diff --git a/README.rst b/README.rst index 7c0bb95e2..133db3f84 100644 --- a/README.rst +++ b/README.rst @@ -371,9 +371,8 @@ Our bot is now up and running (go ahead and try it)! It's not doing anything yet >>> def echo(bot, update): ... bot.sendMessage(chat_id=update.message.chat_id, text=update.message.text) ... - >>> from telegram.ext import MessageHandler - >>> from telegram.ext import filters - >>> echo_handler = MessageHandler([filters.TEXT], echo) + >>> from telegram.ext import MessageHandler, Filters + >>> echo_handler = MessageHandler([Filters.text], echo) >>> dispatcher.addHandler(echo_handler) Our bot should now reply to all text messages that are not a command with a message that has the same content. diff --git a/docs/source/telegram.ext.filters.rst b/docs/source/telegram.ext.filters.rst deleted file mode 100644 index a04a2d1c1..000000000 --- a/docs/source/telegram.ext.filters.rst +++ /dev/null @@ -1,7 +0,0 @@ -telegram.ext.filters module -=========================== - -.. automodule:: telegram.ext.filters - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/telegram.ext.rst b/docs/source/telegram.ext.rst index a924e021e..04cb17f6f 100644 --- a/docs/source/telegram.ext.rst +++ b/docs/source/telegram.ext.rst @@ -14,7 +14,6 @@ Submodules telegram.ext.commandhandler telegram.ext.inlinequeryhandler telegram.ext.messagehandler - telegram.ext.filters telegram.ext.regexhandler telegram.ext.stringcommandhandler telegram.ext.stringregexhandler diff --git a/examples/clibot.py b/examples/clibot.py index 752f10d68..445c8d783 100644 --- a/examples/clibot.py +++ b/examples/clibot.py @@ -19,7 +19,7 @@ Type 'stop' on the command line to stop the bot. """ from telegram.ext import Updater, StringCommandHandler, StringRegexHandler, \ - MessageHandler, CommandHandler, RegexHandler, filters + MessageHandler, CommandHandler, RegexHandler, Filters from telegram.ext.dispatcher import run_async from time import sleep import logging @@ -115,7 +115,7 @@ def main(): dp.addHandler(CommandHandler("start", start)) dp.addHandler(CommandHandler("help", help)) # Message handlers only receive updates that don't contain commands - dp.addHandler(MessageHandler([filters.TEXT], message)) + dp.addHandler(MessageHandler([Filters.text], message)) # Regex handlers will receive all updates on which their regex matches, # but we have to add it in a separate group, since in one group, # only one handler will be executed diff --git a/examples/echobot2.py b/examples/echobot2.py index 492fc0e38..4833b9bb1 100644 --- a/examples/echobot2.py +++ b/examples/echobot2.py @@ -17,7 +17,7 @@ Press Ctrl-C on the command line or send a signal to the process to stop the bot. """ -from telegram.ext import Updater, CommandHandler, MessageHandler, filters +from telegram.ext import Updater, CommandHandler, MessageHandler, Filters import logging # Enable logging @@ -58,7 +58,7 @@ def main(): dp.addHandler(CommandHandler("help", help)) # on noncommand i.e message - echo the message on Telegram - dp.addHandler(MessageHandler([filters.TEXT], echo)) + dp.addHandler(MessageHandler([Filters.text], echo)) # log all errors dp.addErrorHandler(error) diff --git a/examples/inlinekeyboard_example.py b/examples/inlinekeyboard_example.py index 42ce67825..d17eca900 100644 --- a/examples/inlinekeyboard_example.py +++ b/examples/inlinekeyboard_example.py @@ -9,7 +9,7 @@ import logging from telegram import Emoji, ForceReply, InlineKeyboardButton, \ InlineKeyboardMarkup from telegram.ext import Updater, CommandHandler, MessageHandler, \ - CallbackQueryHandler, filters + CallbackQueryHandler, Filters logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - ' '%(message)s', @@ -105,7 +105,7 @@ updater = Updater("TOKEN") # The command updater.dispatcher.addHandler(CommandHandler('set', set_value)) # The answer -updater.dispatcher.addHandler(MessageHandler([filters.TEXT], entered_value)) +updater.dispatcher.addHandler(MessageHandler([Filters.text], entered_value)) # The confirmation updater.dispatcher.addHandler(CallbackQueryHandler(confirm_value)) updater.dispatcher.addHandler(CommandHandler('start', help)) diff --git a/examples/state_machine_bot.py b/examples/state_machine_bot.py index 0ffe6328c..2017a7f18 100644 --- a/examples/state_machine_bot.py +++ b/examples/state_machine_bot.py @@ -6,7 +6,7 @@ import logging from telegram import Emoji, ForceReply, ReplyKeyboardMarkup, KeyboardButton -from telegram.ext import Updater, CommandHandler, MessageHandler, filters +from telegram.ext import Updater, CommandHandler, MessageHandler, Filters logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - ' '%(message)s', @@ -93,7 +93,7 @@ updater = Updater("TOKEN") # The command updater.dispatcher.addHandler(CommandHandler('set', set_value)) # The answer and confirmation -updater.dispatcher.addHandler(MessageHandler([filters.TEXT], set_value)) +updater.dispatcher.addHandler(MessageHandler([Filters.text], set_value)) updater.dispatcher.addHandler(CommandHandler('cancel', cancel)) updater.dispatcher.addHandler(CommandHandler('start', help)) updater.dispatcher.addHandler(CommandHandler('help', help)) diff --git a/telegram/ext/__init__.py b/telegram/ext/__init__.py index f2946ff99..3c6eb304f 100644 --- a/telegram/ext/__init__.py +++ b/telegram/ext/__init__.py @@ -27,7 +27,7 @@ from .choseninlineresulthandler import ChosenInlineResultHandler from .commandhandler import CommandHandler from .handler import Handler from .inlinequeryhandler import InlineQueryHandler -from .messagehandler import MessageHandler +from .messagehandler import MessageHandler, Filters from .regexhandler import RegexHandler from .stringcommandhandler import StringCommandHandler from .stringregexhandler import StringRegexHandler @@ -35,5 +35,5 @@ from .typehandler import TypeHandler __all__ = ('Dispatcher', 'JobQueue', 'Updater', 'CallbackQueryHandler', 'ChosenInlineResultHandler', 'CommandHandler', 'Handler', - 'InlineQueryHandler', 'MessageHandler', 'RegexHandler', + 'InlineQueryHandler', 'MessageHandler', 'Filters', 'RegexHandler', 'StringCommandHandler', 'StringRegexHandler', 'TypeHandler') diff --git a/telegram/ext/filters.py b/telegram/ext/filters.py deleted file mode 100644 index 8bebebe6e..000000000 --- a/telegram/ext/filters.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# -# A library that provides a Python interface to the Telegram Bot API -# Copyright (C) 2015-2016 -# Leandro Toledo de Souza -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser Public License for more details. -# -# You should have received a copy of the GNU Lesser Public License -# along with this program. If not, see [http://www.gnu.org/licenses/]. - -""" This module contains the filters used by the MessageHandler class """ - -TEXT, AUDIO, DOCUMENT, PHOTO, STICKER, VIDEO, VOICE, CONTACT, LOCATION, \ - VENUE, STATUS_UPDATE = range(11) diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index 1dddf56bd..135a08f07 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -22,7 +22,71 @@ from .handler import Handler from telegram import Update -from .filters import * # flake8: noqa + +class Filters(object): + """ + Convenient namespace (class) & methods for the filter funcs of the + MessageHandler class. + """ + + @staticmethod + def text(update): + return update.message.text and not update.message.text.startswith('/') + + @staticmethod + def command(update): + return update.message.text and update.message.text.startswith('/') + + @staticmethod + def audio(update): + return bool(update.message.audio) + + @staticmethod + def document(update): + return bool(update.message.document) + + @staticmethod + def photo(update): + return bool(update.message.photo) + + @staticmethod + def sticker(update): + return bool(update.message.sticker) + + @staticmethod + def video(update): + return bool(update.message.video) + + @staticmethod + def voice(update): + return bool(update.message.voice) + + @staticmethod + def contact(update): + return bool(update.message.contact) + + @staticmethod + def location(update): + return bool(update.message.location) + + @staticmethod + def venue(update): + return bool(update.message.venue) + + @staticmethod + def status_update(update): + return bool( + update.message.new_chat_member or + update.message.left_chat_member or + update.message.new_chat_title or + update.message.new_chat_photo or + update.message.delete_chat_photo or + update.message.group_chat_created or + update.message.supergroup_chat_created or + update.message.channel_chat_created or + update.message.migrate_to_chat_id or + update.message.migrate_from_chat_id or + update.message.pinned_message) class MessageHandler(Handler): @@ -32,8 +96,10 @@ class MessageHandler(Handler): updates. Args: - filters (list): A list of filters defined in ``telegram.ext.filters``. - All messages that match at least one of those filters will be + filters (list[function]): A list of filter functions. Standard filters + can be found in the Filters class above. + | Each `function` takes ``Update`` as arg and returns ``bool``. + | All messages that match at least one of those filters will be accepted. If ``bool(filters)`` evaluates to ``False``, messages are not filtered. callback (function): A function that takes ``bot, update`` as @@ -49,36 +115,14 @@ class MessageHandler(Handler): self.filters = filters def checkUpdate(self, update): - filters = self.filters if isinstance(update, Update) and update.message: - message = update.message - return (not filters or # If filters is empty, accept all messages - TEXT in filters and message.text and - not message.text.startswith('/') or - AUDIO in filters and message.audio or - DOCUMENT in filters and message.document or - PHOTO in filters and message.photo or - STICKER in filters and message.sticker or - VIDEO in filters and message.video or - VOICE in filters and message.voice or - CONTACT in filters and message.contact or - LOCATION in filters and message.location or - VENUE in filters and message.venue or - STATUS_UPDATE in filters and ( - message.new_chat_member or - message.left_chat_member or - message.new_chat_title or - message.new_chat_photo or - message.delete_chat_photo or - message.group_chat_created or - message.supergroup_chat_created or - message.channel_chat_created or - message.migrate_to_chat_id or - message.migrate_from_chat_id or - message.pinned_message) - ) + if not self.filters: + res = True + else: + res = any(func(update) for func in self.filters) else: - return False + res = False + return res def handleUpdate(self, update, dispatcher): optional_args = self.collectOptionalArgs(dispatcher) diff --git a/tests/test_updater.py b/tests/test_updater.py index b981aa52f..426355f8b 100644 --- a/tests/test_updater.py +++ b/tests/test_updater.py @@ -144,8 +144,8 @@ class UpdaterTest(BaseTest, unittest.TestCase): def test_addRemoveTelegramMessageHandler(self): self._setup_updater('Test') d = self.updater.dispatcher - from telegram.ext import filters - handler = MessageHandler([filters.TEXT], self.telegramHandlerTest) + from telegram.ext import Filters + handler = MessageHandler([Filters.text], self.telegramHandlerTest) d.addHandler(handler) self.updater.start_polling(0.01) sleep(.1)