|
|
@@ -48,8 +48,9 @@ export type SendTextOptions = {
|
|
|
timeoutMs?: number;
|
|
|
};
|
|
|
|
|
|
-export function createClient(apiBase: string): WechatAgentClient {
|
|
|
+export function createClient(apiBase: string, appId?: string): WechatAgentClient {
|
|
|
const base = apiBase.replace(/\/+$/, "");
|
|
|
+ const deviceAppId = appId?.trim() || undefined;
|
|
|
|
|
|
async function request(
|
|
|
path: string,
|
|
|
@@ -100,7 +101,7 @@ export function createClient(apiBase: string): WechatAgentClient {
|
|
|
const body = (await request("/login/check-online", {
|
|
|
method: "POST",
|
|
|
headers: { "content-type": "application/json" },
|
|
|
- body: "{}",
|
|
|
+ body: JSON.stringify(deviceAppId ? { appId: deviceAppId } : {}),
|
|
|
})) as { ret?: number; data?: unknown } | null;
|
|
|
if (!body) return false;
|
|
|
if (body.ret !== undefined && body.ret !== 200) return false;
|
|
|
@@ -121,7 +122,7 @@ export function createClient(apiBase: string): WechatAgentClient {
|
|
|
const body = (await request("/login/check-online", {
|
|
|
method: "POST",
|
|
|
headers: { "content-type": "application/json" },
|
|
|
- body: "{}",
|
|
|
+ body: JSON.stringify(deviceAppId ? { appId: deviceAppId } : {}),
|
|
|
})) as { ret?: number; data?: unknown } | null;
|
|
|
const d = body?.data;
|
|
|
if (d && typeof d === "object") {
|
|
|
@@ -139,6 +140,7 @@ export function createClient(apiBase: string): WechatAgentClient {
|
|
|
const limit = opts.limit ?? 50;
|
|
|
const direction = opts.direction ?? "received";
|
|
|
const qs = new URLSearchParams({ limit: String(limit), direction });
|
|
|
+ if (deviceAppId) qs.set("appId", deviceAppId);
|
|
|
const body = (await request(`/messages?${qs.toString()}`, {
|
|
|
method: "GET",
|
|
|
signal: opts.signal,
|
|
|
@@ -151,11 +153,12 @@ export function createClient(apiBase: string): WechatAgentClient {
|
|
|
},
|
|
|
|
|
|
async sendText(opts: SendTextOptions): Promise<SendTextResult> {
|
|
|
- const payload = {
|
|
|
+ const payload: Record<string, unknown> = {
|
|
|
toWxid: opts.toWxid,
|
|
|
content: opts.content,
|
|
|
ats: opts.ats ?? "",
|
|
|
};
|
|
|
+ if (deviceAppId) payload.appId = deviceAppId;
|
|
|
const syntheticMessageId = `wx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
|
try {
|
|
|
const body = (await request("/message/send-text", {
|
|
|
@@ -205,19 +208,42 @@ function normalizeMessage(item: unknown): RawWechatMessage | null {
|
|
|
| string
|
|
|
| number;
|
|
|
|
|
|
- const chatroomId = pickString(o, ["chatroomId", "roomId", "groupId"]);
|
|
|
- const isGroup = Boolean(chatroomId) || Boolean(o.isGroup);
|
|
|
- const chatroomMemberWxid = isGroup
|
|
|
+ let chatroomId = pickString(o, ["chatroomId", "roomId", "groupId"]);
|
|
|
+ let isGroup = Boolean(chatroomId) || Boolean(o.isGroup);
|
|
|
+
|
|
|
+ // Fallback: detect group by @chatroom suffix in fromWxid (GEWE format)
|
|
|
+ if (!isGroup && fromWxid.endsWith("@chatroom")) {
|
|
|
+ isGroup = true;
|
|
|
+ chatroomId = chatroomId || fromWxid;
|
|
|
+ }
|
|
|
+ if (!isGroup && toWxid.endsWith("@chatroom")) {
|
|
|
+ isGroup = true;
|
|
|
+ chatroomId = chatroomId || toWxid;
|
|
|
+ }
|
|
|
+
|
|
|
+ let chatroomMemberWxid = isGroup
|
|
|
? pickString(o, ["chatroomMemberWxid", "memberWxid", "groupMember"])
|
|
|
: undefined;
|
|
|
|
|
|
+ // GEWE group messages embed the member wxid as a prefix in content: "memberWxid:\ncontent"
|
|
|
+ let finalContent = String(content);
|
|
|
+ if (isGroup && !chatroomMemberWxid && finalContent.includes(":\n")) {
|
|
|
+ const colonNl = finalContent.indexOf(":\n");
|
|
|
+ const prefix = finalContent.slice(0, colonNl);
|
|
|
+ // Validate prefix looks like a wxid (no spaces, reasonable length)
|
|
|
+ if (prefix.length > 0 && prefix.length < 60 && !prefix.includes(" ")) {
|
|
|
+ chatroomMemberWxid = prefix;
|
|
|
+ finalContent = finalContent.slice(colonNl + 2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return {
|
|
|
msgId,
|
|
|
fromWxid,
|
|
|
toWxid,
|
|
|
fromName,
|
|
|
type: String(type),
|
|
|
- content: String(content),
|
|
|
+ content: finalContent,
|
|
|
timestamp,
|
|
|
isGroup,
|
|
|
chatroomId,
|