From 2797183834e1ef3bae0a69c4f46af89ca956788a Mon Sep 17 00:00:00 2001 From: gitadmin Date: Sun, 2 Aug 2026 15:50:44 +0300 Subject: [PATCH] [ZILANT] debug 2 - test reg script --- gunicorn_bot.conf.py | 15 ++------- register_tg_webhook.py | 73 ++++++++++++++++++++++++++++++++++++++++++ wsgi_bot.py | 32 +++++++++++++++--- 3 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 register_tg_webhook.py diff --git a/gunicorn_bot.conf.py b/gunicorn_bot.conf.py index 2f87186..f868391 100644 --- a/gunicorn_bot.conf.py +++ b/gunicorn_bot.conf.py @@ -1,16 +1,5 @@ """Конфиг gunicorn для responder-бота. -Webhook регистрируется один раз в master (on_starting), а не в каждом worker — -иначе 4 воркера параллельно бьют setWebhook и ловят 429. +Регистрация webhook выполняется в wsgi_bot.py (с file lock), чтобы сработала +даже если unit забыли обновить с --config. """ - - -def on_starting(server): - from tg_mainbot import setup_webhook - - server.log.info("gunicorn on_starting: регистрация Telegram webhook через ретранслятор") - setup_webhook() - - -# На случай, если webhook уже стоит, а воркеры перезапускаются — не трогаем. -# Повторная регистрация только при старте master-процесса. diff --git a/register_tg_webhook.py b/register_tg_webhook.py new file mode 100644 index 0000000..7f9306a --- /dev/null +++ b/register_tg_webhook.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +Ручная регистрация Telegram webhook через internal_relay (с secret_token). + +Запуск на сервере бота: + cd /opt/testbot-git + ./venv/bin/python register_tg_webhook.py + +Печатает полный ответ setWebhook — по нему видно, принял ли Telegram секрет. +""" + +import json +import sys + +from dotenv import load_dotenv +import os +import requests + +load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env")) +load_dotenv() + +from telegram_relay import bot_api_method_url, get_relay_url + +TOKEN = os.getenv("RESPONDER_BOT_TOKEN") +WEBHOOK_URL = os.getenv("WEBHOOK_URL") +WEBHOOK_SECRET = (os.getenv("WEBHOOK_SECRET") or "").strip().strip('"').strip("'") + + +def main() -> int: + if not TOKEN: + print("ERROR: RESPONDER_BOT_TOKEN не задан") + return 1 + if not WEBHOOK_URL: + print("ERROR: WEBHOOK_URL не задан") + return 1 + if not WEBHOOK_SECRET: + print("ERROR: WEBHOOK_SECRET не задан") + return 1 + + api_url = bot_api_method_url(TOKEN, "setWebhook") + form = { + "url": WEBHOOK_URL, + "secret_token": WEBHOOK_SECRET, + "max_connections": "40", + } + print(f"RELAY_URL = {get_relay_url()}") + print(f"WEBHOOK_URL = {WEBHOOK_URL}") + print(f"secret_len = {len(WEBHOOK_SECRET)}") + print(f"POST = {api_url.replace(TOKEN, '')}") + print(f"form keys = {list(form.keys())}") + + resp = requests.post(api_url, data=form, timeout=60) + print(f"HTTP status = {resp.status_code}") + try: + data = resp.json() + print("JSON response:") + print(json.dumps(data, ensure_ascii=False, indent=2)) + except Exception: + print("Raw response:") + print(resp.text[:1000]) + return 1 + + if not data.get("ok"): + print("FAILED: Telegram/relay вернул ok=false") + return 1 + + print("OK: setWebhook принят. Нажмите «Подписка» / отправьте /start боту.") + print("В логе бота не должно быть «Секретный токен отсутствует».") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/wsgi_bot.py b/wsgi_bot.py index 115596f..62eb749 100644 --- a/wsgi_bot.py +++ b/wsgi_bot.py @@ -1,10 +1,32 @@ -from tg_mainbot import app +import fcntl +import hashlib +import os -# Регистрация webhook — в gunicorn_bot.conf.py (on_starting), один раз в master. -# Здесь только WSGI-приложение для воркеров. +from tg_mainbot import WEBHOOK_SECRET, WEBHOOK_URL, app, setup_webhook + + +def _ensure_webhook(): + """ + Один раз на старте gunicorn регистрируем webhook с secret_token. + Блокирующий flock — без гонки 4 воркеров и без 429. + """ + digest = hashlib.sha256( + f"{WEBHOOK_URL}|{WEBHOOK_SECRET or ''}".encode("utf-8") + ).hexdigest()[:16] + marker_path = f"/tmp/zilant_webhook_ok_{digest}" + lock_path = "/tmp/zilant_webhook_setup.lock" + + with open(lock_path, "w") as lock_file: + fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX) + if os.path.exists(marker_path): + return + setup_webhook() + with open(marker_path, "w") as marker: + marker.write("ok\n") + + +_ensure_webhook() if __name__ == "__main__": - from tg_mainbot import setup_webhook - setup_webhook() app.run()