import os import logging from datetime import datetime, timedelta, timezone import aiosqlite import httpx from db import DB_PATH log = logging.getLogger(__name__) API_KEY = os.environ.get("ANTHROPIC_API_KEY", "") BASE_URL = os.environ.get("ANTHROPIC_BASE_URL", "https://www.bytecatcode.org") MODEL = "claude-haiku-4-5-20251001" CST = timezone(timedelta(hours=8)) PROMPT = """You are a chat group digest assistant. Summarize the following chat messages into a concise daily digest. Rules: - Group by topic/theme, not by chat group - Highlight key decisions, shared links, and action items - Skip greetings, small talk, and low-value chatter - Use markdown formatting - Write in the same language as the messages (likely Chinese) - Be concise Messages: {messages}""" async def summarize(date_str: str = None): now = datetime.now(CST) if not date_str: date_str = now.strftime("%Y-%m-%d") start = datetime.strptime(date_str, "%Y-%m-%d").replace(tzinfo=CST) end = start + timedelta(days=1) async with aiosqlite.connect(DB_PATH) as db: cursor = await db.execute( "SELECT group_name, sender_name, text, timestamp FROM messages WHERE timestamp >= ? AND timestamp < ? ORDER BY timestamp", (start.isoformat(), end.isoformat()) ) rows = await cursor.fetchall() if not rows: log.info("No messages for %s, skipping summary", date_str) return None # Format messages for the prompt formatted = [] for group_name, sender, text, ts in rows: formatted.append(f"[{group_name}] {sender}: {text}") messages_text = "\n".join(formatted) # Call Claude API async with httpx.AsyncClient(timeout=120) as client: resp = await client.post( f"{BASE_URL}/v1/messages", headers={"x-api-key": API_KEY, "anthropic-version": "2023-06-01", "content-type": "application/json"}, json={ "model": MODEL, "max_tokens": 4096, "messages": [{"role": "user", "content": PROMPT.format(messages=messages_text)}] } ) resp.raise_for_status() data = resp.json() summary = data["content"][0]["text"] # Store summary async with aiosqlite.connect(DB_PATH) as db: await db.execute( "INSERT OR REPLACE INTO summaries (date, content, created_at) VALUES (?,?,?)", (date_str, summary, now.isoformat()) ) await db.commit() log.info("Generated summary for %s (%d messages)", date_str, len(rows)) return summary