From a1bd24d3fcc3e93172b4f75db2992c9876a17f58 Mon Sep 17 00:00:00 2001 From: Ilya Bezrukov Date: Tue, 30 Jul 2024 16:10:38 +0300 Subject: [PATCH] Fix webhook --- migrations/env.py | 4 ++-- mybot/__init__.py | 9 ++++++++- mybot/config.py | 10 ++++++++-- mybot/webhook/__init__.py | 35 +++++++++++++++++++++++++++++++++++ webapp/__init__.py | 27 --------------------------- webapp/bot.py | 16 ---------------- 6 files changed, 53 insertions(+), 48 deletions(-) create mode 100644 mybot/webhook/__init__.py delete mode 100644 webapp/__init__.py delete mode 100644 webapp/bot.py diff --git a/migrations/env.py b/migrations/env.py index 4ede93e..05db76d 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -19,8 +19,8 @@ if config.config_file_name is not None: target_metadata = Base.metadata # set sqlalchemy.url since it can not be set in alembic.ini file -app_config = AppConfig() -config.set_main_option("sqlalchemy.url", app_config.DB_URL) +app_config = AppConfig.from_env() +config.set_main_option("sqlalchemy.url", app_config.database.url) def run_migrations_offline() -> None: diff --git a/mybot/__init__.py b/mybot/__init__.py index f697dad..35555ee 100644 --- a/mybot/__init__.py +++ b/mybot/__init__.py @@ -8,6 +8,7 @@ from .states import get_state_storage from .handlers import register_handlers from .middlewares import setup_middlewares from .filters import add_custom_filters +from .webhook import create_app def create_bot(config: Config, i18n: I18N, engine): @@ -17,7 +18,8 @@ def create_bot(config: Config, i18n: I18N, engine): skip_pending=config.bot.skip_pending, num_threads=config.bot.num_threads, use_class_middlewares=True, - state_storage=state_storage) + state_storage=state_storage, + threaded=False if config.use_webhook else True) register_handlers(bot) setup_middlewares(bot, i18n, engine) add_custom_filters(bot, config) @@ -35,6 +37,11 @@ def main(): i18n = I18N(config.i18n) engine = get_engine(config.database) bot = create_bot(config, i18n, engine) + + if config.use_webhook: + app = create_app(bot, config) + return app + bot.infinity_polling( timeout=config.bot.timeout, long_polling_timeout=config.bot.polling_timeout, diff --git a/mybot/config.py b/mybot/config.py index 435beb7..398684f 100644 --- a/mybot/config.py +++ b/mybot/config.py @@ -23,13 +23,19 @@ class BotConfig: @dataclass class WebhookConfig: - url: str + domain: str + url_path: str max_connections: int drop_pending_updates: bool + @property + def url(self): + return f"https://{self.domain}/{self.url_path}" + @classmethod def from_env(cls): - return cls(os.getenv("WEBHOOK_URL"), + return cls(os.getenv("WEBHOOK_DOMAIN"), + os.getenv("WEBHOOK_URL_PATH"), int(os.getenv("WEBHOOK_MAX_CONNECTIONS", 40)), bool(int(os.getenv("WEBHOOK_DROP_PENDING", True)))) diff --git a/mybot/webhook/__init__.py b/mybot/webhook/__init__.py new file mode 100644 index 0000000..74f7b09 --- /dev/null +++ b/mybot/webhook/__init__.py @@ -0,0 +1,35 @@ +from flask import Flask, Blueprint, request, abort, g +from telebot import TeleBot +from telebot.types import Update + +from ..config import Config + + +bot_bp = Blueprint("bot", __name__) + + +@bot_bp.route("/", methods=["GET", "POST"]) +def handle_updates(): + if request.method == "GET": + abort(404) + if request.headers.get("content-type") == "application/json": + update = Update.de_json(request.get_json()) + g.bot.process_new_updates([update]) + return "" + else: + abort(403) + + +def inject_g(bot: TeleBot, config: Config): + def inner(): + g.bot = bot + g.config = config + return inner + + +def create_app(bot: TeleBot, config: Config): + app = Flask(__name__) + app.register_blueprint(bot_bp, url_prefix=f"{config.webhook.url_path}") + app.before_request(inject_g(bot, config)) + + return app diff --git a/webapp/__init__.py b/webapp/__init__.py deleted file mode 100644 index 0b94f35..0000000 --- a/webapp/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -from flask import Flask, g -from telebot import TeleBot - -from mybot import create_bot -from mybot.config import load_config -from mybot.database import get_engine -from mybot.i18n import I18N - -from .bot import bp as bot_bp - - -def inject_bot(bot: TeleBot): - def inner(): - g.bot = bot - return inner - - -def create_app(): - config = load_config() - i18n = I18N(config.i18n) - engine = get_engine(config.database) - bot = create_bot(config, i18n, engine) - - app = Flask(__name__) - app.register_blueprint(bot_bp, url_prefix=f"/{config.bot.token}") - app.before_request(inject_bot(bot)) - return app diff --git a/webapp/bot.py b/webapp/bot.py deleted file mode 100644 index 388f500..0000000 --- a/webapp/bot.py +++ /dev/null @@ -1,16 +0,0 @@ -from flask import Blueprint, request, abort, g, Response -from telebot.types import Update - - -bp = Blueprint("bot", __name__) - - -@bp.route("/", methods=["POST"]) -def handle_updates(): - if request.headers.get("content-type") == "application/json": - json_string = request.get_data().decode("utf-8") - update = Update.de_json(json_string) - g.bot.process_new_updates([update]) - return Response("", 200) - else: - abort(403)