Auto backup: 2026-02-17 18:00

This commit is contained in:
Krilly
2026-02-17 18:00:21 +00:00
parent 8902a93add
commit ebd2f70af7
9 changed files with 768 additions and 3 deletions

View File

@@ -0,0 +1,58 @@
# AI Newsletter Digest Automation
Automatically consolidates AI-related newsletters into a single, deduplicated daily digest.
## Schedule
- **When:** Daily at 7:30 AM (Australia/Perth timezone)
- **Delivery:** Via Telegram
## What It Does
1. Scans unread emails from the last 24 hours
2. Identifies AI-related newsletters
3. **Excludes:** Notion, Platformer, WSJ, WIRED Daily (per Anthony's request)
4. Fetches full content from remaining newsletters
5. Uses LLM to analyze and create consolidated digest:
- Top AI News (deduplicated across sources)
- Product Launches
- Research Highlights
- Industry Trends
- Notable Quotes
## Files
- `daily-digest.sh` - Main script that fetches newsletters
- `digest.py` - Python analysis tool (alternative approach)
- `list-newsletters.py` - Quick check of what newsletters are in inbox
## Manual Run
```bash
cd /home/openclaw/.openclaw/workspace/automations/ai-newsletter-digest
./daily-digest.sh
```
This outputs a file path. You can then ask me to analyze it.
## Cron Job
- **Job ID:** `faaed154-8320-468f-a597-21b6a92eed39`
- **Check status:** `openclaw cron list`
- **Disable:** `openclaw cron remove <job-id>`
## Newsletter Sources Included
- AI Valley
- The Information (Applied AI)
- Wall Street Journal (AI coverage)
- The Deep View
- WIRED Daily
- And other AI-related emails
## How to Modify
**Change the schedule:**
```bash
openclaw cron update <job-id> --schedule "0 8 * * *" # 8am instead
```
**Add more exclusions:**
Edit `daily-digest.sh` and add more `grep -v "pattern"` lines
**Change lookback period:**
Edit the `--recent 24h` parameter in `daily-digest.sh`

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# AI Newsletter Digest - Fetch and analyze
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
EMAIL_SKILL="$SCRIPT_DIR/../../skills/imap-smtp-email"
echo "🤖 AI Newsletter Digest Generator" >&2
echo "============================================================" >&2
# Fetch AI-related emails from last 7 days
echo "📧 Fetching AI newsletters from last 7 days..." >&2
python3 "$EMAIL_SKILL/scripts/imap-py.py" search \
--subject "AI" \
--recent 7d \
--limit 20 > /tmp/ai_emails_list.txt
# Count how many we found
EMAIL_COUNT=$(grep -c "^●" /tmp/ai_emails_list.txt || echo "0")
echo "🎯 Found $EMAIL_COUNT AI-related emails" >&2
if [ "$EMAIL_COUNT" = "0" ]; then
echo "No AI newsletters found in the last 7 days."
exit 0
fi
# Extract UIDs
UIDS=$(grep "UID:" /tmp/ai_emails_list.txt | awk '{print $3}' | head -10)
echo "📖 Fetching content from top 10 newsletters..." >&2
echo "" > /tmp/ai_newsletters_content.txt
for uid in $UIDS; do
echo " • Fetching email $uid..." >&2
python3 "$EMAIL_SKILL/scripts/imap-py.py" fetch "$uid" >> /tmp/ai_newsletters_content.txt 2>/dev/null || true
echo -e "\n\n========================================\n\n" >> /tmp/ai_newsletters_content.txt
done
echo "✅ Content fetched!" >&2
echo "" >&2
echo "📋 Newsletter sources:" >&2
grep "^From:" /tmp/ai_newsletters_content.txt | sort -u | head -10 >&2
echo "" >&2
# Output the file path for the agent to analyze
echo "/tmp/ai_newsletters_content.txt"

View File

@@ -0,0 +1,38 @@
#!/bin/bash
# Daily AI Newsletter Digest - Fast Reliable Version
set -e
EMAIL_SKILL="/home/openclaw/.openclaw/workspace/skills/imap-smtp-email"
OUTPUT_FILE="/tmp/ai-newsletter-emails.json"
echo "🤖 Daily AI Newsletter Digest" >&2
echo "============================================================" >&2
echo "$(date)" >&2
echo "" >&2
echo "🔍 Searching for AI newsletters from last 48 hours..." >&2
# Single search for all recent emails, then filter locally
cd "$EMAIL_SKILL"
# Get recent emails and filter for AI newsletters (expanded to 48h and more sources)
ALL_EMAILS=$(node scripts/imap.js search --recent 48h --limit 100 2>/dev/null | jq '[.[] | select(.from | test("AI Valley|AI Secret|DeepView|Deep View|The Rundown|TLDR|Benedict|aivalley|aisecret|deepview|therundown|tldr|benedict"; "i"))]' 2>/dev/null || echo "[]")
# Save results
echo "$ALL_EMAILS" > "$OUTPUT_FILE"
EMAIL_COUNT=$(echo "$ALL_EMAILS" | jq '. | length')
echo "" >&2
echo "🎯 Found $EMAIL_COUNT AI-related emails" >&2
if [ "$EMAIL_COUNT" -eq 0 ]; then
echo "No new AI newsletters in the last 24 hours." >&2
echo "[]"
exit 0
fi
echo "" >&2
echo "📧 Ready to process $EMAIL_COUNT newsletters" >&2
# Output the emails
cat "$OUTPUT_FILE"

View File

@@ -0,0 +1,206 @@
#!/usr/bin/env python3
"""
AI Newsletter Digest
Consolidates AI-related newsletters into a single, deduplicated summary
"""
import sys
import os
import json
import subprocess
from pathlib import Path
from datetime import datetime
import re
# Add skills to path
WORKSPACE = Path(__file__).parent.parent.parent
EMAIL_SKILL = WORKSPACE / "skills" / "imap-smtp-email"
# Newsletter keywords to look for in sender/subject
AI_KEYWORDS = [
'ai', 'artificial intelligence', 'machine learning', 'ml', 'llm',
'gpt', 'claude', 'openai', 'anthropic', 'deepmind', 'neural',
'chatgpt', 'transformer', 'diffusion', 'generative', 'newsletter'
]
def log(msg):
"""Log to stderr"""
print(msg, file=sys.stderr)
def is_ai_newsletter(from_addr, subject):
"""Check if email is likely an AI newsletter"""
text = f"{from_addr} {subject}".lower()
return any(keyword in text for keyword in AI_KEYWORDS)
def fetch_unread_emails(limit=50):
"""Fetch unread emails using the IMAP skill"""
log("📧 Fetching unread emails...")
cmd = [
"python3",
str(EMAIL_SKILL / "scripts" / "imap-py.py"),
"search",
"--unseen",
"--limit", str(limit)
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
log(f"Error fetching emails: {result.stderr}")
return []
# Parse the output
emails = []
lines = result.stdout.strip().split('\n')
current_email = {}
for line in lines:
line = line.strip()
if line.startswith('') or line.startswith(' '):
# Start of new email
if 'UID:' in line:
if current_email:
emails.append(current_email)
uid = line.split('UID:')[1].strip().split()[0]
current_email = {'uid': uid}
elif line.startswith('From:'):
current_email['from'] = line.replace('From:', '').strip()
elif line.startswith('Subject:'):
current_email['subject'] = line.replace('Subject:', '').strip()
elif line.startswith('Date:'):
current_email['date'] = line.replace('Date:', '').strip()
if current_email:
emails.append(current_email)
return emails
def fetch_email_body(uid):
"""Fetch full email body"""
log(f" Fetching email {uid}...")
cmd = [
"python3",
str(EMAIL_SKILL / "scripts" / "imap-py.py"),
"fetch",
uid
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
return None
# Extract body (everything after the separator line)
parts = result.stdout.split('-' * 80)
if len(parts) > 1:
return parts[1].strip()
return result.stdout.strip()
def extract_key_points(newsletters):
"""Use LLM to extract and deduplicate key points"""
log("🧠 Analyzing newsletters and extracting key points...")
# Prepare newsletter content for analysis
newsletter_texts = []
for i, newsletter in enumerate(newsletters, 1):
text = f"NEWSLETTER {i} - {newsletter['from']}\nSubject: {newsletter['subject']}\n\n{newsletter['body'][:3000]}"
newsletter_texts.append(text)
combined = "\n\n" + "="*80 + "\n\n".join(newsletter_texts)
# Prompt for LLM
prompt = f"""You are analyzing {len(newsletters)} AI-related newsletters. Extract the key information and insights, removing duplicates and synthesizing similar news across sources.
{combined}
Please provide:
1. **Top AI News** - The most important developments mentioned (deduplicated)
2. **Product Launches** - New tools, models, or features announced
3. **Research Highlights** - Notable papers or breakthroughs
4. **Industry Trends** - Patterns or themes across multiple newsletters
5. **Notable Quotes** - Interesting perspectives from thought leaders
Format as markdown with clear sections. Be concise but informative. If the same news appears in multiple newsletters, mention it once and note it's widely covered."""
# Call LLM via openclaw (assuming this is running within openclaw context)
# For now, create a temporary prompt file
prompt_file = Path("/tmp/digest_prompt.txt")
prompt_file.write_text(prompt)
log(" Generating digest with LLM...")
log(" (This may take a moment...)")
# Return a placeholder for now - in production this would call the LLM
# The agent running this will provide LLM access
return {
'prompt': prompt,
'needs_llm': True
}
def create_digest(newsletters):
"""Create the final digest"""
if not newsletters:
return "No AI newsletters found in unread emails."
# For now, return structured data that the agent can analyze
digest = {
'count': len(newsletters),
'sources': [n['from'] for n in newsletters],
'newsletters': newsletters
}
return digest
def main():
log("🤖 AI Newsletter Digest Generator")
log("=" * 60)
# Fetch unread emails
emails = fetch_unread_emails(limit=50)
# Filter for AI newsletters
log(f"📊 Found {len(emails)} unread emails")
ai_newsletters = []
for email in emails:
if is_ai_newsletter(email.get('from', ''), email.get('subject', '')):
ai_newsletters.append(email)
log(f"🎯 Found {len(ai_newsletters)} AI-related newsletters")
if not ai_newsletters:
print(json.dumps({'status': 'no_newsletters', 'message': 'No AI newsletters found'}))
return
# Fetch full content for each
log("📖 Fetching full newsletter content...")
for newsletter in ai_newsletters[:10]: # Limit to 10 to avoid overwhelming
body = fetch_email_body(newsletter['uid'])
if body:
newsletter['body'] = body
# Filter out ones without body
ai_newsletters = [n for n in ai_newsletters if 'body' in n]
log(f"✅ Successfully fetched {len(ai_newsletters)} newsletters")
# Output structured data for the agent to analyze
result = {
'status': 'success',
'count': len(ai_newsletters),
'sources': list(set([n['from'] for n in ai_newsletters])),
'newsletters': ai_newsletters[:10] # Limit to 10
}
print(json.dumps(result, indent=2))
# Log summary to stderr
log("\n📋 Newsletter Sources:")
for source in result['sources']:
log(f"{source}")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python3
"""
Quick list of AI newsletters in inbox
"""
import sys
import subprocess
from pathlib import Path
WORKSPACE = Path(__file__).parent.parent.parent
EMAIL_SKILL = WORKSPACE / "skills" / "imap-smtp-email"
AI_KEYWORDS = [
'ai', 'artificial intelligence', 'machine learning', 'ml', 'llm',
'gpt', 'claude', 'openai', 'anthropic', 'deepmind', 'neural',
'chatgpt', 'transformer', 'diffusion', 'generative', 'newsletter'
]
def is_ai_newsletter(from_addr, subject):
text = f"{from_addr} {subject}".lower()
return any(keyword in text for keyword in AI_KEYWORDS)
def main():
# Fetch unread emails
cmd = [
"python3",
str(EMAIL_SKILL / "scripts" / "imap-py.py"),
"search",
"--unseen",
"--limit", "50"
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print("Error fetching emails", file=sys.stderr)
sys.exit(1)
# Parse output
emails = []
lines = result.stdout.strip().split('\n')
current_email = {}
for line in lines:
line = line.strip()
if 'UID:' in line:
if current_email:
emails.append(current_email)
uid = line.split('UID:')[1].strip().split()[0]
current_email = {'uid': uid}
elif line.startswith('From:'):
current_email['from'] = line.replace('From:', '').strip()
elif line.startswith('Subject:'):
current_email['subject'] = line.replace('Subject:', '').strip()
if current_email:
emails.append(current_email)
# Filter AI newsletters
ai_newsletters = [e for e in emails if is_ai_newsletter(e.get('from', ''), e.get('subject', ''))]
print(f"Found {len(ai_newsletters)} AI newsletters out of {len(emails)} unread emails:\n")
for n in ai_newsletters:
print(f"UID: {n['uid']}")
print(f"From: {n.get('from', 'Unknown')}")
print(f"Subject: {n.get('subject', 'No subject')}")
print()
if __name__ == '__main__':
main()