mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 14:50:21 +00:00
refactor: deduplicate channel runtime helpers
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import { buildAccountScopedAllowlistConfigEditor } from "openclaw/plugin-sdk/allowlist-config-edit";
|
||||
import {
|
||||
collectAllowlistProviderGroupPolicyWarnings,
|
||||
collectOpenGroupPolicyRouteAllowlistWarnings,
|
||||
createScopedDmSecurityResolver,
|
||||
} from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import { type OutboundSendDeps, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { normalizeMessageChannel } from "openclaw/plugin-sdk/channel-runtime";
|
||||
buildDmGroupAccountAllowlistAdapter,
|
||||
createNestedAllowlistOverrideResolver,
|
||||
} from "openclaw/plugin-sdk/allowlist-config-edit";
|
||||
import { createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import { createAllowlistProviderRouteAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy";
|
||||
import {
|
||||
createChannelDirectoryAdapter,
|
||||
createPairingPrefixStripper,
|
||||
createTextPairingAdapter,
|
||||
normalizeMessageChannel,
|
||||
type OutboundSendDeps,
|
||||
resolveOutboundSendDep,
|
||||
} from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { buildOutboundBaseSessionKey, normalizeOutboundThreadId } from "openclaw/plugin-sdk/core";
|
||||
import { resolveExecApprovalCommandDisplay } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { buildExecApprovalPendingReplyPayload } from "openclaw/plugin-sdk/infra-runtime";
|
||||
@@ -273,65 +279,66 @@ const resolveTelegramDmPolicy = createScopedDmSecurityResolver<ResolvedTelegramA
|
||||
normalizeEntry: (raw) => raw.replace(/^(telegram|tg):/i, ""),
|
||||
});
|
||||
|
||||
function readTelegramAllowlistConfig(account: ResolvedTelegramAccount) {
|
||||
const groupOverrides: Array<{ label: string; entries: string[] }> = [];
|
||||
for (const [groupId, groupCfg] of Object.entries(account.config.groups ?? {})) {
|
||||
const entries = (groupCfg?.allowFrom ?? []).map(String).filter(Boolean);
|
||||
if (entries.length > 0) {
|
||||
groupOverrides.push({ label: groupId, entries });
|
||||
}
|
||||
for (const [topicId, topicCfg] of Object.entries(groupCfg?.topics ?? {})) {
|
||||
const topicEntries = (topicCfg?.allowFrom ?? []).map(String).filter(Boolean);
|
||||
if (topicEntries.length > 0) {
|
||||
groupOverrides.push({ label: `${groupId} topic ${topicId}`, entries: topicEntries });
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
dmAllowFrom: (account.config.allowFrom ?? []).map(String),
|
||||
groupAllowFrom: (account.config.groupAllowFrom ?? []).map(String),
|
||||
dmPolicy: account.config.dmPolicy,
|
||||
groupPolicy: account.config.groupPolicy,
|
||||
groupOverrides,
|
||||
};
|
||||
}
|
||||
const resolveTelegramAllowlistGroupOverrides = createNestedAllowlistOverrideResolver({
|
||||
resolveRecord: (account: ResolvedTelegramAccount) => account.config.groups,
|
||||
outerLabel: (groupId) => groupId,
|
||||
resolveOuterEntries: (groupCfg) => groupCfg?.allowFrom,
|
||||
resolveChildren: (groupCfg) => groupCfg?.topics,
|
||||
innerLabel: (groupId, topicId) => `${groupId} topic ${topicId}`,
|
||||
resolveInnerEntries: (topicCfg) => topicCfg?.allowFrom,
|
||||
});
|
||||
|
||||
const collectTelegramSecurityWarnings =
|
||||
createAllowlistProviderRouteAllowlistWarningCollector<ResolvedTelegramAccount>({
|
||||
providerConfigPresent: (cfg) => cfg.channels?.telegram !== undefined,
|
||||
resolveGroupPolicy: (account) => account.config.groupPolicy,
|
||||
resolveRouteAllowlistConfigured: (account) =>
|
||||
Boolean(account.config.groups) && Object.keys(account.config.groups ?? {}).length > 0,
|
||||
restrictSenders: {
|
||||
surface: "Telegram groups",
|
||||
openScope: "any member in allowed groups",
|
||||
groupPolicyPath: "channels.telegram.groupPolicy",
|
||||
groupAllowFromPath: "channels.telegram.groupAllowFrom",
|
||||
},
|
||||
noRouteAllowlist: {
|
||||
surface: "Telegram groups",
|
||||
routeAllowlistPath: "channels.telegram.groups",
|
||||
routeScope: "group",
|
||||
groupPolicyPath: "channels.telegram.groupPolicy",
|
||||
groupAllowFromPath: "channels.telegram.groupAllowFrom",
|
||||
},
|
||||
});
|
||||
|
||||
export const telegramPlugin: ChannelPlugin<ResolvedTelegramAccount, TelegramProbe> = {
|
||||
...createTelegramPluginBase({
|
||||
setupWizard: telegramSetupWizard,
|
||||
setup: telegramSetupAdapter,
|
||||
}),
|
||||
pairing: {
|
||||
pairing: createTextPairingAdapter({
|
||||
idLabel: "telegramUserId",
|
||||
normalizeAllowEntry: (entry) => entry.replace(/^(telegram|tg):/i, ""),
|
||||
notifyApproval: async ({ cfg, id }) => {
|
||||
message: PAIRING_APPROVED_MESSAGE,
|
||||
normalizeAllowEntry: createPairingPrefixStripper(/^(telegram|tg):/i),
|
||||
notify: async ({ cfg, id, message }) => {
|
||||
const { token } = getTelegramRuntime().channel.telegram.resolveTelegramToken(cfg);
|
||||
if (!token) {
|
||||
throw new Error("telegram token not configured");
|
||||
}
|
||||
await getTelegramRuntime().channel.telegram.sendMessageTelegram(
|
||||
id,
|
||||
PAIRING_APPROVED_MESSAGE,
|
||||
{
|
||||
token,
|
||||
},
|
||||
);
|
||||
await getTelegramRuntime().channel.telegram.sendMessageTelegram(id, message, {
|
||||
token,
|
||||
});
|
||||
},
|
||||
},
|
||||
allowlist: {
|
||||
supportsScope: ({ scope }) => scope === "dm" || scope === "group" || scope === "all",
|
||||
readConfig: ({ cfg, accountId }) =>
|
||||
readTelegramAllowlistConfig(resolveTelegramAccount({ cfg, accountId })),
|
||||
applyConfigEdit: buildAccountScopedAllowlistConfigEditor({
|
||||
channelId: "telegram",
|
||||
normalize: ({ cfg, accountId, values }) =>
|
||||
telegramConfigAdapter.formatAllowFrom!({ cfg, accountId, allowFrom: values }),
|
||||
resolvePaths: (scope) => ({
|
||||
readPaths: [[scope === "dm" ? "allowFrom" : "groupAllowFrom"]],
|
||||
writePath: [scope === "dm" ? "allowFrom" : "groupAllowFrom"],
|
||||
}),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
allowlist: buildDmGroupAccountAllowlistAdapter({
|
||||
channelId: "telegram",
|
||||
resolveAccount: ({ cfg, accountId }) => resolveTelegramAccount({ cfg, accountId }),
|
||||
normalize: ({ cfg, accountId, values }) =>
|
||||
telegramConfigAdapter.formatAllowFrom!({ cfg, accountId, allowFrom: values }),
|
||||
resolveDmAllowFrom: (account) => account.config.allowFrom,
|
||||
resolveGroupAllowFrom: (account) => account.config.groupAllowFrom,
|
||||
resolveDmPolicy: (account) => account.config.dmPolicy,
|
||||
resolveGroupPolicy: (account) => account.config.groupPolicy,
|
||||
resolveGroupOverrides: resolveTelegramAllowlistGroupOverrides,
|
||||
}),
|
||||
bindings: {
|
||||
compileConfiguredBinding: ({ conversationId }) =>
|
||||
normalizeTelegramAcpConversationId(conversationId),
|
||||
@@ -344,33 +351,7 @@ export const telegramPlugin: ChannelPlugin<ResolvedTelegramAccount, TelegramProb
|
||||
},
|
||||
security: {
|
||||
resolveDmPolicy: resolveTelegramDmPolicy,
|
||||
collectWarnings: ({ account, cfg }) => {
|
||||
const groupAllowlistConfigured =
|
||||
account.config.groups && Object.keys(account.config.groups).length > 0;
|
||||
return collectAllowlistProviderGroupPolicyWarnings({
|
||||
cfg,
|
||||
providerConfigPresent: cfg.channels?.telegram !== undefined,
|
||||
configuredGroupPolicy: account.config.groupPolicy,
|
||||
collect: (groupPolicy) =>
|
||||
collectOpenGroupPolicyRouteAllowlistWarnings({
|
||||
groupPolicy,
|
||||
routeAllowlistConfigured: Boolean(groupAllowlistConfigured),
|
||||
restrictSenders: {
|
||||
surface: "Telegram groups",
|
||||
openScope: "any member in allowed groups",
|
||||
groupPolicyPath: "channels.telegram.groupPolicy",
|
||||
groupAllowFromPath: "channels.telegram.groupAllowFrom",
|
||||
},
|
||||
noRouteAllowlist: {
|
||||
surface: "Telegram groups",
|
||||
routeAllowlistPath: "channels.telegram.groups",
|
||||
routeScope: "group",
|
||||
groupPolicyPath: "channels.telegram.groupPolicy",
|
||||
groupAllowFromPath: "channels.telegram.groupAllowFrom",
|
||||
},
|
||||
}),
|
||||
});
|
||||
},
|
||||
collectWarnings: collectTelegramSecurityWarnings,
|
||||
},
|
||||
groups: {
|
||||
resolveRequireMention: resolveTelegramGroupRequireMention,
|
||||
@@ -471,11 +452,10 @@ export const telegramPlugin: ChannelPlugin<ResolvedTelegramAccount, TelegramProb
|
||||
}).catch(() => {});
|
||||
},
|
||||
},
|
||||
directory: {
|
||||
self: async () => null,
|
||||
directory: createChannelDirectoryAdapter({
|
||||
listPeers: async (params) => listTelegramDirectoryPeersFromConfig(params),
|
||||
listGroups: async (params) => listTelegramDirectoryGroupsFromConfig(params),
|
||||
},
|
||||
}),
|
||||
actions: telegramMessageActions,
|
||||
setup: telegramSetupAdapter,
|
||||
outbound: {
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
import { mapAllowFromEntries } from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import {
|
||||
applyDirectoryQueryAndLimit,
|
||||
collectNormalizedDirectoryIds,
|
||||
listDirectoryGroupEntriesFromMapKeys,
|
||||
toDirectoryEntries,
|
||||
listInspectedDirectoryEntriesFromSources,
|
||||
type DirectoryConfigParams,
|
||||
} from "openclaw/plugin-sdk/directory-runtime";
|
||||
import { inspectTelegramAccount, type InspectedTelegramAccount } from "../api.js";
|
||||
|
||||
export async function listTelegramDirectoryPeersFromConfig(params: DirectoryConfigParams) {
|
||||
const account: InspectedTelegramAccount = inspectTelegramAccount({
|
||||
cfg: params.cfg,
|
||||
accountId: params.accountId,
|
||||
});
|
||||
if (!account.config) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const ids = collectNormalizedDirectoryIds({
|
||||
sources: [mapAllowFromEntries(account.config.allowFrom), Object.keys(account.config.dms ?? {})],
|
||||
return listInspectedDirectoryEntriesFromSources({
|
||||
...params,
|
||||
kind: "user",
|
||||
inspectAccount: (cfg, accountId) =>
|
||||
inspectTelegramAccount({ cfg, accountId }) as InspectedTelegramAccount | null,
|
||||
resolveSources: (account) => [
|
||||
mapAllowFromEntries(account.config.allowFrom),
|
||||
Object.keys(account.config.dms ?? {}),
|
||||
],
|
||||
normalizeId: (entry) => {
|
||||
const trimmed = entry.replace(/^(telegram|tg):/i, "").trim();
|
||||
if (!trimmed) {
|
||||
@@ -30,20 +26,15 @@ export async function listTelegramDirectoryPeersFromConfig(params: DirectoryConf
|
||||
return trimmed.startsWith("@") ? trimmed : `@${trimmed}`;
|
||||
},
|
||||
});
|
||||
return toDirectoryEntries("user", applyDirectoryQueryAndLimit(ids, params));
|
||||
}
|
||||
|
||||
export async function listTelegramDirectoryGroupsFromConfig(params: DirectoryConfigParams) {
|
||||
const account: InspectedTelegramAccount = inspectTelegramAccount({
|
||||
cfg: params.cfg,
|
||||
accountId: params.accountId,
|
||||
});
|
||||
if (!account.config) {
|
||||
return [];
|
||||
}
|
||||
return listDirectoryGroupEntriesFromMapKeys({
|
||||
groups: account.config.groups,
|
||||
query: params.query,
|
||||
limit: params.limit,
|
||||
return listInspectedDirectoryEntriesFromSources({
|
||||
...params,
|
||||
kind: "group",
|
||||
inspectAccount: (cfg, accountId) =>
|
||||
inspectTelegramAccount({ cfg, accountId }) as InspectedTelegramAccount | null,
|
||||
resolveSources: (account) => [Object.keys(account.config.groups ?? {})],
|
||||
normalizeId: (entry) => entry.trim() || null,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user