mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 13:40:20 +00:00
refactor: dedupe telegram matrix lowercase helpers
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { parseTelegramTarget } from "./targets.js";
|
||||
|
||||
export function resolveTelegramAutoThreadId(params: {
|
||||
@@ -13,7 +14,10 @@ export function resolveTelegramAutoThreadId(params: {
|
||||
return undefined;
|
||||
}
|
||||
const parsedChannel = parseTelegramTarget(context.currentChannelId);
|
||||
if (parsedTo.chatId.toLowerCase() !== parsedChannel.chatId.toLowerCase()) {
|
||||
if (
|
||||
normalizeLowercaseStringOrEmpty(parsedTo.chatId) !==
|
||||
normalizeLowercaseStringOrEmpty(parsedChannel.chatId)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return context.currentThreadTs;
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
} from "openclaw/plugin-sdk/reply-history";
|
||||
import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { NormalizedAllowFrom } from "./bot-access.js";
|
||||
import { isSenderAllowed } from "./bot-access.js";
|
||||
import type {
|
||||
@@ -118,7 +119,7 @@ export async function resolveTelegramInboundBody(params: {
|
||||
historyLimit,
|
||||
logger,
|
||||
} = params;
|
||||
const botUsername = primaryCtx.me?.username?.toLowerCase();
|
||||
const botUsername = normalizeOptionalLowercaseString(primaryCtx.me?.username);
|
||||
const mentionRegexes = buildMentionRegexes(cfg, routeAgentId);
|
||||
const messageTextParts = getTelegramTextParts(msg);
|
||||
const allowForCommands = isGroup ? effectiveGroupAllow : effectiveDmAllow;
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
import type { ResolvedAgentRoute } from "openclaw/plugin-sdk/routing";
|
||||
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime";
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { NormalizedAllowFrom } from "./bot-access.js";
|
||||
import { isSenderAllowed, normalizeAllowFrom } from "./bot-access.js";
|
||||
import type {
|
||||
@@ -241,7 +242,7 @@ export async function buildTelegramInboundContextPayload(params: {
|
||||
topicConfig,
|
||||
});
|
||||
const commandBody = normalizeCommandBody(rawBody, {
|
||||
botUsername: primaryCtx.me?.username?.toLowerCase(),
|
||||
botUsername: normalizeOptionalLowercaseString(primaryCtx.me?.username),
|
||||
});
|
||||
const inboundHistory =
|
||||
isGroup && historyKey && historyLimit > 0
|
||||
|
||||
@@ -29,6 +29,7 @@ import { getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-sna
|
||||
import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { getChildLogger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { resolveTelegramAccount } from "./accounts.js";
|
||||
import { withTelegramApiErrorLogging } from "./api-logging.js";
|
||||
import { isSenderAllowed, normalizeDmAllowFromWithStore } from "./bot-access.js";
|
||||
@@ -506,7 +507,7 @@ export const registerTelegramNativeCommands = ({
|
||||
listNativeCommandSpecs().map((command) => normalizeTelegramCommandName(command.name)),
|
||||
);
|
||||
for (const command of skillCommands) {
|
||||
reservedCommands.add(command.name.toLowerCase());
|
||||
reservedCommands.add(normalizeLowercaseStringOrEmpty(command.name));
|
||||
}
|
||||
const customResolution = resolveTelegramCustomCommands({
|
||||
commands: telegramCfg.customCommands,
|
||||
@@ -524,7 +525,7 @@ export const registerTelegramNativeCommands = ({
|
||||
[
|
||||
...nativeCommands.map((command) => normalizeTelegramCommandName(command.name)),
|
||||
...customCommands.map((command) => command.command),
|
||||
].map((command) => command.toLowerCase()),
|
||||
].map((command) => normalizeLowercaseStringOrEmpty(command)),
|
||||
);
|
||||
const pluginCatalog = buildPluginTelegramMenuCommands({
|
||||
specs: pluginCommandSpecs,
|
||||
|
||||
@@ -20,7 +20,10 @@ import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtim
|
||||
import { getChildLogger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { createNonExitingRuntime, type RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import { resolveTelegramAccount } from "./accounts.js";
|
||||
import { defaultTelegramBotDeps, type TelegramBotDeps } from "./bot-deps.js";
|
||||
import { registerTelegramHandlers } from "./bot-handlers.js";
|
||||
@@ -129,7 +132,7 @@ function extractTelegramApiMethod(input: TelegramFetchInput): string | null {
|
||||
const pathname = new URL(url).pathname;
|
||||
const segments = pathname.split("/").filter(Boolean);
|
||||
const method = segments.length > 0 ? (segments.at(-1) ?? null) : null;
|
||||
return method?.toLowerCase() ?? null;
|
||||
return normalizeOptionalLowercaseString(method) ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { Chat, Message, MessageOrigin, User } from "@grammyjs/types";
|
||||
import type { NormalizedLocation } from "openclaw/plugin-sdk/channel-inbound";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
type TelegramMediaMessage = Pick<
|
||||
Message,
|
||||
@@ -123,8 +126,8 @@ function hasStandaloneTelegramMention(text: string, mention: string): boolean {
|
||||
|
||||
export function hasBotMention(msg: Message, botUsername: string) {
|
||||
const { text, entities } = getTelegramTextParts(msg);
|
||||
const mention = `@${botUsername}`.toLowerCase();
|
||||
if (hasStandaloneTelegramMention(text.toLowerCase(), mention)) {
|
||||
const mention = normalizeLowercaseStringOrEmpty(`@${botUsername}`);
|
||||
if (hasStandaloneTelegramMention(normalizeLowercaseStringOrEmpty(text), mention)) {
|
||||
return true;
|
||||
}
|
||||
for (const ent of entities) {
|
||||
@@ -132,7 +135,7 @@ export function hasBotMention(msg: Message, botUsername: string) {
|
||||
continue;
|
||||
}
|
||||
const slice = text.slice(ent.offset, ent.offset + ent.length);
|
||||
if (slice.toLowerCase() === mention) {
|
||||
if (normalizeLowercaseStringOrEmpty(slice) === mention) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
sanitizeAgentId,
|
||||
} from "openclaw/plugin-sdk/routing";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
buildTelegramGroupPeerId,
|
||||
buildTelegramParentPeer,
|
||||
@@ -64,32 +65,29 @@ export function resolveTelegramConversationRoute(params: {
|
||||
// Preserve the configured topic agent ID so topic-bound sessions stay stable
|
||||
// even when that agent is not present in the current config snapshot.
|
||||
const topicAgentId = sanitizeAgentId(rawTopicAgentId);
|
||||
route = {
|
||||
...route,
|
||||
agentId: topicAgentId,
|
||||
sessionKey: buildAgentSessionKey({
|
||||
const sessionKey = normalizeLowercaseStringOrEmpty(
|
||||
buildAgentSessionKey({
|
||||
agentId: topicAgentId,
|
||||
channel: "telegram",
|
||||
accountId: params.accountId,
|
||||
peer: { kind: params.isGroup ? "group" : "direct", id: peerId },
|
||||
dmScope: params.cfg.session?.dmScope,
|
||||
identityLinks: params.cfg.session?.identityLinks,
|
||||
}).toLowerCase(),
|
||||
mainSessionKey: buildAgentMainSessionKey({
|
||||
}),
|
||||
);
|
||||
const mainSessionKey = normalizeLowercaseStringOrEmpty(
|
||||
buildAgentMainSessionKey({
|
||||
agentId: topicAgentId,
|
||||
}).toLowerCase(),
|
||||
}),
|
||||
);
|
||||
route = {
|
||||
...route,
|
||||
agentId: topicAgentId,
|
||||
sessionKey,
|
||||
mainSessionKey,
|
||||
lastRoutePolicy: deriveLastRoutePolicy({
|
||||
sessionKey: buildAgentSessionKey({
|
||||
agentId: topicAgentId,
|
||||
channel: "telegram",
|
||||
accountId: params.accountId,
|
||||
peer: { kind: params.isGroup ? "group" : "direct", id: peerId },
|
||||
dmScope: params.cfg.session?.dmScope,
|
||||
identityLinks: params.cfg.session?.identityLinks,
|
||||
}).toLowerCase(),
|
||||
mainSessionKey: buildAgentMainSessionKey({
|
||||
agentId: topicAgentId,
|
||||
}).toLowerCase(),
|
||||
sessionKey,
|
||||
mainSessionKey,
|
||||
}),
|
||||
};
|
||||
logVerbose(
|
||||
@@ -170,18 +168,20 @@ export function resolveTelegramConversationBaseSessionKey(params: {
|
||||
if (!isNamedAccountFallback || params.isGroup) {
|
||||
return params.route.sessionKey;
|
||||
}
|
||||
return buildAgentSessionKey({
|
||||
agentId: params.route.agentId,
|
||||
channel: "telegram",
|
||||
accountId: params.route.accountId,
|
||||
peer: {
|
||||
kind: "direct",
|
||||
id: resolveTelegramDirectPeerId({
|
||||
chatId: params.chatId,
|
||||
senderId: params.senderId,
|
||||
}),
|
||||
},
|
||||
dmScope: "per-account-channel-peer",
|
||||
identityLinks: params.cfg.session?.identityLinks,
|
||||
}).toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(
|
||||
buildAgentSessionKey({
|
||||
agentId: params.route.agentId,
|
||||
channel: "telegram",
|
||||
accountId: params.route.accountId,
|
||||
peer: {
|
||||
kind: "direct",
|
||||
id: resolveTelegramDirectPeerId({
|
||||
chatId: params.chatId,
|
||||
senderId: params.senderId,
|
||||
}),
|
||||
},
|
||||
dmScope: "per-account-channel-peer",
|
||||
identityLinks: params.cfg.session?.identityLinks,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -402,7 +402,9 @@ function formatErrorCodes(err: unknown): string {
|
||||
function shouldUseTelegramTransportFallback(err: unknown): boolean {
|
||||
const ctx: TelegramTransportFallbackContext = {
|
||||
message:
|
||||
err && typeof err === "object" && "message" in err ? String(err.message).toLowerCase() : "",
|
||||
err && typeof err === "object" && "message" in err
|
||||
? normalizeLowercaseStringOrEmpty(String(err.message))
|
||||
: "",
|
||||
codes: collectErrorCodes(err),
|
||||
};
|
||||
for (const rule of TELEGRAM_TRANSPORT_FALLBACK_RULES) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
FILE_REF_EXTENSIONS_WITH_TLD,
|
||||
isAutoLinkedFileRef,
|
||||
markdownToIR,
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
type MarkdownLinkSpan,
|
||||
type MarkdownIR,
|
||||
renderMarkdownIRChunksWithinLimit,
|
||||
@@ -182,7 +183,7 @@ export function wrapFileReferencesInHtml(html: string): string {
|
||||
const tagStart = match.index;
|
||||
const tagEnd = HTML_TAG_PATTERN.lastIndex;
|
||||
const isClosing = match[1] === "</";
|
||||
const tagName = match[2].toLowerCase();
|
||||
const tagName = normalizeLowercaseStringOrEmpty(match[2]);
|
||||
|
||||
// Process text before this tag
|
||||
const textBefore = deLinkified.slice(lastIndex, tagStart);
|
||||
@@ -393,7 +394,7 @@ export function splitTelegramHtmlChunks(html: string, limit: number): string[] {
|
||||
|
||||
const rawTag = match[0];
|
||||
const isClosing = match[1] === "</";
|
||||
const tagName = match[2].toLowerCase();
|
||||
const tagName = normalizeLowercaseStringOrEmpty(match[2]);
|
||||
const isSelfClosing =
|
||||
!isClosing &&
|
||||
(TELEGRAM_SELF_CLOSING_HTML_TAGS.has(tagName) || rawTag.trimEnd().endsWith("/>"));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { TelegramGroupConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
type TelegramGroups = Record<string, TelegramGroupConfig>;
|
||||
|
||||
@@ -29,7 +30,7 @@ function resolveAccountGroups(
|
||||
return { groups: exact.groups };
|
||||
}
|
||||
const matchKey = Object.keys(accounts).find(
|
||||
(key) => key.toLowerCase() === normalized.toLowerCase(),
|
||||
(key) => normalizeLowercaseStringOrEmpty(key) === normalizeLowercaseStringOrEmpty(normalized),
|
||||
);
|
||||
return { groups: matchKey ? accounts[matchKey]?.groups : undefined };
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ function normalizeTelegramNetworkMethod(method?: string | null): string | null {
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
return trimmed.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(trimmed);
|
||||
}
|
||||
|
||||
export function tagTelegramNetworkError(err: unknown, origin: TelegramNetworkErrorOrigin): void {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeTelegramLookupTarget, parseTelegramTarget } from "./targets.js";
|
||||
|
||||
const TELEGRAM_PREFIX_RE = /^(telegram|tg):/i;
|
||||
@@ -36,7 +37,7 @@ export function normalizeTelegramMessagingTarget(raw: string): string | undefine
|
||||
if (!normalizedBody) {
|
||||
return undefined;
|
||||
}
|
||||
return `telegram:${normalizedBody}`.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(`telegram:${normalizedBody}`);
|
||||
}
|
||||
|
||||
export function looksLikeTelegramTargetId(raw: string): boolean {
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
sleepWithAbort,
|
||||
} from "openclaw/plugin-sdk/runtime-env";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { withTelegramApiErrorLogging } from "./api-logging.js";
|
||||
import { createTelegramBot } from "./bot.js";
|
||||
import { type TelegramTransport } from "./fetch.js";
|
||||
@@ -450,7 +451,7 @@ const isGetUpdatesConflict = (err: unknown) => {
|
||||
}
|
||||
const haystack = [typed.method, typed.description, typed.message]
|
||||
.filter((value): value is string => typeof value === "string")
|
||||
.join(" ")
|
||||
.toLowerCase();
|
||||
return haystack.includes("getupdates");
|
||||
.join(" ");
|
||||
const normalizedHaystack = normalizeLowercaseStringOrEmpty(haystack);
|
||||
return normalizedHaystack.includes("getupdates");
|
||||
};
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { formatReasoningMessage } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { findCodeRegions, isInsideCode } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
stripReasoningTagsFromText,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
const REASONING_MESSAGE_PREFIX = "Reasoning:\n";
|
||||
const REASONING_TAG_PREFIXES = [
|
||||
@@ -44,7 +47,7 @@ function extractThinkingFromTaggedStreamOutsideCode(text: string): string {
|
||||
}
|
||||
|
||||
function isPartialReasoningTagPrefix(text: string): boolean {
|
||||
const trimmed = text.trimStart().toLowerCase();
|
||||
const trimmed = normalizeLowercaseStringOrEmpty(text.trimStart());
|
||||
if (!trimmed.startsWith("<")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
sleepWithAbort,
|
||||
type BackoffPolicy,
|
||||
} from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
export type TelegramSendChatActionLogger = (message: string) => void;
|
||||
|
||||
@@ -60,7 +61,9 @@ function is401Error(error: unknown): boolean {
|
||||
return false;
|
||||
}
|
||||
const message = error instanceof Error ? error.message : JSON.stringify(error);
|
||||
return message.includes("401") || message.toLowerCase().includes("unauthorized");
|
||||
return (
|
||||
message.includes("401") || normalizeLowercaseStringOrEmpty(message).includes("unauthorized")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
} from "openclaw/plugin-sdk/media-runtime";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { STATE_DIR } from "openclaw/plugin-sdk/state-paths";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { getTelegramRuntime } from "./runtime.js";
|
||||
|
||||
const CACHE_FILE = path.join(STATE_DIR, "telegram", "sticker-cache.json");
|
||||
@@ -75,12 +76,12 @@ export function cacheSticker(sticker: CachedSticker): void {
|
||||
*/
|
||||
export function searchStickers(query: string, limit = 10): CachedSticker[] {
|
||||
const cache = loadCache();
|
||||
const queryLower = query.toLowerCase();
|
||||
const queryLower = normalizeLowercaseStringOrEmpty(query);
|
||||
const results: Array<{ sticker: CachedSticker; score: number }> = [];
|
||||
|
||||
for (const sticker of Object.values(cache.stickers)) {
|
||||
let score = 0;
|
||||
const descLower = sticker.description.toLowerCase();
|
||||
const descLower = normalizeLowercaseStringOrEmpty(sticker.description);
|
||||
|
||||
// Exact substring match in description
|
||||
if (descLower.includes(queryLower)) {
|
||||
@@ -102,7 +103,7 @@ export function searchStickers(query: string, limit = 10): CachedSticker[] {
|
||||
}
|
||||
|
||||
// Set name match
|
||||
if (sticker.setName?.toLowerCase().includes(queryLower)) {
|
||||
if (normalizeLowercaseStringOrEmpty(sticker.setName).includes(queryLower)) {
|
||||
score += 3;
|
||||
}
|
||||
|
||||
@@ -193,7 +194,8 @@ export async function describeStickerImage(params: DescribeStickerParams): Promi
|
||||
const selectCatalogModel = (provider: string) => {
|
||||
const entries = catalog.filter(
|
||||
(entry) =>
|
||||
entry.provider.toLowerCase() === provider.toLowerCase() && modelSupportsVision(entry),
|
||||
normalizeLowercaseStringOrEmpty(entry.provider) ===
|
||||
normalizeLowercaseStringOrEmpty(provider) && modelSupportsVision(entry),
|
||||
);
|
||||
if (entries.length === 0) {
|
||||
return undefined;
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
saveCronStore,
|
||||
} from "openclaw/plugin-sdk/config-runtime";
|
||||
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
normalizeTelegramChatId,
|
||||
normalizeTelegramLookupTarget,
|
||||
@@ -30,7 +31,7 @@ function normalizeTelegramLookupTargetForMatch(raw: string): string | undefined
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
return normalized.startsWith("@") ? normalized.toLowerCase() : normalized;
|
||||
return normalized.startsWith("@") ? normalizeLowercaseStringOrEmpty(normalized) : normalized;
|
||||
}
|
||||
|
||||
function normalizeTelegramTargetForMatch(raw: string): string | undefined {
|
||||
|
||||
Reference in New Issue
Block a user