refactor: dedupe signal lowercase helpers

This commit is contained in:
Peter Steinberger
2026-04-07 15:31:59 +01:00
parent 9e007ef759
commit ddde144cb6
10 changed files with 37 additions and 22 deletions

View File

@@ -18,6 +18,7 @@ import {
createComputedAccountStatusAdapter,
createDefaultChannelRuntimeState,
} from "openclaw/plugin-sdk/status-helpers";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { resolveSignalAccount, type ResolvedSignalAccount } from "./accounts.js";
import { signalApprovalAuth } from "./approval-auth.js";
import { markdownToSignalTextChunks } from "./format.js";
@@ -103,7 +104,7 @@ function inferSignalTargetChatType(rawTo: string) {
if (!to) {
return undefined;
}
const lower = to.toLowerCase();
const lower = normalizeLowercaseStringOrEmpty(to);
if (lower.startsWith("group:")) {
return "group" as const;
}

View File

@@ -1,6 +1,7 @@
import type { MarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
import {
markdownToIR,
normalizeLowercaseStringOrEmpty,
type MarkdownIR,
type MarkdownStyle,
renderMarkdownIRChunksWithinLimit,
@@ -35,7 +36,7 @@ type Insertion = {
};
function normalizeUrlForComparison(url: string): string {
let normalized = url.toLowerCase();
let normalized = normalizeLowercaseStringOrEmpty(url);
// Strip protocol
normalized = normalized.replace(/^https?:\/\//, "");
// Strip www. prefix

View File

@@ -1,5 +1,5 @@
import { evaluateSenderGroupAccessForPolicy } from "openclaw/plugin-sdk/group-access";
import { normalizeE164 } from "openclaw/plugin-sdk/text-runtime";
import { normalizeE164, normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { looksLikeUuid } from "./uuid.js";
export type SignalSender =
@@ -69,7 +69,7 @@ function parseSignalAllowEntry(entry: string): SignalAllowEntry | null {
}
const stripped = stripSignalPrefix(trimmed);
const lower = stripped.toLowerCase();
const lower = normalizeLowercaseStringOrEmpty(stripped);
if (lower.startsWith("uuid:")) {
const raw = stripped.slice("uuid:".length).trim();
if (!raw) {

View File

@@ -8,6 +8,7 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/run-command";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { CONFIG_DIR, extractArchive, resolveBrewExecutable } from "openclaw/plugin-sdk/setup-tools";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
export type ReleaseAsset = {
name?: string;
@@ -64,10 +65,12 @@ export function pickAsset(
);
// Archives only, excluding signature files (.asc)
const archives = withName.filter((a) => looksLikeArchive(a.name.toLowerCase()));
const archives = withName.filter((a) =>
looksLikeArchive(normalizeLowercaseStringOrEmpty(a.name)),
);
const byName = (pattern: RegExp) =>
archives.find((asset) => pattern.test(asset.name.toLowerCase()));
archives.find((asset) => pattern.test(normalizeLowercaseStringOrEmpty(asset.name)));
if (platform === "linux") {
// The official "Linux-native" asset is an x86-64 GraalVM binary.
@@ -253,7 +256,7 @@ async function installSignalCliFromRelease(runtime: RuntimeEnv): Promise<SignalI
const installRoot = path.join(CONFIG_DIR, "tools", "signal-cli", version);
await fs.mkdir(installRoot, { recursive: true });
if (!looksLikeArchive(asset.name.toLowerCase())) {
if (!looksLikeArchive(normalizeLowercaseStringOrEmpty(asset.name))) {
return { ok: false, error: `Unsupported archive type: ${asset.name}` };
}
try {

View File

@@ -4,6 +4,7 @@ import type {
ChannelMessageActionAdapter,
ChannelMessageActionName,
} from "openclaw/plugin-sdk/channel-contract";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { removeReactionSignal, sendReactionSignal } from "../reaction-runtime-api.js";
import { listEnabledSignalAccounts, resolveSignalAccount } from "./accounts.js";
import { resolveSignalReactionLevel } from "./reaction-level.js";
@@ -20,7 +21,7 @@ function normalizeSignalReactionRecipient(raw: string): string {
if (!withoutSignal) {
return withoutSignal;
}
if (withoutSignal.toLowerCase().startsWith("uuid:")) {
if (normalizeLowercaseStringOrEmpty(withoutSignal).startsWith("uuid:")) {
return withoutSignal.slice("uuid:".length).trim();
}
return withoutSignal;
@@ -35,7 +36,7 @@ function resolveSignalReactionTarget(raw: string): { recipient?: string; groupId
if (!withoutSignal) {
return {};
}
if (withoutSignal.toLowerCase().startsWith(GROUP_PREFIX)) {
if (normalizeLowercaseStringOrEmpty(withoutSignal).startsWith(GROUP_PREFIX)) {
const groupId = withoutSignal.slice(GROUP_PREFIX.length).trim();
return groupId ? { groupId } : {};
}

View File

@@ -1,33 +1,35 @@
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
export function normalizeSignalMessagingTarget(raw: string): string | undefined {
const trimmed = raw.trim();
if (!trimmed) {
return undefined;
}
let normalized = trimmed;
if (normalized.toLowerCase().startsWith("signal:")) {
if (normalizeLowercaseStringOrEmpty(normalized).startsWith("signal:")) {
normalized = normalized.slice("signal:".length).trim();
}
if (!normalized) {
return undefined;
}
const lower = normalized.toLowerCase();
const lower = normalizeLowercaseStringOrEmpty(normalized);
if (lower.startsWith("group:")) {
const id = normalized.slice("group:".length).trim();
return id ? `group:${id}` : undefined;
}
if (lower.startsWith("username:")) {
const id = normalized.slice("username:".length).trim();
return id ? `username:${id}`.toLowerCase() : undefined;
return id ? normalizeLowercaseStringOrEmpty(`username:${id}`) : undefined;
}
if (lower.startsWith("u:")) {
const id = normalized.slice("u:".length).trim();
return id ? `username:${id}`.toLowerCase() : undefined;
return id ? normalizeLowercaseStringOrEmpty(`username:${id}`) : undefined;
}
if (lower.startsWith("uuid:")) {
const id = normalized.slice("uuid:".length).trim();
return id ? id.toLowerCase() : undefined;
return id ? normalizeLowercaseStringOrEmpty(id) : undefined;
}
return normalized.toLowerCase();
return normalizeLowercaseStringOrEmpty(normalized);
}
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

View File

@@ -1,4 +1,5 @@
import { type RoutePeer } from "openclaw/plugin-sdk/routing";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { resolveSignalPeerId, resolveSignalRecipient, resolveSignalSender } from "./identity.js";
import { looksLikeUuid } from "./uuid.js";
@@ -11,7 +12,7 @@ export type ResolvedSignalOutboundTarget = {
export function resolveSignalOutboundTarget(target: string): ResolvedSignalOutboundTarget | null {
const stripped = target.replace(/^signal:/i, "").trim();
const lowered = stripped.toLowerCase();
const lowered = normalizeLowercaseStringOrEmpty(stripped);
if (lowered.startsWith("group:")) {
const groupId = stripped.slice("group:".length).trim();
if (!groupId) {
@@ -35,7 +36,7 @@ export function resolveSignalOutboundTarget(target: string): ResolvedSignalOutbo
return null;
}
const uuidCandidate = recipient.toLowerCase().startsWith("uuid:")
const uuidCandidate = normalizeLowercaseStringOrEmpty(recipient).startsWith("uuid:")
? recipient.slice("uuid:".length)
: recipient;
const sender = resolveSignalSender({

View File

@@ -3,6 +3,7 @@
*/
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { resolveSignalAccount } from "./accounts.js";
import { signalRpcRequest } from "./client.js";
import { resolveSignalRpcContext } from "./rpc-context.js";
@@ -52,7 +53,7 @@ function normalizeSignalUuid(raw: string): string {
if (!trimmed) {
return "";
}
if (trimmed.toLowerCase().startsWith("uuid:")) {
if (normalizeLowercaseStringOrEmpty(trimmed).startsWith("uuid:")) {
return trimmed.slice("uuid:".length).trim();
}
return trimmed;

View File

@@ -2,6 +2,7 @@ import { loadConfig, type OpenClawConfig } from "openclaw/plugin-sdk/config-runt
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
import { kindFromMime } from "openclaw/plugin-sdk/media-runtime";
import { resolveOutboundAttachmentFromUrl } from "openclaw/plugin-sdk/media-runtime";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { resolveSignalAccount } from "./accounts.js";
import { signalRpcRequest } from "./client.js";
import { markdownToSignalText, type SignalTextStyleRange } from "./format.js";
@@ -66,11 +67,11 @@ function parseTarget(raw: string): SignalTarget {
if (!value) {
throw new Error("Signal recipient is required");
}
const lower = value.toLowerCase();
const lower = normalizeLowercaseStringOrEmpty(value);
if (lower.startsWith("signal:")) {
value = value.slice("signal:".length).trim();
}
const normalized = value.toLowerCase();
const normalized = normalizeLowercaseStringOrEmpty(value);
if (normalized.startsWith("group:")) {
return { type: "group", groupId: value.slice("group:".length).trim() };
}

View File

@@ -18,7 +18,11 @@ import {
type WizardPrompter,
} from "openclaw/plugin-sdk/setup-runtime";
import { formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
import { normalizeE164, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import {
normalizeE164,
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "openclaw/plugin-sdk/text-runtime";
import { resolveDefaultSignalAccountId, resolveSignalAccount } from "./accounts.js";
const channel = "signal" as const;
@@ -50,7 +54,7 @@ function isUuidLike(value: string): boolean {
export function parseSignalAllowFromEntries(raw: string): { entries: string[]; error?: string } {
return parseSetupEntriesAllowingWildcard(raw, (entry) => {
if (entry.toLowerCase().startsWith("uuid:")) {
if (normalizeLowercaseStringOrEmpty(entry).startsWith("uuid:")) {
const id = entry.slice("uuid:".length).trim();
if (!id) {
return { error: "Invalid uuid entry" };