mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:50:43 +00:00
fix(telegram): require numeric allowFrom ids in setup
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import type { TelegramNetworkConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { ChannelSetupAdapter } from "openclaw/plugin-sdk/setup-runtime";
|
||||
import {
|
||||
createEnvPatchedAccountSetupAdapter,
|
||||
@@ -11,7 +10,6 @@ import {
|
||||
import { formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
||||
import { resolveDefaultTelegramAccountId, resolveTelegramAccount } from "./accounts.js";
|
||||
import { isNumericTelegramSenderUserId } from "./allow-from.js";
|
||||
import { lookupTelegramChatId } from "./api-fetch.js";
|
||||
|
||||
const channel = "telegram" as const;
|
||||
|
||||
@@ -44,36 +42,6 @@ export function parseTelegramAllowFromId(raw: string): string | null {
|
||||
return isNumericTelegramSenderUserId(stripped) ? stripped : null;
|
||||
}
|
||||
|
||||
export async function resolveTelegramAllowFromEntries(params: {
|
||||
entries: string[];
|
||||
credentialValue?: string;
|
||||
apiRoot?: string;
|
||||
proxyUrl?: string;
|
||||
network?: TelegramNetworkConfig;
|
||||
}) {
|
||||
return await Promise.all(
|
||||
params.entries.map(async (entry) => {
|
||||
const numericId = parseTelegramAllowFromId(entry);
|
||||
if (numericId) {
|
||||
return { input: entry, resolved: true, id: numericId };
|
||||
}
|
||||
const stripped = normalizeTelegramAllowFromInput(entry);
|
||||
if (!stripped || !params.credentialValue?.trim()) {
|
||||
return { input: entry, resolved: false, id: null };
|
||||
}
|
||||
const username = stripped.startsWith("@") ? stripped : `@${stripped}`;
|
||||
const id = await lookupTelegramChatId({
|
||||
token: params.credentialValue,
|
||||
chatId: username,
|
||||
apiRoot: params.apiRoot,
|
||||
proxyUrl: params.proxyUrl,
|
||||
network: params.network,
|
||||
});
|
||||
return { input: entry, resolved: Boolean(id), id };
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export async function promptTelegramAllowFromForAccount(params: {
|
||||
cfg: OpenClawConfig;
|
||||
prompter: WizardPrompter;
|
||||
@@ -82,30 +50,20 @@ export async function promptTelegramAllowFromForAccount(params: {
|
||||
const accountId = params.accountId ?? resolveDefaultTelegramAccountId(params.cfg);
|
||||
const resolved = resolveTelegramAccount({ cfg: params.cfg, accountId });
|
||||
await params.prompter.note(TELEGRAM_USER_ID_HELP_LINES.join("\n"), "Telegram user id");
|
||||
if (!resolved.token?.trim()) {
|
||||
await params.prompter.note(
|
||||
"Telegram token missing; username lookup is unavailable.",
|
||||
"Telegram",
|
||||
);
|
||||
}
|
||||
const unique = await promptResolvedAllowFrom({
|
||||
prompter: params.prompter,
|
||||
existing: resolved.config.allowFrom ?? [],
|
||||
token: resolved.token,
|
||||
message: "Telegram allowFrom (numeric sender id; @username resolves to id)",
|
||||
placeholder: "@username",
|
||||
message: "Telegram allowFrom (numeric sender id)",
|
||||
placeholder: "123456789",
|
||||
label: "Telegram allowlist",
|
||||
parseInputs: splitSetupEntries,
|
||||
parseId: parseTelegramAllowFromId,
|
||||
invalidWithoutTokenNote:
|
||||
"Telegram token missing; use numeric sender ids (usernames require a bot token).",
|
||||
resolveEntries: async ({ entries, token }) =>
|
||||
resolveTelegramAllowFromEntries({
|
||||
credentialValue: token,
|
||||
entries,
|
||||
apiRoot: resolved.config.apiRoot,
|
||||
proxyUrl: resolved.config.proxy,
|
||||
network: resolved.config.network,
|
||||
"Telegram allowFrom requires numeric sender ids. DM your bot first, then copy from.id from logs or getUpdates.",
|
||||
resolveEntries: async ({ entries }) =>
|
||||
entries.map((entry) => {
|
||||
const id = parseTelegramAllowFromId(entry);
|
||||
return { input: entry, resolved: Boolean(id), id };
|
||||
}),
|
||||
});
|
||||
return patchChannelConfigForAccount({
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/setup";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { resolveTelegramAllowFromEntries } from "./setup-core.js";
|
||||
import {
|
||||
buildTelegramDmAccessWarningLines,
|
||||
ensureTelegramDefaultGroupMentionGate,
|
||||
shouldShowTelegramDmAccessWarning,
|
||||
telegramSetupDmPolicy,
|
||||
} from "./setup-surface.helpers.js";
|
||||
import { telegramSetupWizard } from "./setup-surface.js";
|
||||
|
||||
describe("ensureTelegramDefaultGroupMentionGate", () => {
|
||||
it('adds groups["*"].requireMention=true for fresh setups', async () => {
|
||||
@@ -167,45 +167,26 @@ describe("telegramSetupDmPolicy", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveTelegramAllowFromEntries", () => {
|
||||
it("passes apiRoot through username lookups", async () => {
|
||||
describe("telegramSetupWizard allowFrom", () => {
|
||||
it("accepts numeric sender ids only", async () => {
|
||||
const globalFetch = vi.fn(async () => {
|
||||
throw new Error("global fetch should not be called");
|
||||
});
|
||||
const fetchMock = vi.fn(async () => ({
|
||||
ok: true,
|
||||
json: async () => ({ ok: true, result: { id: 12345 } }),
|
||||
}));
|
||||
vi.stubGlobal("fetch", globalFetch);
|
||||
const proxyFetch = vi.fn();
|
||||
const fetchModule = await import("./fetch.js");
|
||||
const proxyModule = await import("./proxy.js");
|
||||
const resolveTelegramFetch = vi.spyOn(fetchModule, "resolveTelegramFetch");
|
||||
const makeProxyFetch = vi.spyOn(proxyModule, "makeProxyFetch");
|
||||
makeProxyFetch.mockReturnValue(proxyFetch as unknown as typeof fetch);
|
||||
resolveTelegramFetch.mockReturnValue(fetchMock as unknown as typeof fetch);
|
||||
|
||||
try {
|
||||
const resolved = await resolveTelegramAllowFromEntries({
|
||||
const resolved = await telegramSetupWizard.allowFrom?.resolveEntries({
|
||||
cfg: {},
|
||||
accountId: DEFAULT_ACCOUNT_ID,
|
||||
credentialValues: { token: "tok" },
|
||||
entries: ["@user"],
|
||||
credentialValue: "tok",
|
||||
apiRoot: "https://custom.telegram.test/root/",
|
||||
proxyUrl: "http://127.0.0.1:8080",
|
||||
network: { autoSelectFamily: false, dnsResultOrder: "ipv4first" },
|
||||
});
|
||||
|
||||
expect(resolved).toEqual([{ input: "@user", resolved: true, id: "12345" }]);
|
||||
expect(makeProxyFetch).toHaveBeenCalledWith("http://127.0.0.1:8080");
|
||||
expect(resolveTelegramFetch).toHaveBeenCalledWith(proxyFetch, {
|
||||
network: { autoSelectFamily: false, dnsResultOrder: "ipv4first" },
|
||||
});
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
"https://custom.telegram.test/root/bottok/getChat?chat_id=%40user",
|
||||
undefined,
|
||||
);
|
||||
expect(telegramSetupWizard.allowFrom?.message).toBe("Telegram allowFrom (numeric sender id)");
|
||||
expect(telegramSetupWizard.allowFrom?.placeholder).toBe("123456789");
|
||||
expect(resolved).toEqual([{ input: "@user", resolved: false, id: null }]);
|
||||
expect(globalFetch).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
makeProxyFetch.mockRestore();
|
||||
resolveTelegramFetch.mockRestore();
|
||||
vi.unstubAllGlobals();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,7 +13,6 @@ import { inspectTelegramAccount } from "./account-inspect.js";
|
||||
import { listTelegramAccountIds, resolveTelegramAccount } from "./accounts.js";
|
||||
import {
|
||||
parseTelegramAllowFromId,
|
||||
resolveTelegramAllowFromEntries,
|
||||
TELEGRAM_TOKEN_HELP_LINES,
|
||||
TELEGRAM_USER_ID_HELP_LINES,
|
||||
telegramSetupAdapter,
|
||||
@@ -79,18 +78,16 @@ export const telegramSetupWizard: ChannelSetupWizard = {
|
||||
allowFrom: createAllowFromSection({
|
||||
helpTitle: "Telegram user id",
|
||||
helpLines: TELEGRAM_USER_ID_HELP_LINES,
|
||||
credentialInputKey: "token",
|
||||
message: "Telegram allowFrom (numeric sender id; @username resolves to id)",
|
||||
placeholder: "@username",
|
||||
message: "Telegram allowFrom (numeric sender id)",
|
||||
placeholder: "123456789",
|
||||
invalidWithoutCredentialNote:
|
||||
"Telegram token missing; use numeric sender ids (usernames require a bot token).",
|
||||
"Telegram allowFrom requires numeric sender ids. DM your bot first, then copy from.id from logs or getUpdates.",
|
||||
parseInputs: splitSetupEntries,
|
||||
parseId: parseTelegramAllowFromId,
|
||||
resolveEntries: async ({ cfg, accountId, credentialValues, entries }) =>
|
||||
resolveTelegramAllowFromEntries({
|
||||
credentialValue: credentialValues.token,
|
||||
entries,
|
||||
apiRoot: resolveTelegramAccount({ cfg, accountId }).config.apiRoot,
|
||||
resolveEntries: async ({ entries }) =>
|
||||
entries.map((entry) => {
|
||||
const id = parseTelegramAllowFromId(entry);
|
||||
return { input: entry, resolved: Boolean(id), id };
|
||||
}),
|
||||
apply: async ({ cfg, accountId, allowFrom }) =>
|
||||
patchChannelConfigForAccount({
|
||||
|
||||
Reference in New Issue
Block a user