refactor(doctor): extract telegram provider warnings (#51704)

* refactor(doctor): extract telegram provider warnings

* docs(changelog): note doctor provider refactor
This commit is contained in:
Vincent Koc
2026-03-21 08:57:06 -07:00
committed by GitHub
parent a90c5092f2
commit a267c5d9ae
4 changed files with 121 additions and 21 deletions

View File

@@ -76,6 +76,7 @@ import {
import { runDoctorConfigPreflight } from "./doctor-config-preflight.js";
import { normalizeCompatibilityConfigValues } from "./doctor-legacy-config.js";
import type { DoctorOptions } from "./doctor-prompter.js";
import { collectTelegramGroupPolicyWarnings } from "./doctor/providers/telegram.js";
type TelegramAllowFromUsernameHit = { path: string; entry: string };
@@ -1330,16 +1331,6 @@ function detectEmptyAllowlistPolicy(cfg: OpenClawConfig): string[] {
);
};
const hasConfiguredGroups = (
account: Record<string, unknown>,
parent?: Record<string, unknown>,
): boolean => {
const groups =
(account.groups as Record<string, unknown> | undefined) ??
(parent?.groups as Record<string, unknown> | undefined);
return Boolean(groups) && Object.keys(groups ?? {}).length > 0;
};
const checkAccount = (
account: Record<string, unknown>,
prefix: string,
@@ -1382,18 +1373,15 @@ function detectEmptyAllowlistPolicy(cfg: OpenClawConfig): string[] {
undefined;
if (groupPolicy === "allowlist" && usesSenderBasedGroupAllowlist(channelName)) {
if (channelName === "telegram" && !hasConfiguredGroups(account, parent)) {
const effectiveDmPolicy = dmPolicy ?? "pairing";
const dmSetupLine =
effectiveDmPolicy === "pairing"
? `DMs use pairing mode, so new senders must start a chat and be approved before regular messages are accepted.`
: effectiveDmPolicy === "allowlist"
? `DMs use allowlist mode, so only sender IDs in ${prefix}.allowFrom are accepted.`
: effectiveDmPolicy === "open"
? `DMs are open.`
: `DMs are disabled.`;
if (channelName === "telegram") {
warnings.push(
`- ${prefix}: Telegram is in first-time setup mode. ${dmSetupLine} Group messages stay blocked until you add allowed chats under ${prefix}.groups (and optional sender IDs under ${prefix}.groupAllowFrom), or set ${prefix}.groupPolicy to "open" if you want broad group access.`,
...collectTelegramGroupPolicyWarnings({
account,
prefix,
effectiveAllowFrom,
dmPolicy,
parent,
}),
);
return;
}

View File

@@ -0,0 +1,56 @@
import { describe, expect, it } from "vitest";
import { collectTelegramGroupPolicyWarnings } from "./telegram.js";
describe("doctor telegram provider warnings", () => {
it("shows first-run guidance when groups are not configured yet", () => {
const warnings = collectTelegramGroupPolicyWarnings({
account: {
botToken: "123:abc",
groupPolicy: "allowlist",
},
prefix: "channels.telegram",
dmPolicy: "pairing",
});
expect(warnings).toEqual([
expect.stringContaining("channels.telegram: Telegram is in first-time setup mode."),
]);
expect(warnings[0]).toContain("DMs use pairing mode");
expect(warnings[0]).toContain("channels.telegram.groups");
});
it("warns when configured groups still have no usable sender allowlist", () => {
const warnings = collectTelegramGroupPolicyWarnings({
account: {
botToken: "123:abc",
groupPolicy: "allowlist",
groups: {
ops: { allow: true },
},
},
prefix: "channels.telegram",
});
expect(warnings).toEqual([
expect.stringContaining(
'channels.telegram.groupPolicy is "allowlist" but groupAllowFrom (and allowFrom) is empty',
),
]);
});
it("stays quiet when allowFrom can satisfy group allowlist mode", () => {
const warnings = collectTelegramGroupPolicyWarnings({
account: {
botToken: "123:abc",
groupPolicy: "allowlist",
groups: {
ops: { allow: true },
},
},
prefix: "channels.telegram",
effectiveAllowFrom: ["123456"],
});
expect(warnings).toEqual([]);
});
});

View File

@@ -0,0 +1,55 @@
type DoctorAccountRecord = Record<string, unknown>;
function hasAllowFromEntries(list?: Array<string | number>) {
return Array.isArray(list) && list.map((v) => String(v).trim()).filter(Boolean).length > 0;
}
function hasConfiguredGroups(account: DoctorAccountRecord, parent?: DoctorAccountRecord): boolean {
const groups =
(account.groups as Record<string, unknown> | undefined) ??
(parent?.groups as Record<string, unknown> | undefined);
return Boolean(groups) && Object.keys(groups ?? {}).length > 0;
}
type CollectTelegramGroupPolicyWarningsParams = {
account: DoctorAccountRecord;
prefix: string;
effectiveAllowFrom?: Array<string | number>;
dmPolicy?: string;
parent?: DoctorAccountRecord;
};
export function collectTelegramGroupPolicyWarnings(
params: CollectTelegramGroupPolicyWarningsParams,
): string[] {
if (!hasConfiguredGroups(params.account, params.parent)) {
const effectiveDmPolicy = params.dmPolicy ?? "pairing";
const dmSetupLine =
effectiveDmPolicy === "pairing"
? "DMs use pairing mode, so new senders must start a chat and be approved before regular messages are accepted."
: effectiveDmPolicy === "allowlist"
? `DMs use allowlist mode, so only sender IDs in ${params.prefix}.allowFrom are accepted.`
: effectiveDmPolicy === "open"
? "DMs are open."
: "DMs are disabled.";
return [
`- ${params.prefix}: Telegram is in first-time setup mode. ${dmSetupLine} Group messages stay blocked until you add allowed chats under ${params.prefix}.groups (and optional sender IDs under ${params.prefix}.groupAllowFrom), or set ${params.prefix}.groupPolicy to "open" if you want broad group access.`,
];
}
const rawGroupAllowFrom =
(params.account.groupAllowFrom as Array<string | number> | undefined) ??
(params.parent?.groupAllowFrom as Array<string | number> | undefined);
// Match runtime semantics: resolveGroupAllowFromSources treats empty arrays as
// unset and falls back to allowFrom.
const groupAllowFrom = hasAllowFromEntries(rawGroupAllowFrom) ? rawGroupAllowFrom : undefined;
const effectiveGroupAllowFrom = groupAllowFrom ?? params.effectiveAllowFrom;
if (hasAllowFromEntries(effectiveGroupAllowFrom)) {
return [];
}
return [
`- ${params.prefix}.groupPolicy is "allowlist" but groupAllowFrom (and allowFrom) is empty — all group messages will be silently dropped. Add sender IDs to ${params.prefix}.groupAllowFrom or ${params.prefix}.allowFrom, or set ${params.prefix}.groupPolicy to "open".`,
];
}