mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 00:00:22 +00:00
refactor(bluebubbles): centralize private-api status handling
This commit is contained in:
@@ -2,7 +2,11 @@ import crypto from "node:crypto";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk";
|
||||
import { stripMarkdown } from "openclaw/plugin-sdk";
|
||||
import { resolveBlueBubblesAccount } from "./accounts.js";
|
||||
import { getCachedBlueBubblesPrivateApiStatus } from "./probe.js";
|
||||
import {
|
||||
getCachedBlueBubblesPrivateApiStatus,
|
||||
isBlueBubblesPrivateApiStatusEnabled,
|
||||
} from "./probe.js";
|
||||
import { warnBlueBubbles } from "./runtime.js";
|
||||
import { extractBlueBubblesMessageId, resolveBlueBubblesSendTarget } from "./send-helpers.js";
|
||||
import { extractHandleFromChatGuid, normalizeBlueBubblesHandle } from "./targets.js";
|
||||
import {
|
||||
@@ -71,6 +75,38 @@ function resolveEffectId(raw?: string): string | undefined {
|
||||
return raw;
|
||||
}
|
||||
|
||||
type PrivateApiDecision = {
|
||||
canUsePrivateApi: boolean;
|
||||
throwEffectDisabledError: boolean;
|
||||
warningMessage?: string;
|
||||
};
|
||||
|
||||
function resolvePrivateApiDecision(params: {
|
||||
privateApiStatus: boolean | null;
|
||||
wantsReplyThread: boolean;
|
||||
wantsEffect: boolean;
|
||||
}): PrivateApiDecision {
|
||||
const { privateApiStatus, wantsReplyThread, wantsEffect } = params;
|
||||
const needsPrivateApi = wantsReplyThread || wantsEffect;
|
||||
const canUsePrivateApi =
|
||||
needsPrivateApi && isBlueBubblesPrivateApiStatusEnabled(privateApiStatus);
|
||||
const throwEffectDisabledError = wantsEffect && privateApiStatus === false;
|
||||
if (!needsPrivateApi || privateApiStatus !== null) {
|
||||
return { canUsePrivateApi, throwEffectDisabledError };
|
||||
}
|
||||
const requested = [
|
||||
wantsReplyThread ? "reply threading" : null,
|
||||
wantsEffect ? "message effects" : null,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" + ");
|
||||
return {
|
||||
canUsePrivateApi,
|
||||
throwEffectDisabledError,
|
||||
warningMessage: `Private API status unknown; sending without ${requested}. Run a status probe to restore private-api features.`,
|
||||
};
|
||||
}
|
||||
|
||||
type BlueBubblesChatRecord = Record<string, unknown>;
|
||||
|
||||
function extractChatGuid(chat: BlueBubblesChatRecord): string | null {
|
||||
@@ -372,41 +408,36 @@ export async function sendMessageBlueBubbles(
|
||||
const effectId = resolveEffectId(opts.effectId);
|
||||
const wantsReplyThread = Boolean(opts.replyToMessageGuid?.trim());
|
||||
const wantsEffect = Boolean(effectId);
|
||||
const needsPrivateApi = wantsReplyThread || wantsEffect;
|
||||
const canUsePrivateApi = needsPrivateApi && privateApiStatus === true;
|
||||
if (wantsEffect && privateApiStatus === false) {
|
||||
const privateApiDecision = resolvePrivateApiDecision({
|
||||
privateApiStatus,
|
||||
wantsReplyThread,
|
||||
wantsEffect,
|
||||
});
|
||||
if (privateApiDecision.throwEffectDisabledError) {
|
||||
throw new Error(
|
||||
"BlueBubbles send failed: reply/effect requires Private API, but it is disabled on the BlueBubbles server.",
|
||||
);
|
||||
}
|
||||
if (needsPrivateApi && privateApiStatus === null) {
|
||||
const requested = [
|
||||
wantsReplyThread ? "reply threading" : null,
|
||||
wantsEffect ? "message effects" : null,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" + ");
|
||||
console.warn(
|
||||
`[bluebubbles] Private API status unknown; sending without ${requested}. Run a status probe to restore private-api features.`,
|
||||
);
|
||||
if (privateApiDecision.warningMessage) {
|
||||
warnBlueBubbles(privateApiDecision.warningMessage);
|
||||
}
|
||||
const payload: Record<string, unknown> = {
|
||||
chatGuid,
|
||||
tempGuid: crypto.randomUUID(),
|
||||
message: strippedText,
|
||||
};
|
||||
if (canUsePrivateApi) {
|
||||
if (privateApiDecision.canUsePrivateApi) {
|
||||
payload.method = "private-api";
|
||||
}
|
||||
|
||||
// Add reply threading support
|
||||
if (wantsReplyThread && canUsePrivateApi) {
|
||||
if (wantsReplyThread && privateApiDecision.canUsePrivateApi) {
|
||||
payload.selectedMessageGuid = opts.replyToMessageGuid;
|
||||
payload.partIndex = typeof opts.replyToPartIndex === "number" ? opts.replyToPartIndex : 0;
|
||||
}
|
||||
|
||||
// Add message effects support
|
||||
if (effectId && canUsePrivateApi) {
|
||||
if (effectId && privateApiDecision.canUsePrivateApi) {
|
||||
payload.effectId = effectId;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user