This commit is contained in:
parent
88c4c84dec
commit
a8723bb3ee
4 changed files with 43 additions and 4 deletions
|
|
@ -12,9 +12,12 @@
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# ── Агностичное представление клавиатуры ──────────────────────────────────────
|
# ── Агностичное представление клавиатуры ──────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -101,39 +104,48 @@ class TelegramChannelNotifier(Notifier):
|
||||||
# ── Реализация интерфейса ──────────────────────────────────────────────────
|
# ── Реализация интерфейса ──────────────────────────────────────────────────
|
||||||
|
|
||||||
def send(self, text: str, keyboard: Keyboard | None = None) -> int:
|
def send(self, text: str, keyboard: Keyboard | None = None) -> int:
|
||||||
|
log.info("Telegram send_message → channel %s", self._channel_id)
|
||||||
msg = self._bot.send_message(
|
msg = self._bot.send_message(
|
||||||
self._channel_id, text,
|
self._channel_id, text,
|
||||||
parse_mode="Markdown",
|
parse_mode="Markdown",
|
||||||
disable_web_page_preview=True,
|
disable_web_page_preview=True,
|
||||||
reply_markup=self._to_markup(keyboard),
|
reply_markup=self._to_markup(keyboard),
|
||||||
)
|
)
|
||||||
|
log.info("Telegram send_message OK, message_id=%s", msg.message_id)
|
||||||
return msg.message_id
|
return msg.message_id
|
||||||
|
|
||||||
def edit_text(self, message_id: int, text: str, keyboard: Keyboard | None = None):
|
def edit_text(self, message_id: int, text: str, keyboard: Keyboard | None = None):
|
||||||
|
log.info("Telegram edit_message_text → message_id=%s", message_id)
|
||||||
self._bot.edit_message_text(
|
self._bot.edit_message_text(
|
||||||
text, self._channel_id, message_id,
|
text, self._channel_id, message_id,
|
||||||
parse_mode="Markdown",
|
parse_mode="Markdown",
|
||||||
disable_web_page_preview=True,
|
disable_web_page_preview=True,
|
||||||
reply_markup=self._to_markup(keyboard),
|
reply_markup=self._to_markup(keyboard),
|
||||||
)
|
)
|
||||||
|
log.info("Telegram edit_message_text OK, message_id=%s", message_id)
|
||||||
|
|
||||||
def edit_keyboard(self, message_id: int, keyboard: Keyboard | None):
|
def edit_keyboard(self, message_id: int, keyboard: Keyboard | None):
|
||||||
|
log.info("Telegram edit_message_reply_markup → message_id=%s", message_id)
|
||||||
self._bot.edit_message_reply_markup(
|
self._bot.edit_message_reply_markup(
|
||||||
self._channel_id, message_id,
|
self._channel_id, message_id,
|
||||||
reply_markup=self._to_markup(keyboard),
|
reply_markup=self._to_markup(keyboard),
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete(self, message_id: int):
|
def delete(self, message_id: int):
|
||||||
|
log.info("Telegram delete_message → message_id=%s", message_id)
|
||||||
try:
|
try:
|
||||||
self._bot.delete_message(self._channel_id, message_id)
|
self._bot.delete_message(self._channel_id, message_id)
|
||||||
except Exception:
|
log.info("Telegram delete_message OK, message_id=%s", message_id)
|
||||||
pass
|
except Exception as e:
|
||||||
|
log.warning("Telegram delete_message failed (message_id=%s): %s", message_id, e)
|
||||||
|
|
||||||
def send_animation(self, url: str, disable_notification: bool = True) -> int:
|
def send_animation(self, url: str, disable_notification: bool = True) -> int:
|
||||||
|
log.info("Telegram send_animation → channel %s", self._channel_id)
|
||||||
msg = self._bot.send_animation(
|
msg = self._bot.send_animation(
|
||||||
self._channel_id, url,
|
self._channel_id, url,
|
||||||
disable_notification=disable_notification,
|
disable_notification=disable_notification,
|
||||||
)
|
)
|
||||||
|
log.info("Telegram send_animation OK, message_id=%s", msg.message_id)
|
||||||
return msg.message_id
|
return msg.message_id
|
||||||
|
|
||||||
def is_stale_error(self, exc: Exception) -> bool:
|
def is_stale_error(self, exc: Exception) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ def recreate_post(
|
||||||
Комментарии (💬 ...) и описания (📝 ...) добавляются всегда.
|
Комментарии (💬 ...) и описания (📝 ...) добавляются всегда.
|
||||||
"""
|
"""
|
||||||
notifier = get_notifier()
|
notifier = get_notifier()
|
||||||
|
|
||||||
stored = database.get_stored_events(task_id)
|
stored = database.get_stored_events(task_id)
|
||||||
stored_set = set(stored)
|
stored_set = set(stored)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,17 @@ access_log_format = '%(h)s "%(r)s" %(s)s %(b)s %(D)sµs'
|
||||||
|
|
||||||
def on_starting(server):
|
def on_starting(server):
|
||||||
"""Инициализация до форка воркеров (выполняется в мастер-процессе)."""
|
"""Инициализация до форка воркеров (выполняется в мастер-процессе)."""
|
||||||
|
import logging
|
||||||
import config
|
import config
|
||||||
import database
|
import database
|
||||||
from intradesk import reference
|
from intradesk import reference
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
||||||
|
handlers=[logging.StreamHandler()],
|
||||||
|
)
|
||||||
|
|
||||||
os.makedirs(os.path.dirname(config.DB_FILE), exist_ok=True)
|
os.makedirs(os.path.dirname(config.DB_FILE), exist_ok=True)
|
||||||
database.init_db()
|
database.init_db()
|
||||||
reference.seed_static()
|
reference.seed_static()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import queue
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from flask import Flask, Response, jsonify, render_template, request, stream_with_context, abort
|
from flask import Flask, Response, jsonify, render_template, request, stream_with_context, abort
|
||||||
|
|
@ -19,6 +20,24 @@ from intradesk.handler import handle_webhook
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
app = Flask(__name__, template_folder=os.path.join(os.path.dirname(__file__), "templates"))
|
app = Flask(__name__, template_folder=os.path.join(os.path.dirname(__file__), "templates"))
|
||||||
|
|
||||||
|
# ── Очередь вебхуков (последовательная обработка) ─────────────────────────────
|
||||||
|
|
||||||
|
_webhook_queue: queue.Queue = queue.Queue()
|
||||||
|
|
||||||
|
|
||||||
|
def _webhook_worker():
|
||||||
|
while True:
|
||||||
|
data = _webhook_queue.get()
|
||||||
|
try:
|
||||||
|
handle_webhook(data)
|
||||||
|
except Exception:
|
||||||
|
log.exception("Unhandled error in webhook worker")
|
||||||
|
finally:
|
||||||
|
_webhook_queue.task_done()
|
||||||
|
|
||||||
|
|
||||||
|
threading.Thread(target=_webhook_worker, daemon=True, name="webhook-worker").start()
|
||||||
|
|
||||||
|
|
||||||
# ── Авторизация ────────────────────────────────────────────────────────────────
|
# ── Авторизация ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -97,7 +116,7 @@ def webhook():
|
||||||
if not data:
|
if not data:
|
||||||
return jsonify({"error": "Invalid JSON"}), 400
|
return jsonify({"error": "Invalid JSON"}), 400
|
||||||
|
|
||||||
threading.Thread(target=handle_webhook, args=(data,), daemon=True).start()
|
_webhook_queue.put(data)
|
||||||
return jsonify({"ok": True}), 200
|
return jsonify({"ok": True}), 200
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue