feat: metadata enrichment for alerts and subscription plugins

Alert backends now populate structured `extra` field with engagement
metrics (views, stars, votes, etc.) instead of embedding them in titles.
Subscription plugins show richer announcements: Twitch viewer counts,
YouTube views/likes/dates, RSS published dates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-19 10:00:17 +01:00
parent c3b19feb0f
commit 1fe7da9ed8
10 changed files with 614 additions and 52 deletions

View File

@@ -49,6 +49,15 @@ def _truncate(text: str, max_len: int = _MAX_TITLE_LEN) -> str:
return text[: max_len - 3].rstrip() + "..."
def _compact_num(n: int) -> str:
"""Format large numbers compactly: 1234 -> 1.2k, 1234567 -> 1.2M."""
if n >= 1_000_000:
return f"{n / 1_000_000:.1f}M".replace(".0M", "M")
if n >= 1_000:
return f"{n / 1_000:.1f}k".replace(".0k", "k")
return str(n)
# -- Blocking helpers (for executor) -----------------------------------------
def _query_stream(login: str) -> dict:
@@ -172,15 +181,19 @@ async def _poll_once(bot, key: str, announce: bool = True) -> None:
new_stream_id = result["stream_id"]
data["last_title"] = result["title"]
data["last_game"] = result["game"]
data["last_viewers"] = result["viewers"]
if announce and (not was_live or new_stream_id != old_stream_id):
channel = data["channel"]
name = data["name"]
title = _truncate(result["title"]) if result["title"] else "(no title)"
game = result["game"]
viewers = result["viewers"]
line = f"[{name}] is live: {title}"
if game:
line += f" ({game})"
if viewers:
line += f" | {_compact_num(viewers)} viewers"
line += f" -- https://twitch.tv/{login}"
await bot.send(channel, line)
@@ -286,7 +299,13 @@ async def cmd_twitch(bot, message):
if err:
streamers.append(f"{name} (error)")
elif live:
streamers.append(f"{name} (live)")
viewers = data.get("last_viewers", 0)
if viewers:
streamers.append(
f"{name} (live, {_compact_num(viewers)})"
)
else:
streamers.append(f"{name} (live)")
else:
streamers.append(name)
if not streamers:
@@ -318,9 +337,12 @@ async def cmd_twitch(bot, message):
elif data.get("was_live"):
title = _truncate(data.get("last_title", ""))
game = data.get("last_game", "")
viewers = data.get("last_viewers", 0)
line = f"{name}: live -- {title}"
if game:
line += f" ({game})"
if viewers:
line += f" | {_compact_num(viewers)} viewers"
await bot.reply(message, line)
else:
await bot.reply(message, f"{name}: offline")