@gloablehive/celphone-wechat-plugin 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL.md +231 -0
- package/README.md +259 -0
- package/dist/index-simple.js +9 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +77 -0
- package/dist/mock-server.d.ts +6 -0
- package/dist/mock-server.js +203 -0
- package/dist/openclaw.plugin.json +96 -0
- package/dist/setup-entry.d.ts +9 -0
- package/dist/setup-entry.js +8 -0
- package/dist/src/cache/compactor.d.ts +36 -0
- package/dist/src/cache/compactor.js +154 -0
- package/dist/src/cache/extractor.d.ts +48 -0
- package/dist/src/cache/extractor.js +120 -0
- package/dist/src/cache/index.d.ts +15 -0
- package/dist/src/cache/index.js +16 -0
- package/dist/src/cache/indexer.d.ts +41 -0
- package/dist/src/cache/indexer.js +262 -0
- package/dist/src/cache/manager.d.ts +113 -0
- package/dist/src/cache/manager.js +271 -0
- package/dist/src/cache/message-queue.d.ts +59 -0
- package/dist/src/cache/message-queue.js +147 -0
- package/dist/src/cache/saas-connector.d.ts +94 -0
- package/dist/src/cache/saas-connector.js +289 -0
- package/dist/src/cache/syncer.d.ts +60 -0
- package/dist/src/cache/syncer.js +177 -0
- package/dist/src/cache/types.d.ts +198 -0
- package/dist/src/cache/types.js +43 -0
- package/dist/src/cache/writer.d.ts +81 -0
- package/dist/src/cache/writer.js +461 -0
- package/dist/src/channel.d.ts +65 -0
- package/dist/src/channel.js +334 -0
- package/dist/src/client.d.ts +280 -0
- package/dist/src/client.js +248 -0
- package/index-simple.ts +11 -0
- package/index.ts +89 -0
- package/mock-server.ts +237 -0
- package/openclaw.plugin.json +98 -0
- package/package.json +37 -0
- package/setup-entry.ts +10 -0
- package/src/channel.ts +398 -0
- package/src/client.ts +412 -0
- package/test-cache.ts +260 -0
- package/test-integration.ts +319 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkPhone WeChat Channel Plugin for OpenClaw
|
|
3
|
+
*
|
|
4
|
+
* This channel plugin connects OpenClaw to WorkPhone's WeChat API,
|
|
5
|
+
* enabling sending and receiving WeChat messages through the WorkPhone platform.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT - Human Account Model:
|
|
8
|
+
* Unlike Telegram/WhatsApp bots, this connects to a real human WeChat account.
|
|
9
|
+
* The agent communicates with ALL friends and groups under that WeChat account,
|
|
10
|
+
* not just one DM context. This is "human mode" vs "bot mode".
|
|
11
|
+
*
|
|
12
|
+
* Includes Local Cache:
|
|
13
|
+
* - Per-account, per-user/conversation MD files
|
|
14
|
+
* - YAML frontmatter (aligned with Claude Code)
|
|
15
|
+
* - MEMORY.md indexing
|
|
16
|
+
* - 4-layer compression
|
|
17
|
+
* - AI summary extraction
|
|
18
|
+
* - SAAS connectivity + offline fallback
|
|
19
|
+
* - Cloud sync
|
|
20
|
+
*/
|
|
21
|
+
import { createChatChannelPlugin, createChannelPluginBase, } from "openclaw/plugin-sdk/core";
|
|
22
|
+
import { createWorkPhoneClient } from "./client.js";
|
|
23
|
+
// Import cache modules
|
|
24
|
+
import { createCacheManager, } from "./cache/index.js";
|
|
25
|
+
// Cache manager instance (lazy initialized)
|
|
26
|
+
let cacheManager = null;
|
|
27
|
+
/**
|
|
28
|
+
* Get or create cache manager
|
|
29
|
+
*/
|
|
30
|
+
function getCacheManager(cfg) {
|
|
31
|
+
if (cacheManager)
|
|
32
|
+
return cacheManager;
|
|
33
|
+
const section = cfg.channels?.["celphone-wechat"];
|
|
34
|
+
const accounts = (section?.accounts || []);
|
|
35
|
+
// If no accounts configured, create default from main config
|
|
36
|
+
if (accounts.length === 0 && section?.wechatAccountId) {
|
|
37
|
+
accounts.push({
|
|
38
|
+
accountId: section.accountId || 'default',
|
|
39
|
+
wechatAccountId: section.wechatAccountId,
|
|
40
|
+
wechatId: section.wechatId || section.wechatAccountId,
|
|
41
|
+
nickName: section.nickName || 'WeChat User',
|
|
42
|
+
enabled: true,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const basePath = globalThis?.process?.env?.OPENCLAW_CACHE_PATH
|
|
46
|
+
|| '~/.openclaw/channels/celphone-wechat';
|
|
47
|
+
cacheManager = createCacheManager({
|
|
48
|
+
basePath,
|
|
49
|
+
accounts,
|
|
50
|
+
saasConfig: section?.saas ? {
|
|
51
|
+
apiBaseUrl: section.saas.apiBaseUrl,
|
|
52
|
+
apiKey: section.saas.apiKey,
|
|
53
|
+
timeout: section.saas.timeout || 5000,
|
|
54
|
+
} : undefined,
|
|
55
|
+
syncConfig: section?.sync ? {
|
|
56
|
+
databaseUrl: section.sync.databaseUrl,
|
|
57
|
+
syncMode: section.sync.syncMode || 'interval',
|
|
58
|
+
syncIntervalMs: section.sync.syncIntervalMs || 5 * 60 * 1000,
|
|
59
|
+
} : undefined,
|
|
60
|
+
});
|
|
61
|
+
// Initialize cache manager
|
|
62
|
+
cacheManager.init().catch(err => {
|
|
63
|
+
console.error('[CelPhoneWeChat] Cache manager init failed:', err);
|
|
64
|
+
});
|
|
65
|
+
return cacheManager;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolve account from OpenClaw config
|
|
69
|
+
*
|
|
70
|
+
* Note: This is a "human account" model - the WeChat account represents
|
|
71
|
+
* a real person with all their friends and groups, not a bot.
|
|
72
|
+
*/
|
|
73
|
+
function resolveAccount(cfg, accountId) {
|
|
74
|
+
const section = cfg.channels?.["celphone-wechat"];
|
|
75
|
+
const apiKey = section?.apiKey;
|
|
76
|
+
const baseUrl = section?.baseUrl || "https://api.workphone.example.com";
|
|
77
|
+
const wechatAccountId = section?.wechatAccountId;
|
|
78
|
+
if (!apiKey) {
|
|
79
|
+
throw new Error("celphone-wechat: apiKey is required");
|
|
80
|
+
}
|
|
81
|
+
if (!wechatAccountId) {
|
|
82
|
+
throw new Error("celphone-wechat: wechatAccountId is required (the WeChat account to use)");
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
accountId: accountId ?? null,
|
|
86
|
+
apiKey,
|
|
87
|
+
baseUrl,
|
|
88
|
+
wechatAccountId,
|
|
89
|
+
wechatId: section?.wechatId || wechatAccountId, // Actual WeChat ID (wxid_xxx)
|
|
90
|
+
nickName: section?.nickName || "WeChat User", // Display name
|
|
91
|
+
allowFrom: section?.allowFrom ?? [],
|
|
92
|
+
dmPolicy: section?.dmSecurity,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create the channel plugin
|
|
97
|
+
*/
|
|
98
|
+
export const celPhoneWeChatPlugin = createChatChannelPlugin({
|
|
99
|
+
base: createChannelPluginBase({
|
|
100
|
+
id: "celphone-wechat",
|
|
101
|
+
setup: {
|
|
102
|
+
resolveAccount,
|
|
103
|
+
inspectAccount(cfg, accountId) {
|
|
104
|
+
const section = cfg.channels?.["celphone-wechat"];
|
|
105
|
+
const hasApiKey = Boolean(section?.apiKey);
|
|
106
|
+
return {
|
|
107
|
+
enabled: hasApiKey,
|
|
108
|
+
configured: hasApiKey,
|
|
109
|
+
tokenStatus: hasApiKey ? "available" : "missing",
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
// DM security: who can message the bot
|
|
115
|
+
security: {
|
|
116
|
+
dm: {
|
|
117
|
+
channelKey: "celphone-wechat",
|
|
118
|
+
resolvePolicy: (account) => account.dmPolicy,
|
|
119
|
+
resolveAllowFrom: (account) => account.allowFrom,
|
|
120
|
+
defaultPolicy: "allowlist", // Default to allowlist for security
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
// Pairing: not currently supported for this channel
|
|
124
|
+
// WorkPhone WeChat doesn't have a standard pairing flow
|
|
125
|
+
// pairing: { ... },
|
|
126
|
+
// Threading: how replies are delivered
|
|
127
|
+
// For WeChat, replies go back to the same chat (friend or chatroom)
|
|
128
|
+
threading: {
|
|
129
|
+
topLevelReplyToMode: "reply", // Reply to the last message in the thread
|
|
130
|
+
},
|
|
131
|
+
// Outbound: send messages to WeChat via WorkPhone API
|
|
132
|
+
//
|
|
133
|
+
// HUMAN ACCOUNT MODEL IMPORTANT:
|
|
134
|
+
// This channel connects to a real person's WeChat account.
|
|
135
|
+
// The agent needs to communicate with ALL their friends and groups,
|
|
136
|
+
// not just one conversation. We distinguish by conversation type:
|
|
137
|
+
// - DM (direct): friendWechatId in params.to
|
|
138
|
+
// - Group chat: chatroomId in params.to (detect by format or metadata)
|
|
139
|
+
outbound: {
|
|
140
|
+
attachedResults: {
|
|
141
|
+
// Send text - detect if DM or group based on conversation metadata
|
|
142
|
+
sendText: async (params) => {
|
|
143
|
+
const client = createWorkPhoneClient({
|
|
144
|
+
baseUrl: params.account.baseUrl,
|
|
145
|
+
apiKey: params.account.apiKey,
|
|
146
|
+
accountId: params.account.accountId || undefined,
|
|
147
|
+
wechatAccountId: params.account.wechatAccountId,
|
|
148
|
+
});
|
|
149
|
+
// Check if this is a group message (chatroom)
|
|
150
|
+
// Chatroom IDs typically start with certain prefix or have specific format
|
|
151
|
+
const isChatroom = params.metadata?.conversationType === 'group' ||
|
|
152
|
+
(params.to && params.to.includes('@chatroom'));
|
|
153
|
+
let result;
|
|
154
|
+
if (isChatroom) {
|
|
155
|
+
// Send to chatroom (group)
|
|
156
|
+
result = await client.sendChatroomMessage({
|
|
157
|
+
wechatAccountId: params.account.wechatAccountId,
|
|
158
|
+
chatroomId: params.to,
|
|
159
|
+
content: params.text,
|
|
160
|
+
type: 'text',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Send to friend (DM)
|
|
165
|
+
result = await client.sendFriendMessage({
|
|
166
|
+
wechatAccountId: params.account.wechatAccountId,
|
|
167
|
+
friendWechatId: params.to,
|
|
168
|
+
content: params.text,
|
|
169
|
+
type: 'text',
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return { messageId: result.messageId };
|
|
173
|
+
},
|
|
174
|
+
// Send media - also support both DM and group
|
|
175
|
+
sendMedia: async (params) => {
|
|
176
|
+
const client = createWorkPhoneClient({
|
|
177
|
+
baseUrl: params.account.baseUrl,
|
|
178
|
+
apiKey: params.account.apiKey,
|
|
179
|
+
accountId: params.account.accountId || undefined,
|
|
180
|
+
wechatAccountId: params.account.wechatAccountId,
|
|
181
|
+
});
|
|
182
|
+
const isChatroom = params.metadata?.conversationType === 'group' ||
|
|
183
|
+
(params.to && params.to.includes('@chatroom'));
|
|
184
|
+
let result;
|
|
185
|
+
if (isChatroom) {
|
|
186
|
+
result = await client.sendChatroomMessage({
|
|
187
|
+
wechatAccountId: params.account.wechatAccountId,
|
|
188
|
+
chatroomId: params.to,
|
|
189
|
+
content: params.filePath || '',
|
|
190
|
+
type: 'file',
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
result = await client.sendFriendMessage({
|
|
195
|
+
wechatAccountId: params.account.wechatAccountId,
|
|
196
|
+
friendWechatId: params.to,
|
|
197
|
+
content: params.filePath || '',
|
|
198
|
+
type: 'file',
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return { messageId: result.messageId };
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
// Additional outbound handlers can be added here for:
|
|
205
|
+
// - sendLink: Send link cards
|
|
206
|
+
// - sendLocation: Send location
|
|
207
|
+
// - sendContact: Send contact card
|
|
208
|
+
},
|
|
209
|
+
// Additional capabilities
|
|
210
|
+
// - Describe the channel's message types and features
|
|
211
|
+
capabilities: {
|
|
212
|
+
supportedMessageTypes: [
|
|
213
|
+
"text",
|
|
214
|
+
"image",
|
|
215
|
+
"video",
|
|
216
|
+
"file",
|
|
217
|
+
"link",
|
|
218
|
+
"location",
|
|
219
|
+
"contact",
|
|
220
|
+
],
|
|
221
|
+
maxAttachmentSize: 25 * 1024 * 1024, // 25MB
|
|
222
|
+
supportsMarkdown: false, // WeChat uses a limited markup
|
|
223
|
+
supportsHtml: false,
|
|
224
|
+
supportsEmoji: true,
|
|
225
|
+
supportsReactions: false, // WeChat doesn't support reactions
|
|
226
|
+
supportsThreads: true, // Can reply in chat
|
|
227
|
+
supportsEditing: false, // Cannot edit sent messages
|
|
228
|
+
supportsDeleting: false, // Cannot delete sent messages
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
/**
|
|
232
|
+
* Helper function to handle inbound webhook messages
|
|
233
|
+
* This should be called from your HTTP route handler
|
|
234
|
+
*
|
|
235
|
+
* Integrates with Cache Manager for:
|
|
236
|
+
* - Local MD file caching
|
|
237
|
+
* - User profile storage
|
|
238
|
+
* - Session memory
|
|
239
|
+
* - Cloud sync
|
|
240
|
+
* - Offline fallback
|
|
241
|
+
*/
|
|
242
|
+
export async function handleInboundMessage(api, payload, cfg) {
|
|
243
|
+
const { event, accountId, wechatAccountId, message, friendRequest } = payload;
|
|
244
|
+
if (event === 'message' && message) {
|
|
245
|
+
// Determine conversation type
|
|
246
|
+
const isChatroom = !!message.chatroomId;
|
|
247
|
+
const conversationId = isChatroom
|
|
248
|
+
? message.chatroomId
|
|
249
|
+
: message.fromUser || message.toUser || '';
|
|
250
|
+
// Convert to cache format and store locally
|
|
251
|
+
if (cacheManager && accountId) {
|
|
252
|
+
try {
|
|
253
|
+
await cacheManager.onMessage({
|
|
254
|
+
messageId: message.messageId,
|
|
255
|
+
msgSvrId: message.msgSvrId,
|
|
256
|
+
accountId: accountId,
|
|
257
|
+
conversationType: isChatroom ? 'chatroom' : 'friend',
|
|
258
|
+
conversationId,
|
|
259
|
+
senderId: message.fromUser || '',
|
|
260
|
+
content: message.content,
|
|
261
|
+
messageType: message.type || 1,
|
|
262
|
+
timestamp: message.timestamp || Date.now(),
|
|
263
|
+
isSelf: message.isSelf || false,
|
|
264
|
+
direction: message.isSelf ? 'outbound' : 'inbound',
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
console.error('[CelPhoneWeChat] Cache write failed:', err);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Convert WorkPhone message format to OpenClaw format
|
|
272
|
+
const openclawMessage = {
|
|
273
|
+
id: message.messageId,
|
|
274
|
+
rawId: message.msgSvrId || message.messageId,
|
|
275
|
+
conversation: {
|
|
276
|
+
type: isChatroom ? 'group' : 'dm',
|
|
277
|
+
id: conversationId,
|
|
278
|
+
chatroomId: isChatroom ? conversationId : undefined,
|
|
279
|
+
},
|
|
280
|
+
sender: {
|
|
281
|
+
id: message.fromUser || '',
|
|
282
|
+
platformId: message.wechatId,
|
|
283
|
+
},
|
|
284
|
+
content: {
|
|
285
|
+
type: message.type === 1 ? 'text' : 'media',
|
|
286
|
+
text: message.content,
|
|
287
|
+
},
|
|
288
|
+
timestamp: new Date(message.timestamp || Date.now()),
|
|
289
|
+
isSelf: message.isSelf || false,
|
|
290
|
+
};
|
|
291
|
+
// Dispatch to OpenClaw
|
|
292
|
+
await api.inbound.dispatchMessage(openclawMessage);
|
|
293
|
+
}
|
|
294
|
+
else if (event === 'friend_request' && friendRequest) {
|
|
295
|
+
// Handle friend request
|
|
296
|
+
await api.inbound.dispatchFriendRequest({
|
|
297
|
+
id: friendRequest.v1,
|
|
298
|
+
platformId: friendRequest.fromUser,
|
|
299
|
+
scene: friendRequest.scene,
|
|
300
|
+
ticket: friendRequest.ticket,
|
|
301
|
+
accountId,
|
|
302
|
+
wechatAccountId,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get user profile from cache (for agent use)
|
|
308
|
+
*/
|
|
309
|
+
export async function getUserProfile(accountId, wechatId) {
|
|
310
|
+
if (!cacheManager)
|
|
311
|
+
return null;
|
|
312
|
+
return await cacheManager.getProfile(accountId, wechatId);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Update user profile in cache
|
|
316
|
+
*/
|
|
317
|
+
export async function updateUserProfile(accountId, wechatId, updates) {
|
|
318
|
+
if (!cacheManager)
|
|
319
|
+
return;
|
|
320
|
+
await cacheManager.updateProfile(accountId, wechatId, updates);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Get SAAS connection status
|
|
324
|
+
*/
|
|
325
|
+
export function getConnectionStatus() {
|
|
326
|
+
return cacheManager?.getConnectionStatus();
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Check if system is online (SAAS connected)
|
|
330
|
+
*/
|
|
331
|
+
export function isOnline() {
|
|
332
|
+
return cacheManager?.isSAASOnline() ?? false;
|
|
333
|
+
}
|
|
334
|
+
export default celPhoneWeChatPlugin;
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkPhone WeChat API Client
|
|
3
|
+
*
|
|
4
|
+
* Interfaces with the WorkPhone API for sending/receiving WeChat messages
|
|
5
|
+
* Based on the Apifox API manual: data/apifox-workphone-3/
|
|
6
|
+
*/
|
|
7
|
+
export interface WorkPhoneConfig {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
apiKey: string;
|
|
10
|
+
accountId?: string;
|
|
11
|
+
wechatAccountId?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface WeChatFriend {
|
|
14
|
+
wechatFriendId: string;
|
|
15
|
+
wechatId: string;
|
|
16
|
+
nickName: string;
|
|
17
|
+
remark: string;
|
|
18
|
+
avatar?: string;
|
|
19
|
+
label?: string[];
|
|
20
|
+
phones?: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface WeChatChatroom {
|
|
23
|
+
wechatChatroomId: string;
|
|
24
|
+
chatroomId: string;
|
|
25
|
+
name: string;
|
|
26
|
+
ownerId: string;
|
|
27
|
+
memberCount: number;
|
|
28
|
+
}
|
|
29
|
+
export interface WeChatMessage {
|
|
30
|
+
messageId: string;
|
|
31
|
+
msgSvrId?: string;
|
|
32
|
+
wechatId: string;
|
|
33
|
+
content: string;
|
|
34
|
+
type: number;
|
|
35
|
+
timestamp: number;
|
|
36
|
+
isSelf: boolean;
|
|
37
|
+
fromUser?: string;
|
|
38
|
+
toUser?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface SendMessageParams {
|
|
41
|
+
wechatAccountId: string;
|
|
42
|
+
toUser: string;
|
|
43
|
+
content: string;
|
|
44
|
+
type?: 'text' | 'image' | 'video' | 'file' | 'link' | 'card';
|
|
45
|
+
}
|
|
46
|
+
export interface SendMessageResult {
|
|
47
|
+
messageId: string;
|
|
48
|
+
msgSvrId?: string;
|
|
49
|
+
success: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface WebhookPayload {
|
|
52
|
+
event: 'message' | 'friend_request' | 'group_invite' | 'system';
|
|
53
|
+
accountId: string;
|
|
54
|
+
wechatAccountId: string;
|
|
55
|
+
message?: WeChatMessage;
|
|
56
|
+
friendRequest?: {
|
|
57
|
+
v1: string;
|
|
58
|
+
scene: number;
|
|
59
|
+
fromUser: string;
|
|
60
|
+
ticket?: string;
|
|
61
|
+
};
|
|
62
|
+
timestamp: number;
|
|
63
|
+
}
|
|
64
|
+
export declare class WorkPhoneWeChatClient {
|
|
65
|
+
private config;
|
|
66
|
+
constructor(config: WorkPhoneConfig);
|
|
67
|
+
private request;
|
|
68
|
+
/**
|
|
69
|
+
* Get all WeChat accounts for an account
|
|
70
|
+
* GET /api/v1/accounts/{accountId}/wechatAccounts
|
|
71
|
+
*/
|
|
72
|
+
getWeChatAccounts(accountId: string): Promise<WeChatFriend[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Get WeChat account info by wechatId
|
|
75
|
+
* GET /wp/api/v1/wechatAccounts/{wechatId}/byWechatId
|
|
76
|
+
*/
|
|
77
|
+
getWeChatAccountById(wechatId: string): Promise<any>;
|
|
78
|
+
/**
|
|
79
|
+
* Get all friends for a WeChat account
|
|
80
|
+
* GET /wp/api/v1/wechatAccounts/{wechatAccountId}/friends
|
|
81
|
+
*/
|
|
82
|
+
getFriends(wechatAccountId: string, options?: {
|
|
83
|
+
page?: number;
|
|
84
|
+
pageSize?: number;
|
|
85
|
+
labelId?: string;
|
|
86
|
+
}): Promise<{
|
|
87
|
+
list: WeChatFriend[];
|
|
88
|
+
total: number;
|
|
89
|
+
}>;
|
|
90
|
+
/**
|
|
91
|
+
* Search friends
|
|
92
|
+
* GET /wp/api/v1/wechatFriends
|
|
93
|
+
*/
|
|
94
|
+
searchFriends(params: {
|
|
95
|
+
accountId?: string;
|
|
96
|
+
wechatAccountId?: string;
|
|
97
|
+
keyword?: string;
|
|
98
|
+
}): Promise<WeChatFriend[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Get friend by ID
|
|
101
|
+
* GET /wp/api/v1/wechatFriends/{wechatFriendId}
|
|
102
|
+
*/
|
|
103
|
+
getFriend(wechatFriendId: string): Promise<WeChatFriend>;
|
|
104
|
+
/**
|
|
105
|
+
* Add friend (send friend request)
|
|
106
|
+
* POST /wp/api/v1/wechatFriends/addFriend
|
|
107
|
+
*/
|
|
108
|
+
addFriend(params: {
|
|
109
|
+
wechatAccountId: string;
|
|
110
|
+
v1: string;
|
|
111
|
+
verifyMessage?: string;
|
|
112
|
+
scene?: number;
|
|
113
|
+
}): Promise<{
|
|
114
|
+
success: boolean;
|
|
115
|
+
taskId?: string;
|
|
116
|
+
}>;
|
|
117
|
+
/**
|
|
118
|
+
* Accept friend request
|
|
119
|
+
* POST /wp/api/v1/wechatFriends/{wechatFriendId}/acceptFriend
|
|
120
|
+
*/
|
|
121
|
+
acceptFriend(wechatFriendId: string): Promise<{
|
|
122
|
+
success: boolean;
|
|
123
|
+
}>;
|
|
124
|
+
/**
|
|
125
|
+
* Update friend remark
|
|
126
|
+
* PUT /wp/api/v1/wechatFriends/{wechatFriendId}/remark
|
|
127
|
+
*/
|
|
128
|
+
updateFriendRemark(wechatFriendId: string, remark: string): Promise<{
|
|
129
|
+
success: boolean;
|
|
130
|
+
}>;
|
|
131
|
+
/**
|
|
132
|
+
* Update friend labels
|
|
133
|
+
* PUT /wp/api/v1/wechatFriends/{wechatFriendId}/label
|
|
134
|
+
*/
|
|
135
|
+
updateFriendLabels(wechatFriendId: string, labelIds: string[]): Promise<{
|
|
136
|
+
success: boolean;
|
|
137
|
+
}>;
|
|
138
|
+
/**
|
|
139
|
+
* Get all chatrooms for a WeChat account
|
|
140
|
+
* GET /wp/api/v1/wechatAccounts/{wechatAccountId}/chatrooms
|
|
141
|
+
*/
|
|
142
|
+
getChatrooms(wechatAccountId: string): Promise<WeChatChatroom[]>;
|
|
143
|
+
/**
|
|
144
|
+
* Get chatroom info by chatroomId
|
|
145
|
+
* GET /wp/api/v1/wechatChatrooms/{wechatChatroomId}
|
|
146
|
+
*/
|
|
147
|
+
getChatroom(wechatChatroomId: string): Promise<WeChatChatroom>;
|
|
148
|
+
/**
|
|
149
|
+
* Update chatroom name (announcement)
|
|
150
|
+
* PUT /wp/api/v1/wechatChatrooms/{wechatChatroomId}/chatroomName
|
|
151
|
+
*/
|
|
152
|
+
updateChatroomName(wechatChatroomId: string, name: string): Promise<{
|
|
153
|
+
success: boolean;
|
|
154
|
+
}>;
|
|
155
|
+
/**
|
|
156
|
+
* Publish chatroom announcement
|
|
157
|
+
* PUT /api/v1/wechat/chatroom/announcement
|
|
158
|
+
*/
|
|
159
|
+
publishChatroomAnnouncement(wechatChatroomId: string, content: string): Promise<{
|
|
160
|
+
success: boolean;
|
|
161
|
+
}>;
|
|
162
|
+
/**
|
|
163
|
+
* Get friend messages (1-on-1 chat)
|
|
164
|
+
* GET /wp/api/v1/wechat/friendMessages
|
|
165
|
+
*/
|
|
166
|
+
getFriendMessages(params: {
|
|
167
|
+
wechatAccountId: string;
|
|
168
|
+
friendWechatId: string;
|
|
169
|
+
startTime?: number;
|
|
170
|
+
endTime?: number;
|
|
171
|
+
limit?: number;
|
|
172
|
+
offset?: number;
|
|
173
|
+
}): Promise<{
|
|
174
|
+
list: WeChatMessage[];
|
|
175
|
+
total: number;
|
|
176
|
+
}>;
|
|
177
|
+
/**
|
|
178
|
+
* Get chatroom messages (group chat)
|
|
179
|
+
* GET /wp/api/v1/wechat/chatroomMessages
|
|
180
|
+
*/
|
|
181
|
+
getChatroomMessages(params: {
|
|
182
|
+
wechatAccountId: string;
|
|
183
|
+
chatroomId: string;
|
|
184
|
+
startTime?: number;
|
|
185
|
+
endTime?: number;
|
|
186
|
+
limit?: number;
|
|
187
|
+
offset?: number;
|
|
188
|
+
}): Promise<{
|
|
189
|
+
list: WeChatMessage[];
|
|
190
|
+
total: number;
|
|
191
|
+
}>;
|
|
192
|
+
/**
|
|
193
|
+
* Send friend message (1-on-1)
|
|
194
|
+
* POST /wp/api/v1/wechat/friendMessages
|
|
195
|
+
*/
|
|
196
|
+
sendFriendMessage(params: {
|
|
197
|
+
wechatAccountId: string;
|
|
198
|
+
friendWechatId: string;
|
|
199
|
+
content: string;
|
|
200
|
+
type?: 'text' | 'image' | 'video' | 'file' | 'link';
|
|
201
|
+
}): Promise<SendMessageResult>;
|
|
202
|
+
/**
|
|
203
|
+
* Send chatroom message (group)
|
|
204
|
+
* POST /wp/api/v1/wechat/chatroomMessages
|
|
205
|
+
*/
|
|
206
|
+
sendChatroomMessage(params: {
|
|
207
|
+
wechatAccountId: string;
|
|
208
|
+
chatroomId: string;
|
|
209
|
+
content: string;
|
|
210
|
+
type?: 'text' | 'image' | 'video' | 'file' | 'link';
|
|
211
|
+
atUsers?: string[];
|
|
212
|
+
}): Promise<SendMessageResult>;
|
|
213
|
+
/**
|
|
214
|
+
* Get moments
|
|
215
|
+
* GET /wp/api/v1/moments
|
|
216
|
+
*/
|
|
217
|
+
getMoments(params: {
|
|
218
|
+
wechatAccountId: string;
|
|
219
|
+
startTime?: number;
|
|
220
|
+
endTime?: number;
|
|
221
|
+
limit?: number;
|
|
222
|
+
}): Promise<{
|
|
223
|
+
list: any[];
|
|
224
|
+
total: number;
|
|
225
|
+
}>;
|
|
226
|
+
/**
|
|
227
|
+
* Publish moment (post to Moments)
|
|
228
|
+
* POST /wp/api/v1/moments
|
|
229
|
+
*/
|
|
230
|
+
publishMoment(params: {
|
|
231
|
+
wechatAccountId: string;
|
|
232
|
+
content: string;
|
|
233
|
+
images?: string[];
|
|
234
|
+
videos?: string[];
|
|
235
|
+
location?: {
|
|
236
|
+
lat: number;
|
|
237
|
+
lng: number;
|
|
238
|
+
name: string;
|
|
239
|
+
};
|
|
240
|
+
}): Promise<{
|
|
241
|
+
momentId: string;
|
|
242
|
+
success: boolean;
|
|
243
|
+
}>;
|
|
244
|
+
/**
|
|
245
|
+
* Comment on a moment
|
|
246
|
+
* POST /wp/api/v1/moments/{momentId}/comment
|
|
247
|
+
*/
|
|
248
|
+
commentMoment(momentId: string, content: string, replyCommentId?: string): Promise<{
|
|
249
|
+
success: boolean;
|
|
250
|
+
}>;
|
|
251
|
+
/**
|
|
252
|
+
* Like a moment
|
|
253
|
+
* POST /wp/api/v1/moments/{momentId}/like
|
|
254
|
+
*/
|
|
255
|
+
likeMoment(momentId: string): Promise<{
|
|
256
|
+
success: boolean;
|
|
257
|
+
}>;
|
|
258
|
+
/**
|
|
259
|
+
* Download friend message file
|
|
260
|
+
*/
|
|
261
|
+
downloadFriendFile(messageId: string, wechatTime: number): Promise<Blob>;
|
|
262
|
+
/**
|
|
263
|
+
* Download chatroom message file
|
|
264
|
+
*/
|
|
265
|
+
downloadChatroomFile(messageId: string, wechatTime: number): Promise<Blob>;
|
|
266
|
+
/**
|
|
267
|
+
* Parse webhook payload from WorkPhone callback
|
|
268
|
+
* This should be called by your webhook endpoint handler
|
|
269
|
+
*/
|
|
270
|
+
parseWebhookPayload(payload: any): WebhookPayload | null;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Factory function to create a WorkPhone client from OpenClaw config
|
|
274
|
+
*/
|
|
275
|
+
export declare function createWorkPhoneClient(config: {
|
|
276
|
+
baseUrl: string;
|
|
277
|
+
apiKey: string;
|
|
278
|
+
accountId?: string;
|
|
279
|
+
wechatAccountId?: string;
|
|
280
|
+
}): WorkPhoneWeChatClient;
|