Feat : STRCHA Stream status
This commit is contained in:
@@ -110,6 +110,7 @@ export function handleAgentConnection(
|
||||
obs: record.obs,
|
||||
statusIntervalMs: config.statusIntervalMs,
|
||||
autoConnectObs: record.autoConnectObs,
|
||||
watch: record.watch,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { Router } from 'express';
|
||||
import type { ObsSettings } from '@stream-control/shared';
|
||||
import { AGENT_ACTIONS, DEFAULT_OBS_SETTINGS, isAgentAction } from '@stream-control/shared';
|
||||
import {
|
||||
AGENT_ACTIONS,
|
||||
DEFAULT_OBS_SETTINGS,
|
||||
isAgentAction,
|
||||
normalizeWatchSettings,
|
||||
} from '@stream-control/shared';
|
||||
import { config } from './config.ts';
|
||||
import { generateToken, hashToken, issueSession, requireSession, safeEqual } from './auth.ts';
|
||||
import { agentsRepo, logsRepo } from './db.ts';
|
||||
@@ -81,6 +86,7 @@ api.patch('/agents/:id', (req, res) => {
|
||||
obs,
|
||||
autoConnectObs:
|
||||
typeof req.body?.autoConnectObs === 'boolean' ? req.body.autoConnectObs : record.autoConnectObs,
|
||||
watch: normalizeWatchSettings(req.body?.watch ?? record.watch),
|
||||
notes: typeof req.body?.notes === 'string' ? req.body.notes : record.notes,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { DatabaseSync } from 'node:sqlite';
|
||||
import type { LogEntry, LogLevel, ObsSettings, Platform } from '@stream-control/shared';
|
||||
import { DEFAULT_OBS_SETTINGS } from '@stream-control/shared';
|
||||
import type {
|
||||
LogEntry,
|
||||
LogLevel,
|
||||
ObsSettings,
|
||||
Platform,
|
||||
WatchSettings,
|
||||
} from '@stream-control/shared';
|
||||
import {
|
||||
DEFAULT_OBS_SETTINGS,
|
||||
DEFAULT_WATCH_SETTINGS,
|
||||
normalizeWatchSettings,
|
||||
safeJsonParse,
|
||||
} from '@stream-control/shared';
|
||||
import { config } from './config.ts';
|
||||
|
||||
fs.mkdirSync(path.dirname(config.dbPath), { recursive: true });
|
||||
@@ -40,6 +51,19 @@ db.exec(`
|
||||
CREATE INDEX IF NOT EXISTS idx_logs_ts ON logs (ts DESC);
|
||||
`);
|
||||
|
||||
/** Migrations additives : sûres à rejouer sur une base déjà peuplée. */
|
||||
function addColumnIfMissing(table: string, column: string, definition: string): void {
|
||||
const columns = db.prepare(`PRAGMA table_info(${table})`).all() as unknown as Array<{
|
||||
name: string;
|
||||
}>;
|
||||
if (columns.some((entry) => entry.name === column)) return;
|
||||
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
||||
}
|
||||
|
||||
// Surveillance du stream source : stockée en JSON, le schéma évolue plus vite
|
||||
// que la table (nouveaux fournisseurs, nouveaux statuts).
|
||||
addColumnIfMissing('agents', 'watch_json', 'TEXT');
|
||||
|
||||
export interface AgentRow {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -51,6 +75,7 @@ export interface AgentRow {
|
||||
obs_port: number;
|
||||
obs_password: string;
|
||||
auto_connect: number;
|
||||
watch_json: string | null;
|
||||
notes: string | null;
|
||||
created_at: number;
|
||||
last_seen_at: number | null;
|
||||
@@ -65,6 +90,7 @@ export interface AgentRecord {
|
||||
tokenHash: string;
|
||||
obs: ObsSettings;
|
||||
autoConnectObs: boolean;
|
||||
watch: WatchSettings;
|
||||
notes: string | null;
|
||||
createdAt: number;
|
||||
lastSeenAt: number | null;
|
||||
@@ -84,6 +110,9 @@ function toRecord(row: AgentRow): AgentRecord {
|
||||
password: row.obs_password ?? '',
|
||||
},
|
||||
autoConnectObs: Number(row.auto_connect) === 1,
|
||||
watch: normalizeWatchSettings(
|
||||
row.watch_json ? safeJsonParse<WatchSettings>(row.watch_json) : DEFAULT_WATCH_SETTINGS,
|
||||
),
|
||||
notes: row.notes,
|
||||
createdAt: Number(row.created_at),
|
||||
lastSeenAt: row.last_seen_at === null ? null : Number(row.last_seen_at),
|
||||
@@ -96,8 +125,9 @@ const stmts = {
|
||||
getAgentByTokenHash: db.prepare('SELECT * FROM agents WHERE token_hash = ?'),
|
||||
insertAgent: db.prepare(`
|
||||
INSERT INTO agents (id, name, hostname, platform, agent_version, token_hash,
|
||||
obs_host, obs_port, obs_password, auto_connect, notes, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
obs_host, obs_port, obs_password, auto_connect, watch_json,
|
||||
notes, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`),
|
||||
updateIdentity: db.prepare(`
|
||||
UPDATE agents SET hostname = ?, platform = ?, agent_version = ?, last_seen_at = ?
|
||||
@@ -105,7 +135,7 @@ const stmts = {
|
||||
`),
|
||||
updateSettings: db.prepare(`
|
||||
UPDATE agents SET name = ?, obs_host = ?, obs_port = ?, obs_password = ?,
|
||||
auto_connect = ?, notes = ?
|
||||
auto_connect = ?, watch_json = ?, notes = ?
|
||||
WHERE id = ?
|
||||
`),
|
||||
touchAgent: db.prepare('UPDATE agents SET last_seen_at = ? WHERE id = ?'),
|
||||
@@ -147,6 +177,7 @@ export const agentsRepo = {
|
||||
agentVersion?: string | null;
|
||||
obs?: Partial<ObsSettings>;
|
||||
autoConnectObs?: boolean;
|
||||
watch?: WatchSettings;
|
||||
notes?: string | null;
|
||||
}): AgentRecord {
|
||||
const obs = { ...DEFAULT_OBS_SETTINGS, ...input.obs };
|
||||
@@ -161,6 +192,7 @@ export const agentsRepo = {
|
||||
obs.port,
|
||||
obs.password,
|
||||
input.autoConnectObs === false ? 0 : 1,
|
||||
JSON.stringify(normalizeWatchSettings(input.watch ?? DEFAULT_WATCH_SETTINGS)),
|
||||
input.notes ?? null,
|
||||
Date.now(),
|
||||
);
|
||||
@@ -188,6 +220,7 @@ export const agentsRepo = {
|
||||
name: string;
|
||||
obs: ObsSettings;
|
||||
autoConnectObs: boolean;
|
||||
watch: WatchSettings;
|
||||
notes: string | null;
|
||||
},
|
||||
): void {
|
||||
@@ -197,6 +230,7 @@ export const agentsRepo = {
|
||||
settings.obs.port,
|
||||
settings.obs.password,
|
||||
settings.autoConnectObs ? 1 : 0,
|
||||
JSON.stringify(normalizeWatchSettings(settings.watch)),
|
||||
settings.notes,
|
||||
id,
|
||||
);
|
||||
|
||||
@@ -135,6 +135,7 @@ class Hub {
|
||||
type: 'config',
|
||||
obs: record.obs,
|
||||
autoConnectObs: record.autoConnectObs,
|
||||
watch: record.watch,
|
||||
};
|
||||
connection.socket.send(JSON.stringify(message));
|
||||
}
|
||||
@@ -171,6 +172,7 @@ class Hub {
|
||||
// Le mot de passe OBS n'est jamais renvoyé au navigateur.
|
||||
obs: { ...record.obs, password: record.obs.password ? '********' : '' },
|
||||
autoConnectObs: record.autoConnectObs,
|
||||
watch: record.watch,
|
||||
notes: record.notes,
|
||||
status: this.statusOf(record.id),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user