mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 12:41:12 +00:00
170 lines
6.7 KiB
TypeScript
170 lines
6.7 KiB
TypeScript
import {
|
|
createApproverRestrictedNativeApprovalCapability,
|
|
splitChannelApprovalCapability,
|
|
} from "openclaw/plugin-sdk/approval-delivery-runtime";
|
|
import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
|
|
import type { ChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
|
|
import {
|
|
createChannelApproverDmTargetResolver,
|
|
createChannelNativeOriginTargetResolver,
|
|
} from "openclaw/plugin-sdk/approval-native-runtime";
|
|
import type { ChannelApprovalCapability } from "openclaw/plugin-sdk/channel-contract";
|
|
import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
|
|
import {
|
|
normalizeLowercaseStringOrEmpty,
|
|
normalizeOptionalString,
|
|
} from "openclaw/plugin-sdk/text-runtime";
|
|
import { listTelegramAccountIds } from "./accounts.js";
|
|
import {
|
|
getTelegramExecApprovalApprovers,
|
|
isTelegramExecApprovalApprover,
|
|
isTelegramExecApprovalAuthorizedSender,
|
|
isTelegramExecApprovalClientEnabled,
|
|
isTelegramExecApprovalTargetRecipient,
|
|
resolveTelegramExecApprovalTarget,
|
|
shouldHandleTelegramExecApprovalRequest,
|
|
} from "./exec-approvals.js";
|
|
import { parseTelegramThreadId } from "./outbound-params.js";
|
|
import { normalizeTelegramChatId, parseTelegramTarget } from "./targets.js";
|
|
|
|
type ApprovalRequest = ExecApprovalRequest | PluginApprovalRequest;
|
|
type TelegramOriginTarget = { to: string; threadId?: number };
|
|
|
|
function resolveTurnSourceTelegramOriginTarget(
|
|
request: ApprovalRequest,
|
|
): TelegramOriginTarget | null {
|
|
const turnSourceChannel = normalizeLowercaseStringOrEmpty(request.request.turnSourceChannel);
|
|
const rawTurnSourceTo = normalizeOptionalString(request.request.turnSourceTo) ?? "";
|
|
const parsedTurnSourceTarget = rawTurnSourceTo ? parseTelegramTarget(rawTurnSourceTo) : null;
|
|
const turnSourceTo = normalizeTelegramChatId(parsedTurnSourceTarget?.chatId ?? rawTurnSourceTo);
|
|
if (turnSourceChannel !== "telegram" || !turnSourceTo) {
|
|
return null;
|
|
}
|
|
const rawThreadId =
|
|
request.request.turnSourceThreadId ?? parsedTurnSourceTarget?.messageThreadId ?? undefined;
|
|
return {
|
|
to: turnSourceTo,
|
|
threadId: parseTelegramThreadId(rawThreadId),
|
|
};
|
|
}
|
|
|
|
function resolveSessionTelegramOriginTarget(sessionTarget: {
|
|
to: string;
|
|
threadId?: string | number | null;
|
|
}): TelegramOriginTarget {
|
|
return {
|
|
to: normalizeTelegramChatId(sessionTarget.to) ?? sessionTarget.to,
|
|
threadId: parseTelegramThreadId(sessionTarget.threadId),
|
|
};
|
|
}
|
|
|
|
function telegramTargetsMatch(a: TelegramOriginTarget, b: TelegramOriginTarget): boolean {
|
|
const normalizedA = normalizeTelegramChatId(a.to) ?? a.to;
|
|
const normalizedB = normalizeTelegramChatId(b.to) ?? b.to;
|
|
return normalizedA === normalizedB && a.threadId === b.threadId;
|
|
}
|
|
|
|
const resolveTelegramOriginTarget = createChannelNativeOriginTargetResolver({
|
|
channel: "telegram",
|
|
shouldHandleRequest: ({ cfg, accountId, request }) =>
|
|
shouldHandleTelegramExecApprovalRequest({
|
|
cfg,
|
|
accountId,
|
|
request,
|
|
}),
|
|
resolveTurnSourceTarget: resolveTurnSourceTelegramOriginTarget,
|
|
resolveSessionTarget: resolveSessionTelegramOriginTarget,
|
|
targetsMatch: telegramTargetsMatch,
|
|
});
|
|
|
|
const resolveTelegramApproverDmTargets = createChannelApproverDmTargetResolver({
|
|
shouldHandleRequest: ({ cfg, accountId, request }) =>
|
|
shouldHandleTelegramExecApprovalRequest({
|
|
cfg,
|
|
accountId,
|
|
request,
|
|
}),
|
|
resolveApprovers: getTelegramExecApprovalApprovers,
|
|
mapApprover: (approver) => ({ to: approver }),
|
|
});
|
|
|
|
const telegramNativeApprovalCapability = createApproverRestrictedNativeApprovalCapability({
|
|
channel: "telegram",
|
|
channelLabel: "Telegram",
|
|
describeExecApprovalSetup: ({ accountId }) => {
|
|
const prefix =
|
|
accountId && accountId !== "default"
|
|
? `channels.telegram.accounts.${accountId}`
|
|
: "channels.telegram";
|
|
return `Approve it from the Web UI or terminal UI for now. Telegram supports native exec approvals for this account. Configure \`${prefix}.execApprovals.approvers\`; if you leave it unset, OpenClaw can infer numeric owner IDs from \`${prefix}.allowFrom\` or direct-message \`${prefix}.defaultTo\` when possible. Leave \`${prefix}.execApprovals.enabled\` unset/\`auto\` or set it to \`true\`.`;
|
|
},
|
|
listAccountIds: listTelegramAccountIds,
|
|
hasApprovers: ({ cfg, accountId }) =>
|
|
getTelegramExecApprovalApprovers({ cfg, accountId }).length > 0,
|
|
isExecAuthorizedSender: ({ cfg, accountId, senderId }) =>
|
|
isTelegramExecApprovalAuthorizedSender({ cfg, accountId, senderId }),
|
|
isPluginAuthorizedSender: ({ cfg, accountId, senderId }) =>
|
|
isTelegramExecApprovalApprover({ cfg, accountId, senderId }),
|
|
isNativeDeliveryEnabled: ({ cfg, accountId }) =>
|
|
isTelegramExecApprovalClientEnabled({ cfg, accountId }),
|
|
resolveNativeDeliveryMode: ({ cfg, accountId }) =>
|
|
resolveTelegramExecApprovalTarget({ cfg, accountId }),
|
|
requireMatchingTurnSourceChannel: true,
|
|
resolveSuppressionAccountId: ({ target, request }) =>
|
|
normalizeOptionalString(target.accountId) ??
|
|
normalizeOptionalString(request.request.turnSourceAccountId),
|
|
resolveOriginTarget: resolveTelegramOriginTarget,
|
|
resolveApproverDmTargets: resolveTelegramApproverDmTargets,
|
|
notifyOriginWhenDmOnly: true,
|
|
nativeRuntime: createLazyChannelApprovalNativeRuntimeAdapter({
|
|
eventKinds: ["exec", "plugin"],
|
|
isConfigured: ({ cfg, accountId }) =>
|
|
isTelegramExecApprovalClientEnabled({
|
|
cfg,
|
|
accountId,
|
|
}),
|
|
shouldHandle: ({ cfg, accountId, request }) =>
|
|
shouldHandleTelegramExecApprovalRequest({
|
|
cfg,
|
|
accountId,
|
|
request,
|
|
}),
|
|
load: async () =>
|
|
(await import("./approval-handler.runtime.js"))
|
|
.telegramApprovalNativeRuntime as unknown as ChannelApprovalNativeRuntimeAdapter,
|
|
}),
|
|
});
|
|
|
|
const resolveTelegramApproveCommandBehavior: NonNullable<
|
|
ChannelApprovalCapability["resolveApproveCommandBehavior"]
|
|
> = ({ cfg, accountId, senderId, approvalKind }) => {
|
|
if (approvalKind !== "exec") {
|
|
return undefined;
|
|
}
|
|
if (isTelegramExecApprovalClientEnabled({ cfg, accountId })) {
|
|
return undefined;
|
|
}
|
|
if (isTelegramExecApprovalTargetRecipient({ cfg, accountId, senderId })) {
|
|
return undefined;
|
|
}
|
|
if (
|
|
isTelegramExecApprovalAuthorizedSender({ cfg, accountId, senderId }) &&
|
|
!isTelegramExecApprovalApprover({ cfg, accountId, senderId })
|
|
) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
kind: "reply",
|
|
text: "❌ Telegram exec approvals are not enabled for this bot account.",
|
|
};
|
|
};
|
|
|
|
export const telegramApprovalCapability: ChannelApprovalCapability = {
|
|
...telegramNativeApprovalCapability,
|
|
resolveApproveCommandBehavior: resolveTelegramApproveCommandBehavior,
|
|
};
|
|
|
|
export const telegramNativeApprovalAdapter = splitChannelApprovalCapability(
|
|
telegramApprovalCapability,
|
|
);
|