refactor: split gateway server methods
This commit is contained in:
215
src/gateway/server-methods/providers.ts
Normal file
215
src/gateway/server-methods/providers.ts
Normal file
@@ -0,0 +1,215 @@
|
||||
import { type DiscordProbe, probeDiscord } from "../../discord/probe.js";
|
||||
import { type IMessageProbe, probeIMessage } from "../../imessage/probe.js";
|
||||
import type { ClawdisConfig } from "../../config/config.js";
|
||||
import { loadConfig, readConfigFileSnapshot, writeConfigFile } from "../../config/config.js";
|
||||
import { webAuthExists } from "../../providers/web/index.js";
|
||||
import { getWebAuthAgeMs, readWebSelfId } from "../../web/session.js";
|
||||
import { probeSignal, type SignalProbe } from "../../signal/probe.js";
|
||||
import { probeTelegram, type TelegramProbe } from "../../telegram/probe.js";
|
||||
import { resolveTelegramToken } from "../../telegram/token.js";
|
||||
import {
|
||||
ErrorCodes,
|
||||
errorShape,
|
||||
formatValidationErrors,
|
||||
validateProvidersStatusParams,
|
||||
} from "../protocol/index.js";
|
||||
import { formatForLog } from "../ws-log.js";
|
||||
import type { GatewayRequestHandlers } from "./types.js";
|
||||
|
||||
export const providersHandlers: GatewayRequestHandlers = {
|
||||
"providers.status": async ({ params, respond, context }) => {
|
||||
if (!validateProvidersStatusParams(params)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid providers.status params: ${formatValidationErrors(validateProvidersStatusParams.errors)}`,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
const probe = (params as { probe?: boolean }).probe === true;
|
||||
const timeoutMsRaw = (params as { timeoutMs?: unknown }).timeoutMs;
|
||||
const timeoutMs =
|
||||
typeof timeoutMsRaw === "number" ? Math.max(1000, timeoutMsRaw) : 10_000;
|
||||
const cfg = loadConfig();
|
||||
const telegramCfg = cfg.telegram;
|
||||
const telegramEnabled = Boolean(telegramCfg) && telegramCfg?.enabled !== false;
|
||||
const { token: telegramToken, source: tokenSource } = telegramEnabled
|
||||
? resolveTelegramToken(cfg)
|
||||
: { token: "", source: "none" as const };
|
||||
let telegramProbe: TelegramProbe | undefined;
|
||||
let lastProbeAt: number | null = null;
|
||||
if (probe && telegramToken && telegramEnabled) {
|
||||
telegramProbe = await probeTelegram(
|
||||
telegramToken,
|
||||
timeoutMs,
|
||||
telegramCfg?.proxy,
|
||||
);
|
||||
lastProbeAt = Date.now();
|
||||
}
|
||||
|
||||
const discordCfg = cfg.discord;
|
||||
const discordEnabled = Boolean(discordCfg) && discordCfg?.enabled !== false;
|
||||
const discordEnvToken = discordEnabled
|
||||
? process.env.DISCORD_BOT_TOKEN?.trim()
|
||||
: "";
|
||||
const discordConfigToken = discordEnabled
|
||||
? discordCfg?.token?.trim()
|
||||
: "";
|
||||
const discordToken = discordEnvToken || discordConfigToken || "";
|
||||
const discordTokenSource = discordEnvToken
|
||||
? "env"
|
||||
: discordConfigToken
|
||||
? "config"
|
||||
: "none";
|
||||
let discordProbe: DiscordProbe | undefined;
|
||||
let discordLastProbeAt: number | null = null;
|
||||
if (probe && discordToken && discordEnabled) {
|
||||
discordProbe = await probeDiscord(discordToken, timeoutMs);
|
||||
discordLastProbeAt = Date.now();
|
||||
}
|
||||
|
||||
const signalCfg = cfg.signal;
|
||||
const signalEnabled = signalCfg?.enabled !== false;
|
||||
const signalHost = signalCfg?.httpHost?.trim() || "127.0.0.1";
|
||||
const signalPort = signalCfg?.httpPort ?? 8080;
|
||||
const signalBaseUrl =
|
||||
signalCfg?.httpUrl?.trim() || `http://${signalHost}:${signalPort}`;
|
||||
const signalConfigured =
|
||||
Boolean(signalCfg) &&
|
||||
signalEnabled &&
|
||||
Boolean(
|
||||
signalCfg?.account?.trim() ||
|
||||
signalCfg?.httpUrl?.trim() ||
|
||||
signalCfg?.cliPath?.trim() ||
|
||||
signalCfg?.httpHost?.trim() ||
|
||||
typeof signalCfg?.httpPort === "number" ||
|
||||
typeof signalCfg?.autoStart === "boolean",
|
||||
);
|
||||
let signalProbe: SignalProbe | undefined;
|
||||
let signalLastProbeAt: number | null = null;
|
||||
if (probe && signalConfigured) {
|
||||
signalProbe = await probeSignal(signalBaseUrl, timeoutMs);
|
||||
signalLastProbeAt = Date.now();
|
||||
}
|
||||
|
||||
const imessageCfg = cfg.imessage;
|
||||
const imessageEnabled = imessageCfg?.enabled !== false;
|
||||
const imessageConfigured = Boolean(imessageCfg) && imessageEnabled;
|
||||
let imessageProbe: IMessageProbe | undefined;
|
||||
let imessageLastProbeAt: number | null = null;
|
||||
if (probe && imessageConfigured) {
|
||||
imessageProbe = await probeIMessage(timeoutMs);
|
||||
imessageLastProbeAt = Date.now();
|
||||
}
|
||||
|
||||
const linked = await webAuthExists();
|
||||
const authAgeMs = getWebAuthAgeMs();
|
||||
const self = readWebSelfId();
|
||||
const runtime = context.getRuntimeSnapshot();
|
||||
|
||||
respond(
|
||||
true,
|
||||
{
|
||||
ts: Date.now(),
|
||||
whatsapp: {
|
||||
configured: linked,
|
||||
linked,
|
||||
authAgeMs,
|
||||
self,
|
||||
running: runtime.whatsapp.running,
|
||||
connected: runtime.whatsapp.connected,
|
||||
lastConnectedAt: runtime.whatsapp.lastConnectedAt ?? null,
|
||||
lastDisconnect: runtime.whatsapp.lastDisconnect ?? null,
|
||||
reconnectAttempts: runtime.whatsapp.reconnectAttempts,
|
||||
lastMessageAt: runtime.whatsapp.lastMessageAt ?? null,
|
||||
lastEventAt: runtime.whatsapp.lastEventAt ?? null,
|
||||
lastError: runtime.whatsapp.lastError ?? null,
|
||||
},
|
||||
telegram: {
|
||||
configured: telegramEnabled && Boolean(telegramToken),
|
||||
tokenSource,
|
||||
running: runtime.telegram.running,
|
||||
mode: runtime.telegram.mode ?? null,
|
||||
lastStartAt: runtime.telegram.lastStartAt ?? null,
|
||||
lastStopAt: runtime.telegram.lastStopAt ?? null,
|
||||
lastError: runtime.telegram.lastError ?? null,
|
||||
probe: telegramProbe,
|
||||
lastProbeAt,
|
||||
},
|
||||
discord: {
|
||||
configured: discordEnabled && Boolean(discordToken),
|
||||
tokenSource: discordTokenSource,
|
||||
running: runtime.discord.running,
|
||||
lastStartAt: runtime.discord.lastStartAt ?? null,
|
||||
lastStopAt: runtime.discord.lastStopAt ?? null,
|
||||
lastError: runtime.discord.lastError ?? null,
|
||||
probe: discordProbe,
|
||||
lastProbeAt: discordLastProbeAt,
|
||||
},
|
||||
signal: {
|
||||
configured: signalConfigured,
|
||||
baseUrl: signalBaseUrl,
|
||||
running: runtime.signal.running,
|
||||
lastStartAt: runtime.signal.lastStartAt ?? null,
|
||||
lastStopAt: runtime.signal.lastStopAt ?? null,
|
||||
lastError: runtime.signal.lastError ?? null,
|
||||
probe: signalProbe,
|
||||
lastProbeAt: signalLastProbeAt,
|
||||
},
|
||||
imessage: {
|
||||
configured: imessageConfigured,
|
||||
running: runtime.imessage.running,
|
||||
lastStartAt: runtime.imessage.lastStartAt ?? null,
|
||||
lastStopAt: runtime.imessage.lastStopAt ?? null,
|
||||
lastError: runtime.imessage.lastError ?? null,
|
||||
cliPath: runtime.imessage.cliPath ?? null,
|
||||
dbPath: runtime.imessage.dbPath ?? null,
|
||||
probe: imessageProbe,
|
||||
lastProbeAt: imessageLastProbeAt,
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
);
|
||||
},
|
||||
"telegram.logout": async ({ respond, context }) => {
|
||||
try {
|
||||
await context.stopTelegramProvider();
|
||||
const snapshot = await readConfigFileSnapshot();
|
||||
if (!snapshot.valid) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
"config invalid; fix it before logging out",
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
const cfg = snapshot.config ?? {};
|
||||
const envToken = process.env.TELEGRAM_BOT_TOKEN?.trim() ?? "";
|
||||
const hadToken = Boolean(cfg.telegram?.botToken);
|
||||
const nextTelegram = cfg.telegram ? { ...cfg.telegram } : undefined;
|
||||
if (nextTelegram) {
|
||||
delete nextTelegram.botToken;
|
||||
}
|
||||
const nextCfg = { ...cfg } as ClawdisConfig;
|
||||
if (nextTelegram && Object.keys(nextTelegram).length > 0) {
|
||||
nextCfg.telegram = nextTelegram;
|
||||
} else {
|
||||
delete nextCfg.telegram;
|
||||
}
|
||||
await writeConfigFile(nextCfg);
|
||||
respond(true, { cleared: hadToken, envToken: Boolean(envToken) }, undefined);
|
||||
} catch (err) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(ErrorCodes.UNAVAILABLE, formatForLog(err)),
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user