Files
youlu-openclaw-workspace/scripts/news_digest/send_digest.py
2026-02-22 14:06:50 -08:00

176 lines
5.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Daily News Digest - Fetch news and send email summary
Runs news_digest, formats output, sends via himalaya
"""
import json
import subprocess
import sys
from datetime import datetime
from pathlib import Path
# Config
SCRIPT_DIR = Path(__file__).resolve().parent
DB_PATH = SCRIPT_DIR / "news_digest.db"
CONFIG_PATH = SCRIPT_DIR / "config.json"
# Email config
EMAIL_TO = "lu@luyx.org"
EMAIL_FROM = "youlu@luyanxin.com"
def run_news_digest():
"""Run news_digest and get articles with summaries"""
# Fetch new articles using run.sh (handles uv dependencies)
fetch_cmd = [
str(SCRIPT_DIR / "run.sh"),
]
# Run fetch (this saves articles to DB and generates summaries)
try:
result = subprocess.run(fetch_cmd, capture_output=True, text=True, cwd=SCRIPT_DIR, timeout=300)
except subprocess.TimeoutExpired:
print("Fetch timed out after 300s", file=sys.stderr)
sys.exit(1)
if result.returncode != 0:
print(f"Fetch failed: {result.stderr}", file=sys.stderr)
return None
# Now query with summary field
query_cmd = [
str(SCRIPT_DIR / "run.sh"),
"--no-fetch",
"-f", "id,title,url,summary,feed_name,category"
]
try:
result = subprocess.run(query_cmd, capture_output=True, text=True, cwd=SCRIPT_DIR, timeout=30)
except subprocess.TimeoutExpired:
print("Query timed out after 30s", file=sys.stderr)
sys.exit(1)
if result.returncode != 0:
print(f"Query failed: {result.stderr}", file=sys.stderr)
return None
# Parse JSON output
try:
articles = json.loads(result.stdout)
return articles
except json.JSONDecodeError as e:
print(f"Failed to parse JSON: {e}", file=sys.stderr)
print(f"Raw output: {result.stdout[:500]}", file=sys.stderr)
return []
def format_email(articles):
"""Format articles into email body"""
if not articles:
return None
today = datetime.now().strftime('%Y-%m-%d')
lines = [
f"📰 每日新闻摘要 ({today})",
"=" * 50,
""
]
# Group by category
by_category = {}
for a in articles:
cat = a.get('category', 'Other')
if cat not in by_category:
by_category[cat] = []
by_category[cat].append(a)
# Sort categories
category_order = ['Tech', 'China', 'World', 'Other']
ordered_cats = category_order + [c for c in by_category if c not in category_order]
for cat in ordered_cats:
if cat not in by_category:
continue
cat_name = {
'Tech': '💻 科技',
'China': '🇨🇳 国内',
'World': '🌍 国际',
'Other': '📄 其他'
}.get(cat, cat)
lines.append(f"\n{cat_name}")
lines.append("-" * 30)
for article in by_category[cat]:
title = article.get('title', '无标题')
url = article.get('url', '')
summary = article.get('summary', '')
source = article.get('feed_name', '未知来源')
lines.append(f"\n{title}")
if summary:
# Clean up summary (remove excessive newlines, preserve content)
summary_clean = summary.replace('\n', ' ').strip()
lines.append(f" {summary_clean}")
lines.append(f" 来源: {source} | {url}")
lines.append("\n" + "=" * 50)
lines.append("由 RSS News Digest 自动生成")
return '\n'.join(lines)
def send_email(subject, body):
"""Send email via himalaya"""
# Construct raw email message with headers
message = f"""From: {EMAIL_FROM}
To: {EMAIL_TO}
Subject: {subject}
Content-Type: text/plain; charset=utf-8
{body}"""
cmd = [
"himalaya",
"message", "send",
"-a", "Youlu" # Account name from config.toml
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, input=message, timeout=30)
except subprocess.TimeoutExpired:
return False, "himalaya timed out after 30s"
return result.returncode == 0, result.stderr
def main():
# Fetch and get articles
articles = run_news_digest()
if articles is None:
# Fetch failed, don't send email
sys.exit(1)
if not articles:
# No new articles, send a "no news" email or skip
# Let's skip sending email if no articles
print("No articles to send")
return
# Format email
body = format_email(articles)
if not body:
print("Failed to format email")
sys.exit(1)
# Send email
today = datetime.now().strftime('%Y-%m-%d')
subject = f"📰 每日新闻摘要 - {today}"
success, error = send_email(subject, body)
if success:
print(f"Email sent successfully: {len(articles)} articles")
else:
print(f"Failed to send email: {error}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()