mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 17:51:22 +00:00
123 lines
3.8 KiB
TypeScript
123 lines
3.8 KiB
TypeScript
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
|
|
|
export type TelegramCustomCommandInput = {
|
|
command?: string | null;
|
|
description?: string | null;
|
|
};
|
|
|
|
export type TelegramCustomCommandIssue = {
|
|
index: number;
|
|
field: "command" | "description";
|
|
message: string;
|
|
};
|
|
const TELEGRAM_COMMAND_NAME_PATTERN_VALUE = /^[a-z0-9_]{1,32}$/;
|
|
|
|
function normalizeTelegramCommandNameImpl(value: string): string {
|
|
const trimmed = value.trim();
|
|
if (!trimmed) {
|
|
return "";
|
|
}
|
|
const withoutSlash = trimmed.startsWith("/") ? trimmed.slice(1) : trimmed;
|
|
return normalizeLowercaseStringOrEmpty(withoutSlash).replace(/-/g, "_");
|
|
}
|
|
|
|
function normalizeTelegramCommandDescriptionImpl(value: string): string {
|
|
return value.trim();
|
|
}
|
|
|
|
function resolveTelegramCustomCommandsImpl(params: {
|
|
commands?: TelegramCustomCommandInput[] | null;
|
|
reservedCommands?: Set<string>;
|
|
checkReserved?: boolean;
|
|
checkDuplicates?: boolean;
|
|
}): {
|
|
commands: Array<{ command: string; description: string }>;
|
|
issues: TelegramCustomCommandIssue[];
|
|
} {
|
|
const entries = Array.isArray(params.commands) ? params.commands : [];
|
|
const reserved = params.reservedCommands ?? new Set<string>();
|
|
const checkReserved = params.checkReserved !== false;
|
|
const checkDuplicates = params.checkDuplicates !== false;
|
|
const seen = new Set<string>();
|
|
const resolved: Array<{ command: string; description: string }> = [];
|
|
const issues: TelegramCustomCommandIssue[] = [];
|
|
|
|
for (let index = 0; index < entries.length; index += 1) {
|
|
const entry = entries[index];
|
|
const normalized = normalizeTelegramCommandNameImpl(String(entry?.command ?? ""));
|
|
if (!normalized) {
|
|
issues.push({
|
|
index,
|
|
field: "command",
|
|
message: "Telegram custom command is missing a command name.",
|
|
});
|
|
continue;
|
|
}
|
|
if (!TELEGRAM_COMMAND_NAME_PATTERN_VALUE.test(normalized)) {
|
|
issues.push({
|
|
index,
|
|
field: "command",
|
|
message: `Telegram custom command "/${normalized}" is invalid (use a-z, 0-9, underscore; max 32 chars).`,
|
|
});
|
|
continue;
|
|
}
|
|
if (checkReserved && reserved.has(normalized)) {
|
|
issues.push({
|
|
index,
|
|
field: "command",
|
|
message: `Telegram custom command "/${normalized}" conflicts with a native command.`,
|
|
});
|
|
continue;
|
|
}
|
|
if (checkDuplicates && seen.has(normalized)) {
|
|
issues.push({
|
|
index,
|
|
field: "command",
|
|
message: `Telegram custom command "/${normalized}" is duplicated.`,
|
|
});
|
|
continue;
|
|
}
|
|
const description = normalizeTelegramCommandDescriptionImpl(String(entry?.description ?? ""));
|
|
if (!description) {
|
|
issues.push({
|
|
index,
|
|
field: "description",
|
|
message: `Telegram custom command "/${normalized}" is missing a description.`,
|
|
});
|
|
continue;
|
|
}
|
|
if (checkDuplicates) {
|
|
seen.add(normalized);
|
|
}
|
|
resolved.push({ command: normalized, description });
|
|
}
|
|
|
|
return { commands: resolved, issues };
|
|
}
|
|
|
|
export function getTelegramCommandNamePattern(): RegExp {
|
|
return TELEGRAM_COMMAND_NAME_PATTERN_VALUE;
|
|
}
|
|
|
|
export const TELEGRAM_COMMAND_NAME_PATTERN = TELEGRAM_COMMAND_NAME_PATTERN_VALUE;
|
|
|
|
export function normalizeTelegramCommandName(value: string): string {
|
|
return normalizeTelegramCommandNameImpl(value);
|
|
}
|
|
|
|
export function normalizeTelegramCommandDescription(value: string): string {
|
|
return normalizeTelegramCommandDescriptionImpl(value);
|
|
}
|
|
|
|
export function resolveTelegramCustomCommands(params: {
|
|
commands?: TelegramCustomCommandInput[] | null;
|
|
reservedCommands?: Set<string>;
|
|
checkReserved?: boolean;
|
|
checkDuplicates?: boolean;
|
|
}): {
|
|
commands: Array<{ command: string; description: string }>;
|
|
issues: TelegramCustomCommandIssue[];
|
|
} {
|
|
return resolveTelegramCustomCommandsImpl(params);
|
|
}
|