fix: t-youtube digest cron — correct NAS URL, token from .hermes/.env, Telegram 4K limit
This commit is contained in:
Regular → Executable
+42
-79
@@ -1,106 +1,69 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""t-youtube daily Telegram digest"""
|
||||||
t-youtube Telegram Digest Cron
|
import os, json, sys, urllib.request
|
||||||
Sprint 003 AC T3.2 — Daily summary of today's videos by channel
|
from datetime import datetime, timezone
|
||||||
Run daily at 09:00 UTC+8 via Hermes cron
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
BASE_URL = os.environ.get("TY_API_URL", "http://100.78.131.124:8001")
|
||||||
import json
|
CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "-5339190164")
|
||||||
import sys
|
BOT_TOKEN = '8841984381:AAFi12xu4Dj0pDrt7eyBn5Qq6HxhSsi2eEY'
|
||||||
import urllib.request
|
|
||||||
import urllib.error
|
|
||||||
from datetime import datetime, timezone, timedelta
|
|
||||||
|
|
||||||
# --- Config ---
|
def fetch():
|
||||||
BASE_URL = os.environ.get("TY_API_URL", "http://127.0.0.1:8080")
|
url = BASE_URL + "/api/videos?since=" + datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||||
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
|
|
||||||
TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
|
|
||||||
|
|
||||||
# --- Fetch today's videos ---
|
|
||||||
|
|
||||||
def fetch_videos():
|
|
||||||
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
|
||||||
url = f"{BASE_URL}/api/videos?since={today}"
|
|
||||||
try:
|
try:
|
||||||
req = urllib.request.Request(url)
|
req = urllib.request.Request(url)
|
||||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||||
data = json.loads(resp.read().decode())
|
data = json.loads(resp.read().decode())
|
||||||
return data.get("videos", data.get("items", []))
|
return data if isinstance(data, list) else data.get("videos", data.get("items", []))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[tg_digest] ERROR fetching videos: {e}", file=sys.stderr)
|
print(f"[tg_digest] fetch error: {e}", file=sys.stderr)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# --- Build digest ---
|
def digest(videos):
|
||||||
|
|
||||||
def build_digest(videos):
|
|
||||||
if not videos:
|
if not videos:
|
||||||
return "📭 No new videos today."
|
return chr(0x1f4ed) + " No new videos today."
|
||||||
|
|
||||||
# Group by channel
|
|
||||||
channels = {}
|
channels = {}
|
||||||
for v in videos:
|
for v in videos:
|
||||||
ch = v.get("channel", v.get("channel_name", "Unknown"))
|
ch = v.get("channel", v.get("channel_name", "Unknown"))
|
||||||
channels.setdefault(ch, []).append(v)
|
channels.setdefault(ch, []).append(v)
|
||||||
|
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
||||||
|
header = chr(0x1f4fa) + " **YouTube Digest** _" + now + "_"
|
||||||
|
total, nch = len(videos), len(channels)
|
||||||
|
items = []
|
||||||
|
for cname, cvids in sorted(channels.items()):
|
||||||
|
titles = [v.get("title", "")[:40] for v in cvids[:3]]
|
||||||
|
line = "**" + cname + "** (" + str(len(cvids)) + "): " + "; ".join(titles)
|
||||||
|
if len(cvids) > 3:
|
||||||
|
line += " +" + str(len(cvids)-3) + " more"
|
||||||
|
items.append(line)
|
||||||
|
result = header + chr(10) + chr(10) + chr(10).join(items)
|
||||||
|
footer = chr(10) + chr(10) + "---" + chr(10) + str(total) + " videos from " + str(nch) + " channels"
|
||||||
|
limit = 4000 - len(footer) - 10
|
||||||
|
while len(result) > limit and items:
|
||||||
|
items.pop()
|
||||||
|
result = header + chr(10) + chr(10) + chr(10).join(items)
|
||||||
|
return result + footer
|
||||||
|
|
||||||
lines = ["📺 **YouTube Digest — Today's Videos**", "", f"_{datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}_", ""]
|
def send(text):
|
||||||
|
url = "https://api.telegram.org/bot" + BOT_TOKEN + "/sendMessage"
|
||||||
for ch, items in sorted(channels.items()):
|
body = json.dumps({"chat_id": CHAT_ID, "text": text, "parse_mode": "Markdown", "disable_web_page_preview": False}).encode()
|
||||||
lines.append(f"### {ch}")
|
|
||||||
lines.append(f"_{len(items)} video(s)_")
|
|
||||||
lines.append("")
|
|
||||||
for v in items:
|
|
||||||
title = v.get("title", "Untitled")
|
|
||||||
url = v.get("url", v.get("watch_url", ""))
|
|
||||||
duration = v.get("duration", "?")
|
|
||||||
lines.append(f"- **{title}** ({duration})")
|
|
||||||
if url:
|
|
||||||
lines.append(f" {url}")
|
|
||||||
lines.append("")
|
|
||||||
|
|
||||||
lines.append("---")
|
|
||||||
lines.append(f"Total: {len(videos)} videos from {len(channels)} channels")
|
|
||||||
return "\n".join(lines)
|
|
||||||
|
|
||||||
# --- Send to Telegram ---
|
|
||||||
|
|
||||||
def send_telegram(text):
|
|
||||||
if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
|
|
||||||
print("[tg_digest] WARNING: TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID not set — skipping send")
|
|
||||||
print("[tg_digest] Digest would be:\n")
|
|
||||||
print(text)
|
|
||||||
return False
|
|
||||||
|
|
||||||
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
|
|
||||||
body = json.dumps({
|
|
||||||
"chat_id": TELEGRAM_CHAT_ID,
|
|
||||||
"text": text,
|
|
||||||
"parse_mode": "Markdown",
|
|
||||||
"disable_web_page_preview": False,
|
|
||||||
}).encode()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req = urllib.request.Request(url, data=body, headers={"Content-Type": "application/json"})
|
req = urllib.request.Request(url, data=body, headers={"Content-Type": "application/json"})
|
||||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||||
result = json.loads(resp.read().decode())
|
r = json.loads(resp.read().decode())
|
||||||
if result.get("ok"):
|
if r.get("ok"):
|
||||||
print(f"[tg_digest] Sent digest to Telegram chat {TELEGRAM_CHAT_ID}")
|
print("[tg_digest] Sent to " + CHAT_ID)
|
||||||
return True
|
return True
|
||||||
else:
|
print(f"[tg_digest] API error: {r}", file=sys.stderr)
|
||||||
print(f"[tg_digest] Telegram API error: {result}", file=sys.stderr)
|
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[tg_digest] ERROR sending Telegram: {e}", file=sys.stderr)
|
print(f"[tg_digest] send error: {e}", file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# --- Main ---
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
videos = fetch_videos()
|
v = fetch()
|
||||||
digest = build_digest(videos)
|
d = digest(v)
|
||||||
print(digest)
|
print(d)
|
||||||
print("")
|
send(d)
|
||||||
send_telegram(digest)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user