refactor(telegram): share setup wizard base

This commit is contained in:
Peter Steinberger
2026-03-17 03:34:36 +00:00
parent a3474dda33
commit b058077b16
2 changed files with 112 additions and 102 deletions

View File

@@ -6,6 +6,8 @@ import {
normalizeAccountId,
patchChannelConfigForAccount,
promptResolvedAllowFrom,
setSetupChannelEnabled,
setChannelDmPolicyWithAllowFrom,
splitSetupEntries,
type OpenClawConfig,
type WizardPrompter,
@@ -13,9 +15,15 @@ import {
import type {
ChannelSetupAdapter,
ChannelSetupDmPolicy,
ChannelSetupWizard,
} from "../../../src/plugin-sdk-internal/setup.js";
import { formatDocsLink } from "../../../src/terminal/links.js";
import { resolveDefaultTelegramAccountId, resolveTelegramAccount } from "./accounts.js";
import { inspectTelegramAccount } from "./account-inspect.js";
import {
listTelegramAccountIds,
resolveDefaultTelegramAccountId,
resolveTelegramAccount,
} from "./accounts.js";
import { fetchTelegramChatId } from "./api-fetch.js";
const channel = "telegram" as const;
@@ -112,6 +120,91 @@ export async function promptTelegramAllowFromForAccount(params: {
});
}
type TelegramSetupWizardHandlers = {
inspectToken: (params: { cfg: OpenClawConfig; accountId: string }) => {
accountConfigured: boolean;
hasConfiguredValue: boolean;
resolvedValue?: string;
envValue?: string;
};
};
export function createTelegramSetupWizardBase(
handlers: TelegramSetupWizardHandlers,
): ChannelSetupWizard {
const dmPolicy: ChannelSetupDmPolicy = {
label: "Telegram",
channel,
policyKey: "channels.telegram.dmPolicy",
allowFromKey: "channels.telegram.allowFrom",
getCurrent: (cfg) => cfg.channels?.telegram?.dmPolicy ?? "pairing",
setPolicy: (cfg, policy) =>
setChannelDmPolicyWithAllowFrom({
cfg,
channel,
dmPolicy: policy,
}),
promptAllowFrom: promptTelegramAllowFromForAccount,
};
return {
channel,
status: {
configuredLabel: "configured",
unconfiguredLabel: "needs token",
configuredHint: "recommended · configured",
unconfiguredHint: "recommended · newcomer-friendly",
configuredScore: 1,
unconfiguredScore: 10,
resolveConfigured: ({ cfg }) =>
listTelegramAccountIds(cfg).some((accountId) => {
const account = inspectTelegramAccount({ cfg, accountId });
return account.configured;
}),
},
credentials: [
{
inputKey: "token",
providerHint: channel,
credentialLabel: "Telegram bot token",
preferredEnvVar: "TELEGRAM_BOT_TOKEN",
helpTitle: "Telegram bot token",
helpLines: TELEGRAM_TOKEN_HELP_LINES,
envPrompt: "TELEGRAM_BOT_TOKEN detected. Use env var?",
keepPrompt: "Telegram token already configured. Keep it?",
inputPrompt: "Enter Telegram bot token",
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
inspect: ({ cfg, accountId }) => handlers.inspectToken({ cfg, accountId }),
},
],
allowFrom: {
helpTitle: "Telegram user id",
helpLines: TELEGRAM_USER_ID_HELP_LINES,
credentialInputKey: "token",
message: "Telegram allowFrom (numeric sender id; @username resolves to id)",
placeholder: "@username",
invalidWithoutCredentialNote:
"Telegram token missing; use numeric sender ids (usernames require a bot token).",
parseInputs: splitSetupEntries,
parseId: parseTelegramAllowFromId,
resolveEntries: async ({ credentialValues, entries }) =>
resolveTelegramAllowFromEntries({
credentialValue: credentialValues.token,
entries,
}),
apply: async ({ cfg, accountId, allowFrom }) =>
patchChannelConfigForAccount({
cfg,
channel,
accountId,
patch: { dmPolicy: "allowlist", allowFrom },
}),
},
dmPolicy,
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
} satisfies ChannelSetupWizard;
}
export const telegramSetupAdapter: ChannelSetupAdapter = {
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
applyAccountName: ({ cfg, accountId, name }) =>

View File

@@ -1,113 +1,30 @@
import {
DEFAULT_ACCOUNT_ID,
hasConfiguredSecretInput,
type OpenClawConfig,
patchChannelConfigForAccount,
setChannelDmPolicyWithAllowFrom,
setSetupChannelEnabled,
splitSetupEntries,
} from "../../../src/plugin-sdk-internal/setup.js";
import type {
ChannelSetupDmPolicy,
ChannelSetupWizard,
} from "../../../src/plugin-sdk-internal/setup.js";
import { inspectTelegramAccount } from "./account-inspect.js";
import { listTelegramAccountIds, resolveTelegramAccount } from "./accounts.js";
import type { ChannelSetupWizard } from "../../../src/plugin-sdk-internal/setup.js";
import { resolveTelegramAccount } from "./accounts.js";
import {
createTelegramSetupWizardBase,
parseTelegramAllowFromId,
promptTelegramAllowFromForAccount,
resolveTelegramAllowFromEntries,
TELEGRAM_TOKEN_HELP_LINES,
TELEGRAM_USER_ID_HELP_LINES,
telegramSetupAdapter,
} from "./setup-core.js";
const channel = "telegram" as const;
const dmPolicy: ChannelSetupDmPolicy = {
label: "Telegram",
channel,
policyKey: "channels.telegram.dmPolicy",
allowFromKey: "channels.telegram.allowFrom",
getCurrent: (cfg) => cfg.channels?.telegram?.dmPolicy ?? "pairing",
setPolicy: (cfg, policy) =>
setChannelDmPolicyWithAllowFrom({
cfg,
channel,
dmPolicy: policy,
}),
promptAllowFrom: promptTelegramAllowFromForAccount,
};
export const telegramSetupWizard: ChannelSetupWizard = {
channel,
status: {
configuredLabel: "configured",
unconfiguredLabel: "needs token",
configuredHint: "recommended · configured",
unconfiguredHint: "recommended · newcomer-friendly",
configuredScore: 1,
unconfiguredScore: 10,
resolveConfigured: ({ cfg }) =>
listTelegramAccountIds(cfg).some((accountId) => {
const account = inspectTelegramAccount({ cfg, accountId });
return account.configured;
}),
export const telegramSetupWizard: ChannelSetupWizard = createTelegramSetupWizardBase({
inspectToken: ({ cfg, accountId }) => {
const resolved = resolveTelegramAccount({ cfg, accountId });
const hasConfiguredBotToken = hasConfiguredSecretInput(resolved.config.botToken);
const hasConfiguredValue = hasConfiguredBotToken || Boolean(resolved.config.tokenFile?.trim());
return {
accountConfigured: Boolean(resolved.token) || hasConfiguredValue,
hasConfiguredValue,
resolvedValue: resolved.token?.trim() || undefined,
envValue:
accountId === DEFAULT_ACCOUNT_ID
? process.env.TELEGRAM_BOT_TOKEN?.trim() || undefined
: undefined,
};
},
credentials: [
{
inputKey: "token",
providerHint: channel,
credentialLabel: "Telegram bot token",
preferredEnvVar: "TELEGRAM_BOT_TOKEN",
helpTitle: "Telegram bot token",
helpLines: TELEGRAM_TOKEN_HELP_LINES,
envPrompt: "TELEGRAM_BOT_TOKEN detected. Use env var?",
keepPrompt: "Telegram token already configured. Keep it?",
inputPrompt: "Enter Telegram bot token",
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
inspect: ({ cfg, accountId }) => {
const resolved = resolveTelegramAccount({ cfg, accountId });
const hasConfiguredBotToken = hasConfiguredSecretInput(resolved.config.botToken);
const hasConfiguredValue =
hasConfiguredBotToken || Boolean(resolved.config.tokenFile?.trim());
return {
accountConfigured: Boolean(resolved.token) || hasConfiguredValue,
hasConfiguredValue,
resolvedValue: resolved.token?.trim() || undefined,
envValue:
accountId === DEFAULT_ACCOUNT_ID
? process.env.TELEGRAM_BOT_TOKEN?.trim() || undefined
: undefined,
};
},
},
],
allowFrom: {
helpTitle: "Telegram user id",
helpLines: TELEGRAM_USER_ID_HELP_LINES,
credentialInputKey: "token",
message: "Telegram allowFrom (numeric sender id; @username resolves to id)",
placeholder: "@username",
invalidWithoutCredentialNote:
"Telegram token missing; use numeric sender ids (usernames require a bot token).",
parseInputs: splitSetupEntries,
parseId: parseTelegramAllowFromId,
resolveEntries: async ({ credentialValues, entries }) =>
resolveTelegramAllowFromEntries({
credentialValue: credentialValues.token,
entries,
}),
apply: async ({ cfg, accountId, allowFrom }) =>
patchChannelConfigForAccount({
cfg,
channel,
accountId,
patch: { dmPolicy: "allowlist", allowFrom },
}),
},
dmPolicy,
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
};
});
export { parseTelegramAllowFromId, telegramSetupAdapter };