refactor(shared): centralize @/# slug normalization

This commit is contained in:
Peter Steinberger
2026-02-18 23:32:41 +00:00
parent b366279030
commit 136bd59ba5
4 changed files with 23 additions and 24 deletions

View File

@@ -3,6 +3,7 @@ import { getChannelDock } from "../../channels/dock.js";
import { normalizeChannelId } from "../../channels/plugins/index.js";
import { CHAT_CHANNEL_ORDER } from "../../channels/registry.js";
import type { AgentElevatedAllowFromConfig, OpenClawConfig } from "../../config/config.js";
import { normalizeAtHashSlug } from "../../shared/string-normalization.js";
import { INTERNAL_MESSAGE_CHANNEL } from "../../utils/message-channel.js";
import type { MsgContext } from "../templating.js";
export { formatElevatedUnavailableMessage } from "./elevated-unavailable.js";
@@ -15,17 +16,7 @@ function normalizeAllowToken(value?: string) {
}
function slugAllowToken(value?: string) {
if (!value) {
return "";
}
let text = value.trim().toLowerCase();
if (!text) {
return "";
}
text = text.replace(/^[@#]+/, "");
text = text.replace(/[\s_]+/g, "-");
text = text.replace(/[^a-z0-9-]+/g, "-");
return text.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
return normalizeAtHashSlug(value);
}
const SENDER_PREFIXES = [

View File

@@ -9,7 +9,7 @@ import type {
GroupToolPolicyBySenderConfig,
GroupToolPolicyConfig,
} from "../../config/types.tools.js";
import { normalizeHyphenSlug } from "../../shared/string-normalization.js";
import { normalizeAtHashSlug, normalizeHyphenSlug } from "../../shared/string-normalization.js";
import { resolveSlackAccount } from "../../slack/accounts.js";
type GroupMentionParams = {
@@ -25,18 +25,7 @@ type GroupMentionParams = {
};
function normalizeDiscordSlug(value?: string | null) {
if (!value) {
return "";
}
let text = value.trim().toLowerCase();
if (!text) {
return "";
}
text = text.replace(/^[@#]+/, "");
text = text.replace(/[\s_]+/g, "-");
text = text.replace(/[^a-z0-9-]+/g, "-");
text = text.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
return text;
return normalizeAtHashSlug(value);
}
function parseTelegramGroupId(value?: string | null) {

View File

@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import {
normalizeAtHashSlug,
normalizeHyphenSlug,
normalizeStringEntries,
normalizeStringEntriesLower,
@@ -22,4 +23,11 @@ describe("shared/string-normalization", () => {
expect(normalizeHyphenSlug(undefined)).toBe("");
expect(normalizeHyphenSlug(null)).toBe("");
});
it("normalizes @/# prefixed slugs used by channel allowlists", () => {
expect(normalizeAtHashSlug(" #My_Channel + Alerts ")).toBe("my-channel-alerts");
expect(normalizeAtHashSlug("@@Room___Name")).toBe("room-name");
expect(normalizeAtHashSlug(undefined)).toBe("");
expect(normalizeAtHashSlug(null)).toBe("");
});
});

View File

@@ -15,3 +15,14 @@ export function normalizeHyphenSlug(raw?: string | null) {
const cleaned = dashed.replace(/[^a-z0-9#@._+-]+/g, "-");
return cleaned.replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "");
}
export function normalizeAtHashSlug(raw?: string | null) {
const trimmed = raw?.trim().toLowerCase() ?? "";
if (!trimmed) {
return "";
}
const withoutPrefix = trimmed.replace(/^[@#]+/, "");
const dashed = withoutPrefix.replace(/[\s_]+/g, "-");
const cleaned = dashed.replace(/[^a-z0-9-]+/g, "-");
return cleaned.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
}