mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-11 07:14:33 +00:00
chore: Lint extensions folder.
This commit is contained in:
@@ -25,14 +25,22 @@ const CHAT_IDENTIFIER_HEX_RE = /^[0-9a-f]{24,64}$/i;
|
||||
|
||||
function parseRawChatGuid(value: string): string | null {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return null;
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
const parts = trimmed.split(";");
|
||||
if (parts.length !== 3) return null;
|
||||
if (parts.length !== 3) {
|
||||
return null;
|
||||
}
|
||||
const service = parts[0]?.trim();
|
||||
const separator = parts[1]?.trim();
|
||||
const identifier = parts[2]?.trim();
|
||||
if (!service || !identifier) return null;
|
||||
if (separator !== "+" && separator !== "-") return null;
|
||||
if (!service || !identifier) {
|
||||
return null;
|
||||
}
|
||||
if (separator !== "+" && separator !== "-") {
|
||||
return null;
|
||||
}
|
||||
return `${service};${separator};${identifier}`;
|
||||
}
|
||||
|
||||
@@ -42,26 +50,44 @@ function stripPrefix(value: string, prefix: string): string {
|
||||
|
||||
function stripBlueBubblesPrefix(value: string): string {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return "";
|
||||
if (!trimmed.toLowerCase().startsWith("bluebubbles:")) return trimmed;
|
||||
if (!trimmed) {
|
||||
return "";
|
||||
}
|
||||
if (!trimmed.toLowerCase().startsWith("bluebubbles:")) {
|
||||
return trimmed;
|
||||
}
|
||||
return trimmed.slice("bluebubbles:".length).trim();
|
||||
}
|
||||
|
||||
function looksLikeRawChatIdentifier(value: string): boolean {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return false;
|
||||
if (/^chat\d+$/i.test(trimmed)) return true;
|
||||
if (!trimmed) {
|
||||
return false;
|
||||
}
|
||||
if (/^chat\d+$/i.test(trimmed)) {
|
||||
return true;
|
||||
}
|
||||
return CHAT_IDENTIFIER_UUID_RE.test(trimmed) || CHAT_IDENTIFIER_HEX_RE.test(trimmed);
|
||||
}
|
||||
|
||||
export function normalizeBlueBubblesHandle(raw: string): string {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return "";
|
||||
if (!trimmed) {
|
||||
return "";
|
||||
}
|
||||
const lowered = trimmed.toLowerCase();
|
||||
if (lowered.startsWith("imessage:")) return normalizeBlueBubblesHandle(trimmed.slice(9));
|
||||
if (lowered.startsWith("sms:")) return normalizeBlueBubblesHandle(trimmed.slice(4));
|
||||
if (lowered.startsWith("auto:")) return normalizeBlueBubblesHandle(trimmed.slice(5));
|
||||
if (trimmed.includes("@")) return trimmed.toLowerCase();
|
||||
if (lowered.startsWith("imessage:")) {
|
||||
return normalizeBlueBubblesHandle(trimmed.slice(9));
|
||||
}
|
||||
if (lowered.startsWith("sms:")) {
|
||||
return normalizeBlueBubblesHandle(trimmed.slice(4));
|
||||
}
|
||||
if (lowered.startsWith("auto:")) {
|
||||
return normalizeBlueBubblesHandle(trimmed.slice(5));
|
||||
}
|
||||
if (trimmed.includes("@")) {
|
||||
return trimmed.toLowerCase();
|
||||
}
|
||||
return trimmed.replace(/\s+/g, "");
|
||||
}
|
||||
|
||||
@@ -75,30 +101,44 @@ export function extractHandleFromChatGuid(chatGuid: string): string | null {
|
||||
// DM format: service;-;handle (3 parts, middle is "-")
|
||||
if (parts.length === 3 && parts[1] === "-") {
|
||||
const handle = parts[2]?.trim();
|
||||
if (handle) return normalizeBlueBubblesHandle(handle);
|
||||
if (handle) {
|
||||
return normalizeBlueBubblesHandle(handle);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function normalizeBlueBubblesMessagingTarget(raw: string): string | undefined {
|
||||
let trimmed = raw.trim();
|
||||
if (!trimmed) return undefined;
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
trimmed = stripBlueBubblesPrefix(trimmed);
|
||||
if (!trimmed) return undefined;
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
const parsed = parseBlueBubblesTarget(trimmed);
|
||||
if (parsed.kind === "chat_id") return `chat_id:${parsed.chatId}`;
|
||||
if (parsed.kind === "chat_id") {
|
||||
return `chat_id:${parsed.chatId}`;
|
||||
}
|
||||
if (parsed.kind === "chat_guid") {
|
||||
// For DM chat_guids, normalize to just the handle for easier comparison.
|
||||
// This allows "chat_guid:iMessage;-;+1234567890" to match "+1234567890".
|
||||
const handle = extractHandleFromChatGuid(parsed.chatGuid);
|
||||
if (handle) return handle;
|
||||
if (handle) {
|
||||
return handle;
|
||||
}
|
||||
// For group chats or unrecognized formats, keep the full chat_guid
|
||||
return `chat_guid:${parsed.chatGuid}`;
|
||||
}
|
||||
if (parsed.kind === "chat_identifier") return `chat_identifier:${parsed.chatIdentifier}`;
|
||||
if (parsed.kind === "chat_identifier") {
|
||||
return `chat_identifier:${parsed.chatIdentifier}`;
|
||||
}
|
||||
const handle = normalizeBlueBubblesHandle(parsed.to);
|
||||
if (!handle) return undefined;
|
||||
if (!handle) {
|
||||
return undefined;
|
||||
}
|
||||
return parsed.service === "auto" ? handle : `${parsed.service}:${handle}`;
|
||||
} catch {
|
||||
return trimmed;
|
||||
@@ -107,12 +147,20 @@ export function normalizeBlueBubblesMessagingTarget(raw: string): string | undef
|
||||
|
||||
export function looksLikeBlueBubblesTargetId(raw: string, normalized?: string): boolean {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
if (!trimmed) {
|
||||
return false;
|
||||
}
|
||||
const candidate = stripBlueBubblesPrefix(trimmed);
|
||||
if (!candidate) return false;
|
||||
if (parseRawChatGuid(candidate)) return true;
|
||||
if (!candidate) {
|
||||
return false;
|
||||
}
|
||||
if (parseRawChatGuid(candidate)) {
|
||||
return true;
|
||||
}
|
||||
const lowered = candidate.toLowerCase();
|
||||
if (/^(imessage|sms|auto):/.test(lowered)) return true;
|
||||
if (/^(imessage|sms|auto):/.test(lowered)) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
/^(chat_id|chatid|chat|chat_guid|chatguid|guid|chat_identifier|chatidentifier|chatident|group):/.test(
|
||||
lowered,
|
||||
@@ -121,14 +169,24 @@ export function looksLikeBlueBubblesTargetId(raw: string, normalized?: string):
|
||||
return true;
|
||||
}
|
||||
// Recognize chat<digits> patterns (e.g., "chat660250192681427962") as chat IDs
|
||||
if (/^chat\d+$/i.test(candidate)) return true;
|
||||
if (looksLikeRawChatIdentifier(candidate)) return true;
|
||||
if (candidate.includes("@")) return true;
|
||||
if (/^chat\d+$/i.test(candidate)) {
|
||||
return true;
|
||||
}
|
||||
if (looksLikeRawChatIdentifier(candidate)) {
|
||||
return true;
|
||||
}
|
||||
if (candidate.includes("@")) {
|
||||
return true;
|
||||
}
|
||||
const digitsOnly = candidate.replace(/[\s().-]/g, "");
|
||||
if (/^\+?\d{3,}$/.test(digitsOnly)) return true;
|
||||
if (/^\+?\d{3,}$/.test(digitsOnly)) {
|
||||
return true;
|
||||
}
|
||||
if (normalized) {
|
||||
const normalizedTrimmed = normalized.trim();
|
||||
if (!normalizedTrimmed) return false;
|
||||
if (!normalizedTrimmed) {
|
||||
return false;
|
||||
}
|
||||
const normalizedLower = normalizedTrimmed.toLowerCase();
|
||||
if (
|
||||
/^(imessage|sms|auto):/.test(normalizedLower) ||
|
||||
@@ -142,13 +200,17 @@ export function looksLikeBlueBubblesTargetId(raw: string, normalized?: string):
|
||||
|
||||
export function parseBlueBubblesTarget(raw: string): BlueBubblesTarget {
|
||||
const trimmed = stripBlueBubblesPrefix(raw);
|
||||
if (!trimmed) throw new Error("BlueBubbles target is required");
|
||||
if (!trimmed) {
|
||||
throw new Error("BlueBubbles target is required");
|
||||
}
|
||||
const lower = trimmed.toLowerCase();
|
||||
|
||||
for (const { prefix, service } of SERVICE_PREFIXES) {
|
||||
if (lower.startsWith(prefix)) {
|
||||
const remainder = stripPrefix(trimmed, prefix);
|
||||
if (!remainder) throw new Error(`${prefix} target is required`);
|
||||
if (!remainder) {
|
||||
throw new Error(`${prefix} target is required`);
|
||||
}
|
||||
const remainderLower = remainder.toLowerCase();
|
||||
const isChatTarget =
|
||||
CHAT_ID_PREFIXES.some((p) => remainderLower.startsWith(p)) ||
|
||||
@@ -176,7 +238,9 @@ export function parseBlueBubblesTarget(raw: string): BlueBubblesTarget {
|
||||
for (const prefix of CHAT_GUID_PREFIXES) {
|
||||
if (lower.startsWith(prefix)) {
|
||||
const value = stripPrefix(trimmed, prefix);
|
||||
if (!value) throw new Error("chat_guid is required");
|
||||
if (!value) {
|
||||
throw new Error("chat_guid is required");
|
||||
}
|
||||
return { kind: "chat_guid", chatGuid: value };
|
||||
}
|
||||
}
|
||||
@@ -184,7 +248,9 @@ export function parseBlueBubblesTarget(raw: string): BlueBubblesTarget {
|
||||
for (const prefix of CHAT_IDENTIFIER_PREFIXES) {
|
||||
if (lower.startsWith(prefix)) {
|
||||
const value = stripPrefix(trimmed, prefix);
|
||||
if (!value) throw new Error("chat_identifier is required");
|
||||
if (!value) {
|
||||
throw new Error("chat_identifier is required");
|
||||
}
|
||||
return { kind: "chat_identifier", chatIdentifier: value };
|
||||
}
|
||||
}
|
||||
@@ -195,7 +261,9 @@ export function parseBlueBubblesTarget(raw: string): BlueBubblesTarget {
|
||||
if (Number.isFinite(chatId)) {
|
||||
return { kind: "chat_id", chatId };
|
||||
}
|
||||
if (!value) throw new Error("group target is required");
|
||||
if (!value) {
|
||||
throw new Error("group target is required");
|
||||
}
|
||||
return { kind: "chat_guid", chatGuid: value };
|
||||
}
|
||||
|
||||
@@ -220,13 +288,17 @@ export function parseBlueBubblesTarget(raw: string): BlueBubblesTarget {
|
||||
|
||||
export function parseBlueBubblesAllowTarget(raw: string): BlueBubblesAllowTarget {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return { kind: "handle", handle: "" };
|
||||
if (!trimmed) {
|
||||
return { kind: "handle", handle: "" };
|
||||
}
|
||||
const lower = trimmed.toLowerCase();
|
||||
|
||||
for (const { prefix } of SERVICE_PREFIXES) {
|
||||
if (lower.startsWith(prefix)) {
|
||||
const remainder = stripPrefix(trimmed, prefix);
|
||||
if (!remainder) return { kind: "handle", handle: "" };
|
||||
if (!remainder) {
|
||||
return { kind: "handle", handle: "" };
|
||||
}
|
||||
return parseBlueBubblesAllowTarget(remainder);
|
||||
}
|
||||
}
|
||||
@@ -235,29 +307,39 @@ export function parseBlueBubblesAllowTarget(raw: string): BlueBubblesAllowTarget
|
||||
if (lower.startsWith(prefix)) {
|
||||
const value = stripPrefix(trimmed, prefix);
|
||||
const chatId = Number.parseInt(value, 10);
|
||||
if (Number.isFinite(chatId)) return { kind: "chat_id", chatId };
|
||||
if (Number.isFinite(chatId)) {
|
||||
return { kind: "chat_id", chatId };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const prefix of CHAT_GUID_PREFIXES) {
|
||||
if (lower.startsWith(prefix)) {
|
||||
const value = stripPrefix(trimmed, prefix);
|
||||
if (value) return { kind: "chat_guid", chatGuid: value };
|
||||
if (value) {
|
||||
return { kind: "chat_guid", chatGuid: value };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const prefix of CHAT_IDENTIFIER_PREFIXES) {
|
||||
if (lower.startsWith(prefix)) {
|
||||
const value = stripPrefix(trimmed, prefix);
|
||||
if (value) return { kind: "chat_identifier", chatIdentifier: value };
|
||||
if (value) {
|
||||
return { kind: "chat_identifier", chatIdentifier: value };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lower.startsWith("group:")) {
|
||||
const value = stripPrefix(trimmed, "group:");
|
||||
const chatId = Number.parseInt(value, 10);
|
||||
if (Number.isFinite(chatId)) return { kind: "chat_id", chatId };
|
||||
if (value) return { kind: "chat_guid", chatGuid: value };
|
||||
if (Number.isFinite(chatId)) {
|
||||
return { kind: "chat_id", chatId };
|
||||
}
|
||||
if (value) {
|
||||
return { kind: "chat_guid", chatGuid: value };
|
||||
}
|
||||
}
|
||||
|
||||
// Handle chat<digits> pattern (e.g., "chat660250192681427962") as chat_identifier
|
||||
@@ -282,8 +364,12 @@ export function isAllowedBlueBubblesSender(params: {
|
||||
chatIdentifier?: string | null;
|
||||
}): boolean {
|
||||
const allowFrom = params.allowFrom.map((entry) => String(entry).trim());
|
||||
if (allowFrom.length === 0) return true;
|
||||
if (allowFrom.includes("*")) return true;
|
||||
if (allowFrom.length === 0) {
|
||||
return true;
|
||||
}
|
||||
if (allowFrom.includes("*")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const senderNormalized = normalizeBlueBubblesHandle(params.sender);
|
||||
const chatId = params.chatId ?? undefined;
|
||||
@@ -291,16 +377,26 @@ export function isAllowedBlueBubblesSender(params: {
|
||||
const chatIdentifier = params.chatIdentifier?.trim();
|
||||
|
||||
for (const entry of allowFrom) {
|
||||
if (!entry) continue;
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
const parsed = parseBlueBubblesAllowTarget(entry);
|
||||
if (parsed.kind === "chat_id" && chatId !== undefined) {
|
||||
if (parsed.chatId === chatId) return true;
|
||||
if (parsed.chatId === chatId) {
|
||||
return true;
|
||||
}
|
||||
} else if (parsed.kind === "chat_guid" && chatGuid) {
|
||||
if (parsed.chatGuid === chatGuid) return true;
|
||||
if (parsed.chatGuid === chatGuid) {
|
||||
return true;
|
||||
}
|
||||
} else if (parsed.kind === "chat_identifier" && chatIdentifier) {
|
||||
if (parsed.chatIdentifier === chatIdentifier) return true;
|
||||
if (parsed.chatIdentifier === chatIdentifier) {
|
||||
return true;
|
||||
}
|
||||
} else if (parsed.kind === "handle" && senderNormalized) {
|
||||
if (parsed.handle === senderNormalized) return true;
|
||||
if (parsed.handle === senderNormalized) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -315,8 +411,12 @@ export function formatBlueBubblesChatTarget(params: {
|
||||
return `chat_id:${params.chatId}`;
|
||||
}
|
||||
const guid = params.chatGuid?.trim();
|
||||
if (guid) return `chat_guid:${guid}`;
|
||||
if (guid) {
|
||||
return `chat_guid:${guid}`;
|
||||
}
|
||||
const identifier = params.chatIdentifier?.trim();
|
||||
if (identifier) return `chat_identifier:${identifier}`;
|
||||
if (identifier) {
|
||||
return `chat_identifier:${identifier}`;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user