Skip to content

Commit 424b65b

Browse files
committed
refactor: dedupe bluebubbles and zalouser readers
1 parent 90a45a4 commit 424b65b

13 files changed

Lines changed: 45 additions & 27 deletions

File tree

extensions/bluebubbles/src/attachments.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import crypto from "node:crypto";
22
import path from "node:path";
33
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
4+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
45
import { resolveBlueBubblesServerAccount } from "./account-resolve.js";
56
import { assertMultipartActionOk, postMultipartFormData } from "./multipart.js";
67
import {
@@ -161,7 +162,7 @@ export async function sendBlueBubblesAttachment(params: {
161162
const wantsVoice = asVoice === true;
162163
const fallbackName = wantsVoice ? "Audio Message" : "attachment";
163164
filename = sanitizeFilename(filename, fallbackName);
164-
contentType = contentType?.trim() || undefined;
165+
contentType = normalizeOptionalString(contentType);
165166
const { baseUrl, password, accountId, allowPrivateNetwork } = resolveAccount(opts);
166167
const privateApiStatus = getCachedBlueBubblesPrivateApiStatus(accountId);
167168
const privateApiEnabled = isBlueBubblesPrivateApiStatusEnabled(privateApiStatus);

extensions/bluebubbles/src/monitor-normalize.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { parseFiniteNumber } from "openclaw/plugin-sdk/infra-runtime";
2-
import { asNullableRecord, readStringField } from "openclaw/plugin-sdk/text-runtime";
2+
import {
3+
asNullableRecord,
4+
normalizeOptionalString,
5+
readStringField,
6+
} from "openclaw/plugin-sdk/text-runtime";
37
import { extractHandleFromChatGuid, normalizeBlueBubblesHandle } from "./targets.js";
48
import type { BlueBubblesAttachment } from "./types.js";
59

@@ -164,8 +168,8 @@ function extractReplyMetadata(message: Record<string, unknown>): {
164168
: undefined;
165169

166170
return {
167-
replyToId: (replyToId ?? fallbackReplyId)?.trim() || undefined,
168-
replyToBody: replyToBody?.trim() || undefined,
171+
replyToId: normalizeOptionalString(replyToId ?? fallbackReplyId),
172+
replyToBody: normalizeOptionalString(replyToBody),
169173
replyToSender: normalizedSender || undefined,
170174
};
171175
}
@@ -336,7 +340,7 @@ function normalizeParticipantEntry(entry: unknown): BlueBubblesParticipant | nul
336340
if (!normalizedId) {
337341
return null;
338342
}
339-
const name = nameRaw?.trim() || undefined;
343+
const name = normalizeOptionalString(nameRaw);
340344
return { id: normalizedId, name };
341345
}
342346

@@ -563,7 +567,9 @@ export function resolveTapbackContext(message: NormalizedWebhookMessage): {
563567
if (!hasTapbackType && !hasTapbackMarker) {
564568
return null;
565569
}
566-
const replyToId = message.associatedMessageGuid?.trim() || message.replyToId?.trim() || undefined;
570+
const replyToId =
571+
normalizeOptionalString(message.associatedMessageGuid) ??
572+
normalizeOptionalString(message.replyToId);
567573
const actionHint = resolveTapbackActionHint(associatedType);
568574
const emojiHint =
569575
message.associatedMessageEmoji?.trim() || REACTION_TYPE_MAP.get(associatedType ?? -1)?.emoji;

extensions/bluebubbles/src/monitor-processing.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
sendMediaWithLeadingCaption,
55
} from "openclaw/plugin-sdk/reply-payload";
66
import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime";
7+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
78
import { downloadBlueBubblesAttachment } from "./attachments.js";
89
import { markBlueBubblesChatRead, sendBlueBubblesTyping } from "./chat.js";
910
import { resolveBlueBubblesConversationRoute } from "./conversation-route.js";
@@ -92,8 +93,7 @@ const pendingOutboundMessageIds: PendingOutboundMessageId[] = [];
9293
let pendingOutboundMessageIdCounter = 0;
9394

9495
function trimOrUndefined(value?: string | null): string | undefined {
95-
const trimmed = value?.trim();
96-
return trimmed ? trimmed : undefined;
96+
return normalizeOptionalString(value);
9797
}
9898

9999
function normalizeSnippet(value: string): string {
@@ -732,7 +732,7 @@ export async function processMessage(
732732
chatId: message.chatId ?? undefined,
733733
chatIdentifier: message.chatIdentifier ?? undefined,
734734
});
735-
const groupName = message.chatName?.trim() || undefined;
735+
const groupName = normalizeOptionalString(message.chatName);
736736

737737
if (accessDecision.decision !== "allow") {
738738
if (isGroup) {
@@ -1105,11 +1105,11 @@ export async function processMessage(
11051105
// The sender identity is included in the envelope body via formatInboundEnvelope.
11061106
const senderLabel = message.senderName || `user:${message.senderId}`;
11071107
const fromLabel = isGroup
1108-
? `${message.chatName?.trim() || "Group"} id:${peerId}`
1108+
? `${normalizeOptionalString(message.chatName) || "Group"} id:${peerId}`
11091109
: senderLabel !== message.senderId
11101110
? `${senderLabel} id:${message.senderId}`
11111111
: senderLabel;
1112-
const groupSubject = isGroup ? message.chatName?.trim() || undefined : undefined;
1112+
const groupSubject = isGroup ? normalizeOptionalString(message.chatName) : undefined;
11131113
const groupMembers = isGroup
11141114
? formatGroupMembers({
11151115
participants: message.participants,

extensions/bluebubbles/src/participant-contact-names.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { execFile, type ExecFileOptionsWithStringEncoding } from "node:child_pro
22
import { access, readdir } from "node:fs/promises";
33
import { join } from "node:path";
44
import { promisify } from "node:util";
5+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
56
import type { BlueBubblesParticipant } from "./monitor-normalize.js";
67

78
const execFileAsync = promisify(execFile) as ExecFileRunner;
@@ -313,7 +314,7 @@ export async function enrichBlueBubblesParticipantsWithContactNames(
313314
try {
314315
const resolved = await lookup([...pendingPhoneKeys]);
315316
for (const phoneKey of pendingPhoneKeys) {
316-
const name = resolved.get(phoneKey)?.trim() || undefined;
317+
const name = normalizeOptionalString(resolved.get(phoneKey));
317318
writeCacheEntry(phoneKey, name, nowMs);
318319
if (name) {
319320
cachedNames.set(phoneKey, name);

extensions/browser/src/cli/browser-cli-state.cookies-storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export function registerBrowserCookiesAndStorageCommands(
146146
method: "GET",
147147
path: `/storage/${kind}`,
148148
query: {
149-
key: key?.trim() || undefined,
149+
key: normalizeOptionalString(key),
150150
targetId,
151151
profile,
152152
},

extensions/llm-task/src/llm-task-tool.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
22
import path from "node:path";
33
import { Type } from "@sinclair/typebox";
44
import Ajv from "ajv";
5+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
56
import {
67
formatXHighModelHint,
78
normalizeThinkLevel,
@@ -96,8 +97,8 @@ export function createLlmTaskTool(api: OpenClawPluginApi) {
9697
const defaultsModel = api.config?.agents?.defaults?.model;
9798
const primary =
9899
typeof defaultsModel === "string"
99-
? defaultsModel.trim()
100-
: (defaultsModel?.primary?.trim() ?? undefined);
100+
? normalizeOptionalString(defaultsModel)
101+
: normalizeOptionalString(defaultsModel?.primary);
101102
const primaryProvider = typeof primary === "string" ? primary.split("/")[0] : undefined;
102103
const primaryModel =
103104
typeof primary === "string" ? primary.split("/").slice(1).join("/") : undefined;

extensions/memory-wiki/src/markdown.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export function renderWikiMarkdown(params: {
8181

8282
export function extractTitleFromMarkdown(body: string): string | undefined {
8383
const match = body.match(/^#\s+(.+?)\s*$/m);
84-
return match?.[1]?.trim() || undefined;
84+
return normalizeOptionalString(match?.[1]);
8585
}
8686

8787
export function normalizeSourceIds(value: unknown): string[] {

extensions/zalouser/src/zalo-js.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import os from "node:os";
55
import path from "node:path";
66
import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
77
import { resolveStateDir as resolvePluginStateDir } from "openclaw/plugin-sdk/state-paths";
8+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
89
import { normalizeZaloReactionIcon } from "./reaction.js";
910
import type {
1011
ZaloAuthStatus,
@@ -500,7 +501,7 @@ function resolveUploadedVoiceAsset(
500501
continue;
501502
}
502503
if (fileType === "others" || fileType === "video") {
503-
return { fileUrl, fileName: item.fileName?.trim() || undefined };
504+
return { fileUrl, fileName: normalizeOptionalString(item.fileName) };
504505
}
505506
}
506507
return undefined;
@@ -963,7 +964,8 @@ export async function listZaloGroupMembers(
963964
continue;
964965
}
965966
currentById.set(id, {
966-
displayName: member.dName?.trim() || member.zaloName?.trim() || undefined,
967+
displayName:
968+
normalizeOptionalString(member.dName) ?? normalizeOptionalString(member.zaloName),
967969
avatar: member.avatar || undefined,
968970
});
969971
}
@@ -990,7 +992,9 @@ export async function listZaloGroupMembers(
990992
continue;
991993
}
992994
profileMap.set(id, {
993-
displayName: profileValue.displayName?.trim() || profileValue.zaloName?.trim() || undefined,
995+
displayName:
996+
normalizeOptionalString(profileValue.displayName) ??
997+
normalizeOptionalString(profileValue.zaloName),
994998
avatar: profileValue.avatar || undefined,
995999
});
9961000
}
@@ -1024,7 +1028,7 @@ export async function resolveZaloGroupContext(
10241028
| undefined;
10251029
const context: ZaloGroupContext = {
10261030
groupId: normalizedGroupId,
1027-
name: groupInfo?.name?.trim() || undefined,
1031+
name: normalizeOptionalString(groupInfo?.name),
10281032
members: extractGroupMembersFromInfo(groupInfo),
10291033
};
10301034
writeCachedGroupContext(profile, context);

scripts/debug-claude-usage.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import crypto from "node:crypto";
33
import fs from "node:fs";
44
import os from "node:os";
55
import path from "node:path";
6+
import { normalizeOptionalString } from "../src/shared/string-coerce.ts";
67

78
type Args = {
89
agentId: string;
@@ -36,7 +37,7 @@ const parseArgs = (): Args => {
3637
continue;
3738
}
3839
if (arg === "--session-key" && args[i + 1]) {
39-
sessionKey = String(args[++i]).trim() || undefined;
40+
sessionKey = normalizeOptionalString(String(args[++i]));
4041
continue;
4142
}
4243
}

scripts/lib/plugin-npm-release.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { execFileSync } from "node:child_process";
22
import { mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
33
import { tmpdir } from "node:os";
44
import { join, resolve } from "node:path";
5+
import { normalizeOptionalString } from "../../src/shared/string-coerce.ts";
56
import { parseReleaseVersion } from "../openclaw-npm-release-check.ts";
67
import { resolveNpmPublishPlan } from "./npm-publish-plan.mjs";
78

@@ -270,7 +271,7 @@ export function collectPublishablePluginPackages(
270271
version,
271272
channel: parsedVersion.channel,
272273
publishTag: resolveNpmPublishPlan(version).publishTag,
273-
installNpmSpec: packageJson.openclaw?.install?.npmSpec?.trim() || undefined,
274+
installNpmSpec: normalizeOptionalString(packageJson.openclaw?.install?.npmSpec),
274275
});
275276
}
276277

0 commit comments

Comments
 (0)