/** * Message sending API for the QQ Open Platform. * * Key design improvements: * - Unified `sendMessage(scope, ...)` replaces `sendC2CMessage` + `sendGroupMessage`. * - `onMessageSent` hook is scoped to the instance, not a module-level global. * - Markdown support flag is per-instance, not a global Map.
*/
import type {
ChatScope,
MessageResponse,
OutboundMeta,
EngineLogger,
InlineKeyboard,
} from "../types.js"; import { formatErrorMessage } from "../utils/format.js"; import { ApiClient } from "./api-client.js"; import {
messagePath,
channelMessagePath,
dmMessagePath,
gatewayPath,
interactionPath,
getNextMsgSeq,
} from "./routes.js"; import { TokenManager } from "./token.js";
export interface MessageApiConfig { /** Whether the QQ Bot has markdown permission. */
markdownSupport: boolean; /** Logger for diagnostics. */
logger?: EngineLogger;
}
type OnMessageSentCallback = (refIdx: string, meta: OutboundMeta) => void;
/** Register a callback invoked when a sent message returns a ref_idx. */
onMessageSent(callback: OnMessageSentCallback): void { this.messageSentHook = callback;
}
/** * Notify the registered hook about a sent message. * Use this for media sends that bypass `sendAndNotify`.
*/
notifyMessageSent(refIdx: string, meta: OutboundMeta): void { if (this.messageSentHook) { try { this.messageSentHook(refIdx, meta);
} catch (err) { this.logger?.error?.(
`[qqbot:messages] onMessageSent hook error: ${formatErrorMessage(err)}`,
);
}
}
}
// ---- Unified message sending ----
/** * Send a text message to a C2C or Group target. * * Automatically constructs the correct path, body format (markdown vs plain), * and message sequence number.
*/
async sendMessage(
scope: ChatScope,
targetId: string,
content: string,
creds: Credentials,
opts?: {
msgId?: string;
messageReference?: string;
inlineKeyboard?: InlineKeyboard;
},
): Promise<MessageResponse> { const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret); const msgSeq = opts?.msgId ? getNextMsgSeq(opts.msgId) : 1; const body = this.buildMessageBody(
content,
opts?.msgId,
msgSeq,
opts?.messageReference,
opts?.inlineKeyboard,
); const path = messagePath(scope, targetId); returnthis.sendAndNotify(creds.appId, token, "POST", path, body, { text: content });
}
/** Send a proactive (no msgId) message to a C2C or Group target. */
async sendProactiveMessage(
scope: ChatScope,
targetId: string,
content: string,
creds: Credentials,
): Promise<MessageResponse> { if (!content?.trim()) { thrownew Error("Proactive message content must not be empty");
} const token = await this.tokenManager.getAccessToken(creds.appId, creds.clientSecret); const body = this.buildProactiveBody(content); const path = messagePath(scope, targetId); returnthis.sendAndNotify(creds.appId, token, "POST", path, body, { text: content });
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.