blob: 0c54adfb67ff72266fb72217db3e6e141f98bf2a [file] [log] [blame]
Issam E. Maghnif796a092022-10-09 20:25:26 +00001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
Issam E. Maghni0432cb72022-11-12 06:09:26 +000018import {
19 AccountDetails,
20 AccountTextMessage,
21 ConversationMessage,
22 Message,
23 VolatileDetails,
24 WebSocketMessage,
25 WebSocketMessageType,
26} from 'jami-web-common';
Issam E. Maghnif796a092022-10-09 20:25:26 +000027import log from 'loglevel';
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -040028import { filter, firstValueFrom, map, Subject } from 'rxjs';
Issam E. Maghnif796a092022-10-09 20:25:26 +000029import { Service } from 'typedi';
30
Charlie2bc0d672022-11-04 11:53:44 -040031import { Ws } from '../ws.js';
Misha Krieger-Raynauldaddd6fe2022-10-22 12:46:04 -040032import { JamiSignal } from './jami-signal.js';
33import {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040034 AccountDetailsChanged,
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -050035 AccountMessageStatusChanged,
36 ContactAdded,
37 ContactRemoved,
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040038 ConversationLoaded,
39 ConversationReady,
40 ConversationRemoved,
Charlieb62c6782022-10-30 15:14:56 -040041 IncomingAccountMessage,
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040042 KnownDevicesChanged,
43 MessageReceived,
Misha Krieger-Raynauldaddd6fe2022-10-22 12:46:04 -040044 NameRegistrationEnded,
45 RegisteredNameFound,
46 RegistrationStateChanged,
47 VolatileDetailsChanged,
48} from './jami-signal-interfaces.js';
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -040049import { JamiSwig, StringMap, stringMapToRecord, stringVectToArray, vectMapToRecordArray } from './jami-swig.js';
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -040050import { require } from './utils.js';
Issam E. Maghnif796a092022-10-09 20:25:26 +000051
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040052// TODO: Mechanism to map account IDs to a list of WebSockets
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -040053// TODO: Convert Records to interfaces and replace them in common/ (e.g. Contact)
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040054
Issam E. Maghnif796a092022-10-09 20:25:26 +000055@Service()
56export class Jamid {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -040057 private readonly jamiSwig: JamiSwig;
58 private readonly usernamesToAccountIds: Map<string, string>;
Issam E. Maghnif796a092022-10-09 20:25:26 +000059 private readonly events;
60
Charlie2bc0d672022-11-04 11:53:44 -040061 constructor(private ws: Ws) {
Issam E. Maghnif796a092022-10-09 20:25:26 +000062 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
simon7d4386c2022-10-26 17:47:59 -040063 this.jamiSwig = require('../../jamid.node') as JamiSwig; // TODO: we should put the path in the .env
Issam E. Maghnif796a092022-10-09 20:25:26 +000064
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040065 this.usernamesToAccountIds = new Map<string, string>();
66
67 // Setup signal handlers
Issam E. Maghnif796a092022-10-09 20:25:26 +000068 const handlers: Record<string, unknown> = {};
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040069
70 // Add default handler for all signals
71 const createDefaultHandler = (signal: string) => {
72 return (...args: unknown[]) => log.warn('Unhandled', signal, args);
Issam E. Maghnif796a092022-10-09 20:25:26 +000073 };
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040074 for (const signal in JamiSignal) {
75 handlers[signal] = createDefaultHandler(signal);
76 }
77
78 // Overwrite handlers for handled signals using RxJS Subjects, converting multiple arguments to objects
79 const onAccountsChanged = new Subject<void>();
80 handlers.AccountsChanged = () => onAccountsChanged.next();
81
82 const onAccountDetailsChanged = new Subject<AccountDetailsChanged>();
83 handlers.AccountDetailsChanged = (accountId: string, details: AccountDetails) =>
84 onAccountDetailsChanged.next({ accountId, details });
Issam E. Maghnif796a092022-10-09 20:25:26 +000085
86 const onVolatileDetailsChanged = new Subject<VolatileDetailsChanged>();
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040087 handlers.VolatileDetailsChanged = (accountId: string, details: VolatileDetails) =>
88 onVolatileDetailsChanged.next({ accountId, details });
Issam E. Maghnif796a092022-10-09 20:25:26 +000089
90 const onRegistrationStateChanged = new Subject<RegistrationStateChanged>();
91 handlers.RegistrationStateChanged = (accountId: string, state: string, code: number, details: string) =>
92 onRegistrationStateChanged.next({ accountId, state, code, details });
93
94 const onNameRegistrationEnded = new Subject<NameRegistrationEnded>();
95 handlers.NameRegistrationEnded = (accountId: string, state: number, username: string) =>
96 onNameRegistrationEnded.next({ accountId, state, username });
97
98 const onRegisteredNameFound = new Subject<RegisteredNameFound>();
99 handlers.RegisteredNameFound = (accountId: string, state: number, address: string, username: string) =>
100 onRegisteredNameFound.next({ accountId, state, address, username });
101
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400102 const onKnownDevicesChanged = new Subject<KnownDevicesChanged>();
103 handlers.KnownDevicesChanged = (accountId: string, devices: Record<string, string>) =>
104 onKnownDevicesChanged.next({ accountId, devices });
105
Charlieb62c6782022-10-30 15:14:56 -0400106 const onIncomingAccountMessage = new Subject<IncomingAccountMessage>();
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -0500107 handlers.IncomingAccountMessage = (accountId: string, from: string, payload: Record<string, string>) =>
108 onIncomingAccountMessage.next({ accountId, from, payload });
109
110 const onAccountMessageStatusChanged = new Subject<AccountMessageStatusChanged>();
111 handlers.AccountMessageStatusChanged = (accountId: string, messageId: string, peer: string, state: number) =>
112 onAccountMessageStatusChanged.next({ accountId, messageId, peer, state });
113
114 const onContactAdded = new Subject<ContactAdded>();
115 handlers.ContactAdded = (accountId: string, contactId: string, confirmed: boolean) =>
116 onContactAdded.next({ accountId, contactId, confirmed });
117
118 const onContactRemoved = new Subject<ContactRemoved>();
119 handlers.ContactRemoved = (accountId: string, contactId: string, banned: boolean) =>
120 onContactRemoved.next({ accountId, contactId, banned });
Charlieb62c6782022-10-30 15:14:56 -0400121
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400122 const onConversationReady = new Subject<ConversationReady>();
123 handlers.ConversationReady = (accountId: string, conversationId: string) =>
124 onConversationReady.next({ accountId, conversationId });
125
126 const onConversationRemoved = new Subject<ConversationRemoved>();
127 handlers.ConversationRemoved = (accountId: string, conversationId: string) =>
128 onConversationRemoved.next({ accountId, conversationId });
129
130 const onConversationLoaded = new Subject<ConversationLoaded>();
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400131 handlers.ConversationLoaded = (id: number, accountId: string, conversationId: string, messages: Message[]) =>
132 onConversationLoaded.next({ id, accountId, conversationId, messages });
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400133
134 const onMessageReceived = new Subject<MessageReceived>();
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400135 handlers.MessageReceived = (accountId: string, conversationId: string, message: Message) =>
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400136 onMessageReceived.next({ accountId, conversationId, message });
137
138 // Expose all signals in an events object to allow other handlers to subscribe after jamiSwig.init()
Issam E. Maghnif796a092022-10-09 20:25:26 +0000139 this.events = {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400140 onAccountsChanged: onAccountsChanged.asObservable(),
141 onAccountDetailsChanged: onAccountDetailsChanged.asObservable(),
Issam E. Maghnif796a092022-10-09 20:25:26 +0000142 onVolatileDetailsChanged: onVolatileDetailsChanged.asObservable(),
143 onRegistrationStateChanged: onRegistrationStateChanged.asObservable(),
144 onNameRegistrationEnded: onNameRegistrationEnded.asObservable(),
145 onRegisteredNameFound: onRegisteredNameFound.asObservable(),
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400146 onKnownDevicesChanged: onKnownDevicesChanged.asObservable(),
Charlieb62c6782022-10-30 15:14:56 -0400147 onIncomingAccountMessage: onIncomingAccountMessage.asObservable(),
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -0500148 onAccountMessageStatusChanged: onAccountMessageStatusChanged.asObservable(),
149 onContactAdded: onContactAdded.asObservable(),
150 onContactRemoved: onContactRemoved.asObservable(),
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400151 onConversationReady: onConversationReady.asObservable(),
152 onConversationRemoved: onConversationRemoved.asObservable(),
153 onConversationLoaded: onConversationLoaded.asObservable(),
154 onMessageReceived: onMessageReceived.asObservable(),
Issam E. Maghnif796a092022-10-09 20:25:26 +0000155 };
156
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400157 this.setupSignalHandlers();
Issam E. Maghnif796a092022-10-09 20:25:26 +0000158
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400159 // RxJS Subjects are used as signal handlers for the following reasons:
160 // 1. You cannot change event handlers after calling jamiSwig.init()
Issam E. Maghnif796a092022-10-09 20:25:26 +0000161 // 2. You cannot specify multiple handlers for the same event
162 // 3. You cannot specify a default handler
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400163 this.jamiSwig.init(handlers);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000164 }
165
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400166 stop(): void {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400167 this.jamiSwig.fini();
Misha Krieger-Raynauld62a0da92022-10-22 13:46:59 -0400168 }
169
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400170 getVolatileAccountDetails(accountId: string): VolatileDetails {
171 return stringMapToRecord(this.jamiSwig.getVolatileAccountDetails(accountId)) as unknown as VolatileDetails;
Issam E. Maghnif796a092022-10-09 20:25:26 +0000172 }
173
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400174 getAccountDetails(accountId: string): AccountDetails {
175 return stringMapToRecord(this.jamiSwig.getAccountDetails(accountId)) as unknown as AccountDetails;
176 }
Issam E. Maghnif796a092022-10-09 20:25:26 +0000177
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400178 setAccountDetails(accountId: string, accountDetails: AccountDetails): void {
simon43da57b2022-10-26 18:22:22 -0400179 const accountDetailsStringMap: StringMap = new this.jamiSwig.StringMap();
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400180 for (const [key, value] of Object.entries(accountDetails)) {
181 accountDetailsStringMap.set(key, value);
182 }
183 this.jamiSwig.setAccountDetails(accountId, accountDetailsStringMap);
184 }
Issam E. Maghnif796a092022-10-09 20:25:26 +0000185
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400186 async addAccount(details: Map<string, string | number | boolean>): Promise<string> {
simon43da57b2022-10-26 18:22:22 -0400187 const detailsStringMap: StringMap = new this.jamiSwig.StringMap();
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400188
189 detailsStringMap.set('Account.type', 'RING');
190 for (const [key, value] of details.entries()) {
191 detailsStringMap.set('Account.' + key, value.toString());
192 }
193
194 const accountId = this.jamiSwig.addAccount(detailsStringMap);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000195 return firstValueFrom(
196 this.events.onRegistrationStateChanged.pipe(
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400197 filter((value) => value.accountId === accountId),
Issam E. Maghnif796a092022-10-09 20:25:26 +0000198 // TODO: is it the only state?
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400199 // TODO: Replace with string enum in common/
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400200 filter((value) => value.state === 'REGISTERED'),
201 map((value) => value.accountId)
Issam E. Maghnif796a092022-10-09 20:25:26 +0000202 )
203 );
204 }
205
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400206 removeAccount(accountId: string): void {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400207 this.jamiSwig.removeAccount(accountId);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000208 }
209
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400210 getAccountIds(): string[] {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400211 return stringVectToArray(this.jamiSwig.getAccountList());
Issam E. Maghnif796a092022-10-09 20:25:26 +0000212 }
213
Charlie2bc0d672022-11-04 11:53:44 -0400214 sendAccountTextMessage(from: string, to: string, message: string): void {
Charlieb62c6782022-10-30 15:14:56 -0400215 const messageStringMap: StringMap = new this.jamiSwig.StringMap();
Charlie2bc0d672022-11-04 11:53:44 -0400216 messageStringMap.set('application/json', message);
217 this.jamiSwig.sendAccountTextMessage(from, to, messageStringMap);
Charlieb62c6782022-10-30 15:14:56 -0400218 }
219
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400220 // TODO: Add interface for returned type
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400221 async lookupUsername(username: string, accountId?: string) {
222 const hasRingNs = this.jamiSwig.lookupName(accountId || '', '', username);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000223 if (!hasRingNs) {
Issam E. Maghnif796a092022-10-09 20:25:26 +0000224 throw new Error('Jami does not have NS');
225 }
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400226 return firstValueFrom(
227 this.events.onRegisteredNameFound.pipe(
228 filter((value) => value.username === username),
229 map(({ accountId: _, ...response }) => response) // Remove accountId from response
230 )
231 );
232 }
233
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400234 // TODO: Add interface for returned type
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400235 async lookupAddress(address: string, accountId?: string) {
236 const hasRingNs = this.jamiSwig.lookupAddress(accountId || '', '', address);
237 if (!hasRingNs) {
238 throw new Error('Jami does not have NS');
239 }
240 return firstValueFrom(
241 this.events.onRegisteredNameFound.pipe(
242 filter((value) => value.address === address),
243 map(({ accountId: _, ...response }) => response) // Remove accountId from response
244 )
245 );
Issam E. Maghnif796a092022-10-09 20:25:26 +0000246 }
247
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400248 // TODO: Create enum for state and return that rather than a number
249 async registerUsername(accountId: string, username: string, password: string): Promise<number> {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400250 const hasRingNs = this.jamiSwig.registerName(accountId, password, username);
251 if (!hasRingNs) {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400252 throw new Error('Jami does not have NS');
253 }
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400254 return firstValueFrom(
255 this.events.onNameRegistrationEnded.pipe(
256 filter((value) => value.accountId === accountId),
257 map((value) => value.state)
258 )
259 );
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400260 }
261
262 getDevices(accountId: string): Record<string, string> {
263 return stringMapToRecord(this.jamiSwig.getKnownRingDevices(accountId));
264 }
265
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400266 addContact(accountId: string, contactId: string): void {
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400267 this.jamiSwig.addContact(accountId, contactId);
268 }
269
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400270 removeContact(accountId: string, contactId: string): void {
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400271 this.jamiSwig.removeContact(accountId, contactId, false);
272 }
273
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400274 blockContact(accountId: string, contactId: string): void {
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400275 this.jamiSwig.removeContact(accountId, contactId, true);
276 }
277
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400278 // TODO: Replace Record with interface
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400279 getContacts(accountId: string): Record<string, string>[] {
280 return vectMapToRecordArray(this.jamiSwig.getContacts(accountId));
281 }
282
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400283 // TODO: Replace Record with interface
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400284 getContactDetails(accountId: string, contactId: string): Record<string, string> {
285 return stringMapToRecord(this.jamiSwig.getContactDetails(accountId, contactId));
286 }
287
Misha Krieger-Raynauld153a1482022-11-05 12:00:41 -0400288 getDefaultModeratorUris(accountId: string): string[] {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400289 return stringVectToArray(this.jamiSwig.getDefaultModerators(accountId));
290 }
291
Misha Krieger-Raynauld153a1482022-11-05 12:00:41 -0400292 addDefaultModerator(accountId: string, contactId: string): void {
293 this.jamiSwig.setDefaultModerator(accountId, contactId, true);
294 }
295
296 removeDefaultModerator(accountId: string, contactId: string): void {
297 this.jamiSwig.setDefaultModerator(accountId, contactId, false);
298 }
299
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400300 getConversationIds(accountId: string): string[] {
301 return stringVectToArray(this.jamiSwig.getConversations(accountId));
302 }
303
304 // TODO: Replace Record with interface
305 getConversationInfos(accountId: string, conversationId: string): Record<string, string> {
306 return stringMapToRecord(this.jamiSwig.conversationInfos(accountId, conversationId));
307 }
308
309 // TODO: Replace Record with interface
310 getConversationMembers(accountId: string, conversationId: string): Record<string, string>[] {
311 return vectMapToRecordArray(this.jamiSwig.getConversationMembers(accountId, conversationId));
312 }
313
314 async getConversationMessages(accountId: string, conversationId: string, fromMessage?: string): Promise<Message[]> {
315 const requestId = this.jamiSwig.loadConversationMessages(accountId, conversationId, fromMessage || '', 32);
316 return firstValueFrom(
317 this.events.onConversationLoaded.pipe(
318 filter((value) => value.id === requestId),
319 map((value) => value.messages)
320 )
321 );
322 }
323
324 sendConversationMessage(accountId: string, conversationId: string, message: string, replyTo?: string): void {
325 this.jamiSwig.sendMessage(accountId, conversationId, message, replyTo || '');
326 }
327
Misha Krieger-Raynauld7f959332022-11-04 15:12:53 -0400328 getCallIds(accountId: string): string[] {
329 return stringVectToArray(this.jamiSwig.getCallList(accountId));
330 }
331
332 // TODO: Replace Record with interface
333 getCallDetails(accountId: string, callId: string): Record<string, string> {
334 return stringMapToRecord(this.jamiSwig.getCallDetails(accountId, callId));
335 }
336
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400337 getAccountIdFromUsername(username: string): string | undefined {
338 return this.usernamesToAccountIds.get(username);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000339 }
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400340
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400341 private setupSignalHandlers(): void {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400342 this.events.onAccountsChanged.subscribe(() => {
343 log.debug('Received AccountsChanged');
344 });
345
346 this.events.onAccountDetailsChanged.subscribe((signal) => {
347 log.debug('Received AccountsDetailsChanged', JSON.stringify(signal));
348 });
349
350 this.events.onVolatileDetailsChanged.subscribe(({ accountId, details }) => {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400351 const username = details['Account.registeredName'];
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400352 log.debug(
353 `Received VolatileDetailsChanged: {"accountId":"${accountId}",` +
354 `"details":{"Account.registeredName":"${username}", ...}}`
355 );
356 // Keep map of usernames to account IDs
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400357 if (username) {
358 this.usernamesToAccountIds.set(username, accountId);
359 }
360 });
361
362 this.events.onRegistrationStateChanged.subscribe((signal) => {
363 log.debug('Received RegistrationStateChanged:', JSON.stringify(signal));
364 });
365
366 this.events.onNameRegistrationEnded.subscribe((signal) => {
367 log.debug('Received NameRegistrationEnded:', JSON.stringify(signal));
368 });
369
370 this.events.onRegisteredNameFound.subscribe((signal) => {
371 log.debug('Received RegisteredNameFound:', JSON.stringify(signal));
372 });
373
374 this.events.onKnownDevicesChanged.subscribe(({ accountId }) => {
375 log.debug(`Received KnownDevicesChanged: {"accountId":"${accountId}", ...}`);
376 });
377
378 this.events.onIncomingAccountMessage.subscribe((signal) => {
379 log.debug('Received IncomingAccountMessage:', JSON.stringify(signal));
Issam E. Maghni0432cb72022-11-12 06:09:26 +0000380 const message: WebSocketMessage<any> = JSON.parse(signal.payload['application/json']);
Charlie2bc0d672022-11-04 11:53:44 -0400381
382 if (message === undefined) {
383 log.debug('Undefined account message');
384 return;
385 }
386
387 if (!Object.values(WebSocketMessageType).includes(message.type)) {
388 log.warn(`Unhandled account message type: ${message.type}`);
389 return;
390 }
391
Issam E. Maghni0432cb72022-11-12 06:09:26 +0000392 const data: AccountTextMessage<unknown> = {
393 from: signal.from,
394 to: signal.accountId,
395 message: message.data.message,
396 };
397 message.data = data;
398
Charlie2bc0d672022-11-04 11:53:44 -0400399 log.info(`Sending ${JSON.stringify(message)} to ${signal.accountId}`);
Issam E. Maghni0432cb72022-11-12 06:09:26 +0000400 this.ws.send(signal.accountId, message.type, data);
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400401 });
402
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -0500403 this.events.onAccountMessageStatusChanged.subscribe((signal) => {
404 log.debug('Received AccountMessageStatusChanged:', JSON.stringify(signal));
405 });
406
407 this.events.onContactAdded.subscribe((signal) => {
408 log.debug('Received ContactAdded:', JSON.stringify(signal));
409 });
410
411 this.events.onContactRemoved.subscribe((signal) => {
412 log.debug('Received ContactRemoved:', JSON.stringify(signal));
413 });
414
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400415 this.events.onConversationReady.subscribe((signal) => {
416 log.debug('Received ConversationReady:', JSON.stringify(signal));
417 });
418
419 this.events.onConversationRemoved.subscribe((signal) => {
420 log.debug('Received ConversationRemoved:', JSON.stringify(signal));
421 });
422
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400423 this.events.onConversationLoaded.subscribe(({ id, accountId, conversationId }) => {
424 log.debug(
425 `Received ConversationLoaded: {"id":"${id}","accountId":"${accountId}",` +
426 `"conversationId":"${conversationId}","messages":[...]}`
427 );
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400428 });
429
430 this.events.onMessageReceived.subscribe((signal) => {
431 log.debug('Received MessageReceived:', JSON.stringify(signal));
Issam E. Maghni0432cb72022-11-12 06:09:26 +0000432 const data: ConversationMessage = {
433 conversationId: signal.conversationId,
434 message: signal.message,
435 };
436 this.ws.send(signal.accountId, WebSocketMessageType.ConversationMessage, data);
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400437 });
438 }
Issam E. Maghnif796a092022-10-09 20:25:26 +0000439}