Initial commit with translated description

This commit is contained in:
2026-03-29 13:18:46 +08:00
commit 37406a2ec4
51 changed files with 9545 additions and 0 deletions

215
scripts/digest.py Normal file
View File

@@ -0,0 +1,215 @@
#!/usr/bin/env python3
"""
Generate and send weekly research digest.
Compiles medium-priority findings from the week into a readable report.
"""
import sys
import json
import argparse
from datetime import datetime, timedelta
from pathlib import Path
from collections import defaultdict
sys.path.insert(0, str(Path(__file__).parent))
from config import load_config, get_topic, FINDINGS_DIR
def get_week_range(offset_weeks: int = 0) -> tuple[datetime, datetime]:
"""Get start and end of current week (or offset)."""
today = datetime.now()
# Find most recent Sunday
days_since_sunday = (today.weekday() + 1) % 7
sunday = today - timedelta(days=days_since_sunday)
# Apply offset
start = sunday - timedelta(weeks=offset_weeks)
end = start + timedelta(days=6, hours=23, minutes=59, seconds=59)
return start, end
def load_week_findings(start: datetime, end: datetime) -> dict:
"""Load all findings from the week."""
if not FINDINGS_DIR.exists():
return {}
findings_by_topic = defaultdict(list)
# Scan findings directory
for findings_file in FINDINGS_DIR.glob("*.json"):
# Parse filename: YYYY-MM-DD_topic-id.json
parts = findings_file.stem.split("_", 1)
if len(parts) != 2:
continue
date_str, topic_id = parts
try:
file_date = datetime.strptime(date_str, "%Y-%m-%d")
except ValueError:
continue
# Check if in week range
if not (start <= file_date <= end):
continue
# Load findings
with open(findings_file) as f:
findings = json.load(f)
findings_by_topic[topic_id].extend(findings)
return dict(findings_by_topic)
def generate_digest(findings_by_topic: dict, start: datetime, end: datetime) -> str:
"""Generate digest markdown."""
config = load_config()
# Header
digest = f"# 📊 Weekly Research Digest\n\n"
digest += f"**{start.strftime('%B %d')} - {end.strftime('%B %d, %Y')}**\n\n"
digest += "---\n\n"
# Summary stats
total_findings = sum(len(f) for f in findings_by_topic.values())
topic_count = len(findings_by_topic)
if total_findings == 0:
digest += "No new findings this week.\n"
return digest
digest += f"📈 **Summary:** {total_findings} findings across {topic_count} topic(s)\n\n"
digest += "---\n\n"
# Highlights (highest scored findings)
all_findings = []
for topic_id, findings in findings_by_topic.items():
topic = get_topic(topic_id)
if not topic:
continue
for finding in findings:
all_findings.append({
"topic": topic,
"finding": finding
})
# Sort by score
all_findings.sort(key=lambda x: x["finding"].get("score", 0), reverse=True)
if len(all_findings) >= 3:
digest += "## 🔥 Top Highlights\n\n"
for item in all_findings[:3]:
topic = item["topic"]
finding = item["finding"]
result = finding.get("result", {})
score = finding.get("score", 0)
digest += f"### {topic.get('name')} ({score:.2f})\n\n"
digest += f"**{result.get('title', 'Untitled')}**\n\n"
digest += f"{result.get('snippet', '')}\n\n"
digest += f"🔗 [{result.get('url', '')}]({result.get('url', '')})\n\n"
digest += "---\n\n"
# Findings by topic
digest += "## 📚 Findings by Topic\n\n"
for topic_id, findings in sorted(findings_by_topic.items()):
topic = get_topic(topic_id)
if not topic:
continue
topic_name = topic.get("name", topic_id)
topic_emoji = topic.get("emoji", "📌")
digest += f"### {topic_emoji} {topic_name}\n\n"
digest += f"**{len(findings)} finding(s) this week**\n\n"
# Sort findings by score
sorted_findings = sorted(findings, key=lambda x: x.get("score", 0), reverse=True)
for finding in sorted_findings[:5]: # Top 5 per topic
result = finding.get("result", {})
score = finding.get("score", 0)
reason = finding.get("reason", "")
sentiment = finding.get("sentiment", "")
digest += f"- **{result.get('title', 'Untitled')}** ({score:.2f})\n"
digest += f" {result.get('snippet', '')[:150]}...\n"
digest += f" 🔗 {result.get('url', '')}\n"
if reason:
digest += f" _Reason: {reason}_\n"
if sentiment:
digest += f" _Sentiment: {sentiment}_\n"
digest += "\n"
if len(sorted_findings) > 5:
digest += f"_...and {len(sorted_findings) - 5} more_\n\n"
digest += "\n"
# Recommendations (future enhancement)
digest += "---\n\n"
digest += "## 💡 Recommendations\n\n"
digest += "_Feature coming soon: AI-powered topic suggestions based on your findings_\n\n"
return digest
def send_digest(digest: str, dry_run: bool = False):
"""Send digest via configured channels."""
config = load_config()
settings = config.get("settings", {})
# For now, just print (would integrate with message tool in real environment)
if dry_run:
print("\n" + "="*60)
print("DIGEST PREVIEW:")
print("="*60 + "\n")
print(digest)
print("\n" + "="*60)
else:
# Would send via Telegram, Discord, Email
print("📧 Sending digest...")
print(digest)
print("\n✅ Digest sent")
def main():
parser = argparse.ArgumentParser(description="Generate weekly research digest")
parser.add_argument("--preview", action="store_true", help="Preview without sending")
parser.add_argument("--send", action="store_true", help="Generate and send")
parser.add_argument("--week-offset", type=int, default=0,
help="Week offset (0=current, 1=last week, etc.)")
args = parser.parse_args()
# Get week range
start, end = get_week_range(args.week_offset)
print(f"📊 Generating digest for {start.strftime('%Y-%m-%d')} to {end.strftime('%Y-%m-%d')}")
# Load findings
findings_by_topic = load_week_findings(start, end)
if not findings_by_topic:
print("⚠️ No findings for this period")
return
# Generate digest
digest = generate_digest(findings_by_topic, start, end)
# Send or preview
if args.send:
send_digest(digest, dry_run=False)
else:
send_digest(digest, dry_run=True)
if __name__ == "__main__":
main()