* refactor: move Telegram channel implementation to extensions/telegram/src/ Move all Telegram channel code (123 files + 10 bot/ files + 8 channel plugin files) from src/telegram/ and src/channels/plugins/*/telegram.ts to extensions/telegram/src/. Leave thin re-export shims at original locations so cross-cutting src/ imports continue to resolve. - Fix all relative import paths in moved files (../X/ -> ../../../src/X/) - Fix vi.mock paths in 60 test files - Fix inline typeof import() expressions - Update tsconfig.plugin-sdk.dts.json rootDir to "." for cross-directory DTS - Update write-plugin-sdk-entry-dts.ts for new rootDir structure - Move channel plugin files with correct path remapping * fix: support keyed telegram send deps * fix: sync telegram extension copies with latest main * fix: correct import paths and remove misplaced files in telegram extension * fix: sync outbound-adapter with main (add sendTelegramPayloadMessages) and fix delivery.test import path
77 lines
2.6 KiB
TypeScript
77 lines
2.6 KiB
TypeScript
import { isRecord } from "../../../src/utils.js";
|
|
import { fetchWithTimeout } from "../../../src/utils/fetch-timeout.js";
|
|
import type {
|
|
AuditTelegramGroupMembershipParams,
|
|
TelegramGroupMembershipAudit,
|
|
TelegramGroupMembershipAuditEntry,
|
|
} from "./audit.js";
|
|
import { resolveTelegramFetch } from "./fetch.js";
|
|
import { makeProxyFetch } from "./proxy.js";
|
|
|
|
const TELEGRAM_API_BASE = "https://api.telegram.org";
|
|
|
|
type TelegramApiOk<T> = { ok: true; result: T };
|
|
type TelegramApiErr = { ok: false; description?: string };
|
|
type TelegramGroupMembershipAuditData = Omit<TelegramGroupMembershipAudit, "elapsedMs">;
|
|
|
|
export async function auditTelegramGroupMembershipImpl(
|
|
params: AuditTelegramGroupMembershipParams,
|
|
): Promise<TelegramGroupMembershipAuditData> {
|
|
const proxyFetch = params.proxyUrl ? makeProxyFetch(params.proxyUrl) : undefined;
|
|
const fetcher = resolveTelegramFetch(proxyFetch, { network: params.network });
|
|
const base = `${TELEGRAM_API_BASE}/bot${params.token}`;
|
|
const groups: TelegramGroupMembershipAuditEntry[] = [];
|
|
|
|
for (const chatId of params.groupIds) {
|
|
try {
|
|
const url = `${base}/getChatMember?chat_id=${encodeURIComponent(chatId)}&user_id=${encodeURIComponent(String(params.botId))}`;
|
|
const res = await fetchWithTimeout(url, {}, params.timeoutMs, fetcher);
|
|
const json = (await res.json()) as TelegramApiOk<{ status?: string }> | TelegramApiErr;
|
|
if (!res.ok || !isRecord(json) || !json.ok) {
|
|
const desc =
|
|
isRecord(json) && !json.ok && typeof json.description === "string"
|
|
? json.description
|
|
: `getChatMember failed (${res.status})`;
|
|
groups.push({
|
|
chatId,
|
|
ok: false,
|
|
status: null,
|
|
error: desc,
|
|
matchKey: chatId,
|
|
matchSource: "id",
|
|
});
|
|
continue;
|
|
}
|
|
const status = isRecord((json as TelegramApiOk<unknown>).result)
|
|
? ((json as TelegramApiOk<{ status?: string }>).result.status ?? null)
|
|
: null;
|
|
const ok = status === "creator" || status === "administrator" || status === "member";
|
|
groups.push({
|
|
chatId,
|
|
ok,
|
|
status,
|
|
error: ok ? null : "bot not in group",
|
|
matchKey: chatId,
|
|
matchSource: "id",
|
|
});
|
|
} catch (err) {
|
|
groups.push({
|
|
chatId,
|
|
ok: false,
|
|
status: null,
|
|
error: err instanceof Error ? err.message : String(err),
|
|
matchKey: chatId,
|
|
matchSource: "id",
|
|
});
|
|
}
|
|
}
|
|
|
|
return {
|
|
ok: groups.every((g) => g.ok),
|
|
checkedGroups: groups.length,
|
|
unresolvedGroups: 0,
|
|
hasWildcardUnmentionedGroups: false,
|
|
groups,
|
|
};
|
|
}
|