refactor: dedupe google chat lowercase helpers

This commit is contained in:
Peter Steinberger
2026-04-07 13:21:52 +01:00
parent a93a94788a
commit f09cee84f2
6 changed files with 36 additions and 27 deletions

View File

@@ -2,6 +2,7 @@ import {
createResolvedApproverActionAuthAdapter,
resolveApprovalApprovers,
} from "openclaw/plugin-sdk/approval-auth-runtime";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { resolveGoogleChatAccount } from "./accounts.js";
import { isGoogleChatUserTarget, normalizeGoogleChatTarget } from "./targets.js";
@@ -10,7 +11,7 @@ function normalizeGoogleChatApproverId(value: string | number): string | undefin
if (!normalized || !isGoogleChatUserTarget(normalized)) {
return undefined;
}
const suffix = normalized.slice("users/".length).trim().toLowerCase();
const suffix = normalizeLowercaseStringOrEmpty(normalized.slice("users/".length));
if (!suffix || suffix.includes("@")) {
return undefined;
}

View File

@@ -1,4 +1,5 @@
import { GoogleAuth, OAuth2Client } from "google-auth-library";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import type { ResolvedGoogleChatAccount } from "./accounts.js";
const CHAT_SCOPE = "https://www.googleapis.com/auth/chat.bot";
@@ -113,9 +114,7 @@ export async function verifyGoogleChatRequest(params: {
audience,
});
const payload = ticket.getPayload();
const email = String(payload?.email ?? "")
.trim()
.toLowerCase();
const email = normalizeLowercaseStringOrEmpty(String(payload?.email ?? ""));
if (!payload?.email_verified) {
return { ok: false, reason: "email not verified" };
}
@@ -125,13 +124,13 @@ export async function verifyGoogleChatRequest(params: {
if (!ADDON_ISSUER_PATTERN.test(email)) {
return { ok: false, reason: `invalid issuer: ${email}` };
}
const expectedAddOnPrincipal = params.expectedAddOnPrincipal?.trim().toLowerCase();
const expectedAddOnPrincipal = normalizeLowercaseStringOrEmpty(
params.expectedAddOnPrincipal ?? "",
);
if (!expectedAddOnPrincipal) {
return { ok: false, reason: "missing add-on principal binding" };
}
const tokenPrincipal = String(payload?.sub ?? "")
.trim()
.toLowerCase();
const tokenPrincipal = normalizeLowercaseStringOrEmpty(String(payload?.sub ?? ""));
if (!tokenPrincipal || tokenPrincipal !== expectedAddOnPrincipal) {
return {
ok: false,

View File

@@ -21,6 +21,7 @@ import {
createComputedAccountStatusAdapter,
createDefaultChannelRuntimeState,
} from "openclaw/plugin-sdk/status-helpers";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { googlechatMessageActions } from "./actions.js";
import { googleChatApprovalAuth } from "./approval-auth.js";
import {
@@ -73,12 +74,13 @@ const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(
);
const formatAllowFromEntry = (entry: string) =>
entry
.trim()
.replace(/^(googlechat|google-chat|gchat):/i, "")
.replace(/^user:/i, "")
.replace(/^users\//i, "")
.toLowerCase();
normalizeLowercaseStringOrEmpty(
entry
.trim()
.replace(/^(googlechat|google-chat|gchat):/i, "")
.replace(/^user:/i, "")
.replace(/^users\//i, ""),
);
const googleChatConfigAdapter = createScopedChannelConfigAdapter<ResolvedGoogleChatAccount>({
sectionKey: "googlechat",

View File

@@ -1,5 +1,8 @@
import { resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-inbound";
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "openclaw/plugin-sdk/text-runtime";
import {
GROUP_POLICY_BLOCKED_LABEL,
createChannelPairingController,
@@ -22,7 +25,7 @@ function normalizeUserId(raw?: string | null): string {
if (!trimmed) {
return "";
}
return trimmed.replace(/^users\//i, "").toLowerCase();
return normalizeLowercaseStringOrEmpty(trimmed.replace(/^users\//i, ""));
}
function isEmailLike(value: string): boolean {
@@ -40,9 +43,9 @@ export function isSenderAllowed(
return true;
}
const normalizedSenderId = normalizeUserId(senderId);
const normalizedEmail = senderEmail?.trim().toLowerCase() ?? "";
const normalizedEmail = normalizeLowercaseStringOrEmpty(senderEmail ?? "");
return allowFrom.some((entry) => {
const normalized = String(entry).trim().toLowerCase();
const normalized = normalizeLowercaseStringOrEmpty(String(entry));
if (!normalized) {
return false;
}
@@ -81,7 +84,7 @@ function resolveGroupConfig(params: {
return { entry: undefined, allowlistConfigured: false, deprecatedNameMatch: false };
}
const entry = entries[groupId];
const normalizedGroupName = groupName?.trim().toLowerCase() ?? "";
const normalizedGroupName = normalizeLowercaseStringOrEmpty(groupName ?? "");
const deprecatedNameMatch =
!entry &&
Boolean(
@@ -91,7 +94,9 @@ function resolveGroupConfig(params: {
if (!trimmed || trimmed === "*" || /^spaces\//i.test(trimmed)) {
return false;
}
return trimmed === groupName || trimmed.toLowerCase() === normalizedGroupName;
return (
trimmed === groupName || normalizeLowercaseStringOrEmpty(trimmed) === normalizedGroupName
);
}),
);
const fallback = entries["*"];
@@ -129,7 +134,7 @@ function warnDeprecatedUsersEmailEntries(logVerbose: (message: string) => void,
return;
}
const key = deprecated
.map((v) => v.toLowerCase())
.map((v) => normalizeLowercaseStringOrEmpty(v))
.toSorted()
.join(",");
if (warnedDeprecatedUsersEmailAllowFrom.has(key)) {
@@ -152,7 +157,7 @@ function warnMutableGroupKeysConfigured(
return;
}
const warningKey = mutableKeys
.map((key) => key.toLowerCase())
.map((key) => normalizeLowercaseStringOrEmpty(key))
.toSorted()
.join(",");
if (warnedMutableGroupKeys.has(warningKey)) {

View File

@@ -1,4 +1,5 @@
import type { IncomingMessage, ServerResponse } from "node:http";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import {
readJsonWebhookBodyOrReject,
resolveWebhookTargetWithAuthOrReject,
@@ -22,7 +23,7 @@ function extractBearerToken(header: unknown): string {
: typeof header === "string"
? header
: "";
return authHeader.toLowerCase().startsWith("bearer ")
return normalizeLowercaseStringOrEmpty(authHeader).startsWith("bearer ")
? authHeader.slice("bearer ".length).trim()
: "";
}

View File

@@ -1,3 +1,4 @@
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import type { ResolvedGoogleChatAccount } from "./accounts.js";
import { findGoogleChatDirectMessage } from "./api.js";
@@ -12,23 +13,23 @@ export function normalizeGoogleChatTarget(raw?: string | null): string | undefin
.replace(/^space:(spaces\/)?/i, "spaces/");
if (isGoogleChatUserTarget(normalized)) {
const suffix = normalized.slice("users/".length);
return suffix.includes("@") ? `users/${suffix.toLowerCase()}` : normalized;
return suffix.includes("@") ? `users/${normalizeLowercaseStringOrEmpty(suffix)}` : normalized;
}
if (isGoogleChatSpaceTarget(normalized)) {
return normalized;
}
if (normalized.includes("@")) {
return `users/${normalized.toLowerCase()}`;
return `users/${normalizeLowercaseStringOrEmpty(normalized)}`;
}
return normalized;
}
export function isGoogleChatUserTarget(value: string): boolean {
return value.toLowerCase().startsWith("users/");
return normalizeLowercaseStringOrEmpty(value).startsWith("users/");
}
export function isGoogleChatSpaceTarget(value: string): boolean {
return value.toLowerCase().startsWith("spaces/");
return normalizeLowercaseStringOrEmpty(value).startsWith("spaces/");
}
function stripMessageSuffix(target: string): string {