alemonjs 2.1.81 → 2.1.83-alpha.1
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/lib/app/event-error.d.ts +2 -0
- package/lib/app/event-error.js +20 -0
- package/lib/app/event-processor-callHandler.d.ts +5 -1
- package/lib/app/event-processor-callHandler.js +18 -2
- package/lib/app/event-processor-cycleFiles.d.ts +4 -1
- package/lib/app/event-processor-cycleFiles.js +21 -6
- package/lib/app/event-processor-cycleRoute.d.ts +4 -1
- package/lib/app/event-processor-cycleRoute.js +16 -2
- package/lib/app/event-processor-event.js +2 -2
- package/lib/app/event-processor-middleware.js +2 -2
- package/lib/app/event-processor-subscribe.js +31 -3
- package/lib/app/event-processor.js +6 -1
- package/lib/app/hook-event-context.d.ts +7 -3
- package/lib/app/hook-event-context.js +24 -5
- package/lib/app/hook-use/subscribe.js +3 -1
- package/lib/app/index.js +2 -2
- package/lib/app/lifecycle-callbacks.d.ts +14 -0
- package/lib/app/lifecycle-callbacks.js +99 -0
- package/lib/app/load_modules/loadChild.js +13 -10
- package/lib/app/router/dsl.js +2 -2
- package/lib/app/store.d.ts +2 -0
- package/lib/app/store.js +35 -12
- package/lib/cbp/connects/client.js +34 -32
- package/lib/cbp/connects/platform.js +45 -68
- package/lib/cbp/normalize.d.ts +16 -0
- package/lib/cbp/normalize.js +328 -0
- package/lib/cbp/processor/actions.js +15 -13
- package/lib/cbp/processor/api.js +15 -13
- package/lib/cbp/processor/config.d.ts +8 -4
- package/lib/cbp/processor/config.js +9 -5
- package/lib/cbp/server/main.js +28 -30
- package/lib/cbp/typings.d.ts +139 -0
- package/lib/client.js +11 -7
- package/lib/core/config.d.ts +3 -3
- package/lib/index.js +2 -2
- package/lib/server/routers/router.js +111 -17
- package/lib/types/actions.d.ts +20 -1
- package/lib/types/apis.d.ts +2 -1
- package/lib/types/cycle/index.d.ts +50 -0
- package/lib/types/event/index.d.ts +1 -0
- package/lib/types/subscribe/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
const now = () => Date.now();
|
|
2
|
+
const asRecord = (value) => {
|
|
3
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
4
|
+
};
|
|
5
|
+
const asResults = (value) => {
|
|
6
|
+
return Array.isArray(value) ? value : [];
|
|
7
|
+
};
|
|
8
|
+
const inferEventRouteId = (event) => {
|
|
9
|
+
const channelId = event.ChannelId;
|
|
10
|
+
const guildId = event.GuildId;
|
|
11
|
+
const deviceId = event.DeviceId;
|
|
12
|
+
if (typeof channelId === 'string' && channelId) {
|
|
13
|
+
return channelId;
|
|
14
|
+
}
|
|
15
|
+
if (typeof guildId === 'string' && guildId) {
|
|
16
|
+
return guildId;
|
|
17
|
+
}
|
|
18
|
+
if (typeof deviceId === 'string' && deviceId) {
|
|
19
|
+
return deviceId;
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
};
|
|
23
|
+
const createRequestEnvelope = (type, id, deviceId, payload) => {
|
|
24
|
+
return {
|
|
25
|
+
protocol: 'cbp',
|
|
26
|
+
version: 1,
|
|
27
|
+
type,
|
|
28
|
+
id,
|
|
29
|
+
timestamp: now(),
|
|
30
|
+
source: {
|
|
31
|
+
role: 'app-client',
|
|
32
|
+
deviceId
|
|
33
|
+
},
|
|
34
|
+
payload
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
const createResponseEnvelope = (type, replyTo, deviceId, payload, error) => {
|
|
38
|
+
return {
|
|
39
|
+
protocol: 'cbp',
|
|
40
|
+
version: 1,
|
|
41
|
+
type,
|
|
42
|
+
id: `${replyTo}:res`,
|
|
43
|
+
replyTo,
|
|
44
|
+
timestamp: now(),
|
|
45
|
+
source: {
|
|
46
|
+
role: 'platform',
|
|
47
|
+
deviceId
|
|
48
|
+
},
|
|
49
|
+
target: {
|
|
50
|
+
role: 'app-client',
|
|
51
|
+
deviceId
|
|
52
|
+
},
|
|
53
|
+
payload: {
|
|
54
|
+
results: payload
|
|
55
|
+
},
|
|
56
|
+
error
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
const normalizeEnvelopeMessage = (input) => {
|
|
60
|
+
const payload = input.payload;
|
|
61
|
+
const meta = asRecord(input.meta);
|
|
62
|
+
const deviceId = input.source?.deviceId ?? input.target?.deviceId;
|
|
63
|
+
const sourceRole = input.source?.role;
|
|
64
|
+
const targetRole = input.target?.role;
|
|
65
|
+
switch (input.type) {
|
|
66
|
+
case 'event': {
|
|
67
|
+
const eventPayload = asRecord(payload);
|
|
68
|
+
const event = asRecord(eventPayload.event);
|
|
69
|
+
return {
|
|
70
|
+
kind: 'event',
|
|
71
|
+
id: input.id,
|
|
72
|
+
timestamp: input.timestamp,
|
|
73
|
+
deviceId,
|
|
74
|
+
sourceRole,
|
|
75
|
+
targetRole,
|
|
76
|
+
eventName: String(eventPayload.name ?? ''),
|
|
77
|
+
event,
|
|
78
|
+
raw: eventPayload.raw,
|
|
79
|
+
meta
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
case 'action.req': {
|
|
83
|
+
const actionPayload = asRecord(payload);
|
|
84
|
+
return {
|
|
85
|
+
kind: 'action.req',
|
|
86
|
+
id: input.id,
|
|
87
|
+
timestamp: input.timestamp,
|
|
88
|
+
deviceId,
|
|
89
|
+
sourceRole,
|
|
90
|
+
targetRole,
|
|
91
|
+
action: String(actionPayload.action ?? ''),
|
|
92
|
+
input: asRecord(actionPayload.input),
|
|
93
|
+
meta
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
case 'action.res':
|
|
97
|
+
return {
|
|
98
|
+
kind: 'action.res',
|
|
99
|
+
id: input.id,
|
|
100
|
+
replyTo: String(input.replyTo ?? ''),
|
|
101
|
+
timestamp: input.timestamp,
|
|
102
|
+
deviceId,
|
|
103
|
+
sourceRole,
|
|
104
|
+
targetRole,
|
|
105
|
+
results: asResults(asRecord(payload).results),
|
|
106
|
+
error: input.error,
|
|
107
|
+
meta
|
|
108
|
+
};
|
|
109
|
+
case 'api.req': {
|
|
110
|
+
const apiPayload = asRecord(payload);
|
|
111
|
+
return {
|
|
112
|
+
kind: 'api.req',
|
|
113
|
+
id: input.id,
|
|
114
|
+
timestamp: input.timestamp,
|
|
115
|
+
deviceId,
|
|
116
|
+
sourceRole,
|
|
117
|
+
targetRole,
|
|
118
|
+
api: String(apiPayload.api ?? ''),
|
|
119
|
+
input: asRecord(apiPayload.input),
|
|
120
|
+
meta
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
case 'api.res':
|
|
124
|
+
return {
|
|
125
|
+
kind: 'api.res',
|
|
126
|
+
id: input.id,
|
|
127
|
+
replyTo: String(input.replyTo ?? ''),
|
|
128
|
+
timestamp: input.timestamp,
|
|
129
|
+
deviceId,
|
|
130
|
+
sourceRole,
|
|
131
|
+
targetRole,
|
|
132
|
+
results: asResults(asRecord(payload).results),
|
|
133
|
+
error: input.error,
|
|
134
|
+
meta
|
|
135
|
+
};
|
|
136
|
+
case 'control': {
|
|
137
|
+
const controlPayload = asRecord(payload);
|
|
138
|
+
return {
|
|
139
|
+
kind: 'control',
|
|
140
|
+
id: input.id,
|
|
141
|
+
timestamp: input.timestamp,
|
|
142
|
+
deviceId,
|
|
143
|
+
sourceRole,
|
|
144
|
+
targetRole,
|
|
145
|
+
op: String(controlPayload.op ?? 'error'),
|
|
146
|
+
payload: controlPayload,
|
|
147
|
+
error: input.error,
|
|
148
|
+
meta
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
default:
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const normalizeLegacyMessage = (input) => {
|
|
156
|
+
if (input?.apiId) {
|
|
157
|
+
if (Array.isArray(input.payload)) {
|
|
158
|
+
return {
|
|
159
|
+
kind: 'api.res',
|
|
160
|
+
id: String(input.apiId),
|
|
161
|
+
replyTo: String(input.apiId),
|
|
162
|
+
timestamp: now(),
|
|
163
|
+
deviceId: typeof input.DeviceId === 'string' ? input.DeviceId : undefined,
|
|
164
|
+
results: input.payload,
|
|
165
|
+
meta: {}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
kind: 'api.req',
|
|
170
|
+
id: String(input.apiId),
|
|
171
|
+
timestamp: now(),
|
|
172
|
+
deviceId: typeof input.DeviceId === 'string' ? input.DeviceId : undefined,
|
|
173
|
+
api: typeof input.action === 'string' ? input.action : '',
|
|
174
|
+
input: asRecord(input.payload),
|
|
175
|
+
meta: {}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (input?.actionId) {
|
|
179
|
+
if (Array.isArray(input.payload)) {
|
|
180
|
+
return {
|
|
181
|
+
kind: 'action.res',
|
|
182
|
+
id: String(input.actionId),
|
|
183
|
+
replyTo: String(input.actionId),
|
|
184
|
+
timestamp: now(),
|
|
185
|
+
deviceId: typeof input.DeviceId === 'string' ? input.DeviceId : undefined,
|
|
186
|
+
results: input.payload,
|
|
187
|
+
meta: {}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
kind: 'action.req',
|
|
192
|
+
id: String(input.actionId),
|
|
193
|
+
timestamp: now(),
|
|
194
|
+
deviceId: typeof input.DeviceId === 'string' ? input.DeviceId : undefined,
|
|
195
|
+
action: typeof input.action === 'string' ? input.action : '',
|
|
196
|
+
input: asRecord(input.payload),
|
|
197
|
+
meta: {}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
if (input?.activeId && input?.active === 'sync') {
|
|
201
|
+
const payload = asRecord(input.payload);
|
|
202
|
+
return {
|
|
203
|
+
kind: 'control',
|
|
204
|
+
id: String(input.activeId),
|
|
205
|
+
timestamp: now(),
|
|
206
|
+
deviceId: typeof input.DeviceId === 'string' ? input.DeviceId : undefined,
|
|
207
|
+
op: 'sync',
|
|
208
|
+
payload,
|
|
209
|
+
meta: {}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (input?.name) {
|
|
213
|
+
const event = input;
|
|
214
|
+
return {
|
|
215
|
+
kind: 'event',
|
|
216
|
+
id: typeof input.MessageId === 'string' ? input.MessageId : typeof input.DeviceId === 'string' ? input.DeviceId : `${input.name}:${now()}`,
|
|
217
|
+
timestamp: typeof input.CreateAt === 'number' ? input.CreateAt : now(),
|
|
218
|
+
deviceId: typeof input.DeviceId === 'string' ? input.DeviceId : undefined,
|
|
219
|
+
eventName: input.name,
|
|
220
|
+
event,
|
|
221
|
+
raw: input.value,
|
|
222
|
+
meta: {}
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
};
|
|
227
|
+
const isCBPEnvelope = (input) => {
|
|
228
|
+
if (!input || typeof input !== 'object') {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
const value = input;
|
|
232
|
+
return value.protocol === 'cbp' && value.version === 1 && typeof value.type === 'string' && typeof value.id === 'string';
|
|
233
|
+
};
|
|
234
|
+
const normalizeInboundMessage = (input) => {
|
|
235
|
+
if (!input || typeof input !== 'object') {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
if (isCBPEnvelope(input)) {
|
|
239
|
+
return normalizeEnvelopeMessage(input);
|
|
240
|
+
}
|
|
241
|
+
return normalizeLegacyMessage(input);
|
|
242
|
+
};
|
|
243
|
+
const toLegacyActionData = (message) => {
|
|
244
|
+
return {
|
|
245
|
+
action: message.action,
|
|
246
|
+
payload: message.input,
|
|
247
|
+
actionId: message.id,
|
|
248
|
+
DeviceId: message.deviceId
|
|
249
|
+
};
|
|
250
|
+
};
|
|
251
|
+
const toLegacyApiData = (message) => {
|
|
252
|
+
const input = message.input;
|
|
253
|
+
const key = typeof input.key === 'string' ? input.key : '';
|
|
254
|
+
const params = Array.isArray(input.params) ? input.params : [];
|
|
255
|
+
return {
|
|
256
|
+
action: message.api,
|
|
257
|
+
payload: {
|
|
258
|
+
event: input.event,
|
|
259
|
+
key,
|
|
260
|
+
params
|
|
261
|
+
},
|
|
262
|
+
apiId: message.id,
|
|
263
|
+
DeviceId: message.deviceId
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
const isNormalizedActionRequest = (message) => {
|
|
267
|
+
return message?.kind === 'action.req';
|
|
268
|
+
};
|
|
269
|
+
const isNormalizedApiRequest = (message) => {
|
|
270
|
+
return message?.kind === 'api.req';
|
|
271
|
+
};
|
|
272
|
+
const getNormalizedDeviceId = (message) => {
|
|
273
|
+
return message.deviceId;
|
|
274
|
+
};
|
|
275
|
+
const getNormalizedEventRouteId = (message) => {
|
|
276
|
+
if (message.kind !== 'event') {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
return inferEventRouteId(message.event);
|
|
280
|
+
};
|
|
281
|
+
const createActionRequestEnvelope = (data) => {
|
|
282
|
+
return createRequestEnvelope('action.req', String(data.actionId ?? ''), data.DeviceId, {
|
|
283
|
+
action: data.action,
|
|
284
|
+
input: asRecord(data.payload)
|
|
285
|
+
});
|
|
286
|
+
};
|
|
287
|
+
const createApiRequestEnvelope = (data) => {
|
|
288
|
+
return createRequestEnvelope('api.req', String(data.apiId ?? ''), data.DeviceId, {
|
|
289
|
+
api: data.action,
|
|
290
|
+
input: asRecord(data.payload)
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
const createActionResponseEnvelope = (data, payload, error) => {
|
|
294
|
+
return createResponseEnvelope('action.res', String(data.actionId ?? ''), data.DeviceId, payload, error);
|
|
295
|
+
};
|
|
296
|
+
const createApiResponseEnvelope = (data, payload, error) => {
|
|
297
|
+
return createResponseEnvelope('api.res', String(data.apiId ?? ''), data.DeviceId, payload, error);
|
|
298
|
+
};
|
|
299
|
+
const createEventEnvelope = (data) => {
|
|
300
|
+
const deviceId = typeof data.DeviceId === 'string' ? data.DeviceId : undefined;
|
|
301
|
+
const eventName = typeof data.name === 'string' ? data.name : '';
|
|
302
|
+
const event = { ...data };
|
|
303
|
+
return {
|
|
304
|
+
protocol: 'cbp',
|
|
305
|
+
version: 1,
|
|
306
|
+
type: 'event',
|
|
307
|
+
id: typeof data.MessageId === 'string'
|
|
308
|
+
? data.MessageId
|
|
309
|
+
: typeof deviceId === 'string'
|
|
310
|
+
? `${deviceId}:${now()}`
|
|
311
|
+
: `${eventName}:${now()}`,
|
|
312
|
+
timestamp: typeof data.CreateAt === 'number' ? data.CreateAt : now(),
|
|
313
|
+
source: {
|
|
314
|
+
role: 'platform',
|
|
315
|
+
deviceId
|
|
316
|
+
},
|
|
317
|
+
payload: {
|
|
318
|
+
name: eventName,
|
|
319
|
+
event,
|
|
320
|
+
raw: data.value
|
|
321
|
+
},
|
|
322
|
+
meta: {
|
|
323
|
+
routeId: inferEventRouteId(event)
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
export { createActionRequestEnvelope, createActionResponseEnvelope, createApiRequestEnvelope, createApiResponseEnvelope, createEventEnvelope, getNormalizedDeviceId, getNormalizedEventRouteId, isCBPEnvelope, isNormalizedActionRequest, isNormalizedApiRequest, normalizeInboundMessage, toLegacyActionData, toLegacyApiData };
|
|
@@ -4,36 +4,38 @@ import 'fs';
|
|
|
4
4
|
import 'path';
|
|
5
5
|
import 'yaml';
|
|
6
6
|
import { sanitizeForSerialization, createResult } from '../../core/utils.js';
|
|
7
|
-
import { generateUniqueId, deviceId,
|
|
7
|
+
import { generateUniqueId, deviceId, actionRequestResolves, actionRequestTimeouts, timeoutTime } from './config.js';
|
|
8
8
|
import { getDirectSend } from './transport.js';
|
|
9
|
+
import { createActionRequestEnvelope } from '../normalize.js';
|
|
9
10
|
|
|
10
|
-
const setupActionResolve = (
|
|
11
|
-
|
|
11
|
+
const setupActionResolve = (requestId, resolve) => {
|
|
12
|
+
actionRequestResolves.set(requestId, resolve);
|
|
12
13
|
const timeout = setTimeout(() => {
|
|
13
|
-
if (!
|
|
14
|
+
if (!actionRequestResolves.has(requestId) || !actionRequestTimeouts.has(requestId)) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
actionRequestResolves.delete(requestId);
|
|
18
|
+
actionRequestTimeouts.delete(requestId);
|
|
18
19
|
resolve([createResult(ResultCode.Fail, '行为超时', null)]);
|
|
19
20
|
}, timeoutTime);
|
|
20
|
-
|
|
21
|
+
actionRequestTimeouts.set(requestId, timeout);
|
|
21
22
|
};
|
|
22
23
|
const sendAction = (data) => {
|
|
23
|
-
const
|
|
24
|
+
const requestId = generateUniqueId();
|
|
24
25
|
return new Promise(resolve => {
|
|
25
|
-
data.actionId =
|
|
26
|
+
data.actionId = requestId;
|
|
26
27
|
data.DeviceId = deviceId;
|
|
27
|
-
const
|
|
28
|
+
const envelope = createActionRequestEnvelope(data);
|
|
29
|
+
const safeData = sanitizeForSerialization(envelope);
|
|
28
30
|
const directSend = getDirectSend();
|
|
29
31
|
if (directSend) {
|
|
30
32
|
directSend(safeData);
|
|
31
|
-
setupActionResolve(
|
|
33
|
+
setupActionResolve(requestId, resolve);
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
if (process.env.__ALEMON_IPC === '1' && typeof process.send === 'function') {
|
|
35
37
|
process.send({ type: 'ipc:data', data: safeData });
|
|
36
|
-
setupActionResolve(
|
|
38
|
+
setupActionResolve(requestId, resolve);
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
41
|
if (!global.chatbotClient?.send) {
|
|
@@ -41,7 +43,7 @@ const sendAction = (data) => {
|
|
|
41
43
|
return;
|
|
42
44
|
}
|
|
43
45
|
global.chatbotClient?.send(flattedJSON.stringify(safeData));
|
|
44
|
-
setupActionResolve(
|
|
46
|
+
setupActionResolve(requestId, resolve);
|
|
45
47
|
});
|
|
46
48
|
};
|
|
47
49
|
|
package/lib/cbp/processor/api.js
CHANGED
|
@@ -3,37 +3,39 @@ import 'fs';
|
|
|
3
3
|
import 'path';
|
|
4
4
|
import 'yaml';
|
|
5
5
|
import { sanitizeForSerialization, createResult } from '../../core/utils.js';
|
|
6
|
-
import { generateUniqueId, deviceId,
|
|
6
|
+
import { generateUniqueId, deviceId, apiRequestResolves, apiRequestTimeouts, timeoutTime } from './config.js';
|
|
7
7
|
import * as flattedJSON from 'flatted';
|
|
8
8
|
import { getDirectSend } from './transport.js';
|
|
9
|
+
import { createApiRequestEnvelope } from '../normalize.js';
|
|
9
10
|
|
|
10
|
-
const setupApiResolve = (
|
|
11
|
-
|
|
11
|
+
const setupApiResolve = (requestId, resolve) => {
|
|
12
|
+
apiRequestResolves.set(requestId, resolve);
|
|
12
13
|
const timeout = setTimeout(() => {
|
|
13
|
-
if (!
|
|
14
|
+
if (!apiRequestResolves.has(requestId) || !apiRequestTimeouts.has(requestId)) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
apiRequestResolves.delete(requestId);
|
|
18
|
+
apiRequestTimeouts.delete(requestId);
|
|
18
19
|
resolve([createResult(ResultCode.Fail, '接口超时', null)]);
|
|
19
20
|
}, timeoutTime);
|
|
20
|
-
|
|
21
|
+
apiRequestTimeouts.set(requestId, timeout);
|
|
21
22
|
};
|
|
22
23
|
const sendAPI = (data) => {
|
|
23
|
-
const
|
|
24
|
+
const requestId = generateUniqueId();
|
|
24
25
|
return new Promise(resolve => {
|
|
25
|
-
data.apiId =
|
|
26
|
+
data.apiId = requestId;
|
|
26
27
|
data.DeviceId = deviceId;
|
|
27
|
-
const
|
|
28
|
+
const envelope = createApiRequestEnvelope(data);
|
|
29
|
+
const safeData = sanitizeForSerialization(envelope);
|
|
28
30
|
const directSend = getDirectSend();
|
|
29
31
|
if (directSend) {
|
|
30
32
|
directSend(safeData);
|
|
31
|
-
setupApiResolve(
|
|
33
|
+
setupApiResolve(requestId, resolve);
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
if (process.env.__ALEMON_IPC === '1' && typeof process.send === 'function') {
|
|
35
37
|
process.send({ type: 'ipc:data', data: safeData });
|
|
36
|
-
setupApiResolve(
|
|
38
|
+
setupApiResolve(requestId, resolve);
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
41
|
if (!global.chatbotClient?.send) {
|
|
@@ -41,7 +43,7 @@ const sendAPI = (data) => {
|
|
|
41
43
|
return;
|
|
42
44
|
}
|
|
43
45
|
global.chatbotClient?.send(flattedJSON.stringify(safeData));
|
|
44
|
-
setupApiResolve(
|
|
46
|
+
setupApiResolve(requestId, resolve);
|
|
45
47
|
});
|
|
46
48
|
};
|
|
47
49
|
|
|
@@ -12,10 +12,14 @@ export declare const USER_AGENT_HEADER_VALUE_MAP: {
|
|
|
12
12
|
};
|
|
13
13
|
export declare const DEVICE_ID_HEADER = "x-device-id";
|
|
14
14
|
export declare const FULL_RECEIVE_HEADER = "x-full-receive";
|
|
15
|
-
type
|
|
16
|
-
type
|
|
17
|
-
export declare const
|
|
18
|
-
export declare const
|
|
15
|
+
type RequestReplyValue = Result[] | PromiseLike<Result[]>;
|
|
16
|
+
type RequestReplyResolve = (value: RequestReplyValue) => void;
|
|
17
|
+
export declare const actionRequestResolves: Map<string, RequestReplyResolve>;
|
|
18
|
+
export declare const apiRequestResolves: Map<string, RequestReplyResolve>;
|
|
19
|
+
export declare const actionRequestTimeouts: Map<string, NodeJS.Timeout>;
|
|
20
|
+
export declare const apiRequestTimeouts: Map<string, NodeJS.Timeout>;
|
|
21
|
+
export declare const actionResolves: Map<string, RequestReplyResolve>;
|
|
22
|
+
export declare const apiResolves: Map<string, RequestReplyResolve>;
|
|
19
23
|
export declare const actionTimeouts: Map<string, NodeJS.Timeout>;
|
|
20
24
|
export declare const apiTimeouts: Map<string, NodeJS.Timeout>;
|
|
21
25
|
export declare const childrenBind: Map<string, string>;
|
|
@@ -12,10 +12,14 @@ const USER_AGENT_HEADER_VALUE_MAP = {
|
|
|
12
12
|
};
|
|
13
13
|
const DEVICE_ID_HEADER = 'x-device-id';
|
|
14
14
|
const FULL_RECEIVE_HEADER = 'x-full-receive';
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
15
|
+
const actionRequestResolves = new Map();
|
|
16
|
+
const apiRequestResolves = new Map();
|
|
17
|
+
const actionRequestTimeouts = new Map();
|
|
18
|
+
const apiRequestTimeouts = new Map();
|
|
19
|
+
const actionResolves = actionRequestResolves;
|
|
20
|
+
const apiResolves = apiRequestResolves;
|
|
21
|
+
const actionTimeouts = actionRequestTimeouts;
|
|
22
|
+
const apiTimeouts = apiRequestTimeouts;
|
|
19
23
|
const childrenBind = new Map();
|
|
20
24
|
const clientBindCount = new Map();
|
|
21
25
|
const bindChannelToClient = (channelId, clientId) => {
|
|
@@ -49,4 +53,4 @@ const timeoutTime = 1000 * 60 * 3;
|
|
|
49
53
|
const reconnectInterval = 1000 * 6;
|
|
50
54
|
const HEARTBEAT_INTERVAL = 1000 * 18;
|
|
51
55
|
|
|
52
|
-
export { DEVICE_ID_HEADER, FULL_RECEIVE_HEADER, HEARTBEAT_INTERVAL, USER_AGENT_HEADER, USER_AGENT_HEADER_VALUE_MAP, actionResolves, actionTimeouts, apiResolves, apiTimeouts, bindChannelToClient, childrenBind, childrenClient, clientBindCount, deviceId, fullClient, generateUniqueId, platformClient, reconnectInterval, timeoutTime, unbindClient };
|
|
56
|
+
export { DEVICE_ID_HEADER, FULL_RECEIVE_HEADER, HEARTBEAT_INTERVAL, USER_AGENT_HEADER, USER_AGENT_HEADER_VALUE_MAP, actionRequestResolves, actionRequestTimeouts, actionResolves, actionTimeouts, apiRequestResolves, apiRequestTimeouts, apiResolves, apiTimeouts, bindChannelToClient, childrenBind, childrenClient, clientBindCount, deviceId, fullClient, generateUniqueId, platformClient, reconnectInterval, timeoutTime, unbindClient };
|
package/lib/cbp/server/main.js
CHANGED
|
@@ -11,7 +11,27 @@ import '../../core/utils.js';
|
|
|
11
11
|
import { USER_AGENT_HEADER, USER_AGENT_HEADER_VALUE_MAP, DEVICE_ID_HEADER, FULL_RECEIVE_HEADER, platformClient, childrenClient, fullClient, childrenBind, clientBindCount, unbindClient, bindChannelToClient } from '../processor/config.js';
|
|
12
12
|
import { createTestOneController } from './testone.js';
|
|
13
13
|
import { getClientChild } from '../../process/ipc-bridge.js';
|
|
14
|
+
import { normalizeInboundMessage, getNormalizedDeviceId, getNormalizedEventRouteId } from '../normalize.js';
|
|
14
15
|
|
|
16
|
+
const routeNormalizedMessage = (message, input) => {
|
|
17
|
+
const normalized = normalizeInboundMessage(input);
|
|
18
|
+
if (!normalized) {
|
|
19
|
+
return { normalized: null, handled: false };
|
|
20
|
+
}
|
|
21
|
+
if (normalized.kind === 'api.res' || normalized.kind === 'action.res') {
|
|
22
|
+
const resolvedDeviceId = getNormalizedDeviceId(normalized);
|
|
23
|
+
if (resolvedDeviceId) {
|
|
24
|
+
routeMessageToDevice(resolvedDeviceId, message);
|
|
25
|
+
}
|
|
26
|
+
return { normalized, handled: true };
|
|
27
|
+
}
|
|
28
|
+
if (normalized.kind === 'event') {
|
|
29
|
+
const routeId = getNormalizedEventRouteId(normalized);
|
|
30
|
+
handleEvent(message, routeId || '');
|
|
31
|
+
return { normalized, handled: true };
|
|
32
|
+
}
|
|
33
|
+
return { normalized, handled: false };
|
|
34
|
+
};
|
|
15
35
|
const routeMessageToDevice = (DeviceId, message) => {
|
|
16
36
|
if (childrenClient.has(DeviceId)) {
|
|
17
37
|
const clientWs = childrenClient.get(DeviceId);
|
|
@@ -204,24 +224,13 @@ const setPlatformClient = (originId, ws) => {
|
|
|
204
224
|
platformClient.set(originId, ws);
|
|
205
225
|
ws.on('message', (message) => {
|
|
206
226
|
try {
|
|
207
|
-
const
|
|
227
|
+
const inbound = flattedJSON.parse(message.toString());
|
|
228
|
+
routeNormalizedMessage(message.toString(), inbound);
|
|
208
229
|
logger.debug({
|
|
209
230
|
code: ResultCode.Ok,
|
|
210
231
|
message: '服务端接收到消息',
|
|
211
|
-
data:
|
|
232
|
+
data: inbound
|
|
212
233
|
});
|
|
213
|
-
if (parsedMessage.apiId) {
|
|
214
|
-
const DeviceId = parsedMessage.DeviceId;
|
|
215
|
-
routeMessageToDevice(DeviceId, message);
|
|
216
|
-
}
|
|
217
|
-
else if (parsedMessage?.actionId) {
|
|
218
|
-
const DeviceId = parsedMessage.DeviceId;
|
|
219
|
-
routeMessageToDevice(DeviceId, message);
|
|
220
|
-
}
|
|
221
|
-
else if (parsedMessage?.name) {
|
|
222
|
-
const ID = parsedMessage.ChannelId || parsedMessage.GuildId || parsedMessage.DeviceId;
|
|
223
|
-
handleEvent(message, ID);
|
|
224
|
-
}
|
|
225
234
|
}
|
|
226
235
|
catch (error) {
|
|
227
236
|
logger.error({
|
|
@@ -255,26 +264,15 @@ const setTestOnePlatformClient = (ws) => {
|
|
|
255
264
|
const controller = createTestOneController(ws);
|
|
256
265
|
ws.on('message', (message) => {
|
|
257
266
|
try {
|
|
258
|
-
const
|
|
267
|
+
const inbound = flattedJSON.parse(message.toString());
|
|
268
|
+
const { handled } = routeNormalizedMessage(message.toString(), inbound);
|
|
259
269
|
logger.debug({
|
|
260
270
|
code: ResultCode.Ok,
|
|
261
271
|
message: '测试端接收到消息',
|
|
262
|
-
data:
|
|
272
|
+
data: inbound
|
|
263
273
|
});
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
routeMessageToDevice(DeviceId, message);
|
|
267
|
-
}
|
|
268
|
-
else if (parsedMessage?.actionId) {
|
|
269
|
-
const DeviceId = parsedMessage.DeviceId;
|
|
270
|
-
routeMessageToDevice(DeviceId, message);
|
|
271
|
-
}
|
|
272
|
-
else if (parsedMessage?.name) {
|
|
273
|
-
const ID = parsedMessage.ChannelId || parsedMessage.GuildId || parsedMessage.DeviceId;
|
|
274
|
-
handleEvent(message, ID);
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
controller.onMessage(parsedMessage);
|
|
274
|
+
if (!handled) {
|
|
275
|
+
controller.onMessage(inbound);
|
|
278
276
|
}
|
|
279
277
|
}
|
|
280
278
|
catch (error) {
|