mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Merge pull request #1742 from byehack/ContinueHandling
Support ContinueHandling
This commit is contained in:
commit
31c3a2b2a3
27
examples/asynchronous_telebot/continue_handling.py
Normal file
27
examples/asynchronous_telebot/continue_handling.py
Normal file
@ -0,0 +1,27 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.asyncio_handler_backends import ContinueHandling
|
||||
|
||||
|
||||
bot = AsyncTeleBot('TOKEN')
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start(message):
|
||||
await bot.send_message(message.chat.id, 'Hello World!')
|
||||
return ContinueHandling()
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start2(message):
|
||||
"""
|
||||
This handler comes after the first one, but it will never be called.
|
||||
But you can call it by returning ContinueHandling() in the first handler.
|
||||
|
||||
If you return ContinueHandling() in the first handler, the next
|
||||
registered handler with appropriate filters will be called.
|
||||
"""
|
||||
await bot.send_message(message.chat.id, 'Hello World2!')
|
||||
|
||||
import asyncio
|
||||
asyncio.run(bot.polling()) # just a reminder that infinity polling
|
||||
# wraps polling into try/except block just as sync version,
|
||||
# but you can use any of them because neither of them stops if you
|
||||
# pass non_stop=True
|
23
examples/continue_handling.py
Normal file
23
examples/continue_handling.py
Normal file
@ -0,0 +1,23 @@
|
||||
from telebot import TeleBot
|
||||
from telebot.handler_backends import ContinueHandling
|
||||
|
||||
|
||||
bot = TeleBot('TOKEN')
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start(message):
|
||||
bot.send_message(message.chat.id, 'Hello World!')
|
||||
return ContinueHandling()
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start2(message):
|
||||
"""
|
||||
This handler comes after the first one, but it will never be called.
|
||||
But you can call it by returning ContinueHandling() in the first handler.
|
||||
|
||||
If you return ContinueHandling() in the first handler, the next
|
||||
registered handler with appropriate filters will be called.
|
||||
"""
|
||||
bot.send_message(message.chat.id, 'Hello World2!')
|
||||
|
||||
bot.infinity_polling()
|
@ -38,7 +38,10 @@ logger.addHandler(console_output_handler)
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
from telebot import apihelper, util, types
|
||||
from telebot.handler_backends import HandlerBackend, MemoryHandlerBackend, FileHandlerBackend, BaseMiddleware, CancelUpdate, SkipHandler, State
|
||||
from telebot.handler_backends import (
|
||||
HandlerBackend, MemoryHandlerBackend, FileHandlerBackend, BaseMiddleware,
|
||||
CancelUpdate, SkipHandler, State, ContinueHandling
|
||||
)
|
||||
from telebot.custom_filters import SimpleCustomFilter, AdvancedCustomFilter
|
||||
|
||||
|
||||
@ -6078,80 +6081,84 @@ class TeleBot:
|
||||
for handler in handlers:
|
||||
if self._test_message_handler(handler, message):
|
||||
if handler.get('pass_bot', False):
|
||||
handler['function'](message, bot = self)
|
||||
result = handler['function'](message, bot=self)
|
||||
else:
|
||||
handler['function'](message)
|
||||
result = handler['function'](message)
|
||||
if not isinstance(result, ContinueHandling):
|
||||
break
|
||||
return
|
||||
|
||||
data = {}
|
||||
params =[]
|
||||
handler_error = None
|
||||
skip_handlers = False
|
||||
|
||||
if middlewares:
|
||||
for middleware in middlewares:
|
||||
if middleware.update_sensitive:
|
||||
if hasattr(middleware, f'pre_process_{update_type}'):
|
||||
result = getattr(middleware, f'pre_process_{update_type}')(message, data)
|
||||
else:
|
||||
logger.error('Middleware {} does not have pre_process_{} method. pre_process function execution was skipped.'.format(middleware.__class__.__name__, update_type))
|
||||
result = None
|
||||
else:
|
||||
result = middleware.pre_process(message, data)
|
||||
# We will break this loop if CancelUpdate is returned
|
||||
# Also, we will not run other middlewares
|
||||
if isinstance(result, CancelUpdate):
|
||||
return
|
||||
elif isinstance(result, SkipHandler):
|
||||
skip_handlers = True
|
||||
|
||||
if handlers and not skip_handlers:
|
||||
try:
|
||||
for handler in handlers:
|
||||
process_handler = self._test_message_handler(handler, message)
|
||||
if not process_handler: continue
|
||||
for i in inspect.signature(handler['function']).parameters:
|
||||
params.append(i)
|
||||
result = None
|
||||
if len(params) == 1:
|
||||
result = handler['function'](message)
|
||||
elif "data" in params:
|
||||
if len(params) == 2:
|
||||
result = handler['function'](message, data)
|
||||
elif len(params) == 3:
|
||||
result = handler['function'](message, data=data, bot=self)
|
||||
else:
|
||||
logger.error("It is not allowed to pass data and values inside data to the handler. Check your handler: {}".format(handler['function']))
|
||||
return
|
||||
else:
|
||||
data_copy = data.copy()
|
||||
for key in list(data_copy):
|
||||
# remove data from data_copy if handler does not accept it
|
||||
if key not in params:
|
||||
del data_copy[key]
|
||||
if handler.get('pass_bot'):
|
||||
data_copy["bot"] = self
|
||||
if len(data_copy) > len(params) - 1: # remove the message parameter
|
||||
logger.error("You are passing more parameters than the handler needs. Check your handler: {}".format(handler['function']))
|
||||
return
|
||||
result = handler["function"](message, **data_copy)
|
||||
if not isinstance(result, ContinueHandling):
|
||||
break
|
||||
else:
|
||||
data = {}
|
||||
params =[]
|
||||
handler_error = None
|
||||
skip_handlers = False
|
||||
except Exception as e:
|
||||
handler_error = e
|
||||
if self.exception_handler:
|
||||
self.exception_handler.handle(e)
|
||||
else:
|
||||
logger.error(str(e))
|
||||
logger.debug("Exception traceback:\n%s", traceback.format_exc())
|
||||
|
||||
if middlewares:
|
||||
for middleware in middlewares:
|
||||
if middleware.update_sensitive:
|
||||
if hasattr(middleware, f'pre_process_{update_type}'):
|
||||
result = getattr(middleware, f'pre_process_{update_type}')(message, data)
|
||||
else:
|
||||
logger.error('Middleware {} does not have pre_process_{} method. pre_process function execution was skipped.'.format(middleware.__class__.__name__, update_type))
|
||||
result = None
|
||||
if middlewares:
|
||||
for middleware in middlewares:
|
||||
if middleware.update_sensitive:
|
||||
if hasattr(middleware, f'post_process_{update_type}'):
|
||||
getattr(middleware, f'post_process_{update_type}')(message, data, handler_error)
|
||||
else:
|
||||
result = middleware.pre_process(message, data)
|
||||
# We will break this loop if CancelUpdate is returned
|
||||
# Also, we will not run other middlewares
|
||||
if isinstance(result, CancelUpdate):
|
||||
return
|
||||
elif isinstance(result, SkipHandler):
|
||||
skip_handlers = True
|
||||
|
||||
if handlers and not(skip_handlers):
|
||||
try:
|
||||
for handler in handlers:
|
||||
process_handler = self._test_message_handler(handler, message)
|
||||
if not process_handler: continue
|
||||
for i in inspect.signature(handler['function']).parameters:
|
||||
params.append(i)
|
||||
if len(params) == 1:
|
||||
handler['function'](message)
|
||||
elif "data" in params:
|
||||
if len(params) == 2:
|
||||
handler['function'](message, data)
|
||||
elif len(params) == 3:
|
||||
handler['function'](message, data=data, bot=self)
|
||||
else:
|
||||
logger.error("It is not allowed to pass data and values inside data to the handler. Check your handler: {}".format(handler['function']))
|
||||
return
|
||||
else:
|
||||
data_copy = data.copy()
|
||||
for key in list(data_copy):
|
||||
# remove data from data_copy if handler does not accept it
|
||||
if key not in params:
|
||||
del data_copy[key]
|
||||
if handler.get('pass_bot'):
|
||||
data_copy["bot"] = self
|
||||
if len(data_copy) > len(params) - 1: # remove the message parameter
|
||||
logger.error("You are passing more parameters than the handler needs. Check your handler: {}".format(handler['function']))
|
||||
return
|
||||
handler["function"](message, **data_copy)
|
||||
break
|
||||
except Exception as e:
|
||||
handler_error = e
|
||||
if self.exception_handler:
|
||||
self.exception_handler.handle(e)
|
||||
else:
|
||||
logger.error(str(e))
|
||||
logger.debug("Exception traceback:\n%s", traceback.format_exc())
|
||||
|
||||
if middlewares:
|
||||
for middleware in middlewares:
|
||||
if middleware.update_sensitive:
|
||||
if hasattr(middleware, f'post_process_{update_type}'):
|
||||
getattr(middleware, f'post_process_{update_type}')(message, data, handler_error)
|
||||
else:
|
||||
logger.error("Middleware: {} does not have post_process_{} method. Post process function was not executed.".format(middleware.__class__.__name__, update_type))
|
||||
else:
|
||||
middleware.post_process(message, data, handler_error)
|
||||
logger.error("Middleware: {} does not have post_process_{} method. Post process function was not executed.".format(middleware.__class__.__name__, update_type))
|
||||
else:
|
||||
middleware.post_process(message, data, handler_error)
|
||||
|
||||
def _notify_command_handlers(self, handlers, new_messages, update_type):
|
||||
"""
|
||||
|
@ -14,7 +14,7 @@ import telebot.types
|
||||
|
||||
# storages
|
||||
from telebot.asyncio_storage import StateMemoryStorage, StatePickleStorage, StateStorageBase
|
||||
from telebot.asyncio_handler_backends import BaseMiddleware, CancelUpdate, SkipHandler, State
|
||||
from telebot.asyncio_handler_backends import BaseMiddleware, CancelUpdate, SkipHandler, State, ContinueHandling
|
||||
|
||||
from inspect import signature
|
||||
|
||||
@ -497,16 +497,14 @@ class AsyncTeleBot:
|
||||
if not process_update: continue
|
||||
for i in signature(handler['function']).parameters:
|
||||
params.append(i)
|
||||
result = None
|
||||
if len(params) == 1:
|
||||
await handler['function'](message)
|
||||
break
|
||||
result = await handler['function'](message)
|
||||
elif "data" in params:
|
||||
if len(params) == 2:
|
||||
await handler['function'](message, data)
|
||||
break
|
||||
result = await handler['function'](message, data)
|
||||
elif len(params) == 3:
|
||||
await handler['function'](message, data=data, bot=self)
|
||||
break
|
||||
result = await handler['function'](message, data=data, bot=self)
|
||||
else:
|
||||
logger.error("It is not allowed to pass data and values inside data to the handler. Check your handler: {}".format(handler['function']))
|
||||
return
|
||||
@ -521,7 +519,8 @@ class AsyncTeleBot:
|
||||
if len(data_copy) > len(params) - 1: # remove the message parameter
|
||||
logger.error("You are passing more data than the handler needs. Check your handler: {}".format(handler['function']))
|
||||
return
|
||||
await handler["function"](message, **data_copy)
|
||||
result = await handler["function"](message, **data_copy)
|
||||
if not isinstance(result, ContinueHandling):
|
||||
break
|
||||
except Exception as e:
|
||||
if self.exception_handler:
|
||||
|
@ -3,8 +3,6 @@ File with all middleware classes, states.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
class BaseMiddleware:
|
||||
"""
|
||||
Base class for middleware.
|
||||
@ -96,6 +94,7 @@ class SkipHandler:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class CancelUpdate:
|
||||
"""
|
||||
Class for canceling updates.
|
||||
@ -106,4 +105,27 @@ class CancelUpdate:
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class ContinueHandling:
|
||||
"""
|
||||
Class for continue updates in handlers.
|
||||
Just return instance of this class
|
||||
in handlers to continue process.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example of using ContinueHandling
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start(message):
|
||||
await bot.send_message(message.chat.id, 'Hello World!')
|
||||
return ContinueHandling()
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start2(message):
|
||||
await bot.send_message(message.chat.id, 'Hello World2!')
|
||||
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
@ -174,7 +174,6 @@ class State:
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
|
||||
class StatesGroup:
|
||||
"""
|
||||
@ -192,9 +191,6 @@ class StatesGroup:
|
||||
value.name = ':'.join((cls.__name__, name))
|
||||
value.group = cls
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BaseMiddleware:
|
||||
"""
|
||||
@ -253,10 +249,10 @@ class SkipHandler:
|
||||
Update will go to post_process,
|
||||
but will skip execution of handler.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class CancelUpdate:
|
||||
"""
|
||||
Class for canceling updates.
|
||||
@ -265,6 +261,28 @@ class CancelUpdate:
|
||||
Update will skip handler and execution
|
||||
of post_process in middlewares.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class ContinueHandling:
|
||||
"""
|
||||
Class for continue updates in handlers.
|
||||
Just return instance of this class
|
||||
in handlers to continue process.
|
||||
|
||||
.. code-block:: python3
|
||||
:caption: Example of using ContinueHandling
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start(message):
|
||||
bot.send_message(message.chat.id, 'Hello World!')
|
||||
return ContinueHandling()
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start2(message):
|
||||
bot.send_message(message.chat.id, 'Hello World2!')
|
||||
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user