mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 17:58:28 +00:00
chore: Enable "curly" rule to avoid single-statement if confusion/errors.
This commit is contained in:
@@ -28,11 +28,17 @@ import { elide } from "./util.js";
|
||||
function resolveHeartbeatReplyPayload(
|
||||
replyResult: ReplyPayload | ReplyPayload[] | undefined,
|
||||
): ReplyPayload | undefined {
|
||||
if (!replyResult) return undefined;
|
||||
if (!Array.isArray(replyResult)) return replyResult;
|
||||
if (!replyResult) {
|
||||
return undefined;
|
||||
}
|
||||
if (!Array.isArray(replyResult)) {
|
||||
return replyResult;
|
||||
}
|
||||
for (let idx = replyResult.length - 1; idx >= 0; idx -= 1) {
|
||||
const payload = replyResult[idx];
|
||||
if (!payload) continue;
|
||||
if (!payload) {
|
||||
continue;
|
||||
}
|
||||
if (payload.text || payload.mediaUrl || (payload.mediaUrls && payload.mediaUrls.length > 0)) {
|
||||
return payload;
|
||||
}
|
||||
@@ -221,7 +227,9 @@ export async function runWebHeartbeatOnce(opts: {
|
||||
store[sessionSnapshot.key].updatedAt = sessionSnapshot.entry.updatedAt;
|
||||
await updateSessionStore(storePath, (nextStore) => {
|
||||
const nextEntry = nextStore[sessionSnapshot.key];
|
||||
if (!nextEntry) return;
|
||||
if (!nextEntry) {
|
||||
return;
|
||||
}
|
||||
nextStore[sessionSnapshot.key] = {
|
||||
...nextEntry,
|
||||
updatedAt: sessionSnapshot.entry.updatedAt,
|
||||
|
||||
@@ -45,10 +45,14 @@ export function isBotMentionedFromTargets(
|
||||
|
||||
const hasMentions = (msg.mentionedJids?.length ?? 0) > 0;
|
||||
if (hasMentions && !isSelfChat) {
|
||||
if (targets.selfE164 && targets.normalizedMentions.includes(targets.selfE164)) return true;
|
||||
if (targets.selfE164 && targets.normalizedMentions.includes(targets.selfE164)) {
|
||||
return true;
|
||||
}
|
||||
if (targets.selfJid) {
|
||||
// Some mentions use the bare JID; match on E.164 to be safe.
|
||||
if (targets.normalizedMentions.includes(targets.selfJid)) return true;
|
||||
if (targets.normalizedMentions.includes(targets.selfJid)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If the message explicitly mentions someone else, do not fall back to regex matches.
|
||||
return false;
|
||||
@@ -56,17 +60,23 @@ export function isBotMentionedFromTargets(
|
||||
// Self-chat mode: ignore WhatsApp @mention JIDs, otherwise @mentioning the owner in group chats triggers the bot.
|
||||
}
|
||||
const bodyClean = clean(msg.body);
|
||||
if (mentionCfg.mentionRegexes.some((re) => re.test(bodyClean))) return true;
|
||||
if (mentionCfg.mentionRegexes.some((re) => re.test(bodyClean))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback: detect body containing our own number (with or without +, spacing)
|
||||
if (targets.selfE164) {
|
||||
const selfDigits = targets.selfE164.replace(/\D/g, "");
|
||||
if (selfDigits) {
|
||||
const bodyDigits = bodyClean.replace(/[^\d]/g, "");
|
||||
if (bodyDigits.includes(selfDigits)) return true;
|
||||
if (bodyDigits.includes(selfDigits)) {
|
||||
return true;
|
||||
}
|
||||
const bodyNoSpace = msg.body.replace(/[\s-]/g, "");
|
||||
const pattern = new RegExp(`\\+?${selfDigits}`, "i");
|
||||
if (pattern.test(bodyNoSpace)) return true;
|
||||
if (pattern.test(bodyNoSpace)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,9 @@ export async function monitorWebChannel(
|
||||
let reconnectAttempts = 0;
|
||||
|
||||
while (true) {
|
||||
if (stopRequested()) break;
|
||||
if (stopRequested()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const connectionId = newConnectionId();
|
||||
const startedAt = Date.now();
|
||||
@@ -175,9 +177,15 @@ export async function monitorWebChannel(
|
||||
|
||||
const inboundDebounceMs = resolveInboundDebounceMs({ cfg, channel: "whatsapp" });
|
||||
const shouldDebounce = (msg: WebInboundMsg) => {
|
||||
if (msg.mediaPath || msg.mediaType) return false;
|
||||
if (msg.location) return false;
|
||||
if (msg.replyToId || msg.replyToBody) return false;
|
||||
if (msg.mediaPath || msg.mediaType) {
|
||||
return false;
|
||||
}
|
||||
if (msg.location) {
|
||||
return false;
|
||||
}
|
||||
if (msg.replyToId || msg.replyToBody) {
|
||||
return false;
|
||||
}
|
||||
return !hasControlCommand(msg.body, cfg);
|
||||
};
|
||||
|
||||
@@ -219,7 +227,9 @@ export async function monitorWebChannel(
|
||||
|
||||
setActiveWebListener(account.accountId, listener);
|
||||
unregisterUnhandled = registerUnhandledRejectionHandler((reason) => {
|
||||
if (!isLikelyWhatsAppCryptoError(reason)) return false;
|
||||
if (!isLikelyWhatsAppCryptoError(reason)) {
|
||||
return false;
|
||||
}
|
||||
const errorStr = formatError(reason);
|
||||
reconnectLogger.warn(
|
||||
{ connectionId, error: errorStr },
|
||||
@@ -239,8 +249,12 @@ export async function monitorWebChannel(
|
||||
unregisterUnhandled();
|
||||
unregisterUnhandled = null;
|
||||
}
|
||||
if (heartbeat) clearInterval(heartbeat);
|
||||
if (watchdogTimer) clearInterval(watchdogTimer);
|
||||
if (heartbeat) {
|
||||
clearInterval(heartbeat);
|
||||
}
|
||||
if (watchdogTimer) {
|
||||
clearInterval(watchdogTimer);
|
||||
}
|
||||
if (backgroundTasks.size > 0) {
|
||||
await Promise.allSettled(backgroundTasks);
|
||||
backgroundTasks.clear();
|
||||
@@ -279,9 +293,13 @@ export async function monitorWebChannel(
|
||||
}, heartbeatSeconds * 1000);
|
||||
|
||||
watchdogTimer = setInterval(() => {
|
||||
if (!lastMessageAt) return;
|
||||
if (!lastMessageAt) {
|
||||
return;
|
||||
}
|
||||
const timeSinceLastMessage = Date.now() - lastMessageAt;
|
||||
if (timeSinceLastMessage <= MESSAGE_TIMEOUT_MS) return;
|
||||
if (timeSinceLastMessage <= MESSAGE_TIMEOUT_MS) {
|
||||
return;
|
||||
}
|
||||
const minutesSinceLastMessage = Math.floor(timeSinceLastMessage / 60000);
|
||||
heartbeatLogger.warn(
|
||||
{
|
||||
|
||||
@@ -17,7 +17,9 @@ export function maybeSendAckReaction(params: {
|
||||
info: (obj: unknown, msg: string) => void;
|
||||
warn: (obj: unknown, msg: string) => void;
|
||||
}) {
|
||||
if (!params.msg.id) return;
|
||||
if (!params.msg.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ackConfig = params.cfg.channels?.whatsapp?.ackReaction;
|
||||
const emoji = (ackConfig?.emoji ?? "").trim();
|
||||
@@ -45,7 +47,9 @@ export function maybeSendAckReaction(params: {
|
||||
groupActivated: activation === "always",
|
||||
});
|
||||
|
||||
if (!shouldSendReaction()) return;
|
||||
if (!shouldSendReaction()) {
|
||||
return;
|
||||
}
|
||||
|
||||
params.info(
|
||||
{ chatId: params.msg.chatId, messageId: params.msg.id, emoji },
|
||||
|
||||
@@ -29,8 +29,12 @@ export async function maybeBroadcastMessage(params: {
|
||||
) => Promise<boolean>;
|
||||
}) {
|
||||
const broadcastAgents = params.cfg.broadcast?.[params.peerId];
|
||||
if (!broadcastAgents || !Array.isArray(broadcastAgents)) return false;
|
||||
if (broadcastAgents.length === 0) return false;
|
||||
if (!broadcastAgents || !Array.isArray(broadcastAgents)) {
|
||||
return false;
|
||||
}
|
||||
if (broadcastAgents.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const strategy = params.cfg.broadcast?.strategy || "parallel";
|
||||
whatsappInboundLog.info(`Broadcasting message to ${broadcastAgents.length} agents (${strategy})`);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export function isStatusCommand(body: string) {
|
||||
const trimmed = body.trim().toLowerCase();
|
||||
if (!trimmed) return false;
|
||||
if (!trimmed) {
|
||||
return false;
|
||||
}
|
||||
return trimmed === "/status" || trimmed === "status" || trimmed.startsWith("/status ");
|
||||
}
|
||||
|
||||
|
||||
@@ -25,13 +25,17 @@ export function createEchoTracker(params: {
|
||||
const trim = () => {
|
||||
while (recentlySent.size > maxItems) {
|
||||
const firstKey = recentlySent.values().next().value;
|
||||
if (!firstKey) break;
|
||||
if (!firstKey) {
|
||||
break;
|
||||
}
|
||||
recentlySent.delete(firstKey);
|
||||
}
|
||||
};
|
||||
|
||||
const rememberText: EchoTracker["rememberText"] = (text, opts) => {
|
||||
if (!text) return;
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
recentlySent.add(text);
|
||||
if (opts.combinedBody && opts.combinedBodySessionKey) {
|
||||
recentlySent.add(
|
||||
|
||||
@@ -21,7 +21,9 @@ export type GroupHistoryEntry = {
|
||||
|
||||
function isOwnerSender(baseMentionConfig: MentionConfig, msg: WebInboundMsg) {
|
||||
const sender = normalizeE164(msg.senderE164 ?? "");
|
||||
if (!sender) return false;
|
||||
if (!sender) {
|
||||
return false;
|
||||
}
|
||||
const owners = resolveOwnerList(baseMentionConfig, msg.selfE164 ?? undefined);
|
||||
return owners.includes(sender);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,14 @@ export function noteGroupMember(
|
||||
e164?: string,
|
||||
name?: string,
|
||||
) {
|
||||
if (!e164 || !name) return;
|
||||
if (!e164 || !name) {
|
||||
return;
|
||||
}
|
||||
const normalized = normalizeE164(e164);
|
||||
const key = normalized ?? e164;
|
||||
if (!key) return;
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
let roster = groupMemberNames.get(conversationId);
|
||||
if (!roster) {
|
||||
roster = new Map();
|
||||
@@ -28,9 +32,13 @@ export function formatGroupMembers(params: {
|
||||
const ordered: string[] = [];
|
||||
if (participants?.length) {
|
||||
for (const entry of participants) {
|
||||
if (!entry) continue;
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
const normalized = normalizeE164(entry) ?? entry;
|
||||
if (!normalized || seen.has(normalized)) continue;
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
ordered.push(normalized);
|
||||
}
|
||||
@@ -38,16 +46,22 @@ export function formatGroupMembers(params: {
|
||||
if (roster) {
|
||||
for (const entry of roster.keys()) {
|
||||
const normalized = normalizeE164(entry) ?? entry;
|
||||
if (!normalized || seen.has(normalized)) continue;
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
ordered.push(normalized);
|
||||
}
|
||||
}
|
||||
if (ordered.length === 0 && fallbackE164) {
|
||||
const normalized = normalizeE164(fallbackE164) ?? fallbackE164;
|
||||
if (normalized) ordered.push(normalized);
|
||||
if (normalized) {
|
||||
ordered.push(normalized);
|
||||
}
|
||||
}
|
||||
if (ordered.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
if (ordered.length === 0) return undefined;
|
||||
return ordered
|
||||
.map((entry) => {
|
||||
const name = roster?.get(entry);
|
||||
|
||||
@@ -51,7 +51,9 @@ export function updateLastRouteInBackground(params: {
|
||||
}
|
||||
|
||||
export function awaitBackgroundTasks(backgroundTasks: Set<Promise<unknown>>) {
|
||||
if (backgroundTasks.size === 0) return Promise.resolve();
|
||||
if (backgroundTasks.size === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.allSettled(backgroundTasks).then(() => {
|
||||
backgroundTasks.clear();
|
||||
});
|
||||
|
||||
@@ -4,7 +4,9 @@ import type { loadConfig } from "../../../config/config.js";
|
||||
import type { WebInboundMsg } from "../types.js";
|
||||
|
||||
export function formatReplyContext(msg: WebInboundMsg) {
|
||||
if (!msg.replyToBody) return null;
|
||||
if (!msg.replyToBody) {
|
||||
return null;
|
||||
}
|
||||
const sender = msg.replyToSender ?? "unknown sender";
|
||||
const idPart = msg.replyToId ? ` id:${msg.replyToId}` : "";
|
||||
return `[Replying to ${sender}${idPart}]\n${msg.replyToBody}\n[/Replying]`;
|
||||
|
||||
@@ -138,7 +138,9 @@ export function createWebOnMessageHandler(params: {
|
||||
logVerbose,
|
||||
replyLogger: params.replyLogger,
|
||||
});
|
||||
if (!gating.shouldProcess) return;
|
||||
if (!gating.shouldProcess) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Ensure `peerId` for DMs is stable and stored as E.164 when possible.
|
||||
if (!msg.senderE164 && peerId && peerId.startsWith("+")) {
|
||||
|
||||
@@ -2,8 +2,14 @@ import { jidToE164, normalizeE164 } from "../../../utils.js";
|
||||
import type { WebInboundMsg } from "../types.js";
|
||||
|
||||
export function resolvePeerId(msg: WebInboundMsg) {
|
||||
if (msg.chatType === "group") return msg.conversationId ?? msg.from;
|
||||
if (msg.senderE164) return normalizeE164(msg.senderE164) ?? msg.senderE164;
|
||||
if (msg.from.includes("@")) return jidToE164(msg.from) ?? msg.from;
|
||||
if (msg.chatType === "group") {
|
||||
return msg.conversationId ?? msg.from;
|
||||
}
|
||||
if (msg.senderE164) {
|
||||
return normalizeE164(msg.senderE164) ?? msg.senderE164;
|
||||
}
|
||||
if (msg.from.includes("@")) {
|
||||
return jidToE164(msg.from) ?? msg.from;
|
||||
}
|
||||
return normalizeE164(msg.from) ?? msg.from;
|
||||
}
|
||||
|
||||
@@ -60,13 +60,17 @@ async function resolveWhatsAppCommandAuthorized(params: {
|
||||
msg: WebInboundMsg;
|
||||
}): Promise<boolean> {
|
||||
const useAccessGroups = params.cfg.commands?.useAccessGroups !== false;
|
||||
if (!useAccessGroups) return true;
|
||||
if (!useAccessGroups) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const isGroup = params.msg.chatType === "group";
|
||||
const senderE164 = normalizeE164(
|
||||
isGroup ? (params.msg.senderE164 ?? "") : (params.msg.senderE164 ?? params.msg.from ?? ""),
|
||||
);
|
||||
if (!senderE164) return false;
|
||||
if (!senderE164) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const configuredAllowFrom = params.cfg.channels?.whatsapp?.allowFrom ?? [];
|
||||
const configuredGroupAllowFrom =
|
||||
@@ -74,8 +78,12 @@ async function resolveWhatsAppCommandAuthorized(params: {
|
||||
(configuredAllowFrom.length > 0 ? configuredAllowFrom : undefined);
|
||||
|
||||
if (isGroup) {
|
||||
if (!configuredGroupAllowFrom || configuredGroupAllowFrom.length === 0) return false;
|
||||
if (configuredGroupAllowFrom.some((v) => String(v).trim() === "*")) return true;
|
||||
if (!configuredGroupAllowFrom || configuredGroupAllowFrom.length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (configuredGroupAllowFrom.some((v) => String(v).trim() === "*")) {
|
||||
return true;
|
||||
}
|
||||
return normalizeAllowFromE164(configuredGroupAllowFrom).includes(senderE164);
|
||||
}
|
||||
|
||||
@@ -89,7 +97,9 @@ async function resolveWhatsAppCommandAuthorized(params: {
|
||||
: params.msg.selfE164
|
||||
? [params.msg.selfE164]
|
||||
: [];
|
||||
if (allowFrom.some((v) => String(v).trim() === "*")) return true;
|
||||
if (allowFrom.some((v) => String(v).trim() === "*")) {
|
||||
return true;
|
||||
}
|
||||
return normalizeAllowFromE164(allowFrom).includes(senderE164);
|
||||
}
|
||||
|
||||
@@ -221,9 +231,13 @@ export async function processMessage(params: {
|
||||
const dmRouteTarget =
|
||||
params.msg.chatType !== "group"
|
||||
? (() => {
|
||||
if (params.msg.senderE164) return normalizeE164(params.msg.senderE164);
|
||||
if (params.msg.senderE164) {
|
||||
return normalizeE164(params.msg.senderE164);
|
||||
}
|
||||
// In direct chats, `msg.from` is already the canonical conversation id.
|
||||
if (params.msg.from.includes("@")) return jidToE164(params.msg.from);
|
||||
if (params.msg.from.includes("@")) {
|
||||
return jidToE164(params.msg.from);
|
||||
}
|
||||
return normalizeE164(params.msg.from);
|
||||
})()
|
||||
: undefined;
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
export function elide(text?: string, limit = 400) {
|
||||
if (!text) return text;
|
||||
if (text.length <= limit) return text;
|
||||
if (!text) {
|
||||
return text;
|
||||
}
|
||||
if (text.length <= limit) {
|
||||
return text;
|
||||
}
|
||||
return `${text.slice(0, limit)}… (truncated ${text.length - limit} chars)`;
|
||||
}
|
||||
|
||||
export function isLikelyWhatsAppCryptoError(reason: unknown) {
|
||||
const formatReason = (value: unknown): string => {
|
||||
if (value == null) return "";
|
||||
if (typeof value === "string") return value;
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
if (value instanceof Error) {
|
||||
return `${value.message}\n${value.stack ?? ""}`;
|
||||
}
|
||||
@@ -18,11 +26,21 @@ export function isLikelyWhatsAppCryptoError(reason: unknown) {
|
||||
return Object.prototype.toString.call(value);
|
||||
}
|
||||
}
|
||||
if (typeof value === "number") return String(value);
|
||||
if (typeof value === "boolean") return String(value);
|
||||
if (typeof value === "bigint") return String(value);
|
||||
if (typeof value === "symbol") return value.description ?? value.toString();
|
||||
if (typeof value === "function") return value.name ? `[function ${value.name}]` : "[function]";
|
||||
if (typeof value === "number") {
|
||||
return String(value);
|
||||
}
|
||||
if (typeof value === "boolean") {
|
||||
return String(value);
|
||||
}
|
||||
if (typeof value === "bigint") {
|
||||
return String(value);
|
||||
}
|
||||
if (typeof value === "symbol") {
|
||||
return value.description ?? value.toString();
|
||||
}
|
||||
if (typeof value === "function") {
|
||||
return value.name ? `[function ${value.name}]` : "[function]";
|
||||
}
|
||||
return Object.prototype.toString.call(value);
|
||||
};
|
||||
const raw =
|
||||
@@ -31,7 +49,9 @@ export function isLikelyWhatsAppCryptoError(reason: unknown) {
|
||||
const hasAuthError =
|
||||
haystack.includes("unsupported state or unable to authenticate data") ||
|
||||
haystack.includes("bad mac");
|
||||
if (!hasAuthError) return false;
|
||||
if (!hasAuthError) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
haystack.includes("@whiskeysockets/baileys") ||
|
||||
haystack.includes("baileys") ||
|
||||
|
||||
Reference in New Issue
Block a user