style: format

This commit is contained in:
Peter Steinberger
2026-01-09 00:31:24 +01:00
parent 71309c064a
commit 4e92ccc0dd
13 changed files with 66 additions and 50 deletions

View File

@@ -240,15 +240,15 @@ export async function doctorCommand(
} }
} }
if (healthOk) { if (healthOk) {
try { try {
const status = await callGateway<Record<string, unknown>>({ const status = await callGateway<Record<string, unknown>>({
method: "providers.status", method: "providers.status",
params: { probe: true, timeoutMs: 5000 }, params: { probe: true, timeoutMs: 5000 },
timeoutMs: 6000, timeoutMs: 6000,
}); });
const issues = collectProvidersStatusIssues(status); const issues = collectProvidersStatusIssues(status);
if (issues.length > 0) { if (issues.length > 0) {
note( note(
issues issues
.map( .map(

View File

@@ -391,7 +391,12 @@ describe("providers command", () => {
hasWildcardUnmentionedGroups: true, hasWildcardUnmentionedGroups: true,
unresolvedGroups: 1, unresolvedGroups: 1,
groups: [ groups: [
{ chatId: "-1001", ok: false, status: "left", error: "not in group" }, {
chatId: "-1001",
ok: false,
status: "left",
error: "not in group",
},
], ],
}, },
}, },

View File

@@ -79,11 +79,13 @@ export function formatGatewayProvidersStatusLines(
bits.push(account.connected ? "connected" : "disconnected"); bits.push(account.connected ? "connected" : "disconnected");
} }
const inboundAt = const inboundAt =
typeof account.lastInboundAt === "number" && Number.isFinite(account.lastInboundAt) typeof account.lastInboundAt === "number" &&
Number.isFinite(account.lastInboundAt)
? account.lastInboundAt ? account.lastInboundAt
: null; : null;
const outboundAt = const outboundAt =
typeof account.lastOutboundAt === "number" && Number.isFinite(account.lastOutboundAt) typeof account.lastOutboundAt === "number" &&
Number.isFinite(account.lastOutboundAt)
? account.lastOutboundAt ? account.lastOutboundAt
: null; : null;
if (inboundAt) bits.push(`in:${formatAge(Date.now() - inboundAt)}`); if (inboundAt) bits.push(`in:${formatAge(Date.now() - inboundAt)}`);

View File

@@ -27,11 +27,16 @@ describe("discord audit", () => {
}, },
} as unknown as import("../config/config.js").ClawdbotConfig; } as unknown as import("../config/config.js").ClawdbotConfig;
const collected = collectDiscordAuditChannelIds({ cfg, accountId: "default" }); const collected = collectDiscordAuditChannelIds({
cfg,
accountId: "default",
});
expect(collected.channelIds).toEqual(["111"]); expect(collected.channelIds).toEqual(["111"]);
expect(collected.unresolvedChannels).toBe(1); expect(collected.unresolvedChannels).toBe(1);
(fetchChannelPermissionsDiscord as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce({ (
fetchChannelPermissionsDiscord as unknown as ReturnType<typeof vi.fn>
).mockResolvedValueOnce({
channelId: "111", channelId: "111",
permissions: ["ViewChannel"], permissions: ["ViewChannel"],
raw: "0", raw: "0",
@@ -49,4 +54,3 @@ describe("discord audit", () => {
expect(audit.channels[0]?.missing).toContain("SendMessages"); expect(audit.channels[0]?.missing).toContain("SendMessages");
}); });
}); });

View File

@@ -27,7 +27,9 @@ function isRecord(value: unknown): value is Record<string, unknown> {
return Boolean(value) && typeof value === "object" && !Array.isArray(value); return Boolean(value) && typeof value === "object" && !Array.isArray(value);
} }
function shouldAuditChannelConfig(config: DiscordGuildChannelConfig | undefined) { function shouldAuditChannelConfig(
config: DiscordGuildChannelConfig | undefined,
) {
if (!config) return true; if (!config) return true;
if (config.allow === false) return false; if (config.allow === false) return false;
if (config.enabled === false) return false; if (config.enabled === false) return false;
@@ -46,7 +48,11 @@ function listConfiguredGuildChannelKeys(
for (const [key, value] of Object.entries(channelsRaw)) { for (const [key, value] of Object.entries(channelsRaw)) {
const channelId = String(key).trim(); const channelId = String(key).trim();
if (!channelId) continue; if (!channelId) continue;
if (!shouldAuditChannelConfig(value as DiscordGuildChannelConfig | undefined)) if (
!shouldAuditChannelConfig(
value as DiscordGuildChannelConfig | undefined,
)
)
continue; continue;
ids.add(channelId); ids.add(channelId);
} }
@@ -119,4 +125,3 @@ export async function auditDiscordChannelPermissions(params: {
elapsedMs: Date.now() - started, elapsedMs: Date.now() - started,
}; };
} }

View File

@@ -18,6 +18,7 @@ import {
} from "discord-api-types/v10"; } from "discord-api-types/v10";
import { loadConfig } from "../config/config.js"; import { loadConfig } from "../config/config.js";
import { recordProviderActivity } from "../infra/provider-activity.js";
import type { RetryConfig } from "../infra/retry.js"; import type { RetryConfig } from "../infra/retry.js";
import { import {
createDiscordRetryRunner, createDiscordRetryRunner,
@@ -32,7 +33,6 @@ import { loadWebMedia, loadWebMediaRaw } from "../web/media.js";
import { resolveDiscordAccount } from "./accounts.js"; import { resolveDiscordAccount } from "./accounts.js";
import { chunkDiscordText } from "./chunk.js"; import { chunkDiscordText } from "./chunk.js";
import { normalizeDiscordToken } from "./token.js"; import { normalizeDiscordToken } from "./token.js";
import { recordProviderActivity } from "../infra/provider-activity.js";
const DISCORD_TEXT_LIMIT = 2000; const DISCORD_TEXT_LIMIT = 2000;
const DISCORD_MAX_STICKERS = 3; const DISCORD_MAX_STICKERS = 3;

View File

@@ -1,15 +1,19 @@
import type { ClawdbotConfig } from "../../config/config.js"; import type { ClawdbotConfig } from "../../config/config.js";
import type { TelegramGroupConfig } from "../../config/types.js";
import { import {
loadConfig, loadConfig,
readConfigFileSnapshot, readConfigFileSnapshot,
writeConfigFile, writeConfigFile,
} from "../../config/config.js"; } from "../../config/config.js";
import type { TelegramGroupConfig } from "../../config/types.js";
import { import {
listDiscordAccountIds, listDiscordAccountIds,
resolveDefaultDiscordAccountId, resolveDefaultDiscordAccountId,
resolveDiscordAccount, resolveDiscordAccount,
} from "../../discord/accounts.js"; } from "../../discord/accounts.js";
import {
auditDiscordChannelPermissions,
collectDiscordAuditChannelIds,
} from "../../discord/audit.js";
import { type DiscordProbe, probeDiscord } from "../../discord/probe.js"; import { type DiscordProbe, probeDiscord } from "../../discord/probe.js";
import { import {
listIMessageAccountIds, listIMessageAccountIds,
@@ -17,6 +21,7 @@ import {
resolveIMessageAccount, resolveIMessageAccount,
} from "../../imessage/accounts.js"; } from "../../imessage/accounts.js";
import { type IMessageProbe, probeIMessage } from "../../imessage/probe.js"; import { type IMessageProbe, probeIMessage } from "../../imessage/probe.js";
import { getProviderActivity } from "../../infra/provider-activity.js";
import { import {
listSignalAccountIds, listSignalAccountIds,
resolveDefaultSignalAccountId, resolveDefaultSignalAccountId,
@@ -34,6 +39,10 @@ import {
resolveDefaultTelegramAccountId, resolveDefaultTelegramAccountId,
resolveTelegramAccount, resolveTelegramAccount,
} from "../../telegram/accounts.js"; } from "../../telegram/accounts.js";
import {
auditTelegramGroupMembership,
collectTelegramUnmentionedGroupIds,
} from "../../telegram/audit.js";
import { probeTelegram, type TelegramProbe } from "../../telegram/probe.js"; import { probeTelegram, type TelegramProbe } from "../../telegram/probe.js";
import { import {
listEnabledWhatsAppAccounts, listEnabledWhatsAppAccounts,
@@ -52,15 +61,6 @@ import {
} from "../protocol/index.js"; } from "../protocol/index.js";
import { formatForLog } from "../ws-log.js"; import { formatForLog } from "../ws-log.js";
import type { GatewayRequestHandlers } from "./types.js"; import type { GatewayRequestHandlers } from "./types.js";
import { getProviderActivity } from "../../infra/provider-activity.js";
import {
auditDiscordChannelPermissions,
collectDiscordAuditChannelIds,
} from "../../discord/audit.js";
import {
auditTelegramGroupMembership,
collectTelegramUnmentionedGroupIds,
} from "../../telegram/audit.js";
export const providersHandlers: GatewayRequestHandlers = { export const providersHandlers: GatewayRequestHandlers = {
"providers.status": async ({ params, respond, context }) => { "providers.status": async ({ params, respond, context }) => {

View File

@@ -39,17 +39,17 @@ describe("provider activity", () => {
direction: "inbound", direction: "inbound",
at: 2, at: 2,
}); });
expect(getProviderActivity({ provider: "whatsapp", accountId: "a" })).toEqual( expect(
{ getProviderActivity({ provider: "whatsapp", accountId: "a" }),
inboundAt: 1, ).toEqual({
outboundAt: null, inboundAt: 1,
}, outboundAt: null,
); });
expect(getProviderActivity({ provider: "whatsapp", accountId: "b" })).toEqual( expect(
{ getProviderActivity({ provider: "whatsapp", accountId: "b" }),
inboundAt: 2, ).toEqual({
outboundAt: null, inboundAt: 2,
}, outboundAt: null,
); });
}); });
}); });

View File

@@ -50,4 +50,3 @@ export function getProviderActivity(params: {
export function resetProviderActivityForTest() { export function resetProviderActivityForTest() {
activity.clear(); activity.clear();
} }

View File

@@ -343,4 +343,3 @@ export function collectProvidersStatusIssues(
return issues; return issues;
} }

View File

@@ -24,10 +24,13 @@ describe("telegram audit", () => {
vi.stubGlobal( vi.stubGlobal(
"fetch", "fetch",
vi.fn().mockResolvedValueOnce( vi.fn().mockResolvedValueOnce(
new Response(JSON.stringify({ ok: true, result: { status: "member" } }), { new Response(
status: 200, JSON.stringify({ ok: true, result: { status: "member" } }),
headers: { "Content-Type": "application/json" }, {
}), status: 200,
headers: { "Content-Type": "application/json" },
},
),
), ),
); );
const res = await auditTelegramGroupMembership({ const res = await auditTelegramGroupMembership({
@@ -63,4 +66,3 @@ describe("telegram audit", () => {
expect(res.groups[0]?.status).toBe("left"); expect(res.groups[0]?.status).toBe("left");
}); });
}); });

View File

@@ -38,6 +38,7 @@ import {
} from "../config/sessions.js"; } from "../config/sessions.js";
import { danger, logVerbose, shouldLogVerbose } from "../globals.js"; import { danger, logVerbose, shouldLogVerbose } from "../globals.js";
import { formatErrorMessage } from "../infra/errors.js"; import { formatErrorMessage } from "../infra/errors.js";
import { recordProviderActivity } from "../infra/provider-activity.js";
import { getChildLogger } from "../logging.js"; import { getChildLogger } from "../logging.js";
import { mediaKindFromMime } from "../media/constants.js"; import { mediaKindFromMime } from "../media/constants.js";
import { detectMime, isGifMedia } from "../media/mime.js"; import { detectMime, isGifMedia } from "../media/mime.js";
@@ -50,7 +51,6 @@ import {
import { resolveAgentRoute } from "../routing/resolve-route.js"; import { resolveAgentRoute } from "../routing/resolve-route.js";
import type { RuntimeEnv } from "../runtime.js"; import type { RuntimeEnv } from "../runtime.js";
import { loadWebMedia } from "../web/media.js"; import { loadWebMedia } from "../web/media.js";
import { recordProviderActivity } from "../infra/provider-activity.js";
import { resolveTelegramAccount } from "./accounts.js"; import { resolveTelegramAccount } from "./accounts.js";
import { createTelegramDraftStream } from "./draft-stream.js"; import { createTelegramDraftStream } from "./draft-stream.js";
import { resolveTelegramFetch } from "./fetch.js"; import { resolveTelegramFetch } from "./fetch.js";

View File

@@ -3,9 +3,9 @@ import type { ApiClientOptions } from "grammy";
import { Bot, InputFile } from "grammy"; import { Bot, InputFile } from "grammy";
import { loadConfig } from "../config/config.js"; import { loadConfig } from "../config/config.js";
import { formatErrorMessage } from "../infra/errors.js"; import { formatErrorMessage } from "../infra/errors.js";
import { recordProviderActivity } from "../infra/provider-activity.js";
import type { RetryConfig } from "../infra/retry.js"; import type { RetryConfig } from "../infra/retry.js";
import { createTelegramRetryRunner } from "../infra/retry-policy.js"; import { createTelegramRetryRunner } from "../infra/retry-policy.js";
import { recordProviderActivity } from "../infra/provider-activity.js";
import { mediaKindFromMime } from "../media/constants.js"; import { mediaKindFromMime } from "../media/constants.js";
import { isGifMedia } from "../media/mime.js"; import { isGifMedia } from "../media/mime.js";
import { loadWebMedia } from "../web/media.js"; import { loadWebMedia } from "../web/media.js";