feat(telegram): candidate list/delete/clear commands

私聊新增 /candidate [页码](待决策列表)、/candi_del(标题按钮逐条删除,删后原地重建键盘、可翻页连续删)、/candi_clear(全部/待决策/取消)。重构 handle_callback 为前缀分派(cdel/cpage/cclr,保留 add/ign/blk/fav);repository 加 list_pending_candidates/delete_all_candidates;LibraryService 加 pending_candidates/delete_candidate/clear_candidates 并刷看板缓存。
This commit is contained in:
kairee committed 2026-11-01 20:45:57 +08:00
1 parent c6790f0ba1
commit 4a9c37f2f3
9 files changed
+473 -23

No files matched your search

+20
View File
@@ -919,6 +919,16 @@ class Repository:
return [dict(row) for row in rows]
return self.db.read(run)
def list_pending_candidates(self) -> list[dict[str, Any]]:
"""待决策候选(``decision IS NULL``),按分数倒序。"""
def run(conn: sqlite3.Connection) -> list[dict[str, Any]]:
rows = conn.execute(
"SELECT * FROM candidate WHERE decision IS NULL "
"ORDER BY COALESCE(score, 0) DESC, first_seen DESC, aid"
).fetchall()
return [dict(row) for row in rows]
return self.db.read(run)
def mark_candidate_decision(
self, aid: int, decision: str, *, now: int | None = None
) -> None:
@@ -944,6 +954,16 @@ class Repository:
"DELETE FROM candidate WHERE aid = ?", (int(aid),)
))
def delete_all_candidates(self, *, pending_only: bool = False) -> int:
"""删除候选:``pending_only=True`` 只删待决策,否则清空整表;返回删除数。"""
def run(conn: sqlite3.Connection) -> int:
if pending_only:
cur = conn.execute("DELETE FROM candidate WHERE decision IS NULL")
else:
cur = conn.execute("DELETE FROM candidate")
return max(cur.rowcount, 0)
return self.db.write(run)
def delete_expired_candidates(
self, *, ttl_days: int, now: int | None = None
) -> int: