
























@@ -25,6 +25,7 @@ import type {
2525TelegramTopicConfig,
2626} from "openclaw/plugin-sdk/config-contracts";
2727import { mutateConfigFile } from "openclaw/plugin-sdk/config-mutation";
28+import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
2829import {
2930buildPluginBindingResolvedText,
3031parsePluginBindingApprovalCustomId,
@@ -37,18 +38,21 @@ import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
3738import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
3839import { resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
3940import { danger, logVerbose, warn } from "openclaw/plugin-sdk/runtime-env";
41+import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime";
4042import {
4143getSessionEntry,
4244listSessionEntries,
4345patchSessionEntry,
4446} from "openclaw/plugin-sdk/session-store-runtime";
4547import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
4648import { expandTelegramAllowFromWithAccessGroups } from "./access-groups.js";
47-import { resolveTelegramMediaRuntimeOptions } from "./accounts.js";
49+import { resolveTelegramAccount, resolveTelegramMediaRuntimeOptions } from "./accounts.js";
4850import { withTelegramApiErrorLogging } from "./api-logging.js";
4951import {
5052normalizeDmAllowFromWithStore,
5153firstDefined,
54+isSenderAllowed,
55+normalizeAllowFrom,
5256resolveTelegramEffectiveDmPolicy,
5357type NormalizedAllowFrom,
5458} from "./bot-access.js";
@@ -123,6 +127,7 @@ import {
123127evaluateTelegramGroupBaseAccess,
124128evaluateTelegramGroupPolicyAccess,
125129} from "./group-access.js";
130+import { resolveTelegramScopedGroupConfig } from "./group-config-helpers.js";
126131import { resolveTelegramGroupHistoryContextMode } from "./group-history-context.js";
127132import { migrateTelegramGroupConfig } from "./group-migration.js";
128133import {
@@ -1292,13 +1297,18 @@ export const registerTelegramHandlers = ({
12921297const resolveReplyMediaForChain = async (
12931298ctx: TelegramContext,
12941299chain: TelegramCachedMessageNode[],
1300+shouldHydrateMedia: (node: TelegramCachedMessageNode, index: number) => Promise<boolean>,
12951301): Promise<{ replyMedia: TelegramMediaRef[]; replyChain: TelegramReplyChainEntry[] }> => {
12961302const replyMedia: TelegramMediaRef[] = [];
12971303const replyChain: TelegramReplyChainEntry[] = [];
1298-for (const node of chain) {
1304+for (const [index, node] of chain.entries()) {
12991305let mediaRef: TelegramMediaRef | undefined;
13001306const replyFileId = resolveInboundMediaFileId(node.sourceMessage);
1301-if (replyFileId && hasInboundMedia(node.sourceMessage)) {
1307+if (
1308+replyFileId &&
1309+hasInboundMedia(node.sourceMessage) &&
1310+(await shouldHydrateMedia(node, index))
1311+) {
13021312try {
13031313const media = await resolveMedia({
13041314ctx: {
@@ -1349,9 +1359,65 @@ export const registerTelegramHandlers = ({
13491359};
13501360try {
13511361const replyChainNodes = await buildReplyChainForMessage(params.msg);
1362+const isGroupConversation =
1363+params.msg.chat.type === "group" || params.msg.chat.type === "supergroup";
1364+const runtimeCfg = telegramDeps.getRuntimeConfig();
1365+const runtimeTelegramCfg = resolveTelegramAccount({ cfg: runtimeCfg, accountId }).config;
1366+const isForum =
1367+params.msg.chat.type === "supergroup" &&
1368+Boolean(params.msg.chat.is_forum || params.msg.is_topic_message);
1369+const scopedThreadId = resolveTelegramForumThreadId({
1370+ isForum,
1371+messageThreadId: params.msg.message_thread_id,
1372+});
1373+const { groupConfig, topicConfig } = resolveTelegramScopedGroupConfig(
1374+runtimeTelegramCfg,
1375+params.msg.chat.id,
1376+scopedThreadId,
1377+);
1378+const scopedAllowFrom = firstDefined(topicConfig?.allowFrom, groupConfig?.allowFrom);
1379+const configuredGroupAllowFrom =
1380+scopedAllowFrom ??
1381+opts.groupAllowFrom ??
1382+runtimeTelegramCfg.groupAllowFrom ??
1383+runtimeTelegramCfg.allowFrom ??
1384+opts.allowFrom;
1385+const contextVisibilityMode = resolveChannelContextVisibilityMode({
1386+cfg: runtimeCfg,
1387+channel: "telegram",
1388+ accountId,
1389+});
1390+const shouldHydrateReplyMedia = async (
1391+node: TelegramCachedMessageNode,
1392+index: number,
1393+): Promise<boolean> => {
1394+if (!isGroupConversation) {
1395+return true;
1396+}
1397+const expandedAllowFrom = await expandTelegramAllowFromWithAccessGroups({
1398+cfg: runtimeCfg,
1399+allowFrom: configuredGroupAllowFrom,
1400+ accountId,
1401+senderId: node.senderId,
1402+});
1403+const effectiveAllow = normalizeAllowFrom(expandedAllowFrom);
1404+const senderAllowed = effectiveAllow.hasEntries
1405+ ? isSenderAllowed({
1406+allow: effectiveAllow,
1407+senderId: node.senderId,
1408+senderUsername: node.senderUsername,
1409+})
1410+ : true;
1411+return evaluateSupplementalContextVisibility({
1412+mode: contextVisibilityMode,
1413+kind: index === 0 ? "quote" : "thread",
1414+ senderAllowed,
1415+}).include;
1416+};
13521417const { replyMedia, replyChain } = await resolveReplyMediaForChain(
13531418params.ctx,
13541419replyChainNodes,
1420+shouldHydrateReplyMedia,
13551421);
13561422const promptContextMediaByMessageId = new Map<string, TelegramMediaRef>();
13571423const currentMessageId =
@@ -1366,19 +1432,15 @@ export const registerTelegramHandlers = ({
13661432path: currentPromptMediaPath,
13671433});
13681434}
1369-const isGroupConversation =
1370-params.msg.chat.type === "group" || params.msg.chat.type === "supergroup";
1371-if (!isGroupConversation) {
1372-for (const entry of replyChain) {
1373-const promptMediaPath = entry.mediaPath
1374- ? resolveTelegramPromptMediaPath(entry.mediaPath)
1375- : undefined;
1376-if (entry.messageId && entry.mediaPath && promptMediaPath) {
1377-promptContextMediaByMessageId.set(entry.messageId, {
1378-path: promptMediaPath,
1379- ...(entry.mediaType ? { contentType: entry.mediaType } : {}),
1380-});
1381-}
1435+for (const entry of replyChain) {
1436+const promptMediaPath = entry.mediaPath
1437+ ? resolveTelegramPromptMediaPath(entry.mediaPath)
1438+ : undefined;
1439+if (entry.messageId && entry.mediaPath && promptMediaPath) {
1440+promptContextMediaByMessageId.set(entry.messageId, {
1441+path: promptMediaPath,
1442+ ...(entry.mediaType ? { contentType: entry.mediaType } : {}),
1443+});
13821444}
13831445}
13841446const promptContext = await buildPromptContextForMessage(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。