@dcrays/dcgchat-test 0.2.8 → 0.2.12
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/package.json +1 -1
- package/src/bot.ts +140 -57
- package/src/channel.ts +89 -71
package/package.json
CHANGED
package/src/bot.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
1
2
|
import path from "node:path";
|
|
2
|
-
import os from "node:os";
|
|
3
3
|
import type { ClawdbotConfig, ReplyPayload, RuntimeEnv } from "openclaw/plugin-sdk";
|
|
4
4
|
import { createReplyPrefixContext } from "openclaw/plugin-sdk";
|
|
5
5
|
import type { InboundMessage, OutboundReply } from "./types.js";
|
|
6
|
-
import { getDcgchatRuntime } from "./runtime.js";
|
|
7
|
-
import { resolveAccount } from "./channel.js";
|
|
6
|
+
import { getDcgchatRuntime, getWorkspaceDir } from "./runtime.js";
|
|
7
|
+
import { resolveAccount, sendDcgchatMedia } from "./channel.js";
|
|
8
8
|
import { setMsgStatus } from "./tool.js";
|
|
9
9
|
import { generateSignUrl } from "./api.js";
|
|
10
|
-
import { ossUpload } from "./oss.js";
|
|
11
10
|
|
|
12
11
|
type MediaInfo = {
|
|
13
12
|
path: string;
|
|
13
|
+
fileName: string;
|
|
14
14
|
contentType: string;
|
|
15
15
|
placeholder: string;
|
|
16
16
|
};
|
|
@@ -53,6 +53,7 @@ async function resolveMediaFromUrls(files: { name: string, url: string }[], botT
|
|
|
53
53
|
const isImage = contentType.startsWith("image/");
|
|
54
54
|
out.push({
|
|
55
55
|
path: saved.path,
|
|
56
|
+
fileName,
|
|
56
57
|
contentType: saved.contentType || "",
|
|
57
58
|
placeholder: isImage ? "<media:image>" : "<media:file>",
|
|
58
59
|
});
|
|
@@ -68,26 +69,89 @@ async function resolveMediaFromUrls(files: { name: string, url: string }[], botT
|
|
|
68
69
|
|
|
69
70
|
function buildMediaPayload(mediaList: MediaInfo[]): {
|
|
70
71
|
MediaPath?: string;
|
|
72
|
+
MediaFileName?: string;
|
|
71
73
|
MediaType?: string;
|
|
72
74
|
MediaUrl?: string;
|
|
75
|
+
MediaFileNames?: string[];
|
|
73
76
|
MediaPaths?: string[];
|
|
74
77
|
MediaUrls?: string[];
|
|
75
78
|
MediaTypes?: string[];
|
|
76
79
|
} {
|
|
77
80
|
if (mediaList.length === 0) return {};
|
|
78
81
|
const first = mediaList[0];
|
|
82
|
+
const mediaFileNames = mediaList.map((m) => m.fileName).filter(Boolean);
|
|
79
83
|
const mediaPaths = mediaList.map((m) => m.path);
|
|
80
84
|
const mediaTypes = mediaList.map((m) => m.contentType).filter(Boolean);
|
|
81
85
|
return {
|
|
82
86
|
MediaPath: first?.path,
|
|
87
|
+
MediaFileName: first?.fileName,
|
|
83
88
|
MediaType: first?.contentType,
|
|
84
89
|
MediaUrl: first?.path,
|
|
90
|
+
MediaFileNames: mediaFileNames.length > 0 ? mediaFileNames : undefined,
|
|
85
91
|
MediaPaths: mediaPaths.length > 0 ? mediaPaths : undefined,
|
|
86
92
|
MediaUrls: mediaPaths.length > 0 ? mediaPaths : undefined,
|
|
87
93
|
MediaTypes: mediaTypes.length > 0 ? mediaTypes : undefined,
|
|
88
94
|
};
|
|
89
95
|
}
|
|
90
96
|
|
|
97
|
+
function resolveReplyMediaList(payload: ReplyPayload): string[] {
|
|
98
|
+
if (payload.mediaUrls?.length) return payload.mediaUrls.filter(Boolean);
|
|
99
|
+
return payload.mediaUrl ? [payload.mediaUrl] : [];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function createFileExtractor() {
|
|
103
|
+
const globalSet = new Set()
|
|
104
|
+
|
|
105
|
+
function getNewFiles(text: string) {
|
|
106
|
+
if (!text) return []
|
|
107
|
+
|
|
108
|
+
const currentSet = new Set()
|
|
109
|
+
const lines = text.split(/\n+/)
|
|
110
|
+
|
|
111
|
+
for (const line of lines) {
|
|
112
|
+
const cleanLine = line.trim()
|
|
113
|
+
if (!cleanLine) continue
|
|
114
|
+
|
|
115
|
+
const matches = cleanLine.matchAll(/`([^`]+)`/g)
|
|
116
|
+
for (const m of matches) {
|
|
117
|
+
handlePath(m[1])
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const rawMatches = cleanLine.match(/\/[^\s))]+/g) || []
|
|
121
|
+
for (const p of rawMatches) {
|
|
122
|
+
handlePath(p)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function handlePath(p: string) {
|
|
127
|
+
const filePath = p.trim()
|
|
128
|
+
if (filePath.includes('\n')) return
|
|
129
|
+
if (isValidFile(filePath)) {
|
|
130
|
+
currentSet.add(filePath)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const newFiles = []
|
|
135
|
+
for (const file of currentSet) {
|
|
136
|
+
if (!globalSet.has(file)) {
|
|
137
|
+
globalSet.add(file)
|
|
138
|
+
newFiles.push(file)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return newFiles
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function isValidFile(p: string) {
|
|
146
|
+
return (
|
|
147
|
+
/\/(upload|mobook)\//i.test(p) &&
|
|
148
|
+
/\.[a-zA-Z0-9]+$/.test(p)
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return { getNewFiles }
|
|
153
|
+
}
|
|
154
|
+
|
|
91
155
|
/**
|
|
92
156
|
* 处理一条用户消息,调用 Agent 并返回回复
|
|
93
157
|
*/
|
|
@@ -101,6 +165,8 @@ export async function handleDcgchatMessage(params: {
|
|
|
101
165
|
const { cfg, msg, accountId, runtime } = params;
|
|
102
166
|
const log = runtime?.log ?? console.log;
|
|
103
167
|
const error = runtime?.error ?? console.error;
|
|
168
|
+
// 完整的文本
|
|
169
|
+
let completeText = ''
|
|
104
170
|
|
|
105
171
|
const account = resolveAccount(cfg, accountId);
|
|
106
172
|
const userId = msg._userId.toString();
|
|
@@ -181,6 +247,8 @@ export async function handleDcgchatMessage(params: {
|
|
|
181
247
|
|
|
182
248
|
log(`dcgchat[${accountId}]: ctxPayload=${JSON.stringify(ctxPayload)}`);
|
|
183
249
|
|
|
250
|
+
const sentMediaKeys = new Set<string>()
|
|
251
|
+
const getMediaKey = (url: string) => url.split(/[\\/]/).slice(-2).join('/')
|
|
184
252
|
let textChunk = ''
|
|
185
253
|
|
|
186
254
|
const prefixContext = createReplyPrefixContext({ cfg, agentId: route.agentId });
|
|
@@ -191,7 +259,7 @@ export async function handleDcgchatMessage(params: {
|
|
|
191
259
|
responsePrefixContextProvider: prefixContext.responsePrefixContextProvider,
|
|
192
260
|
humanDelay: core.channel.reply.resolveHumanDelayConfig(cfg, route.agentId),
|
|
193
261
|
onReplyStart: async () => {},
|
|
194
|
-
deliver: async (payload:
|
|
262
|
+
deliver: async (payload: ReplyPayload) => {
|
|
195
263
|
log(`dcgchat[${accountId}][deliver]: received chunk, text length=${payload.text?.length || 0}`);
|
|
196
264
|
},
|
|
197
265
|
onError: (err: any, info: { kind: any; }) => {
|
|
@@ -222,64 +290,49 @@ export async function handleDcgchatMessage(params: {
|
|
|
222
290
|
onModelSelected: prefixContext.onModelSelected,
|
|
223
291
|
onPartialReply: async (payload: ReplyPayload) => {
|
|
224
292
|
log(`dcgchat[${accountId}][deliver]: received chunk, text length=${payload.text?.length || 0}`);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
? [payload.mediaUrl]
|
|
230
|
-
: [];
|
|
293
|
+
if (payload.text) {
|
|
294
|
+
completeText = payload.text
|
|
295
|
+
}
|
|
296
|
+
const mediaList = resolveReplyMediaList(payload);
|
|
231
297
|
if (mediaList.length > 0) {
|
|
232
|
-
const files = []
|
|
233
298
|
for (let i = 0; i < mediaList.length; i++) {
|
|
234
|
-
const
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
299
|
+
const mediaUrl = mediaList[i];
|
|
300
|
+
const key = getMediaKey(mediaUrl);
|
|
301
|
+
if (sentMediaKeys.has(key)) continue;
|
|
302
|
+
sentMediaKeys.add(key);
|
|
303
|
+
await sendDcgchatMedia({
|
|
304
|
+
cfg,
|
|
305
|
+
accountId,
|
|
306
|
+
log,
|
|
307
|
+
mediaUrl,
|
|
308
|
+
text: "",
|
|
309
|
+
});
|
|
241
310
|
}
|
|
242
|
-
|
|
243
|
-
messageType: "openclaw_bot_chat",
|
|
244
|
-
_userId: msg._userId,
|
|
245
|
-
source: "client",
|
|
246
|
-
content: {
|
|
247
|
-
bot_token: msg.content.bot_token,
|
|
248
|
-
domain_id: msg.content.domain_id,
|
|
249
|
-
app_id: msg.content.app_id,
|
|
250
|
-
bot_id: msg.content.bot_id,
|
|
251
|
-
agent_id: msg.content.agent_id,
|
|
252
|
-
session_id: msg.content.session_id,
|
|
253
|
-
message_id: msg.content.message_id,
|
|
254
|
-
response: '',
|
|
255
|
-
files: files,
|
|
256
|
-
state: 'chunk',
|
|
257
|
-
},
|
|
258
|
-
});
|
|
311
|
+
log(`dcgchat[${accountId}][deliver]: sent ${mediaList.length} media file(s) through channel adapter`);
|
|
259
312
|
}
|
|
260
313
|
if (payload.text) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
314
|
+
const nextTextChunk = payload.text.replace(textChunk, '');
|
|
315
|
+
if (nextTextChunk.trim()) {
|
|
316
|
+
log(`dcgchat[${accountId}][deliver]: sending chunk to user ${msg._userId}, text="${nextTextChunk.slice(0, 50)}..."`);
|
|
317
|
+
params.onChunk({
|
|
318
|
+
messageType: "openclaw_bot_chat",
|
|
319
|
+
_userId: msg._userId,
|
|
320
|
+
source: "client",
|
|
321
|
+
content: {
|
|
322
|
+
bot_token: msg.content.bot_token,
|
|
323
|
+
domain_id: msg.content.domain_id,
|
|
324
|
+
app_id: msg.content.app_id,
|
|
325
|
+
bot_id: msg.content.bot_id,
|
|
326
|
+
agent_id: msg.content.agent_id,
|
|
327
|
+
session_id: msg.content.session_id,
|
|
328
|
+
message_id: msg.content.message_id,
|
|
329
|
+
response: nextTextChunk,
|
|
330
|
+
state: 'chunk',
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
log(`dcgchat[${accountId}][deliver]: chunk sent successfully`);
|
|
334
|
+
}
|
|
278
335
|
textChunk = payload.text
|
|
279
|
-
log(`dcgchat[${accountId}][deliver]: chunk sent successfully`);
|
|
280
|
-
} else if (payload.mediaUrl && payload.mediaUrls) {
|
|
281
|
-
|
|
282
|
-
|
|
283
336
|
} else {
|
|
284
337
|
log(`dcgchat[${accountId}][deliver]: skipping empty chunk`);
|
|
285
338
|
}
|
|
@@ -287,6 +340,35 @@ export async function handleDcgchatMessage(params: {
|
|
|
287
340
|
},
|
|
288
341
|
});
|
|
289
342
|
}
|
|
343
|
+
|
|
344
|
+
const extractor = createFileExtractor()
|
|
345
|
+
const completeFiles = extractor.getNewFiles(completeText)
|
|
346
|
+
if (completeFiles.length > 0) {
|
|
347
|
+
for (let i = 0; i < completeFiles.length; i++) {
|
|
348
|
+
let url = completeFiles[i] as string
|
|
349
|
+
if (!path.isAbsolute(url)) {
|
|
350
|
+
url = path.join(getWorkspaceDir(), url)
|
|
351
|
+
}
|
|
352
|
+
const key = getMediaKey(url);
|
|
353
|
+
if (sentMediaKeys.has(key)) {
|
|
354
|
+
log(`dcgchat[${accountId}]: completeFiles already sent, skipping: ${url}`);
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (!fs.existsSync(url)) {
|
|
358
|
+
log(`dcgchat[${accountId}]: completeFiles file not found, skipping: ${url}`);
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
sentMediaKeys.add(key);
|
|
362
|
+
await sendDcgchatMedia({
|
|
363
|
+
cfg,
|
|
364
|
+
accountId,
|
|
365
|
+
log,
|
|
366
|
+
mediaUrl: url,
|
|
367
|
+
text: "",
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
log(`dcgchat[${accountId}][deliver]: sent ${completeFiles.length} media file(s) through channel adapter`);
|
|
371
|
+
}
|
|
290
372
|
log(`dcgchat[${accountId}]: dispatch complete, sending final state`);
|
|
291
373
|
params.onChunk({
|
|
292
374
|
messageType: "openclaw_bot_chat",
|
|
@@ -304,6 +386,7 @@ export async function handleDcgchatMessage(params: {
|
|
|
304
386
|
state: 'final',
|
|
305
387
|
},
|
|
306
388
|
});
|
|
389
|
+
|
|
307
390
|
setMsgStatus('finished');
|
|
308
391
|
textChunk = ''
|
|
309
392
|
log(`dcgchat[${accountId}]: final state sent`);
|
package/src/channel.ts
CHANGED
|
@@ -5,6 +5,93 @@ import { getWsConnection } from "./connection.js";
|
|
|
5
5
|
import { ossUpload } from "./oss.js";
|
|
6
6
|
import { getMsgParams } from "./tool.js";
|
|
7
7
|
|
|
8
|
+
type DcgchatMediaSendContext = {
|
|
9
|
+
cfg: OpenClawConfig;
|
|
10
|
+
accountId?: string | null;
|
|
11
|
+
log?: (message: string) => void;
|
|
12
|
+
mediaUrl?: string;
|
|
13
|
+
text?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function sendDcgchatMedia(ctx: DcgchatMediaSendContext): Promise<void> {
|
|
17
|
+
const ws = getWsConnection();
|
|
18
|
+
const params = getMsgParams();
|
|
19
|
+
const log = ctx.log ?? console.log;
|
|
20
|
+
|
|
21
|
+
if (ws?.readyState !== WebSocket.OPEN) {
|
|
22
|
+
log(`[dcgchat][${ctx.accountId ?? DEFAULT_ACCOUNT_ID}] outbound media skipped -> ${ws?.readyState}: ${ctx.mediaUrl ?? ""}`);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const fileName = ctx.mediaUrl?.split(/[\\/]/).pop() || "";
|
|
27
|
+
const { botToken } = resolveAccount(ctx.cfg, ctx.accountId);
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const url = ctx.mediaUrl ? await ossUpload(ctx.mediaUrl, botToken) : "";
|
|
31
|
+
console.log("🚀 ~ sendDcgchatMedia ~ ctx.mediaUrl:", ctx.mediaUrl)
|
|
32
|
+
const content = {
|
|
33
|
+
messageType: "openclaw_bot_chat",
|
|
34
|
+
_userId: params.userId,
|
|
35
|
+
source: "client",
|
|
36
|
+
content: {
|
|
37
|
+
bot_token: botToken,
|
|
38
|
+
domain_id: params.domainId,
|
|
39
|
+
app_id: params.appId,
|
|
40
|
+
bot_id: params.botId,
|
|
41
|
+
agent_id: params.agentId,
|
|
42
|
+
response: ctx.text ?? "",
|
|
43
|
+
files: [{
|
|
44
|
+
url,
|
|
45
|
+
name: fileName,
|
|
46
|
+
}],
|
|
47
|
+
session_id: params.sessionId,
|
|
48
|
+
message_id: params.messageId || Date.now().toString(),
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
ws.send(JSON.stringify(content));
|
|
52
|
+
log(`dcgchat[${ctx.accountId}]: sendMedia alioss to ${params.userId}, ${JSON.stringify(content)}`);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
const content = {
|
|
55
|
+
messageType: "openclaw_bot_chat",
|
|
56
|
+
_userId: params.userId,
|
|
57
|
+
source: "client",
|
|
58
|
+
content: {
|
|
59
|
+
bot_token: botToken,
|
|
60
|
+
domain_id: params.domainId,
|
|
61
|
+
app_id: params.appId,
|
|
62
|
+
bot_id: params.botId,
|
|
63
|
+
agent_id: params.agentId,
|
|
64
|
+
response: ctx.text ?? "",
|
|
65
|
+
files: [{
|
|
66
|
+
url: ctx.mediaUrl,
|
|
67
|
+
name: fileName,
|
|
68
|
+
}],
|
|
69
|
+
session_id: params.sessionId || Date.now().toString(),
|
|
70
|
+
message_id: Date.now().toString(),
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
ws.send(JSON.stringify(content));
|
|
74
|
+
log(`dcgchat[${ctx.accountId}]: error sendMedia to ${params.userId}, ${JSON.stringify(content)}`);
|
|
75
|
+
} finally {
|
|
76
|
+
ws.send(JSON.stringify({
|
|
77
|
+
messageType: "openclaw_bot_chat",
|
|
78
|
+
_userId: params.userId,
|
|
79
|
+
source: "client",
|
|
80
|
+
content: {
|
|
81
|
+
bot_token: botToken,
|
|
82
|
+
domain_id: params.domainId,
|
|
83
|
+
app_id: params.appId,
|
|
84
|
+
bot_id: params.botId,
|
|
85
|
+
agent_id: params.agentId,
|
|
86
|
+
ssession_id: params.sessionId,
|
|
87
|
+
message_id: Date.now().toString(),
|
|
88
|
+
response: "",
|
|
89
|
+
state: "final",
|
|
90
|
+
},
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
8
95
|
|
|
9
96
|
export function resolveAccount(cfg: OpenClawConfig, accountId?: string | null): ResolvedDcgchatAccount {
|
|
10
97
|
const id = accountId ?? DEFAULT_ACCOUNT_ID;
|
|
@@ -100,7 +187,7 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
100
187
|
sendText: async (ctx) => {
|
|
101
188
|
const ws = getWsConnection()
|
|
102
189
|
const params = getMsgParams();
|
|
103
|
-
const log =
|
|
190
|
+
const log = console.log;
|
|
104
191
|
if (ws?.readyState === WebSocket.OPEN) {
|
|
105
192
|
const {botToken} = resolveAccount(ctx.cfg, ctx.accountId);
|
|
106
193
|
const content = {
|
|
@@ -146,77 +233,8 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
146
233
|
};
|
|
147
234
|
},
|
|
148
235
|
sendMedia: async (ctx) => {
|
|
149
|
-
const ws = getWsConnection()
|
|
150
236
|
const params = getMsgParams();
|
|
151
|
-
|
|
152
|
-
if (ws?.readyState === WebSocket.OPEN) {
|
|
153
|
-
const fileName = ctx.mediaUrl?.split(/[\\/]/).pop() || ''
|
|
154
|
-
const {botToken} = resolveAccount(ctx.cfg, ctx.accountId);
|
|
155
|
-
try {
|
|
156
|
-
const url = ctx.mediaUrl ? await ossUpload(ctx.mediaUrl, botToken) : '';
|
|
157
|
-
const content = {
|
|
158
|
-
messageType: "openclaw_bot_chat",
|
|
159
|
-
_userId: params.userId,
|
|
160
|
-
source: "client",
|
|
161
|
-
content: {
|
|
162
|
-
bot_token: botToken,
|
|
163
|
-
domain_id: params.domainId,
|
|
164
|
-
app_id: params.appId,
|
|
165
|
-
bot_id: params.botId,
|
|
166
|
-
agent_id: params.agentId,
|
|
167
|
-
response: ctx.text,
|
|
168
|
-
files: [{
|
|
169
|
-
url: url,
|
|
170
|
-
name: fileName,
|
|
171
|
-
}],
|
|
172
|
-
session_id: params.sessionId,
|
|
173
|
-
message_id: params.messageId ||Date.now().toString(),
|
|
174
|
-
},
|
|
175
|
-
};
|
|
176
|
-
ws.send(JSON.stringify(content));
|
|
177
|
-
log(`dcgchat[${ctx.accountId}]: sendMedia alioss to ${params.userId}, ${JSON.stringify(content)}`);
|
|
178
|
-
} catch (error) {
|
|
179
|
-
const content = {
|
|
180
|
-
messageType: "openclaw_bot_chat",
|
|
181
|
-
_userId: params.userId,
|
|
182
|
-
source: "client",
|
|
183
|
-
content: {
|
|
184
|
-
bot_token: botToken,
|
|
185
|
-
domain_id: params.domainId,
|
|
186
|
-
app_id: params.appId,
|
|
187
|
-
bot_id: params.botId,
|
|
188
|
-
agent_id: params.agentId,
|
|
189
|
-
response: ctx.text,
|
|
190
|
-
files: [{
|
|
191
|
-
url: ctx.mediaUrl,
|
|
192
|
-
name: fileName,
|
|
193
|
-
}],
|
|
194
|
-
session_id: params.sessionId || Date.now().toString(),
|
|
195
|
-
message_id: Date.now().toString(),
|
|
196
|
-
},
|
|
197
|
-
};
|
|
198
|
-
ws.send(JSON.stringify(content));
|
|
199
|
-
ws.send(JSON.stringify({
|
|
200
|
-
messageType: "openclaw_bot_chat",
|
|
201
|
-
_userId: params.userId,
|
|
202
|
-
source: "client",
|
|
203
|
-
content: {
|
|
204
|
-
bot_token: botToken,
|
|
205
|
-
domain_id: params.domainId,
|
|
206
|
-
app_id: params.appId,
|
|
207
|
-
bot_id: params.botId,
|
|
208
|
-
agent_id: params.agentId,
|
|
209
|
-
ssession_id: params.sessionId,
|
|
210
|
-
message_id: Date.now().toString(),
|
|
211
|
-
response: '',
|
|
212
|
-
state: 'final',
|
|
213
|
-
},
|
|
214
|
-
}));
|
|
215
|
-
log(`dcgchat[${ctx.accountId}]: error sendMedia to ${params.userId}, ${JSON.stringify(content)}`);
|
|
216
|
-
}
|
|
217
|
-
} else {
|
|
218
|
-
log(`[dcgchat][${ctx.accountId ?? DEFAULT_ACCOUNT_ID}] outbound -> ${ws?.readyState}: ${ctx.text}`);
|
|
219
|
-
}
|
|
237
|
+
await sendDcgchatMedia(ctx);
|
|
220
238
|
return {
|
|
221
239
|
channel: "dcgchat-test",
|
|
222
240
|
messageId: `dcg-${Date.now()}`,
|