@rlynicrisis/link 0.0.1 → 0.0.2
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/openclaw.plugin.json +3 -2
- package/package.json +4 -1
- package/src/bot.ts +4 -3
- package/src/client-manager.ts +21 -1
- package/src/link/client.ts +100 -38
- package/src/link/constants.ts +24 -8
- package/src/link/message.d.ts +587 -0
- package/src/link/protocol.ts +198 -204
- package/src/link/types.ts +2 -2
- package/src/types.ts +3 -1
package/src/link/protocol.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
2
|
import { CmdCodes } from './constants.js';
|
|
3
3
|
import { EmbMessage, EmbCommand } from './types.js';
|
|
4
|
+
import { emb } from './message.js';
|
|
4
5
|
|
|
5
6
|
const HEAD = 0x5;
|
|
6
7
|
const OPT = 0x0;
|
|
@@ -12,26 +13,41 @@ export class ProtocolError extends Error {
|
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
// Simple encryption from Java client:
|
|
16
|
-
export function encryptContent(raw: string): string {
|
|
17
|
-
if (!raw) return raw;
|
|
18
|
-
|
|
16
|
+
// Simple encryption from Java client: Base64
|
|
17
|
+
export function encryptContent(raw: string | Buffer): string {
|
|
18
|
+
if (!raw) return raw as string;
|
|
19
|
+
let buffer: Buffer;
|
|
20
|
+
if (Buffer.isBuffer(raw)) {
|
|
21
|
+
buffer = Buffer.from(raw); // Copy to avoid modifying original
|
|
22
|
+
} else {
|
|
23
|
+
buffer = Buffer.from(raw, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Restore bitwise NOT (~) to match provided Java code
|
|
27
|
+
// It seems sending requires encryption, while receiving might not (or depends on msg type)
|
|
19
28
|
for (let i = 0; i < buffer.length; i++) {
|
|
20
29
|
buffer[i] = ~buffer[i];
|
|
21
30
|
}
|
|
22
31
|
return buffer.toString('base64');
|
|
23
32
|
}
|
|
24
33
|
|
|
25
|
-
export function
|
|
26
|
-
if (!encoded) return
|
|
34
|
+
export function decryptContentBuffer(encoded: string): Buffer {
|
|
35
|
+
if (!encoded) return Buffer.alloc(0);
|
|
27
36
|
const buffer = Buffer.from(encoded, 'base64');
|
|
37
|
+
|
|
28
38
|
for (let i = 0; i < buffer.length; i++) {
|
|
29
39
|
buffer[i] = ~buffer[i];
|
|
30
40
|
}
|
|
41
|
+
|
|
42
|
+
return buffer;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function decryptContent(encoded: string): string {
|
|
46
|
+
const buffer = decryptContentBuffer(encoded);
|
|
31
47
|
return buffer.toString('utf-8');
|
|
32
48
|
}
|
|
33
49
|
|
|
34
|
-
export function encodePacket(cmdCode: number, body?: string): Buffer {
|
|
50
|
+
export function encodePacket(cmdCode: number, body?: string | Buffer): Buffer {
|
|
35
51
|
const header = Buffer.alloc(4);
|
|
36
52
|
header[0] = HEAD;
|
|
37
53
|
header[1] = cmdCode;
|
|
@@ -43,14 +59,21 @@ export function encodePacket(cmdCode: number, body?: string): Buffer {
|
|
|
43
59
|
}
|
|
44
60
|
|
|
45
61
|
header[3] = 1; // Body count = 1
|
|
46
|
-
|
|
62
|
+
|
|
63
|
+
let bodyBuffer: Buffer;
|
|
64
|
+
if (Buffer.isBuffer(body)) {
|
|
65
|
+
bodyBuffer = body;
|
|
66
|
+
} else {
|
|
67
|
+
bodyBuffer = Buffer.from(body, 'utf-8');
|
|
68
|
+
}
|
|
69
|
+
|
|
47
70
|
const lenBuffer = Buffer.alloc(4);
|
|
48
71
|
lenBuffer.writeUInt32BE(bodyBuffer.length, 0);
|
|
49
72
|
|
|
50
73
|
return Buffer.concat([header, lenBuffer, bodyBuffer]);
|
|
51
74
|
}
|
|
52
75
|
|
|
53
|
-
export function decodePacket(buffer: Buffer): { cmdCode: number; body?:
|
|
76
|
+
export function decodePacket(buffer: Buffer): { cmdCode: number; body?: Buffer; consumed: number } {
|
|
54
77
|
if (buffer.length < 4) {
|
|
55
78
|
throw new ProtocolError('Incomplete header');
|
|
56
79
|
}
|
|
@@ -75,221 +98,192 @@ export function decodePacket(buffer: Buffer): { cmdCode: number; body?: string;
|
|
|
75
98
|
if (buffer.length < 8 + bodyLen) {
|
|
76
99
|
throw new ProtocolError('Incomplete body');
|
|
77
100
|
}
|
|
78
|
-
const body = buffer.
|
|
101
|
+
const body = buffer.subarray(8, 8 + bodyLen);
|
|
79
102
|
return { cmdCode, body, consumed: 8 + bodyLen };
|
|
80
103
|
}
|
|
81
104
|
|
|
82
105
|
throw new ProtocolError(`Unsupported body count: ${bodyCount}`);
|
|
83
106
|
}
|
|
84
107
|
|
|
85
|
-
export function encodeMessage(msg: EmbMessage):
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
108
|
+
export function encodeMessage(msg: EmbMessage): Buffer {
|
|
109
|
+
// If protocol version is >= 3.0, server expects Protobuf encoded message in payload,
|
|
110
|
+
// NOT JSON string.
|
|
111
|
+
|
|
112
|
+
// Convert EmbMessage to Protobuf Message object
|
|
113
|
+
// Note: content field in Protobuf is bytes.
|
|
114
|
+
// We need to handle content encryption here:
|
|
115
|
+
// Raw Content -> ~ (Bitwise NOT) -> Buffer -> Protobuf content field
|
|
116
|
+
|
|
117
|
+
let contentBuffer: Buffer;
|
|
118
|
+
if (Buffer.isBuffer(msg.content)) {
|
|
119
|
+
contentBuffer = Buffer.from(msg.content);
|
|
120
|
+
} else {
|
|
121
|
+
contentBuffer = Buffer.from(msg.content, 'utf-8');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Apply encryption (~)
|
|
125
|
+
for (let i = 0; i < contentBuffer.length; i++) {
|
|
126
|
+
contentBuffer[i] = ~contentBuffer[i];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const messagePayload = {
|
|
130
|
+
msgId: msg.id,
|
|
131
|
+
type: msg.type,
|
|
132
|
+
sendTime: msg.sendTime,
|
|
133
|
+
content: contentBuffer,
|
|
134
|
+
from: {
|
|
135
|
+
fromId: msg.fromId,
|
|
136
|
+
fromType: msg.fromType,
|
|
137
|
+
fromName: msg.fromName,
|
|
138
|
+
fromCompany: msg.fromCompany,
|
|
139
|
+
// fromDevice: ... (filled by server session)
|
|
140
|
+
},
|
|
141
|
+
to: {
|
|
142
|
+
toId: msg.toId,
|
|
143
|
+
toType: msg.toType,
|
|
144
|
+
toName: msg.toName,
|
|
145
|
+
toCompany: msg.toCompany
|
|
146
|
+
},
|
|
147
|
+
options: {
|
|
148
|
+
isRead: msg.read
|
|
149
|
+
}
|
|
102
150
|
};
|
|
103
|
-
|
|
151
|
+
|
|
152
|
+
const message = emb.message.format.Message.create(messagePayload);
|
|
153
|
+
return Buffer.from(emb.message.format.Message.encode(message).finish());
|
|
104
154
|
}
|
|
105
155
|
|
|
106
|
-
export function decodeMessage(
|
|
156
|
+
export function decodeMessage(body: Buffer | string): EmbMessage {
|
|
157
|
+
// Try to decode as string first to check for JSON
|
|
158
|
+
let jsonStr = '';
|
|
159
|
+
if (Buffer.isBuffer(body)) {
|
|
160
|
+
jsonStr = body.toString('utf-8');
|
|
161
|
+
} else {
|
|
162
|
+
jsonStr = body;
|
|
163
|
+
}
|
|
164
|
+
|
|
107
165
|
// Try to fix malformed JSON if it has leading garbage
|
|
108
166
|
let cleanJsonStr = jsonStr;
|
|
109
167
|
|
|
110
168
|
// Find first '{'
|
|
111
169
|
const braceIndex = jsonStr.indexOf('{');
|
|
170
|
+
// Check if it looks like JSON
|
|
112
171
|
if (braceIndex >= 0) {
|
|
113
172
|
cleanJsonStr = jsonStr.substring(braceIndex);
|
|
114
|
-
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
173
|
+
|
|
174
|
+
// Find last '}' to handle trailing garbage if any
|
|
175
|
+
const lastBraceIndex = cleanJsonStr.lastIndexOf('}');
|
|
176
|
+
if (lastBraceIndex >= 0 && lastBraceIndex < cleanJsonStr.length - 1) {
|
|
177
|
+
cleanJsonStr = cleanJsonStr.substring(0, lastBraceIndex + 1);
|
|
178
|
+
}
|
|
118
179
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
180
|
+
try {
|
|
181
|
+
const json = JSON.parse(cleanJsonStr);
|
|
182
|
+
const sign = json.sign;
|
|
183
|
+
// Return Buffer if encrypted, otherwise string
|
|
184
|
+
const content = sign ? json.content : decryptContentBuffer(json.content);
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
id: json.msg_id,
|
|
188
|
+
type: json.msg_type,
|
|
189
|
+
content: content,
|
|
190
|
+
fromType: json.from_type,
|
|
191
|
+
fromId: json.from_id,
|
|
192
|
+
fromName: json.from_name,
|
|
193
|
+
fromCompany: json.from_company,
|
|
194
|
+
toType: json.to_type,
|
|
195
|
+
toId: json.to_id,
|
|
196
|
+
toName: json.to_name,
|
|
197
|
+
toCompany: json.to_company,
|
|
198
|
+
sendTime: json.send_time,
|
|
199
|
+
read: json.is_read === 1,
|
|
200
|
+
sign: sign
|
|
201
|
+
};
|
|
202
|
+
} catch (e) {
|
|
203
|
+
// Ignore JSON parse error and fall through to Protobuf check
|
|
204
|
+
}
|
|
123
205
|
}
|
|
124
206
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// BUT the logs show the body content starting with a UUID (maybe msgId?) and NOT a JSON object.
|
|
153
|
-
// Example: $c8b8dca6-a423-48e1-8c15-911eebc316b0c...
|
|
154
|
-
|
|
155
|
-
// Is it possible the server is sending V2 protocol or a different format?
|
|
156
|
-
// Or maybe the body is encrypted?
|
|
157
|
-
// `MessageProtocolV2` has `encrypt`/`decrypt`.
|
|
158
|
-
// But `decode` calls `JsonObject.parse(body)`.
|
|
159
|
-
|
|
160
|
-
// Let's look closely at the Java code again.
|
|
161
|
-
// TcpProtocolV2:
|
|
162
|
-
// byte[] body = ...
|
|
163
|
-
// cmd.setCmdBody(Strings.newStringUtf8(body));
|
|
164
|
-
|
|
165
|
-
// If the server sends `SEND_MSG` (0x3), the client receives it.
|
|
166
|
-
// The body SHOULD be a JSON string representing the message.
|
|
167
|
-
|
|
168
|
-
// Why does the log show `$UUID...`?
|
|
169
|
-
// Maybe the `TcpProtocolV2` logic for parsing the packet is slightly off?
|
|
170
|
-
// Packet structure:
|
|
171
|
-
// HEAD(1) + CMD(1) + OPT(1) + BODY_COUNT(1)
|
|
172
|
-
// If BODY_COUNT=1: + LENGTH(4) + BODY(LENGTH)
|
|
173
|
-
|
|
174
|
-
// My implementation:
|
|
175
|
-
// header[0] = HEAD;
|
|
176
|
-
// header[1] = cmdCode;
|
|
177
|
-
// header[3] = bodyCount;
|
|
178
|
-
// ...
|
|
179
|
-
// const bodyLen = buffer.readUInt32BE(4);
|
|
180
|
-
|
|
181
|
-
// Let's verify if I am reading the length correctly.
|
|
182
|
-
// If I read length wrong, I might be reading into the next packet or reading garbage.
|
|
183
|
-
|
|
184
|
-
// In the logs:
|
|
185
|
-
// Raw body: $c8b8dca6-a423-48e1-8c15-911eebc316b0c...
|
|
186
|
-
// This looks like a UUID.
|
|
187
|
-
// Maybe the body IS just a UUID? But SEND_MSG expects a full message.
|
|
188
|
-
|
|
189
|
-
// Is it possible that `0x3` (SEND_MSG) from server to client has a different format?
|
|
190
|
-
// `SendMessage` class:
|
|
191
|
-
// public byte getCmdCode() { return CmdCodes.SEND_MSG; }
|
|
192
|
-
|
|
193
|
-
// Wait, `SendMessage` is typically Client -> Server.
|
|
194
|
-
// Server -> Client message push is also `SEND_MSG`?
|
|
195
|
-
// Java client `TcpClient` handles received messages.
|
|
196
|
-
// It decodes the command.
|
|
197
|
-
|
|
198
|
-
// If the server is sending `SEND_MSG`, it should contain the message.
|
|
199
|
-
// The logs show what looks like a message ID (UUID).
|
|
200
|
-
|
|
201
|
-
// Maybe the packet has multiple bodies?
|
|
202
|
-
// My code throws "Unsupported body count" if != 0 or 1.
|
|
203
|
-
// It didn't throw that. So bodyCount is 1.
|
|
204
|
-
|
|
205
|
-
// Maybe the length includes something else?
|
|
206
|
-
// `TcpProtocolV2`: `Bytes.bytes4ToInt(bytesLen)` (Big Endian usually).
|
|
207
|
-
|
|
208
|
-
// Let's try to parse the body as if it might be encrypted or formatted differently?
|
|
209
|
-
// Or maybe I should log the hex of the body to see what's going on.
|
|
210
|
-
|
|
211
|
-
// If I look at the "Raw body" output again:
|
|
212
|
-
// $c8b8dca6-a423-48e1-8c15-911eebc316b0c...
|
|
213
|
-
// It starts with `$`.
|
|
214
|
-
// A UUID is 36 chars.
|
|
215
|
-
// The log shows more chars after it.
|
|
216
|
-
// It looks like `UUID` + `Content`?
|
|
217
|
-
|
|
218
|
-
// Wait! In Java `MessageProtocolV2`:
|
|
219
|
-
// encode: writes JSON.
|
|
220
|
-
// decode: parses JSON.
|
|
221
|
-
|
|
222
|
-
// Is it possible the server is using a custom serialization that is NOT JSON?
|
|
223
|
-
// Or maybe I am connecting to a server version that uses a different protocol?
|
|
224
|
-
|
|
225
|
-
// Let's relax the JSON requirement and return a raw message if JSON fails, just to see what happens.
|
|
226
|
-
|
|
227
|
-
try {
|
|
228
|
-
const json = JSON.parse(cleanJsonStr);
|
|
229
|
-
const sign = json.sign;
|
|
230
|
-
const content = sign ? json.content : decryptContent(json.content);
|
|
231
|
-
|
|
232
|
-
return {
|
|
233
|
-
id: json.msg_id,
|
|
234
|
-
type: json.msg_type,
|
|
235
|
-
content: content,
|
|
236
|
-
fromType: json.from_type,
|
|
237
|
-
fromId: json.from_id,
|
|
238
|
-
fromName: json.from_name,
|
|
239
|
-
fromCompany: json.from_company,
|
|
240
|
-
toType: json.to_type,
|
|
241
|
-
toId: json.to_id,
|
|
242
|
-
toName: json.to_name,
|
|
243
|
-
toCompany: json.to_company,
|
|
244
|
-
sendTime: json.send_time,
|
|
245
|
-
read: json.is_read === 1,
|
|
246
|
-
sign: sign
|
|
247
|
-
};
|
|
248
|
-
} catch (e) {
|
|
249
|
-
// If parsing fails, use regex to extract key fields as a fallback
|
|
250
|
-
// The raw body seems to have format: $UUID...{JSON content}...binary?
|
|
251
|
-
// Or maybe: $UUID...JSON...
|
|
252
|
-
|
|
253
|
-
// Let's try to extract JSON-like structure using regex if standard parsing fails
|
|
254
|
-
// This is risky but might work for the mixed content we are seeing
|
|
255
|
-
const jsonMatch = jsonStr.match(/(\{.*\})/s);
|
|
256
|
-
if (jsonMatch) {
|
|
257
|
-
try {
|
|
258
|
-
const json = JSON.parse(jsonMatch[1]);
|
|
259
|
-
const sign = json.sign;
|
|
260
|
-
const content = sign ? json.content : decryptContent(json.content);
|
|
261
|
-
return {
|
|
262
|
-
id: json.msg_id,
|
|
263
|
-
type: json.msg_type,
|
|
264
|
-
content: content,
|
|
265
|
-
fromType: json.from_type,
|
|
266
|
-
fromId: json.from_id,
|
|
267
|
-
fromName: json.from_name,
|
|
268
|
-
fromCompany: json.from_company,
|
|
269
|
-
toType: json.to_type,
|
|
270
|
-
toId: json.to_id,
|
|
271
|
-
toName: json.to_name,
|
|
272
|
-
toCompany: json.to_company,
|
|
273
|
-
sendTime: json.send_time,
|
|
274
|
-
read: json.is_read === 1,
|
|
275
|
-
sign: sign
|
|
276
|
-
};
|
|
277
|
-
} catch (innerE) {
|
|
278
|
-
// ignore
|
|
279
|
-
}
|
|
207
|
+
// Fallback: Try Protobuf decoding
|
|
208
|
+
if (Buffer.isBuffer(body)) {
|
|
209
|
+
try {
|
|
210
|
+
// Check if body starts with $UUID... (Legacy/Custom framing?)
|
|
211
|
+
// If so, we might need to strip it.
|
|
212
|
+
// But let's try to decode the whole body first.
|
|
213
|
+
const message = emb.message.format.Message.decode(body);
|
|
214
|
+
return convertProtoMessage(message);
|
|
215
|
+
} catch (e) {
|
|
216
|
+
// Maybe it has a prefix?
|
|
217
|
+
// Log observed: $UUID...
|
|
218
|
+
// $ is 0x24.
|
|
219
|
+
if (body[0] === 0x24) { // '$'
|
|
220
|
+
// Try to find where the actual protobuf starts.
|
|
221
|
+
// A UUID is 36 chars.
|
|
222
|
+
// $ + 36 chars = 37 bytes.
|
|
223
|
+
// Maybe the protobuf starts after that?
|
|
224
|
+
if (body.length > 37) {
|
|
225
|
+
try {
|
|
226
|
+
const protoBody = body.subarray(37);
|
|
227
|
+
const message = emb.message.format.Message.decode(protoBody);
|
|
228
|
+
return convertProtoMessage(message);
|
|
229
|
+
} catch (innerE) {
|
|
230
|
+
// Ignore
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
280
234
|
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Fallback: return raw content for debugging
|
|
238
|
+
// Try to extract ID if it looks like a UUID (e.g. $UUID...)
|
|
239
|
+
let id = 'unknown';
|
|
240
|
+
const uuidMatch = jsonStr.match(/\$([0-9a-fA-F-]{36})/);
|
|
241
|
+
if (uuidMatch) {
|
|
242
|
+
id = uuidMatch[1];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
id: id,
|
|
247
|
+
type: 1, // TEXT
|
|
248
|
+
content: jsonStr, // Return original string
|
|
249
|
+
fromType: 1,
|
|
250
|
+
fromId: 'unknown',
|
|
251
|
+
toType: 1,
|
|
252
|
+
toId: 'unknown',
|
|
253
|
+
sendTime: Date.now(),
|
|
254
|
+
read: false
|
|
255
|
+
};
|
|
256
|
+
}
|
|
281
257
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
258
|
+
function convertProtoMessage(protoMsg: any): EmbMessage {
|
|
259
|
+
let content: string | Buffer = '';
|
|
260
|
+
if (protoMsg.content && protoMsg.content.length > 0) {
|
|
261
|
+
// Protobuf content is bytes.
|
|
262
|
+
// Keep it as Buffer
|
|
263
|
+
content = Buffer.from(protoMsg.content);
|
|
264
|
+
|
|
265
|
+
// Decrypt content using bitwise NOT (~)
|
|
266
|
+
// This matches the encryption logic provided: raw -> ~ -> Base64 (for JSON)
|
|
267
|
+
// For Protobuf bytes, we just reverse the ~ operation.
|
|
268
|
+
for (let i = 0; i < content.length; i++) {
|
|
269
|
+
content[i] = ~content[i];
|
|
270
|
+
}
|
|
294
271
|
}
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
id: protoMsg.msgId || 'unknown',
|
|
275
|
+
type: protoMsg.type || 1,
|
|
276
|
+
content: content,
|
|
277
|
+
fromType: protoMsg.from?.fromType || 1,
|
|
278
|
+
fromId: protoMsg.from?.fromId || 'unknown',
|
|
279
|
+
fromName: protoMsg.from?.fromName || undefined,
|
|
280
|
+
fromCompany: protoMsg.from?.fromCompany || undefined,
|
|
281
|
+
toType: protoMsg.to?.toType || 1,
|
|
282
|
+
toId: protoMsg.to?.toId || 'unknown',
|
|
283
|
+
toName: protoMsg.to?.toName || undefined,
|
|
284
|
+
toCompany: protoMsg.to?.toCompany || undefined,
|
|
285
|
+
sendTime: typeof protoMsg.sendTime === 'number' ? protoMsg.sendTime : (protoMsg.sendTime?.toNumber() || Date.now()),
|
|
286
|
+
read: protoMsg.options?.isRead || false,
|
|
287
|
+
// Add other fields if needed
|
|
288
|
+
};
|
|
295
289
|
}
|
package/src/link/types.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { MsgType, ParticipantType } from './constants.js';
|
|
|
3
3
|
export interface EmbMessage {
|
|
4
4
|
id: string;
|
|
5
5
|
type: MsgType;
|
|
6
|
-
content: string; // Encrypted or plain? Java code suggests encryption.
|
|
6
|
+
content: string | Buffer; // Encrypted or plain? Java code suggests encryption.
|
|
7
7
|
fromType: ParticipantType;
|
|
8
8
|
fromId: string;
|
|
9
9
|
fromName?: string;
|
|
@@ -14,7 +14,7 @@ export interface EmbMessage {
|
|
|
14
14
|
toCompany?: string;
|
|
15
15
|
sendTime: number;
|
|
16
16
|
read: boolean;
|
|
17
|
-
sign?: string;
|
|
17
|
+
sign?: boolean | string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface ClientVerifyInfo {
|
package/src/types.ts
CHANGED
|
@@ -3,8 +3,10 @@ import { ClientVerifyInfo } from "./link/types.js";
|
|
|
3
3
|
|
|
4
4
|
export interface LinkConfig {
|
|
5
5
|
host: string;
|
|
6
|
-
port: number;
|
|
6
|
+
// port: number; // merged into host
|
|
7
7
|
accessToken: string;
|
|
8
|
+
refreshToken?: string;
|
|
9
|
+
ssoUrl?: string;
|
|
8
10
|
verifyInfo?: Partial<ClientVerifyInfo>;
|
|
9
11
|
heartbeatIntervalMs?: number;
|
|
10
12
|
protocol?: "tcp" | "ws"; // Default tcp
|