simplex-chat 0.1.1 → 0.2.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/dist/client.d.ts +8 -7
- package/dist/client.js +22 -15
- package/dist/client.js.map +1 -1
- package/dist/command.d.ts +152 -15
- package/dist/command.js +81 -13
- package/dist/command.js.map +1 -1
- package/dist/queue.d.ts +1 -1
- package/dist/response.d.ts +117 -29
- package/dist/response.js.map +1 -1
- package/dist/transport.d.ts +1 -1
- package/package.json +3 -3
- package/dist/browser_globals.d.ts +0 -8
- package/dist/browser_globals.js +0 -4
- package/dist/browser_globals.js.map +0 -1
- package/dist/index.mjs +0 -585
package/dist/index.mjs
DELETED
|
@@ -1,585 +0,0 @@
|
|
|
1
|
-
class Sem {
|
|
2
|
-
constructor(permits) {
|
|
3
|
-
this.permits = permits;
|
|
4
|
-
this.promises = [];
|
|
5
|
-
}
|
|
6
|
-
signal() {
|
|
7
|
-
this.permits += 1;
|
|
8
|
-
if (this.promises.length > 0)
|
|
9
|
-
this.promises.pop()();
|
|
10
|
-
}
|
|
11
|
-
async wait() {
|
|
12
|
-
if (this.permits === 0 || this.promises.length > 0) {
|
|
13
|
-
await new Promise((r) => this.promises.unshift(r));
|
|
14
|
-
}
|
|
15
|
-
this.permits -= 1;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
const queueClosed = Symbol();
|
|
19
|
-
class ABQueueError extends Error {
|
|
20
|
-
}
|
|
21
|
-
class ABQueue {
|
|
22
|
-
constructor(maxSize) {
|
|
23
|
-
this.maxSize = maxSize;
|
|
24
|
-
this.queue = [];
|
|
25
|
-
this.enqClosed = false;
|
|
26
|
-
this.deqClosed = false;
|
|
27
|
-
this.enq = new Sem(0);
|
|
28
|
-
this.deq = new Sem(maxSize);
|
|
29
|
-
}
|
|
30
|
-
[Symbol.asyncIterator]() {
|
|
31
|
-
return this;
|
|
32
|
-
}
|
|
33
|
-
enqueue(x) {
|
|
34
|
-
return this._enqueue(x);
|
|
35
|
-
}
|
|
36
|
-
async _enqueue(x) {
|
|
37
|
-
if (this.enqClosed)
|
|
38
|
-
throw new ABQueueError("enqueue: queue closed");
|
|
39
|
-
await this.deq.wait();
|
|
40
|
-
this.queue.push(x);
|
|
41
|
-
this.enq.signal();
|
|
42
|
-
}
|
|
43
|
-
async dequeue() {
|
|
44
|
-
if (this.deqClosed)
|
|
45
|
-
throw new ABQueueError("dequeue: queue closed");
|
|
46
|
-
this.deq.signal();
|
|
47
|
-
await this.enq.wait();
|
|
48
|
-
const x = this.queue.shift();
|
|
49
|
-
if (x === queueClosed) {
|
|
50
|
-
this.deqClosed = true;
|
|
51
|
-
throw new ABQueueError("dequeue: queue closed");
|
|
52
|
-
}
|
|
53
|
-
return x;
|
|
54
|
-
}
|
|
55
|
-
async close() {
|
|
56
|
-
await this._enqueue(queueClosed);
|
|
57
|
-
this.enqClosed = true;
|
|
58
|
-
}
|
|
59
|
-
async next() {
|
|
60
|
-
if (this.deqClosed)
|
|
61
|
-
return { done: true };
|
|
62
|
-
try {
|
|
63
|
-
return { value: await this.dequeue() };
|
|
64
|
-
}
|
|
65
|
-
catch (e) {
|
|
66
|
-
if (e instanceof ABQueueError)
|
|
67
|
-
return { done: true };
|
|
68
|
-
throw e;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
class TransportError extends Error {
|
|
74
|
-
}
|
|
75
|
-
class Transport {
|
|
76
|
-
constructor(qSize) {
|
|
77
|
-
this.queue = new ABQueue(qSize);
|
|
78
|
-
}
|
|
79
|
-
[Symbol.asyncIterator]() {
|
|
80
|
-
return this;
|
|
81
|
-
}
|
|
82
|
-
async read() {
|
|
83
|
-
return this.queue.dequeue();
|
|
84
|
-
}
|
|
85
|
-
async next() {
|
|
86
|
-
return this.queue.next();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
class WSTransport extends Transport {
|
|
90
|
-
constructor(sock, timeout, qSize) {
|
|
91
|
-
super(qSize);
|
|
92
|
-
this.sock = sock;
|
|
93
|
-
this.timeout = timeout;
|
|
94
|
-
}
|
|
95
|
-
static connect(url, timeout, qSize) {
|
|
96
|
-
const sock = new WebSocket(url);
|
|
97
|
-
const t = new WSTransport(sock, timeout, qSize);
|
|
98
|
-
sock.onmessage = async ({ data }) => await t.queue.enqueue(data);
|
|
99
|
-
sock.onclose = async () => await t.queue.close();
|
|
100
|
-
sock.onerror = () => sock.close();
|
|
101
|
-
return withTimeout(timeout, () => new Promise((r) => (sock.onopen = () => r(t))));
|
|
102
|
-
}
|
|
103
|
-
close() {
|
|
104
|
-
this.sock.close();
|
|
105
|
-
return Promise.resolve();
|
|
106
|
-
}
|
|
107
|
-
write(data) {
|
|
108
|
-
const buffered = this.sock.bufferedAmount;
|
|
109
|
-
this.sock.send(data);
|
|
110
|
-
return withTimeout(this.timeout, async () => {
|
|
111
|
-
while (this.sock.bufferedAmount > buffered)
|
|
112
|
-
await delay();
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
async readBinary(size) {
|
|
116
|
-
const data = await this.read();
|
|
117
|
-
if (typeof data == "string")
|
|
118
|
-
throw new TransportError("invalid text block: expected binary");
|
|
119
|
-
if (data.byteLength !== size)
|
|
120
|
-
throw new TransportError("invalid block size");
|
|
121
|
-
return data;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function withTimeout(ms, action) {
|
|
125
|
-
return Promise.race([
|
|
126
|
-
action(),
|
|
127
|
-
(async () => {
|
|
128
|
-
await delay(ms);
|
|
129
|
-
throw new Error("timeout");
|
|
130
|
-
})(),
|
|
131
|
-
]);
|
|
132
|
-
}
|
|
133
|
-
class ChatResponseError extends Error {
|
|
134
|
-
constructor(message, data) {
|
|
135
|
-
super(message);
|
|
136
|
-
this.message = message;
|
|
137
|
-
this.data = data;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
class ChatTransport extends Transport {
|
|
141
|
-
constructor(ws, timeout, qSize) {
|
|
142
|
-
super(qSize);
|
|
143
|
-
this.ws = ws;
|
|
144
|
-
this.timeout = timeout;
|
|
145
|
-
}
|
|
146
|
-
static async connect(srv, timeout, qSize) {
|
|
147
|
-
const ws = await WSTransport.connect(`ws://${srv.host}:${srv.port || "80"}`, timeout, qSize);
|
|
148
|
-
const c = new ChatTransport(ws, timeout, qSize);
|
|
149
|
-
processWSQueue(c, ws).then(noop, noop);
|
|
150
|
-
return c;
|
|
151
|
-
}
|
|
152
|
-
async close() {
|
|
153
|
-
await this.ws.close();
|
|
154
|
-
}
|
|
155
|
-
async write(cmd) {
|
|
156
|
-
return this.ws.write(JSON.stringify(cmd));
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
function noop() { }
|
|
160
|
-
async function processWSQueue(c, ws) {
|
|
161
|
-
var _a;
|
|
162
|
-
for await (const data of ws) {
|
|
163
|
-
const str = data instanceof Promise ? await data : data;
|
|
164
|
-
if (typeof str != "string") {
|
|
165
|
-
await c.queue.enqueue(new ChatResponseError("websocket data is not a string"));
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
let resp;
|
|
169
|
-
try {
|
|
170
|
-
const data = JSON.parse(str);
|
|
171
|
-
if (typeof ((_a = data === null || data === void 0 ? void 0 : data.resp) === null || _a === void 0 ? void 0 : _a.type) == "string") {
|
|
172
|
-
resp = data;
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
resp = new ChatResponseError("invalid response format", str);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
resp = new ChatResponseError(err.message, str);
|
|
180
|
-
}
|
|
181
|
-
await c.queue.enqueue(resp);
|
|
182
|
-
}
|
|
183
|
-
await c.queue.close();
|
|
184
|
-
}
|
|
185
|
-
function delay(ms) {
|
|
186
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
var ChatType;
|
|
190
|
-
(function (ChatType) {
|
|
191
|
-
ChatType["CTDirect"] = "@";
|
|
192
|
-
ChatType["CTGroup"] = "#";
|
|
193
|
-
ChatType["CTContactRequest"] = "<@";
|
|
194
|
-
})(ChatType || (ChatType = {}));
|
|
195
|
-
var DeleteMode;
|
|
196
|
-
(function (DeleteMode) {
|
|
197
|
-
DeleteMode["DMBroadcast"] = "broadcast";
|
|
198
|
-
DeleteMode["DMInternal"] = "internal";
|
|
199
|
-
})(DeleteMode || (DeleteMode = {}));
|
|
200
|
-
function cmdString(cmd) {
|
|
201
|
-
switch (cmd.type) {
|
|
202
|
-
case "showActiveUser":
|
|
203
|
-
return "/u";
|
|
204
|
-
case "createActiveUser":
|
|
205
|
-
return `/u ${JSON.stringify(cmd.profile)}`;
|
|
206
|
-
case "startChat":
|
|
207
|
-
return "/_start";
|
|
208
|
-
case "setFilesFolder":
|
|
209
|
-
return `/_files_folder ${cmd.filePath}`;
|
|
210
|
-
case "apiGetChats":
|
|
211
|
-
return "/_get chats";
|
|
212
|
-
case "apiGetChat":
|
|
213
|
-
return `/_get chat ${cmd.chatType}${cmd.chatId}${paginationStr(cmd.pagination)}`;
|
|
214
|
-
case "apiSendMessage":
|
|
215
|
-
return `/_send ${cmd.chatType}${cmd.chatId}${tagged("file", cmd.filePath)}${tagged("quoted", cmd.quotedItem)} json ${JSON.stringify(cmd.msgContent)}`;
|
|
216
|
-
case "apiUpdateChatItem":
|
|
217
|
-
return `/_update item ${cmd.chatType}${cmd.chatId} ${cmd.chatItemId} json ${JSON.stringify(cmd.msgContent)}`;
|
|
218
|
-
case "apiDeleteChatItem":
|
|
219
|
-
return `/_delete item ${cmd.chatType}${cmd.chatId} ${cmd.chatItemId} ${cmd.deleteMode}`;
|
|
220
|
-
case "apiChatRead":
|
|
221
|
-
return `/_read chat ${cmd.chatType}${cmd.chatId} from=${cmd.fromItem} to=${cmd.toItem}`;
|
|
222
|
-
case "apiDeleteChat":
|
|
223
|
-
return `/_delete ${cmd.chatType}${cmd.chatId}`;
|
|
224
|
-
case "apiAcceptContact":
|
|
225
|
-
return `/_accept ${cmd.contactReqId}`;
|
|
226
|
-
case "apiRejectContact":
|
|
227
|
-
return `/_reject ${cmd.contactReqId}`;
|
|
228
|
-
case "apiUpdateProfile":
|
|
229
|
-
return `/_profile ${JSON.stringify(cmd.profile)}`;
|
|
230
|
-
case "apiParseMarkdown":
|
|
231
|
-
return `/_parse ${cmd.text}`;
|
|
232
|
-
case "getUserSMPServers":
|
|
233
|
-
return "/smp_servers";
|
|
234
|
-
case "setUserSMPServers":
|
|
235
|
-
return `/smp_servers ${cmd.servers.join(",") || "default"}`;
|
|
236
|
-
case "addContact":
|
|
237
|
-
return "/connect";
|
|
238
|
-
case "connect":
|
|
239
|
-
return `/connect ${cmd.connReq}`;
|
|
240
|
-
case "connectSimplex":
|
|
241
|
-
return "/simplex";
|
|
242
|
-
case "createMyAddress":
|
|
243
|
-
return "/address";
|
|
244
|
-
case "deleteMyAddress":
|
|
245
|
-
return "/delete_address";
|
|
246
|
-
case "showMyAddress":
|
|
247
|
-
return "/show_address";
|
|
248
|
-
case "addressAutoAccept":
|
|
249
|
-
return `/auto_accept ${cmd.enable ? "on" : "off"}`;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
function paginationStr(cp) {
|
|
253
|
-
const base = "after" in cp ? ` after=${cp.after}` : "before" in cp ? ` before=${cp.before}` : "";
|
|
254
|
-
return base + ` count=${cp.count}`;
|
|
255
|
-
}
|
|
256
|
-
function tagged(tag, x) {
|
|
257
|
-
return x ? ` ${tag}=${x}` : "";
|
|
258
|
-
}
|
|
259
|
-
var CIDeleteMode;
|
|
260
|
-
(function (CIDeleteMode) {
|
|
261
|
-
CIDeleteMode["Broadcast"] = "broadcast";
|
|
262
|
-
CIDeleteMode["Internal"] = "internal";
|
|
263
|
-
})(CIDeleteMode || (CIDeleteMode = {}));
|
|
264
|
-
|
|
265
|
-
class ChatCommandError extends Error {
|
|
266
|
-
constructor(message, response) {
|
|
267
|
-
super(message);
|
|
268
|
-
this.message = message;
|
|
269
|
-
this.response = response;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
class ChatClient {
|
|
273
|
-
constructor(server, config, msgQ, client, transport) {
|
|
274
|
-
this.server = server;
|
|
275
|
-
this.config = config;
|
|
276
|
-
this.msgQ = msgQ;
|
|
277
|
-
this.client = client;
|
|
278
|
-
this.transport = transport;
|
|
279
|
-
this._connected = true;
|
|
280
|
-
this.clientCorrId = 0;
|
|
281
|
-
this.sentCommands = new Map();
|
|
282
|
-
}
|
|
283
|
-
static async create(server, cfg, msgQ) {
|
|
284
|
-
const transport = await ChatTransport.connect(server, cfg.tcpTimeout, cfg.qSize);
|
|
285
|
-
const client = runClient().then(noop, noop);
|
|
286
|
-
const c = new ChatClient(server, cfg, msgQ, client, transport);
|
|
287
|
-
return c;
|
|
288
|
-
async function runClient() {
|
|
289
|
-
for await (const t of transport) {
|
|
290
|
-
const apiResp = t instanceof Promise ? await t : t;
|
|
291
|
-
if (apiResp instanceof ChatResponseError) {
|
|
292
|
-
console.log("chat response error: ", apiResp);
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
const { corrId, resp } = apiResp;
|
|
296
|
-
if (corrId) {
|
|
297
|
-
const req = c.sentCommands.get(corrId);
|
|
298
|
-
if (req) {
|
|
299
|
-
c.sentCommands.delete(corrId);
|
|
300
|
-
if (resp.type == "chatCmdError") {
|
|
301
|
-
req.reject(resp);
|
|
302
|
-
}
|
|
303
|
-
else {
|
|
304
|
-
req.resolve(resp);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
// TODO send error to errQ?
|
|
309
|
-
console.log("no command sent for chat response: ", apiResp);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
await msgQ.enqueue(resp);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
c._connected = false;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
sendChatCommand(command) {
|
|
321
|
-
const corrId = ++this.clientCorrId;
|
|
322
|
-
const t = { corrId, cmd: cmdString(command) };
|
|
323
|
-
this.transport.write(t).then(noop, noop);
|
|
324
|
-
return new Promise((resolve, reject) => this.sentCommands.set(corrId, { resolve, reject }));
|
|
325
|
-
}
|
|
326
|
-
async disconnect() {
|
|
327
|
-
await this.transport.close();
|
|
328
|
-
await this.client;
|
|
329
|
-
}
|
|
330
|
-
async getActiveUser() {
|
|
331
|
-
const r = await this.sendChatCommand({ type: "showActiveUser" });
|
|
332
|
-
switch (r.type) {
|
|
333
|
-
case "activeUser":
|
|
334
|
-
return r.user;
|
|
335
|
-
case "chatCmdError":
|
|
336
|
-
if (r.chatError.type == "error" && r.chatError.errorType.type == "noActiveUser")
|
|
337
|
-
return undefined;
|
|
338
|
-
throw new ChatCommandError("unexpected response error", r);
|
|
339
|
-
default:
|
|
340
|
-
throw new ChatCommandError("unexpected response", r);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
async createActiveUser(profile) {
|
|
344
|
-
const r = await this.sendChatCommand({ type: "createActiveUser", profile });
|
|
345
|
-
if (r.type == "activeUser")
|
|
346
|
-
return r.user;
|
|
347
|
-
throw new ChatCommandError("unexpected response", r);
|
|
348
|
-
}
|
|
349
|
-
async apiStartChat() {
|
|
350
|
-
const r = await this.sendChatCommand({ type: "startChat" });
|
|
351
|
-
if (r.type != "chatStarted")
|
|
352
|
-
throw new ChatCommandError("unexpected response", r);
|
|
353
|
-
}
|
|
354
|
-
// func apiGetChats() throws -> [Chat] {
|
|
355
|
-
// let r = chatSendCmdSync(.apiGetChats)
|
|
356
|
-
// if case let .apiChats(chats) = r { return chats.map { Chat.init($0) } }
|
|
357
|
-
// throw r
|
|
358
|
-
// }
|
|
359
|
-
// func apiGetChat(type: ChatType, id: Int64) throws -> Chat {
|
|
360
|
-
// let r = chatSendCmdSync(.apiGetChat(type: type, id: id))
|
|
361
|
-
// if case let .apiChat(chat) = r { return Chat.init(chat) }
|
|
362
|
-
// throw r
|
|
363
|
-
// }
|
|
364
|
-
// async sendMessage(type: ChatType, id: number, msg: C.MsgContent)
|
|
365
|
-
// func apiSendMessage(type: ChatType, id: Int64, quotedItemId: Int64?, msg: MsgContent) async throws -> ChatItem {
|
|
366
|
-
// let chatModel = ChatModel.shared
|
|
367
|
-
// let cmd: ChatCommand
|
|
368
|
-
// if let itemId = quotedItemId {
|
|
369
|
-
// cmd = .apiSendMessageQuote(type: type, id: id, itemId: itemId, msg: msg)
|
|
370
|
-
// } else {
|
|
371
|
-
// cmd = .apiSendMessage(type: type, id: id, msg: msg)
|
|
372
|
-
// }
|
|
373
|
-
// let r: ChatResponse
|
|
374
|
-
// if type == .direct {
|
|
375
|
-
// var cItem: ChatItem!
|
|
376
|
-
// let endTask = beginBGTask({ if cItem != nil { chatModel.messageDelivery.removeValue(forKey: cItem.id) } })
|
|
377
|
-
// r = await chatSendCmd(cmd, bgTask: false)
|
|
378
|
-
// if case let .newChatItem(aChatItem) = r {
|
|
379
|
-
// cItem = aChatItem.chatItem
|
|
380
|
-
// chatModel.messageDelivery[cItem.id] = endTask
|
|
381
|
-
// return cItem
|
|
382
|
-
// }
|
|
383
|
-
// endTask()
|
|
384
|
-
// } else {
|
|
385
|
-
// r = await chatSendCmd(cmd, bgDelay: msgDelay)
|
|
386
|
-
// if case let .newChatItem(aChatItem) = r {
|
|
387
|
-
// return aChatItem.chatItem
|
|
388
|
-
// }
|
|
389
|
-
// }
|
|
390
|
-
// throw r
|
|
391
|
-
// }
|
|
392
|
-
// func apiUpdateChatItem(type: ChatType, id: Int64, itemId: Int64, msg: MsgContent) async throws -> ChatItem {
|
|
393
|
-
// let r = await chatSendCmd(.apiUpdateChatItem(type: type, id: id, itemId: itemId, msg: msg), bgDelay: msgDelay)
|
|
394
|
-
// if case let .chatItemUpdated(aChatItem) = r { return aChatItem.chatItem }
|
|
395
|
-
// throw r
|
|
396
|
-
// }
|
|
397
|
-
// func apiDeleteChatItem(type: ChatType, id: Int64, itemId: Int64, mode: CIDeleteMode) async throws -> ChatItem {
|
|
398
|
-
// let r = await chatSendCmd(.apiDeleteChatItem(type: type, id: id, itemId: itemId, mode: mode), bgDelay: msgDelay)
|
|
399
|
-
// if case let .chatItemDeleted(_, toChatItem) = r { return toChatItem.chatItem }
|
|
400
|
-
// throw r
|
|
401
|
-
// }
|
|
402
|
-
// func getUserSMPServers() throws -> [String] {
|
|
403
|
-
// let r = chatSendCmdSync(.getUserSMPServers)
|
|
404
|
-
// if case let .userSMPServers(smpServers) = r { return smpServers }
|
|
405
|
-
// throw r
|
|
406
|
-
// }
|
|
407
|
-
// func setUserSMPServers(smpServers: [String]) async throws {
|
|
408
|
-
// let r = await chatSendCmd(.setUserSMPServers(smpServers: smpServers))
|
|
409
|
-
// if case .cmdOk = r { return }
|
|
410
|
-
// throw r
|
|
411
|
-
// }
|
|
412
|
-
// func apiAddContact() throws -> String {
|
|
413
|
-
// let r = chatSendCmdSync(.addContact, bgTask: false)
|
|
414
|
-
// if case let .invitation(connReqInvitation) = r { return connReqInvitation }
|
|
415
|
-
// throw r
|
|
416
|
-
// }
|
|
417
|
-
// func apiConnect(connReq: String) async throws -> Bool {
|
|
418
|
-
// let r = await chatSendCmd(.connect(connReq: connReq))
|
|
419
|
-
// let am = AlertManager.shared
|
|
420
|
-
// switch r {
|
|
421
|
-
// case .sentConfirmation: return true
|
|
422
|
-
// case .sentInvitation: return true
|
|
423
|
-
// case let .contactAlreadyExists(contact):
|
|
424
|
-
// am.showAlertMsg(
|
|
425
|
-
// title: "Contact already exists",
|
|
426
|
-
// message: "You are already connected to \(contact.displayName) via this link."
|
|
427
|
-
// )
|
|
428
|
-
// return false
|
|
429
|
-
// case .chatCmdError(.error(.invalidConnReq)):
|
|
430
|
-
// am.showAlertMsg(
|
|
431
|
-
// title: "Invalid connection link",
|
|
432
|
-
// message: "Please check that you used the correct link or ask your contact to send you another one."
|
|
433
|
-
// )
|
|
434
|
-
// return false
|
|
435
|
-
// case .chatCmdError(.errorAgent(.BROKER(.TIMEOUT))):
|
|
436
|
-
// am.showAlertMsg(
|
|
437
|
-
// title: "Connection timeout",
|
|
438
|
-
// message: "Please check your network connection and try again."
|
|
439
|
-
// )
|
|
440
|
-
// return false
|
|
441
|
-
// case .chatCmdError(.errorAgent(.BROKER(.NETWORK))):
|
|
442
|
-
// am.showAlertMsg(
|
|
443
|
-
// title: "Connection error",
|
|
444
|
-
// message: "Please check your network connection and try again."
|
|
445
|
-
// )
|
|
446
|
-
// return false
|
|
447
|
-
// default: throw r
|
|
448
|
-
// }
|
|
449
|
-
// }
|
|
450
|
-
// func apiDeleteChat(type: ChatType, id: Int64) async throws {
|
|
451
|
-
// let r = await chatSendCmd(.apiDeleteChat(type: type, id: id), bgTask: false)
|
|
452
|
-
// if case .contactDeleted = r { return }
|
|
453
|
-
// throw r
|
|
454
|
-
// }
|
|
455
|
-
// func apiUpdateProfile(profile: Profile) async throws -> Profile? {
|
|
456
|
-
// let r = await chatSendCmd(.apiUpdateProfile(profile: profile))
|
|
457
|
-
// switch r {
|
|
458
|
-
// case .userProfileNoChange: return nil
|
|
459
|
-
// case let .userProfileUpdated(_, toProfile): return toProfile
|
|
460
|
-
// default: throw r
|
|
461
|
-
// }
|
|
462
|
-
// }
|
|
463
|
-
// func apiParseMarkdown(text: String) throws -> [FormattedText]? {
|
|
464
|
-
// let r = chatSendCmdSync(.apiParseMarkdown(text: text))
|
|
465
|
-
// if case let .apiParsedMarkdown(formattedText) = r { return formattedText }
|
|
466
|
-
// throw r
|
|
467
|
-
// }
|
|
468
|
-
// func apiCreateUserAddress() async throws -> String {
|
|
469
|
-
// let r = await chatSendCmd(.createMyAddress)
|
|
470
|
-
// if case let .userContactLinkCreated(connReq) = r { return connReq }
|
|
471
|
-
// throw r
|
|
472
|
-
// }
|
|
473
|
-
// func apiDeleteUserAddress() async throws {
|
|
474
|
-
// let r = await chatSendCmd(.deleteMyAddress)
|
|
475
|
-
// if case .userContactLinkDeleted = r { return }
|
|
476
|
-
// throw r
|
|
477
|
-
// }
|
|
478
|
-
// func apiGetUserAddress() async throws -> String? {
|
|
479
|
-
// let r = await chatSendCmd(.showMyAddress)
|
|
480
|
-
// switch r {
|
|
481
|
-
// case let .userContactLink(connReq):
|
|
482
|
-
// return connReq
|
|
483
|
-
// case .chatCmdError(chatError: .errorStore(storeError: .userContactLinkNotFound)):
|
|
484
|
-
// return nil
|
|
485
|
-
// default: throw r
|
|
486
|
-
// }
|
|
487
|
-
// }
|
|
488
|
-
// func apiAcceptContactRequest(contactReqId: Int64) async throws -> Contact {
|
|
489
|
-
// let r = await chatSendCmd(.apiAcceptContact(contactReqId: contactReqId))
|
|
490
|
-
// if case let .acceptingContactRequest(contact) = r { return contact }
|
|
491
|
-
// throw r
|
|
492
|
-
// }
|
|
493
|
-
// func apiRejectContactRequest(contactReqId: Int64) async throws {
|
|
494
|
-
// let r = await chatSendCmd(.apiRejectContact(contactReqId: contactReqId))
|
|
495
|
-
// if case .contactRequestRejected = r { return }
|
|
496
|
-
// throw r
|
|
497
|
-
// }
|
|
498
|
-
// func apiChatRead(type: ChatType, id: Int64, itemRange: (Int64, Int64)) async throws {
|
|
499
|
-
// let r = await chatSendCmd(.apiChatRead(type: type, id: id, itemRange: itemRange))
|
|
500
|
-
// if case .cmdOk = r { return }
|
|
501
|
-
// throw r
|
|
502
|
-
// }
|
|
503
|
-
// func acceptContactRequest(_ contactRequest: UserContactRequest) async {
|
|
504
|
-
// do {
|
|
505
|
-
// let contact = try await apiAcceptContactRequest(contactReqId: contactRequest.apiId)
|
|
506
|
-
// let chat = Chat(chatInfo: ChatInfo.direct(contact: contact), chatItems: [])
|
|
507
|
-
// DispatchQueue.main.async { ChatModel.shared.replaceChat(contactRequest.id, chat) }
|
|
508
|
-
// } catch let error {
|
|
509
|
-
// logger.error("acceptContactRequest error: \(error.localizedDescription)")
|
|
510
|
-
// }
|
|
511
|
-
// }
|
|
512
|
-
// func rejectContactRequest(_ contactRequest: UserContactRequest) async {
|
|
513
|
-
// do {
|
|
514
|
-
// try await apiRejectContactRequest(contactReqId: contactRequest.apiId)
|
|
515
|
-
// DispatchQueue.main.async { ChatModel.shared.removeChat(contactRequest.id) }
|
|
516
|
-
// } catch let error {
|
|
517
|
-
// logger.error("rejectContactRequest: \(error.localizedDescription)")
|
|
518
|
-
// }
|
|
519
|
-
// }
|
|
520
|
-
// func markChatRead(_ chat: Chat) async {
|
|
521
|
-
// do {
|
|
522
|
-
// let minItemId = chat.chatStats.minUnreadItemId
|
|
523
|
-
// let itemRange = (minItemId, chat.chatItems.last?.id ?? minItemId)
|
|
524
|
-
// let cInfo = chat.chatInfo
|
|
525
|
-
// try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId, itemRange: itemRange)
|
|
526
|
-
// DispatchQueue.main.async { ChatModel.shared.markChatItemsRead(cInfo) }
|
|
527
|
-
// } catch {
|
|
528
|
-
// logger.error("markChatRead apiChatRead error: \(error.localizedDescription)")
|
|
529
|
-
// }
|
|
530
|
-
// }
|
|
531
|
-
// func markChatItemRead(_ cInfo: ChatInfo, _ cItem: ChatItem) async {
|
|
532
|
-
// do {
|
|
533
|
-
// try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId, itemRange: (cItem.id, cItem.id))
|
|
534
|
-
// DispatchQueue.main.async { ChatModel.shared.markChatItemRead(cInfo, cItem) }
|
|
535
|
-
// } catch {
|
|
536
|
-
// logger.error("markChatItemRead apiChatRead error: \(error.localizedDescription)")
|
|
537
|
-
// }
|
|
538
|
-
// }
|
|
539
|
-
// async createSMPQueue(rcvKey: SignKey, rcvPubKey: PublicKey<KeyType.Verify>): Promise<SMP.IDS> {
|
|
540
|
-
// const pubKeyStr = new Uint8Array(await C.encodePubKey(rcvPubKey))
|
|
541
|
-
// const resp = await this.sendSMPCommand(rcvKey, B.empty, SMP.cNEW(pubKeyStr))
|
|
542
|
-
// if (resp.cmd === "IDS") return resp
|
|
543
|
-
// throw new Error("unexpected response")
|
|
544
|
-
// }
|
|
545
|
-
// subscribeSMPQueue(rcvKey: SignKey, queueId: Uint8Array): Promise<void> {
|
|
546
|
-
// return this.msgSMPCommand(rcvKey, queueId, SMP.cSUB())
|
|
547
|
-
// }
|
|
548
|
-
// async secureSMPQueue(rcvKey: SignKey, queueId: Uint8Array, sndPubKey: PublicKey<KeyType.Verify>): Promise<void> {
|
|
549
|
-
// const pubKeyStr = new Uint8Array(await C.encodePubKey(sndPubKey))
|
|
550
|
-
// return this.okSMPCommand(rcvKey, queueId, SMP.cKEY(pubKeyStr))
|
|
551
|
-
// }
|
|
552
|
-
// async sendSMPMessage(sndKey: SignKey | undefined, queueId: Uint8Array, msg: Uint8Array): Promise<void> {
|
|
553
|
-
// const resp = await this.sendSMPCommand(sndKey, queueId, SMP.cSEND(msg))
|
|
554
|
-
// if (resp.cmd !== "OK") throw new Error("unexpected response")
|
|
555
|
-
// }
|
|
556
|
-
// ackSMPMessage(rcvKey: SignKey, queueId: Uint8Array): Promise<void> {
|
|
557
|
-
// return this.msgSMPCommand(rcvKey, queueId, SMP.cACK())
|
|
558
|
-
// }
|
|
559
|
-
// suspendSMPQueue(rcvKey: SignKey, queueId: Uint8Array): Promise<void> {
|
|
560
|
-
// return this.okSMPCommand(rcvKey, queueId, SMP.cOFF())
|
|
561
|
-
// }
|
|
562
|
-
// deleteSMPQueue(rcvKey: SignKey, queueId: Uint8Array): Promise<void> {
|
|
563
|
-
// return this.okSMPCommand(rcvKey, queueId, SMP.cDEL())
|
|
564
|
-
// }
|
|
565
|
-
// private async msgSMPCommand(rcvKey: SignKey, queueId: Uint8Array, command: SMPCommand<Client>): Promise<void> {
|
|
566
|
-
// const resp = await this.sendSMPCommand(rcvKey, queueId, command)
|
|
567
|
-
// switch (resp.cmd) {
|
|
568
|
-
// case "OK":
|
|
569
|
-
// return
|
|
570
|
-
// case "MSG":
|
|
571
|
-
// return this.msgQ.enqueue({server: this.server, queueId, command: resp})
|
|
572
|
-
// default:
|
|
573
|
-
// throw new Error("unexpected response")
|
|
574
|
-
// }
|
|
575
|
-
// }
|
|
576
|
-
// private async okChatCommand(command: ChatCommand): Promise<void> {
|
|
577
|
-
// const resp = await this.sendChatCommand(command)
|
|
578
|
-
// if (resp.type !== "cmdOk") throw new ChatCommandError("unexpected response", resp)
|
|
579
|
-
// }
|
|
580
|
-
get connected() {
|
|
581
|
-
return this._connected;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
export { ChatClient };
|