blob: a3db747c1c58abba9320d4be8f31e4073a5f8425 [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 */
Charlie2bc0d672022-11-04 11:53:44 -040018import { AccountDetails, Message, VolatileDetails, WebSocketMessageType } from 'jami-web-common';
Issam E. Maghnif796a092022-10-09 20:25:26 +000019import log from 'loglevel';
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -040020import { filter, firstValueFrom, map, Subject } from 'rxjs';
Issam E. Maghnif796a092022-10-09 20:25:26 +000021import { Service } from 'typedi';
22
Charlie2bc0d672022-11-04 11:53:44 -040023import { Ws } from '../ws.js';
Misha Krieger-Raynauldaddd6fe2022-10-22 12:46:04 -040024import { JamiSignal } from './jami-signal.js';
25import {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040026 AccountDetailsChanged,
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -050027 AccountMessageStatusChanged,
28 ContactAdded,
29 ContactRemoved,
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040030 ConversationLoaded,
31 ConversationReady,
32 ConversationRemoved,
Charlieb62c6782022-10-30 15:14:56 -040033 IncomingAccountMessage,
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040034 KnownDevicesChanged,
35 MessageReceived,
Misha Krieger-Raynauldaddd6fe2022-10-22 12:46:04 -040036 NameRegistrationEnded,
37 RegisteredNameFound,
38 RegistrationStateChanged,
39 VolatileDetailsChanged,
40} from './jami-signal-interfaces.js';
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -040041import { JamiSwig, StringMap, stringMapToRecord, stringVectToArray, vectMapToRecordArray } from './jami-swig.js';
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -040042import { require } from './utils.js';
Issam E. Maghnif796a092022-10-09 20:25:26 +000043
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040044// TODO: Mechanism to map account IDs to a list of WebSockets
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -040045// TODO: Convert Records to interfaces and replace them in common/ (e.g. Contact)
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040046
Issam E. Maghnif796a092022-10-09 20:25:26 +000047@Service()
48export class Jamid {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -040049 private readonly jamiSwig: JamiSwig;
50 private readonly usernamesToAccountIds: Map<string, string>;
Issam E. Maghnif796a092022-10-09 20:25:26 +000051 private readonly events;
52
Charlie2bc0d672022-11-04 11:53:44 -040053 constructor(private ws: Ws) {
Issam E. Maghnif796a092022-10-09 20:25:26 +000054 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
simon7d4386c2022-10-26 17:47:59 -040055 this.jamiSwig = require('../../jamid.node') as JamiSwig; // TODO: we should put the path in the .env
Issam E. Maghnif796a092022-10-09 20:25:26 +000056
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040057 this.usernamesToAccountIds = new Map<string, string>();
58
59 // Setup signal handlers
Issam E. Maghnif796a092022-10-09 20:25:26 +000060 const handlers: Record<string, unknown> = {};
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040061
62 // Add default handler for all signals
63 const createDefaultHandler = (signal: string) => {
64 return (...args: unknown[]) => log.warn('Unhandled', signal, args);
Issam E. Maghnif796a092022-10-09 20:25:26 +000065 };
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040066 for (const signal in JamiSignal) {
67 handlers[signal] = createDefaultHandler(signal);
68 }
69
70 // Overwrite handlers for handled signals using RxJS Subjects, converting multiple arguments to objects
71 const onAccountsChanged = new Subject<void>();
72 handlers.AccountsChanged = () => onAccountsChanged.next();
73
74 const onAccountDetailsChanged = new Subject<AccountDetailsChanged>();
75 handlers.AccountDetailsChanged = (accountId: string, details: AccountDetails) =>
76 onAccountDetailsChanged.next({ accountId, details });
Issam E. Maghnif796a092022-10-09 20:25:26 +000077
78 const onVolatileDetailsChanged = new Subject<VolatileDetailsChanged>();
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040079 handlers.VolatileDetailsChanged = (accountId: string, details: VolatileDetails) =>
80 onVolatileDetailsChanged.next({ accountId, details });
Issam E. Maghnif796a092022-10-09 20:25:26 +000081
82 const onRegistrationStateChanged = new Subject<RegistrationStateChanged>();
83 handlers.RegistrationStateChanged = (accountId: string, state: string, code: number, details: string) =>
84 onRegistrationStateChanged.next({ accountId, state, code, details });
85
86 const onNameRegistrationEnded = new Subject<NameRegistrationEnded>();
87 handlers.NameRegistrationEnded = (accountId: string, state: number, username: string) =>
88 onNameRegistrationEnded.next({ accountId, state, username });
89
90 const onRegisteredNameFound = new Subject<RegisteredNameFound>();
91 handlers.RegisteredNameFound = (accountId: string, state: number, address: string, username: string) =>
92 onRegisteredNameFound.next({ accountId, state, address, username });
93
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -040094 const onKnownDevicesChanged = new Subject<KnownDevicesChanged>();
95 handlers.KnownDevicesChanged = (accountId: string, devices: Record<string, string>) =>
96 onKnownDevicesChanged.next({ accountId, devices });
97
Charlieb62c6782022-10-30 15:14:56 -040098 const onIncomingAccountMessage = new Subject<IncomingAccountMessage>();
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -050099 handlers.IncomingAccountMessage = (accountId: string, from: string, payload: Record<string, string>) =>
100 onIncomingAccountMessage.next({ accountId, from, payload });
101
102 const onAccountMessageStatusChanged = new Subject<AccountMessageStatusChanged>();
103 handlers.AccountMessageStatusChanged = (accountId: string, messageId: string, peer: string, state: number) =>
104 onAccountMessageStatusChanged.next({ accountId, messageId, peer, state });
105
106 const onContactAdded = new Subject<ContactAdded>();
107 handlers.ContactAdded = (accountId: string, contactId: string, confirmed: boolean) =>
108 onContactAdded.next({ accountId, contactId, confirmed });
109
110 const onContactRemoved = new Subject<ContactRemoved>();
111 handlers.ContactRemoved = (accountId: string, contactId: string, banned: boolean) =>
112 onContactRemoved.next({ accountId, contactId, banned });
Charlieb62c6782022-10-30 15:14:56 -0400113
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400114 const onConversationReady = new Subject<ConversationReady>();
115 handlers.ConversationReady = (accountId: string, conversationId: string) =>
116 onConversationReady.next({ accountId, conversationId });
117
118 const onConversationRemoved = new Subject<ConversationRemoved>();
119 handlers.ConversationRemoved = (accountId: string, conversationId: string) =>
120 onConversationRemoved.next({ accountId, conversationId });
121
122 const onConversationLoaded = new Subject<ConversationLoaded>();
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400123 handlers.ConversationLoaded = (id: number, accountId: string, conversationId: string, messages: Message[]) =>
124 onConversationLoaded.next({ id, accountId, conversationId, messages });
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400125
126 const onMessageReceived = new Subject<MessageReceived>();
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400127 handlers.MessageReceived = (accountId: string, conversationId: string, message: Message) =>
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400128 onMessageReceived.next({ accountId, conversationId, message });
129
130 // Expose all signals in an events object to allow other handlers to subscribe after jamiSwig.init()
Issam E. Maghnif796a092022-10-09 20:25:26 +0000131 this.events = {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400132 onAccountsChanged: onAccountsChanged.asObservable(),
133 onAccountDetailsChanged: onAccountDetailsChanged.asObservable(),
Issam E. Maghnif796a092022-10-09 20:25:26 +0000134 onVolatileDetailsChanged: onVolatileDetailsChanged.asObservable(),
135 onRegistrationStateChanged: onRegistrationStateChanged.asObservable(),
136 onNameRegistrationEnded: onNameRegistrationEnded.asObservable(),
137 onRegisteredNameFound: onRegisteredNameFound.asObservable(),
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400138 onKnownDevicesChanged: onKnownDevicesChanged.asObservable(),
Charlieb62c6782022-10-30 15:14:56 -0400139 onIncomingAccountMessage: onIncomingAccountMessage.asObservable(),
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -0500140 onAccountMessageStatusChanged: onAccountMessageStatusChanged.asObservable(),
141 onContactAdded: onContactAdded.asObservable(),
142 onContactRemoved: onContactRemoved.asObservable(),
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400143 onConversationReady: onConversationReady.asObservable(),
144 onConversationRemoved: onConversationRemoved.asObservable(),
145 onConversationLoaded: onConversationLoaded.asObservable(),
146 onMessageReceived: onMessageReceived.asObservable(),
Issam E. Maghnif796a092022-10-09 20:25:26 +0000147 };
148
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400149 this.setupSignalHandlers();
Issam E. Maghnif796a092022-10-09 20:25:26 +0000150
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400151 // RxJS Subjects are used as signal handlers for the following reasons:
152 // 1. You cannot change event handlers after calling jamiSwig.init()
Issam E. Maghnif796a092022-10-09 20:25:26 +0000153 // 2. You cannot specify multiple handlers for the same event
154 // 3. You cannot specify a default handler
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400155 this.jamiSwig.init(handlers);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000156 }
157
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400158 stop(): void {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400159 this.jamiSwig.fini();
Misha Krieger-Raynauld62a0da92022-10-22 13:46:59 -0400160 }
161
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400162 getVolatileAccountDetails(accountId: string): VolatileDetails {
163 return stringMapToRecord(this.jamiSwig.getVolatileAccountDetails(accountId)) as unknown as VolatileDetails;
Issam E. Maghnif796a092022-10-09 20:25:26 +0000164 }
165
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400166 getAccountDetails(accountId: string): AccountDetails {
167 return stringMapToRecord(this.jamiSwig.getAccountDetails(accountId)) as unknown as AccountDetails;
168 }
Issam E. Maghnif796a092022-10-09 20:25:26 +0000169
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400170 setAccountDetails(accountId: string, accountDetails: AccountDetails): void {
simon43da57b2022-10-26 18:22:22 -0400171 const accountDetailsStringMap: StringMap = new this.jamiSwig.StringMap();
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400172 for (const [key, value] of Object.entries(accountDetails)) {
173 accountDetailsStringMap.set(key, value);
174 }
175 this.jamiSwig.setAccountDetails(accountId, accountDetailsStringMap);
176 }
Issam E. Maghnif796a092022-10-09 20:25:26 +0000177
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400178 async addAccount(details: Map<string, string | number | boolean>): Promise<string> {
simon43da57b2022-10-26 18:22:22 -0400179 const detailsStringMap: StringMap = new this.jamiSwig.StringMap();
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400180
181 detailsStringMap.set('Account.type', 'RING');
182 for (const [key, value] of details.entries()) {
183 detailsStringMap.set('Account.' + key, value.toString());
184 }
185
186 const accountId = this.jamiSwig.addAccount(detailsStringMap);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000187 return firstValueFrom(
188 this.events.onRegistrationStateChanged.pipe(
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400189 filter((value) => value.accountId === accountId),
Issam E. Maghnif796a092022-10-09 20:25:26 +0000190 // TODO: is it the only state?
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400191 // TODO: Replace with string enum in common/
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400192 filter((value) => value.state === 'REGISTERED'),
193 map((value) => value.accountId)
Issam E. Maghnif796a092022-10-09 20:25:26 +0000194 )
195 );
196 }
197
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400198 removeAccount(accountId: string): void {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400199 this.jamiSwig.removeAccount(accountId);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000200 }
201
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400202 getAccountIds(): string[] {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400203 return stringVectToArray(this.jamiSwig.getAccountList());
Issam E. Maghnif796a092022-10-09 20:25:26 +0000204 }
205
Charlie2bc0d672022-11-04 11:53:44 -0400206 sendAccountTextMessage(from: string, to: string, message: string): void {
Charlieb62c6782022-10-30 15:14:56 -0400207 const messageStringMap: StringMap = new this.jamiSwig.StringMap();
Charlie2bc0d672022-11-04 11:53:44 -0400208 messageStringMap.set('application/json', message);
209 this.jamiSwig.sendAccountTextMessage(from, to, messageStringMap);
Charlieb62c6782022-10-30 15:14:56 -0400210 }
211
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400212 // TODO: Add interface for returned type
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400213 async lookupUsername(username: string, accountId?: string) {
214 const hasRingNs = this.jamiSwig.lookupName(accountId || '', '', username);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000215 if (!hasRingNs) {
Issam E. Maghnif796a092022-10-09 20:25:26 +0000216 throw new Error('Jami does not have NS');
217 }
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400218 return firstValueFrom(
219 this.events.onRegisteredNameFound.pipe(
220 filter((value) => value.username === username),
221 map(({ accountId: _, ...response }) => response) // Remove accountId from response
222 )
223 );
224 }
225
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400226 // TODO: Add interface for returned type
Misha Krieger-Raynauld6f9c7ae2022-10-28 11:41:45 -0400227 async lookupAddress(address: string, accountId?: string) {
228 const hasRingNs = this.jamiSwig.lookupAddress(accountId || '', '', address);
229 if (!hasRingNs) {
230 throw new Error('Jami does not have NS');
231 }
232 return firstValueFrom(
233 this.events.onRegisteredNameFound.pipe(
234 filter((value) => value.address === address),
235 map(({ accountId: _, ...response }) => response) // Remove accountId from response
236 )
237 );
Issam E. Maghnif796a092022-10-09 20:25:26 +0000238 }
239
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400240 // TODO: Create enum for state and return that rather than a number
241 async registerUsername(accountId: string, username: string, password: string): Promise<number> {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400242 const hasRingNs = this.jamiSwig.registerName(accountId, password, username);
243 if (!hasRingNs) {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400244 throw new Error('Jami does not have NS');
245 }
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400246 return firstValueFrom(
247 this.events.onNameRegistrationEnded.pipe(
248 filter((value) => value.accountId === accountId),
249 map((value) => value.state)
250 )
251 );
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400252 }
253
254 getDevices(accountId: string): Record<string, string> {
255 return stringMapToRecord(this.jamiSwig.getKnownRingDevices(accountId));
256 }
257
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400258 addContact(accountId: string, contactId: string): void {
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400259 this.jamiSwig.addContact(accountId, contactId);
260 }
261
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400262 removeContact(accountId: string, contactId: string): void {
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400263 this.jamiSwig.removeContact(accountId, contactId, false);
264 }
265
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400266 blockContact(accountId: string, contactId: string): void {
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400267 this.jamiSwig.removeContact(accountId, contactId, true);
268 }
269
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400270 // TODO: Replace Record with interface
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400271 getContacts(accountId: string): Record<string, string>[] {
272 return vectMapToRecordArray(this.jamiSwig.getContacts(accountId));
273 }
274
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400275 // TODO: Replace Record with interface
Misha Krieger-Raynauldbfed1732022-11-01 20:49:35 -0400276 getContactDetails(accountId: string, contactId: string): Record<string, string> {
277 return stringMapToRecord(this.jamiSwig.getContactDetails(accountId, contactId));
278 }
279
Misha Krieger-Raynauld153a1482022-11-05 12:00:41 -0400280 getDefaultModeratorUris(accountId: string): string[] {
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400281 return stringVectToArray(this.jamiSwig.getDefaultModerators(accountId));
282 }
283
Misha Krieger-Raynauld153a1482022-11-05 12:00:41 -0400284 addDefaultModerator(accountId: string, contactId: string): void {
285 this.jamiSwig.setDefaultModerator(accountId, contactId, true);
286 }
287
288 removeDefaultModerator(accountId: string, contactId: string): void {
289 this.jamiSwig.setDefaultModerator(accountId, contactId, false);
290 }
291
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400292 getConversationIds(accountId: string): string[] {
293 return stringVectToArray(this.jamiSwig.getConversations(accountId));
294 }
295
296 // TODO: Replace Record with interface
297 getConversationInfos(accountId: string, conversationId: string): Record<string, string> {
298 return stringMapToRecord(this.jamiSwig.conversationInfos(accountId, conversationId));
299 }
300
301 // TODO: Replace Record with interface
302 getConversationMembers(accountId: string, conversationId: string): Record<string, string>[] {
303 return vectMapToRecordArray(this.jamiSwig.getConversationMembers(accountId, conversationId));
304 }
305
306 async getConversationMessages(accountId: string, conversationId: string, fromMessage?: string): Promise<Message[]> {
307 const requestId = this.jamiSwig.loadConversationMessages(accountId, conversationId, fromMessage || '', 32);
308 return firstValueFrom(
309 this.events.onConversationLoaded.pipe(
310 filter((value) => value.id === requestId),
311 map((value) => value.messages)
312 )
313 );
314 }
315
316 sendConversationMessage(accountId: string, conversationId: string, message: string, replyTo?: string): void {
317 this.jamiSwig.sendMessage(accountId, conversationId, message, replyTo || '');
318 }
319
Misha Krieger-Raynauld7f959332022-11-04 15:12:53 -0400320 getCallIds(accountId: string): string[] {
321 return stringVectToArray(this.jamiSwig.getCallList(accountId));
322 }
323
324 // TODO: Replace Record with interface
325 getCallDetails(accountId: string, callId: string): Record<string, string> {
326 return stringMapToRecord(this.jamiSwig.getCallDetails(accountId, callId));
327 }
328
Misha Krieger-Raynauldb6f1c322022-10-23 20:42:57 -0400329 getAccountIdFromUsername(username: string): string | undefined {
330 return this.usernamesToAccountIds.get(username);
Issam E. Maghnif796a092022-10-09 20:25:26 +0000331 }
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400332
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400333 private setupSignalHandlers(): void {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400334 this.events.onAccountsChanged.subscribe(() => {
335 log.debug('Received AccountsChanged');
336 });
337
338 this.events.onAccountDetailsChanged.subscribe((signal) => {
339 log.debug('Received AccountsDetailsChanged', JSON.stringify(signal));
340 });
341
342 this.events.onVolatileDetailsChanged.subscribe(({ accountId, details }) => {
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400343 const username = details['Account.registeredName'];
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400344 log.debug(
345 `Received VolatileDetailsChanged: {"accountId":"${accountId}",` +
346 `"details":{"Account.registeredName":"${username}", ...}}`
347 );
348 // Keep map of usernames to account IDs
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400349 if (username) {
350 this.usernamesToAccountIds.set(username, accountId);
351 }
352 });
353
354 this.events.onRegistrationStateChanged.subscribe((signal) => {
355 log.debug('Received RegistrationStateChanged:', JSON.stringify(signal));
356 });
357
358 this.events.onNameRegistrationEnded.subscribe((signal) => {
359 log.debug('Received NameRegistrationEnded:', JSON.stringify(signal));
360 });
361
362 this.events.onRegisteredNameFound.subscribe((signal) => {
363 log.debug('Received RegisteredNameFound:', JSON.stringify(signal));
364 });
365
366 this.events.onKnownDevicesChanged.subscribe(({ accountId }) => {
367 log.debug(`Received KnownDevicesChanged: {"accountId":"${accountId}", ...}`);
368 });
369
370 this.events.onIncomingAccountMessage.subscribe((signal) => {
371 log.debug('Received IncomingAccountMessage:', JSON.stringify(signal));
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -0500372 const message = JSON.parse(signal.payload['application/json']);
Charlie2bc0d672022-11-04 11:53:44 -0400373
374 if (message === undefined) {
375 log.debug('Undefined account message');
376 return;
377 }
378
379 if (!Object.values(WebSocketMessageType).includes(message.type)) {
380 log.warn(`Unhandled account message type: ${message.type}`);
381 return;
382 }
383
384 message.data.from = signal.from;
385 message.data.to = signal.accountId;
386 log.info(`Sending ${JSON.stringify(message)} to ${signal.accountId}`);
387 this.ws.send(signal.accountId, message);
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400388 });
389
Misha Krieger-Raynauldcb11bba2022-11-11 18:08:33 -0500390 this.events.onAccountMessageStatusChanged.subscribe((signal) => {
391 log.debug('Received AccountMessageStatusChanged:', JSON.stringify(signal));
392 });
393
394 this.events.onContactAdded.subscribe((signal) => {
395 log.debug('Received ContactAdded:', JSON.stringify(signal));
396 });
397
398 this.events.onContactRemoved.subscribe((signal) => {
399 log.debug('Received ContactRemoved:', JSON.stringify(signal));
400 });
401
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400402 this.events.onConversationReady.subscribe((signal) => {
403 log.debug('Received ConversationReady:', JSON.stringify(signal));
404 });
405
406 this.events.onConversationRemoved.subscribe((signal) => {
407 log.debug('Received ConversationRemoved:', JSON.stringify(signal));
408 });
409
Misha Krieger-Raynauld8a381da2022-11-03 17:37:51 -0400410 this.events.onConversationLoaded.subscribe(({ id, accountId, conversationId }) => {
411 log.debug(
412 `Received ConversationLoaded: {"id":"${id}","accountId":"${accountId}",` +
413 `"conversationId":"${conversationId}","messages":[...]}`
414 );
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400415 });
416
417 this.events.onMessageReceived.subscribe((signal) => {
418 log.debug('Received MessageReceived:', JSON.stringify(signal));
Charlie6ddaefe2022-11-01 18:36:29 -0400419 // TODO: Send message to client using WS service
Misha Krieger-Raynauld68a9b562022-10-28 19:47:46 -0400420 });
421 }
Issam E. Maghnif796a092022-10-09 20:25:26 +0000422}