#!/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()