feat(ingest): db-only library ingest and telegram manual ingest
This commit is contained in:
1 parent
d2adb65e08
commit
62abbd7ea1
6 files changed
+866
-28
No files matched your search
@@ -1,11 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Telegram getUpdates long polling 与按钮回调分发。"""
|
||||
"""Telegram getUpdates long polling 与回调/文本消息分发。
|
||||
|
||||
回调按钮处理候选「入库 / 忽略 / 拉黑」;私聊文本消息按视频链接、BV 号或 av 号
|
||||
手动入库。两类操作都只写本地库,不写 B 站收藏夹。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from typing import Any, Mapping
|
||||
|
||||
from ..notify.telegram import HELP_TEXT, format_ingest_result, format_manual_reply
|
||||
|
||||
|
||||
class TelegramPoller:
|
||||
def __init__(self, bot, actions, *, logger=None, sleeper=time.sleep) -> None:
|
||||
@@ -27,14 +33,21 @@ class TelegramPoller:
|
||||
callback = update.get("callback_query")
|
||||
if isinstance(callback, Mapping):
|
||||
self.handle_callback(callback)
|
||||
continue
|
||||
message = update.get("message")
|
||||
if isinstance(message, Mapping):
|
||||
self.handle_message(message)
|
||||
return offset
|
||||
|
||||
def _authorized(self, chat_id, from_id) -> bool:
|
||||
return chat_id == self.bot.chat_id and from_id == self.bot.chat_id
|
||||
|
||||
def handle_callback(self, callback: Mapping[str, Any]) -> None:
|
||||
callback_id = str(callback.get("id") or "")
|
||||
message = callback.get("message") or {}
|
||||
chat_id = (message.get("chat") or {}).get("id")
|
||||
from_id = (callback.get("from") or {}).get("id")
|
||||
if chat_id != self.bot.chat_id or from_id != self.bot.chat_id:
|
||||
if not self._authorized(chat_id, from_id):
|
||||
self._log(
|
||||
"warning", "telegram.unauthorized",
|
||||
chat_id=chat_id, from_id=from_id,
|
||||
@@ -49,8 +62,9 @@ class TelegramPoller:
|
||||
self._answer(callback_id, "未知操作")
|
||||
return
|
||||
|
||||
if action == "fav":
|
||||
result = self.actions.favorite(aid)
|
||||
if action in ("add", "fav"):
|
||||
# fav 为旧按钮回调,兼容已发出的历史消息。
|
||||
result = self.actions.ingest_candidate(aid)
|
||||
elif action == "ign":
|
||||
result = self.actions.ignore(aid)
|
||||
elif action == "blk":
|
||||
@@ -59,13 +73,10 @@ class TelegramPoller:
|
||||
self._answer(callback_id, "未知操作")
|
||||
return
|
||||
|
||||
text = result.message
|
||||
if result.ok and result.position is not None:
|
||||
text = f"{text}(位置 #{result.position})"
|
||||
text = format_ingest_result(result)
|
||||
self._log(
|
||||
"info", "telegram.action",
|
||||
action=action, aid=aid, ok=result.ok, state=result.state,
|
||||
position=result.position,
|
||||
)
|
||||
if not self._answer(callback_id, text):
|
||||
# 回调 ID 过期时 answerCallbackQuery 会 400;改用普通消息告知结果。
|
||||
@@ -80,6 +91,40 @@ class TelegramPoller:
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self._log("warning", "telegram.edit_failed", error=str(exc))
|
||||
|
||||
def handle_message(self, message: Mapping[str, Any]) -> None:
|
||||
chat_id = (message.get("chat") or {}).get("id")
|
||||
from_id = (message.get("from") or {}).get("id")
|
||||
if not self._authorized(chat_id, from_id):
|
||||
self._log(
|
||||
"warning", "telegram.unauthorized_message",
|
||||
chat_id=chat_id, from_id=from_id,
|
||||
)
|
||||
return
|
||||
text = message.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
return
|
||||
text = text.strip()
|
||||
if text.startswith("/start") or text.startswith("/help"):
|
||||
self._reply(HELP_TEXT)
|
||||
return
|
||||
try:
|
||||
result = self.actions.ingest_text(text)
|
||||
except Exception as exc: # noqa: BLE001 单条消息失败不影响长轮询
|
||||
self._log("error", "telegram.ingest_error", error=str(exc))
|
||||
self._reply(f"入库失败:{exc}")
|
||||
return
|
||||
self._log(
|
||||
"info", "telegram.manual_ingest",
|
||||
refs=result.refs, added=result.added,
|
||||
)
|
||||
self._reply(format_manual_reply(result))
|
||||
|
||||
def _reply(self, text: str) -> None:
|
||||
try:
|
||||
self.bot.send_text(text)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self._log("warning", "telegram.reply_failed", error=str(exc))
|
||||
|
||||
def _answer(self, callback_id: str, text: str) -> bool:
|
||||
try:
|
||||
self.bot.answer_callback(callback_id, text)
|
||||
@@ -125,4 +170,4 @@ class TelegramPoller:
|
||||
delay = initial_delay
|
||||
iterations += 1
|
||||
if max_iterations is not None and iterations >= max_iterations:
|
||||
break
|
||||
break
|
||||
Reference in new issue
Block a user