add chat system

This commit is contained in:
KingKDot
2026-04-14 21:56:18 -05:00
parent 6f14bf35e2
commit eb6ec86773
20 changed files with 1211 additions and 5 deletions
+84
View File
@@ -293,6 +293,81 @@ db.run(
`CREATE INDEX IF NOT EXISTS idx_auto_deploy_runs_ts ON auto_deploy_runs(ts DESC);`,
);
db.run(`
CREATE TABLE IF NOT EXISTS chat_messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
username TEXT NOT NULL,
user_role TEXT NOT NULL,
message TEXT NOT NULL,
created_at INTEGER NOT NULL
);
`);
db.run(
`CREATE INDEX IF NOT EXISTS idx_chat_messages_created_at ON chat_messages(created_at DESC);`,
);
export type ChatMessageRecord = {
id: number;
userId: number;
username: string;
userRole: string;
message: string;
createdAt: number;
};
export function insertChatMessage(userId: number, username: string, userRole: string, message: string): ChatMessageRecord {
const createdAt = Date.now();
const result = db.run(
`INSERT INTO chat_messages (user_id, username, user_role, message, created_at) VALUES (?, ?, ?, ?, ?)`,
userId, username, userRole, message, createdAt,
);
const id = Number((result as any).lastInsertRowid);
return { id, userId, username, userRole, message, createdAt };
}
export function getChatHistory(before?: number, limit: number = 50, retentionMs?: number): ChatMessageRecord[] {
const maxLimit = Math.min(Math.max(1, limit), 200);
const cutoff = retentionMs && retentionMs > 0 ? Date.now() - retentionMs : 0;
let rows: any[];
if (before) {
if (cutoff > 0) {
rows = db.query<any>(
`SELECT id, user_id, username, user_role, message, created_at FROM chat_messages WHERE created_at < ? AND created_at > ? ORDER BY created_at DESC LIMIT ?`,
).all(before, cutoff, maxLimit);
} else {
rows = db.query<any>(
`SELECT id, user_id, username, user_role, message, created_at FROM chat_messages WHERE created_at < ? ORDER BY created_at DESC LIMIT ?`,
).all(before, maxLimit);
}
} else {
if (cutoff > 0) {
rows = db.query<any>(
`SELECT id, user_id, username, user_role, message, created_at FROM chat_messages WHERE created_at > ? ORDER BY created_at DESC LIMIT ?`,
).all(cutoff, maxLimit);
} else {
rows = db.query<any>(
`SELECT id, user_id, username, user_role, message, created_at FROM chat_messages ORDER BY created_at DESC LIMIT ?`,
).all(maxLimit);
}
}
return rows.map((r: any) => ({
id: r.id,
userId: r.user_id,
username: r.username,
userRole: r.user_role,
message: r.message,
createdAt: r.created_at,
})).reverse();
}
export function deleteExpiredChatMessages(retentionMs: number): number {
if (retentionMs <= 0) return 0;
const cutoff = Date.now() - retentionMs;
const result = db.run(`DELETE FROM chat_messages WHERE created_at < ?`, cutoff);
return Number((result as any).changes ?? 0);
}
db.run(`
CREATE TABLE IF NOT EXISTS shared_files (
id TEXT PRIMARY KEY,
@@ -1164,6 +1239,15 @@ export function getClientMetricsSummaryForUser(userId: number): ClientMetricsSum
};
}
export function getOnlineClientCountForUser(userId: number): number {
const row = db
.query<{ online: number }>(
`SELECT SUM(CASE WHEN online=1 THEN 1 ELSE 0 END) as online FROM clients WHERE built_by_user_id = ?`,
)
.get(userId);
return Number(row?.online) || 0;
}
export function countBuildsForUser(userId: number): number {
const row = db
.query<{ c: number }>(`SELECT COUNT(*) as c FROM builds WHERE built_by_user_id = ?`)