- Telegram collector (Telethon MTProto) with checkpoint-based message fetching - Claude API summarization via proxy (haiku model) - Dashboard page with date picker, markdown summary, raw message drill-down - Separate container lifecycle from dashboard for stable Telethon sessions - Shared SQLite DB mounted read-only into dashboard
This commit is contained in:
@@ -41,5 +41,8 @@ WEBAUTHN_ORIGINS = os.environ.get("WEBAUTHN_ORIGIN", "https://nas.jimmygan.com,h
|
||||
# CORS
|
||||
CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",")
|
||||
|
||||
# Chat Summary
|
||||
CHAT_SUMMARY_DB = os.environ.get("CHAT_SUMMARY_DB", "/app/data/chat-summarizer/chat_summary.db")
|
||||
|
||||
# OpenClaw
|
||||
OPENCLAW_GATEWAY_TOKEN = os.environ.get("OPENCLAW_GATEWAY_TOKEN", "")
|
||||
|
||||
@@ -5,7 +5,7 @@ from fastapi.responses import JSONResponse
|
||||
from slowapi import Limiter
|
||||
from slowapi.util import get_remote_address
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
from routers import docker_router, gitea, files, terminal, system, auth
|
||||
from routers import docker_router, gitea, files, terminal, system, auth, chat_summary
|
||||
import auth as auth_module
|
||||
|
||||
import asyncio
|
||||
@@ -139,6 +139,7 @@ app.include_router(docker_router.router, prefix="/api/docker", dependencies=[Dep
|
||||
app.include_router(gitea.router, prefix="/api/gitea", dependencies=[Depends(auth_module.get_current_user)])
|
||||
app.include_router(files.router, prefix="/api/files", dependencies=[Depends(auth_module.get_current_user)])
|
||||
app.include_router(system.router, prefix="/api/system", dependencies=[Depends(auth_module.get_current_user)])
|
||||
app.include_router(chat_summary.router, prefix="/api/chat-summary", dependencies=[Depends(auth_module.get_current_user)])
|
||||
|
||||
# WebSocket endpoint (auth handled inside handler via Query param)
|
||||
app.add_api_websocket_route("/ws/terminal", terminal.ws_endpoint)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
import aiosqlite
|
||||
from config import CHAT_SUMMARY_DB
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
async def _db():
|
||||
return aiosqlite.connect(CHAT_SUMMARY_DB)
|
||||
|
||||
@router.get("/dates")
|
||||
async def list_dates():
|
||||
async with await _db() as db:
|
||||
cursor = await db.execute("SELECT date FROM summaries ORDER BY date DESC")
|
||||
return [r[0] for r in await cursor.fetchall()]
|
||||
|
||||
@router.get("/summary/{date}")
|
||||
async def get_summary(date: str):
|
||||
async with await _db() as db:
|
||||
cursor = await db.execute("SELECT content, created_at FROM summaries WHERE date=?", (date,))
|
||||
row = await cursor.fetchone()
|
||||
if not row:
|
||||
raise HTTPException(404, "No summary for this date")
|
||||
return {"date": date, "content": row[0], "created_at": row[1]}
|
||||
|
||||
@router.get("/messages/{date}")
|
||||
async def get_messages(date: str):
|
||||
async with await _db() as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT group_name, sender_name, text, timestamp FROM messages WHERE date(timestamp)=? ORDER BY timestamp",
|
||||
(date,)
|
||||
)
|
||||
return [{"group": r[0], "sender": r[1], "text": r[2], "time": r[3]} for r in await cursor.fetchall()]
|
||||
|
||||
@router.post("/trigger")
|
||||
async def trigger_summary():
|
||||
import os
|
||||
trigger_path = os.environ.get("CHAT_SUMMARY_TRIGGER", "/app/data/chat-summarizer/trigger")
|
||||
os.makedirs(os.path.dirname(trigger_path), exist_ok=True)
|
||||
with open(trigger_path, "w") as f:
|
||||
f.write("1")
|
||||
return {"status": "triggered"}
|
||||
Reference in New Issue
Block a user