This commit is contained in:
2026-02-27 08:27:43 +00:00
parent 7bf55af5b3
commit bc4c20929c
48 changed files with 4344 additions and 275 deletions
+36 -5
View File
@@ -11,12 +11,15 @@ emailRouter.get('/messages', async (ctx) => {
const email = ctx.get('user').email;
const page = Number(ctx.req.query('page') ?? '1');
const limit = Number(ctx.req.query('limit') ?? '50');
const folder = ctx.req.query('folder') ?? 'inbox';
const offset = (page - 1) * limit;
const folderWhere = folder === 'all' ? 'deleted = 0' : `deleted = 0 AND labels LIKE '%${folder}%'`;
const db = openEmailDb(email);
try {
const rows = db.query('SELECT * FROM emails WHERE deleted = 0 ORDER BY date DESC LIMIT ? OFFSET ?').all(limit, offset) as Record<string, unknown>[];
const countRow = db.query('SELECT COUNT(*) as total FROM emails WHERE deleted = 0').get() as { total: number };
const rows = db.query(`SELECT * FROM emails WHERE ${folderWhere} ORDER BY date DESC LIMIT ? OFFSET ?`).all(limit, offset) as Record<string, unknown>[];
const countRow = db.query(`SELECT COUNT(*) as total FROM emails WHERE ${folderWhere}`).get() as { total: number };
const messages = rows.map(rowToSummary);
return ctx.json({ messages, total: countRow.total });
} finally {
@@ -122,15 +125,43 @@ emailRouter.get('/sync-status', async (ctx) => {
emailRouter.get('/stats', async (ctx) => {
const email = ctx.get('user').email;
const folder = ctx.req.query('folder') ?? 'inbox';
const folderWhere = folder === 'all' ? 'deleted = 0' : `deleted = 0 AND labels LIKE '%${folder}%'`;
const db = openEmailDb(email);
try {
const total = (db.query('SELECT COUNT(*) as count FROM emails WHERE deleted = 0').get() as { count: number }).count;
const byDomain = db.query('SELECT from_domain, COUNT(*) as count FROM emails WHERE deleted = 0 GROUP BY from_domain ORDER BY count DESC LIMIT 20').all() as Array<{ from_domain: string; count: number }>;
const bySender = db.query('SELECT from_address, from_name, COUNT(*) as count FROM emails WHERE deleted = 0 GROUP BY from_address ORDER BY count DESC LIMIT 20').all() as Array<{ from_address: string; from_name: string; count: number }>;
const total = (db.query(`SELECT COUNT(*) as count FROM emails WHERE ${folderWhere}`).get() as { count: number }).count;
const byDomain = db.query(`SELECT from_domain, COUNT(*) as count FROM emails WHERE ${folderWhere} GROUP BY from_domain ORDER BY count DESC LIMIT 20`).all() as Array<{ from_domain: string; count: number }>;
const bySender = db.query(`SELECT from_address, from_name, COUNT(*) as count FROM emails WHERE ${folderWhere} GROUP BY from_address ORDER BY count DESC LIMIT 20`).all() as Array<{ from_address: string; from_name: string; count: number }>;
return ctx.json({ total, byDomain, bySender });
} finally {
db.close();
}
});
emailRouter.get('/labels', async (ctx) => {
const email = ctx.get('user').email;
const db = openEmailDb(email);
try {
const rows = db.query('SELECT labels FROM emails WHERE deleted = 0 AND labels IS NOT NULL').all() as Array<{ labels: string }>;
const counts = new Map<string, number>();
for (const row of rows) {
for (const label of row.labels.split(',')) {
const trimmed = label.trim().toLowerCase();
if (trimmed) counts.set(trimmed, (counts.get(trimmed) ?? 0) + 1);
}
}
const labels = [...counts.entries()]
.map(([label, count]) => ({ label, count }))
.sort((a, b) => b.count - a.count);
return ctx.json({ labels });
} finally {
db.close();
}
});