UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

100 lines (99 loc) 4.42 kB
import { a as normalizeLowercaseStringOrEmpty, c as normalizeOptionalString, l as normalizeOptionalStringifiedId } from "./string-coerce-mnp54Vah.js"; import "./string-coerce-runtime-CEGJWkQ_.js"; import { n as resolveDiscordDirectoryUserId } from "./directory-cache-DfoYG_5F.js"; //#region extensions/discord/src/mentions.ts const MARKDOWN_CODE_SEGMENT_PATTERN = /```[\s\S]*?```|`[^`\n]*`/g; const MENTION_CANDIDATE_PATTERN = /(^|[\s([{"'.,;:!?])@([a-z0-9_.-]{2,32}(?:#[0-9]{4})?)/gi; const DISCORD_RESERVED_MENTIONS = new Set(["everyone", "here"]); const DISCORD_DISCRIMINATOR_SUFFIX = /#\d{4}$/; const DISCORD_TARGETED_MENTION_PATTERN = /<@!?\d+>|<@&\d+>/; const DISCORD_BROADCAST_MENTION_PATTERN = /@(everyone|here)\b/; function normalizeSnowflake(value) { const text = normalizeOptionalStringifiedId(value) ?? ""; if (!/^\d+$/.test(text)) return null; return text; } function formatMention(params) { const userId = params.userId == null ? null : normalizeSnowflake(params.userId); const roleId = params.roleId == null ? null : normalizeSnowflake(params.roleId); const channelId = params.channelId == null ? null : normalizeSnowflake(params.channelId); const values = [ userId ? { kind: "user", id: userId } : null, roleId ? { kind: "role", id: roleId } : null, channelId ? { kind: "channel", id: channelId } : null ].filter((entry) => Boolean(entry)); if (values.length !== 1) throw new Error("formatMention requires exactly one of userId, roleId, or channelId"); const target = values[0]; if (target.kind === "user") return `<@${target.id}>`; if (target.kind === "role") return `<@&${target.id}>`; return `<#${target.id}>`; } function normalizeHandleKey(raw) { let handle = normalizeOptionalString(raw) ?? ""; if (!handle) return null; if (handle.startsWith("@")) handle = normalizeOptionalString(handle.slice(1)) ?? ""; if (!handle || /\s/.test(handle)) return null; return normalizeLowercaseStringOrEmpty(handle); } function resolveConfiguredMentionAlias(handle, mentionAliases) { const key = normalizeHandleKey(handle); if (!key || !mentionAliases) return; const withoutDiscriminator = key.replace(DISCORD_DISCRIMINATOR_SUFFIX, ""); for (const [rawAlias, rawUserId] of Object.entries(mentionAliases)) { const alias = normalizeHandleKey(rawAlias); if (!alias) continue; const aliasWithoutDiscriminator = alias.replace(DISCORD_DISCRIMINATOR_SUFFIX, ""); if (alias === key || withoutDiscriminator && withoutDiscriminator !== key && alias === withoutDiscriminator || aliasWithoutDiscriminator && aliasWithoutDiscriminator !== alias && aliasWithoutDiscriminator === key) { const userId = normalizeSnowflake(rawUserId); if (userId) return userId; } } } function rewritePlainTextMentions(text, params) { if (!text.includes("@")) return text; return text.replace(MENTION_CANDIDATE_PATTERN, (match, prefix, rawHandle) => { const handle = normalizeOptionalString(rawHandle) ?? ""; if (!handle) return match; const lookup = normalizeLowercaseStringOrEmpty(handle); if (DISCORD_RESERVED_MENTIONS.has(lookup)) return match; const userId = resolveConfiguredMentionAlias(handle, params.mentionAliases) ?? resolveDiscordDirectoryUserId({ accountId: params.accountId, handle }); if (!userId) return match; return `${String(prefix ?? "")}${formatMention({ userId })}`; }); } function rewriteDiscordKnownMentions(text, params) { if (!text.includes("@")) return text; let rewritten = ""; let offset = 0; MARKDOWN_CODE_SEGMENT_PATTERN.lastIndex = 0; for (const match of text.matchAll(MARKDOWN_CODE_SEGMENT_PATTERN)) { const matchIndex = match.index ?? 0; rewritten += rewritePlainTextMentions(text.slice(offset, matchIndex), params); rewritten += match[0]; offset = matchIndex + match[0].length; } rewritten += rewritePlainTextMentions(text.slice(offset), params); return rewritten; } /** Whether text carries a Discord user/role mention (`<@id>`, `<@!id>`, `<@&id>`) that pings when sent fresh. */ function discordTextHasTargetedMention(text) { return DISCORD_TARGETED_MENTION_PATTERN.test(text); } /** Whether text carries an `@everyone`/`@here` broadcast mention. */ function discordTextHasBroadcastMention(text) { return DISCORD_BROADCAST_MENTION_PATTERN.test(text); } //#endregion export { rewriteDiscordKnownMentions as i, discordTextHasTargetedMention as n, formatMention as r, discordTextHasBroadcastMention as t };