From b515f5abc26f770153c41f3165d309917f17ac7b Mon Sep 17 00:00:00 2001 From: Roman Inflianskas Date: Wed, 31 Oct 2018 15:24:28 +0300 Subject: [PATCH 1/2] Add optional route_name argument to dispatcher.webhook.configure_app and utils.executor.start_webhook with default value "webhook_handler" --- aiogram/dispatcher/webhook.py | 6 ++++-- aiogram/utils/executor.py | 18 +++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/aiogram/dispatcher/webhook.py b/aiogram/dispatcher/webhook.py index 2dc9c70b..10a4b3c1 100644 --- a/aiogram/dispatcher/webhook.py +++ b/aiogram/dispatcher/webhook.py @@ -21,6 +21,7 @@ from ..utils.exceptions import TimeoutWarning from ..utils.payload import prepare_arg DEFAULT_WEB_PATH = '/webhook' +DEFAULT_ROUTE_NAME = 'webhook_handler' BOT_DISPATCHER_KEY = 'BOT_DISPATCHER' RESPONSE_TIMEOUT = 55 @@ -266,16 +267,17 @@ class GoneRequestHandler(web.View): raise HTTPGone() -def configure_app(dispatcher, app: web.Application, path=DEFAULT_WEB_PATH): +def configure_app(dispatcher, app: web.Application, path=DEFAULT_WEB_PATH, route_name=DEFAULT_ROUTE_NAME): """ You can prepare web.Application for working with webhook handler. :param dispatcher: Dispatcher instance :param app: :class:`aiohttp.web.Application` :param path: Path to your webhook. + :param route_name: Name of webhook handler route :return: """ - app.router.add_route('*', path, WebhookRequestHandler, name='webhook_handler') + app.router.add_route('*', path, WebhookRequestHandler, name=route_name) app[BOT_DISPATCHER_KEY] = dispatcher diff --git a/aiogram/utils/executor.py b/aiogram/utils/executor.py index 0679de8c..e7adc34f 100644 --- a/aiogram/utils/executor.py +++ b/aiogram/utils/executor.py @@ -7,7 +7,7 @@ from warnings import warn from aiohttp import web from ..bot.api import log -from ..dispatcher.webhook import BOT_DISPATCHER_KEY, WebhookRequestHandler +from ..dispatcher.webhook import BOT_DISPATCHER_KEY, DEFAULT_ROUTE_NAME, WebhookRequestHandler APP_EXECUTOR_KEY = 'APP_EXECUTOR' @@ -39,7 +39,8 @@ def start_polling(dispatcher, *, loop=None, skip_updates=False, reset_webhook=Tr def start_webhook(dispatcher, webhook_path, *, loop=None, skip_updates=None, - on_startup=None, on_shutdown=None, check_ip=False, retry_after=None, **kwargs): + on_startup=None, on_shutdown=None, check_ip=False, retry_after=None, route_name=DEFAULT_ROUTE_NAME, + **kwargs): """ Start bot in webhook mode @@ -50,6 +51,7 @@ def start_webhook(dispatcher, webhook_path, *, loop=None, skip_updates=None, :param on_startup: :param on_shutdown: :param check_ip: + :param route_name: :param kwargs: :return: """ @@ -57,7 +59,7 @@ def start_webhook(dispatcher, webhook_path, *, loop=None, skip_updates=None, loop=loop) _setup_callbacks(executor, on_startup, on_shutdown) - executor.start_webhook(webhook_path, **kwargs) + executor.start_webhook(webhook_path, route_name=route_name, **kwargs) def start(dispatcher, future, *, loop=None, skip_updates=None, @@ -181,7 +183,7 @@ class Executor: # self.loop.set_task_factory(context.task_factory) - def _prepare_webhook(self, path=None, handler=WebhookRequestHandler): + def _prepare_webhook(self, path=None, handler=WebhookRequestHandler, route_name=DEFAULT_ROUTE_NAME): self._check_frozen() self._freeze = True @@ -199,7 +201,7 @@ class Executor: return if path is not None: - app.router.add_route('*', path, handler, name='webhook_handler') + app.router.add_route('*', path, handler, name=route_name) async def _wrap_callback(cb, _): return await cb(self.dispatcher) @@ -219,16 +221,18 @@ class Executor: app[self._identity] = datetime.datetime.now() app['_check_ip'] = self.check_ip - def start_webhook(self, webhook_path=None, request_handler=WebhookRequestHandler, **kwargs): + def start_webhook(self, webhook_path=None, request_handler=WebhookRequestHandler, route_name=DEFAULT_ROUTE_NAME, + **kwargs): """ Start bot in webhook mode :param webhook_path: :param request_handler: + :param route_name: Name of webhook handler route :param kwargs: :return: """ - self._prepare_webhook(webhook_path, request_handler) + self._prepare_webhook(webhook_path, request_handler, route_name) self.loop.run_until_complete(self._startup_webhook()) web.run_app(self._web_app, **kwargs) From ffa6f5cd907be92f8a2dca074fecf89cde108f3e Mon Sep 17 00:00:00 2001 From: Roman Inflianskas Date: Thu, 15 Nov 2018 15:02:46 +0300 Subject: [PATCH 2/2] Add set_webhook to utils.executor --- aiogram/utils/executor.py | 78 +++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/aiogram/utils/executor.py b/aiogram/utils/executor.py index e7adc34f..2b3eaae7 100644 --- a/aiogram/utils/executor.py +++ b/aiogram/utils/executor.py @@ -2,11 +2,14 @@ import asyncio import datetime import functools import secrets +from typing import Callable, Union, Optional, Any from warnings import warn from aiohttp import web +from aiohttp.web_app import Application from ..bot.api import log +from ..dispatcher.dispatcher import Dispatcher from ..dispatcher.webhook import BOT_DISPATCHER_KEY, DEFAULT_ROUTE_NAME, WebhookRequestHandler APP_EXECUTOR_KEY = 'APP_EXECUTOR' @@ -38,6 +41,34 @@ def start_polling(dispatcher, *, loop=None, skip_updates=False, reset_webhook=Tr executor.start_polling(reset_webhook=reset_webhook, timeout=timeout, fast=fast) +def set_webhook(dispatcher: Dispatcher, webhook_path: str, *, loop: Optional[asyncio.AbstractEventLoop] = None, + skip_updates: bool = None, on_startup: Optional[Callable] = None, + on_shutdown: Optional[Callable] = None, check_ip: bool = False, + retry_after: Optional[Union[str, int]] = None, route_name: str = DEFAULT_ROUTE_NAME, + web_app: Optional[Application] = None): + """ + Set webhook for bot + + :param dispatcher: Dispatcher + :param webhook_path: str + :param loop: Optional[asyncio.AbstractEventLoop] (default: None) + :param skip_updates: bool (default: None) + :param on_startup: Optional[Callable] (default: None) + :param on_shutdown: Optional[Callable] (default: None) + :param check_ip: bool (default: False) + :param retry_after: Optional[Union[str, int]] See https://tools.ietf.org/html/rfc7231#section-7.1.3 (default: None) + :param route_name: str (default: 'webhook_handler') + :param web_app: Optional[Application] (default: None) + :return: + """ + executor = Executor(dispatcher, skip_updates=skip_updates, check_ip=check_ip, retry_after=retry_after, + loop=loop) + _setup_callbacks(executor, on_startup, on_shutdown) + + executor.set_webhook(webhook_path, route_name=route_name, web_app=web_app) + return executor + + def start_webhook(dispatcher, webhook_path, *, loop=None, skip_updates=None, on_startup=None, on_shutdown=None, check_ip=False, retry_after=None, route_name=DEFAULT_ROUTE_NAME, **kwargs): @@ -55,11 +86,16 @@ def start_webhook(dispatcher, webhook_path, *, loop=None, skip_updates=None, :param kwargs: :return: """ - executor = Executor(dispatcher, skip_updates=skip_updates, check_ip=check_ip, retry_after=retry_after, - loop=loop) - _setup_callbacks(executor, on_startup, on_shutdown) - - executor.start_webhook(webhook_path, route_name=route_name, **kwargs) + executor = set_webhook(dispatcher=dispatcher, + webhook_path=webhook_path, + loop=loop, + skip_updates=skip_updates, + on_startup=on_startup, + on_shutdown=on_shutdown, + check_ip=check_ip, + retry_after=retry_after, + route_name=route_name) + executor.run_app(**kwargs) def start(dispatcher, future, *, loop=None, skip_updates=None, @@ -183,15 +219,18 @@ class Executor: # self.loop.set_task_factory(context.task_factory) - def _prepare_webhook(self, path=None, handler=WebhookRequestHandler, route_name=DEFAULT_ROUTE_NAME): + def _prepare_webhook(self, path=None, handler=WebhookRequestHandler, route_name=DEFAULT_ROUTE_NAME, app=None): self._check_frozen() self._freeze = True # self.loop.set_task_factory(context.task_factory) - app = self._web_app - if app is None: + if app is not None: + self._web_app = app + elif self._web_app is None: self._web_app = app = web.Application() + else: + raise RuntimeError("web.Application() is already configured!") if self.retry_after: app['RETRY_AFTER'] = self.retry_after @@ -221,6 +260,23 @@ class Executor: app[self._identity] = datetime.datetime.now() app['_check_ip'] = self.check_ip + def set_webhook(self, webhook_path: Optional[str] = None, request_handler: Any = WebhookRequestHandler, + route_name: str = DEFAULT_ROUTE_NAME, web_app: Optional[Application] = None): + """ + Set webhook for bot + + :param webhook_path: Optional[str] (default: None) + :param request_handler: Any (default: WebhookRequestHandler) + :param route_name: str Name of webhook handler route (default: 'webhook_handler') + :param web_app: Optional[Application] (default: None) + :return: + """ + self._prepare_webhook(webhook_path, request_handler, route_name, web_app) + self.loop.run_until_complete(self._startup_webhook()) + + def run_app(self, **kwargs): + web.run_app(self._web_app, **kwargs) + def start_webhook(self, webhook_path=None, request_handler=WebhookRequestHandler, route_name=DEFAULT_ROUTE_NAME, **kwargs): """ @@ -232,10 +288,8 @@ class Executor: :param kwargs: :return: """ - self._prepare_webhook(webhook_path, request_handler, route_name) - self.loop.run_until_complete(self._startup_webhook()) - - web.run_app(self._web_app, **kwargs) + self.set_webhook(webhook_path=webhook_path, request_handler=request_handler, route_name=route_name, **kwargs) + self.run_app(**kwargs) def start_polling(self, reset_webhook=None, timeout=None, fast=True): """