Telegram user: add group tool policy + DM open validation
This commit is contained in:
parent
63929bd70c
commit
39a4627550
@ -8,9 +8,11 @@ import {
|
|||||||
formatPairingApproveHint,
|
formatPairingApproveHint,
|
||||||
normalizeAccountId,
|
normalizeAccountId,
|
||||||
setAccountEnabledInConfigSection,
|
setAccountEnabledInConfigSection,
|
||||||
|
type ChannelGroupContext,
|
||||||
type ChannelPlugin,
|
type ChannelPlugin,
|
||||||
type ChannelSetupInput,
|
type ChannelSetupInput,
|
||||||
type ClawdbotConfig,
|
type ClawdbotConfig,
|
||||||
|
type GroupToolPolicyConfig,
|
||||||
} from "clawdbot/plugin-sdk";
|
} from "clawdbot/plugin-sdk";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -51,6 +53,36 @@ type TelegramUserSetupInput = ChannelSetupInput & {
|
|||||||
apiHash?: string;
|
apiHash?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function normalizeTelegramUserGroupKey(raw?: string | null): string | undefined {
|
||||||
|
if (!raw) return undefined;
|
||||||
|
const trimmed = raw.trim();
|
||||||
|
if (!trimmed) return undefined;
|
||||||
|
const withoutPrefix = trimmed.replace(/^telegram-user:group:/i, "");
|
||||||
|
const [base] = withoutPrefix.split(/:topic:/i);
|
||||||
|
const normalized = base?.trim();
|
||||||
|
return normalized ? normalized : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveTelegramUserGroupToolPolicy(
|
||||||
|
params: ChannelGroupContext,
|
||||||
|
): GroupToolPolicyConfig | undefined {
|
||||||
|
const account = resolveTelegramUserAccount({
|
||||||
|
cfg: params.cfg as CoreConfig,
|
||||||
|
accountId: params.accountId,
|
||||||
|
});
|
||||||
|
const groups = account.config.groups ?? {};
|
||||||
|
const groupId = normalizeTelegramUserGroupKey(params.groupId);
|
||||||
|
const groupChannel = normalizeTelegramUserGroupKey(params.groupChannel);
|
||||||
|
const candidates = [groupId, groupChannel, "*"].filter(
|
||||||
|
(value): value is string => Boolean(value),
|
||||||
|
);
|
||||||
|
for (const key of candidates) {
|
||||||
|
const entry = groups[key];
|
||||||
|
if (entry?.tools) return entry.tools;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const isSessionLinked = async (accountId: string): Promise<boolean> => {
|
const isSessionLinked = async (accountId: string): Promise<boolean> => {
|
||||||
const sessionPath = resolveTelegramUserSessionPath(accountId);
|
const sessionPath = resolveTelegramUserSessionPath(accountId);
|
||||||
return fs.existsSync(sessionPath);
|
return fs.existsSync(sessionPath);
|
||||||
@ -142,6 +174,21 @@ export const telegramUserPlugin: ChannelPlugin<ResolvedTelegramUserAccount> = {
|
|||||||
raw.replace(/^(telegram-user|telegram|tg):/i, "").toLowerCase(),
|
raw.replace(/^(telegram-user|telegram|tg):/i, "").toLowerCase(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
collectWarnings: ({ account, cfg }) => {
|
||||||
|
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
|
||||||
|
const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
|
||||||
|
if (groupPolicy !== "open") return [];
|
||||||
|
const groupAllowlistConfigured =
|
||||||
|
account.config.groups && Object.keys(account.config.groups).length > 0;
|
||||||
|
if (groupAllowlistConfigured) {
|
||||||
|
return [
|
||||||
|
`- Telegram user groups: groupPolicy="open" allows any member in allowed groups to trigger (mention-gated). Set channels.telegram-user.groupPolicy="allowlist" + channels.telegram-user.groupAllowFrom to restrict senders.`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
`- Telegram user groups: groupPolicy="open" with no channels.telegram-user.groups allowlist; any group can add + ping (mention-gated). Set channels.telegram-user.groupPolicy="allowlist" + channels.telegram-user.groupAllowFrom or configure channels.telegram-user.groups.`,
|
||||||
|
];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
groups: {
|
groups: {
|
||||||
resolveRequireMention: ({ cfg, groupId, accountId }) =>
|
resolveRequireMention: ({ cfg, groupId, accountId }) =>
|
||||||
@ -151,6 +198,7 @@ export const telegramUserPlugin: ChannelPlugin<ResolvedTelegramUserAccount> = {
|
|||||||
groupId,
|
groupId,
|
||||||
accountId,
|
accountId,
|
||||||
}),
|
}),
|
||||||
|
resolveToolPolicy: resolveTelegramUserGroupToolPolicy,
|
||||||
},
|
},
|
||||||
threading: {
|
threading: {
|
||||||
resolveReplyToMode: ({ cfg }) => cfg.channels?.["telegram-user"]?.replyToMode ?? "first",
|
resolveReplyToMode: ({ cfg }) => cfg.channels?.["telegram-user"]?.replyToMode ?? "first",
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import {
|
||||||
|
DmPolicySchema,
|
||||||
|
GroupPolicySchema,
|
||||||
|
ToolPolicySchema,
|
||||||
|
requireOpenAllowFrom,
|
||||||
|
} from "clawdbot/plugin-sdk";
|
||||||
|
|
||||||
const allowFromEntry = z.union([z.string(), z.number()]);
|
const allowFromEntry = z.union([z.string(), z.number()]);
|
||||||
|
|
||||||
const TelegramUserTopicSchema = z
|
const TelegramUserTopicSchema = z
|
||||||
@ -16,6 +23,7 @@ const TelegramUserGroupSchema = z
|
|||||||
.object({
|
.object({
|
||||||
requireMention: z.boolean().optional(),
|
requireMention: z.boolean().optional(),
|
||||||
skills: z.array(z.string()).optional(),
|
skills: z.array(z.string()).optional(),
|
||||||
|
tools: ToolPolicySchema,
|
||||||
topics: z.record(z.string(), TelegramUserTopicSchema.optional()).optional(),
|
topics: z.record(z.string(), TelegramUserTopicSchema.optional()).optional(),
|
||||||
enabled: z.boolean().optional(),
|
enabled: z.boolean().optional(),
|
||||||
allowFrom: z.array(allowFromEntry).optional(),
|
allowFrom: z.array(allowFromEntry).optional(),
|
||||||
@ -23,23 +31,43 @@ const TelegramUserGroupSchema = z
|
|||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const TelegramUserAccountSchema = z
|
const TelegramUserAccountSchemaBase = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
enabled: z.boolean().optional(),
|
enabled: z.boolean().optional(),
|
||||||
apiId: z.number().int().positive().optional(),
|
apiId: z.number().int().positive().optional(),
|
||||||
apiHash: z.string().optional(),
|
apiHash: z.string().optional(),
|
||||||
dmPolicy: z.enum(["pairing", "allowlist", "open", "disabled"]).optional(),
|
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
||||||
allowFrom: z.array(allowFromEntry).optional(),
|
allowFrom: z.array(allowFromEntry).optional(),
|
||||||
replyToMode: z.enum(["off", "first", "all"]).optional(),
|
replyToMode: z.enum(["off", "first", "all"]).optional(),
|
||||||
textChunkLimit: z.number().int().positive().optional(),
|
textChunkLimit: z.number().int().positive().optional(),
|
||||||
mediaMaxMb: z.number().positive().optional(),
|
mediaMaxMb: z.number().positive().optional(),
|
||||||
groupAllowFrom: z.array(allowFromEntry).optional(),
|
groupAllowFrom: z.array(allowFromEntry).optional(),
|
||||||
groupPolicy: z.enum(["open", "allowlist", "disabled"]).optional(),
|
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
||||||
groups: z.record(z.string(), TelegramUserGroupSchema.optional()).optional(),
|
groups: z.record(z.string(), TelegramUserGroupSchema.optional()).optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
export const TelegramUserConfigSchema = TelegramUserAccountSchema.extend({
|
const TelegramUserAccountSchema = TelegramUserAccountSchemaBase.superRefine((value, ctx) => {
|
||||||
accounts: z.record(z.string(), TelegramUserAccountSchema.optional()).optional(),
|
requireOpenAllowFrom({
|
||||||
|
policy: value.dmPolicy,
|
||||||
|
allowFrom: value.allowFrom,
|
||||||
|
ctx,
|
||||||
|
path: ["allowFrom"],
|
||||||
|
message:
|
||||||
|
'channels.telegram-user.dmPolicy="open" requires channels.telegram-user.allowFrom to include "*"',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export const TelegramUserConfigSchema = TelegramUserAccountSchemaBase.extend({
|
||||||
|
accounts: z.record(z.string(), TelegramUserAccountSchema.optional()).optional(),
|
||||||
|
}).superRefine((value, ctx) => {
|
||||||
|
requireOpenAllowFrom({
|
||||||
|
policy: value.dmPolicy,
|
||||||
|
allowFrom: value.allowFrom,
|
||||||
|
ctx,
|
||||||
|
path: ["allowFrom"],
|
||||||
|
message:
|
||||||
|
'channels.telegram-user.dmPolicy="open" requires channels.telegram-user.allowFrom to include "*"',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import type { DmPolicy, GroupPolicy } from "clawdbot/plugin-sdk";
|
import type { DmPolicy, GroupPolicy, GroupToolPolicyConfig } from "clawdbot/plugin-sdk";
|
||||||
|
|
||||||
export type TelegramUserTopicConfig = {
|
export type TelegramUserTopicConfig = {
|
||||||
requireMention?: boolean;
|
requireMention?: boolean;
|
||||||
@ -11,6 +11,7 @@ export type TelegramUserTopicConfig = {
|
|||||||
export type TelegramUserGroupConfig = {
|
export type TelegramUserGroupConfig = {
|
||||||
requireMention?: boolean;
|
requireMention?: boolean;
|
||||||
skills?: string[];
|
skills?: string[];
|
||||||
|
tools?: GroupToolPolicyConfig;
|
||||||
topics?: Record<string, TelegramUserTopicConfig>;
|
topics?: Record<string, TelegramUserTopicConfig>;
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
allowFrom?: Array<string | number>;
|
allowFrom?: Array<string | number>;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user