blob: 0355de465525b28342a79813bbc58886157511f8 [file] [log] [blame]
simon06527b02022-10-01 15:01:47 -04001import AccountDetails, { VolatileDetails } from './AccountDetails';
2import Contact from './Contact';
3import Conversation from './Conversation';
4import { Lookup, PromiseExecutor } from './util';
5
6type Devices = Record<string, string>;
7
8export type RegistrationState =
9 | 'UNREGISTERED'
10 | 'TRYING'
11 | 'REGISTERED'
12 | 'ERROR_GENERIC'
13 | 'ERROR_AUTH'
14 | 'ERROR_NETWORK'
15 | 'ERROR_HOST'
16 | 'ERROR_SERVICE_UNAVAILABLE'
17 | 'ERROR_NEED_MIGRATION'
18 | 'INITIALIZING';
19
20interface AccountRegisteringName extends PromiseExecutor<number> {
21 name: string;
22}
23
24class Account {
25 private readonly id: string;
26 private _details: AccountDetails;
27 private _volatileDetails: VolatileDetails;
simon5e32f742022-10-04 18:03:12 -040028 private readonly contactCache: Record<string, Contact>;
29 private _contacts: Contact[];
30 private readonly conversations: Record<string, Conversation>;
31 private defaultModerators: Contact[];
32 private _lookups: Lookup[];
33 private devices: Devices;
34 private _registrationState: RegistrationState | undefined;
35 private _registeringName: AccountRegisteringName | undefined;
simon06527b02022-10-01 15:01:47 -040036
37 static TYPE_JAMI: string;
38 static TYPE_SIP: string;
39 static BOOL_TRUE: string;
40 static BOOL_FALSE: string;
41
42 constructor(id: string, details: AccountDetails, volatileDetails: VolatileDetails) {
43 this.id = id;
simon5e32f742022-10-04 18:03:12 -040044 this._details = details || {};
45 this._volatileDetails = volatileDetails || {};
46 this.contactCache = {};
47 this._contacts = [];
48 this.conversations = {};
49 this.defaultModerators = [];
50 this._lookups = [];
51 this.devices = {};
52 this.registrationState = undefined;
53 this._registeringName = undefined;
simon06527b02022-10-01 15:01:47 -040054 }
55
simon5e32f742022-10-04 18:03:12 -040056 static from(object: any) {
57 const account = new Account(object.id, object.details, object.volatileDetails);
58 if (object.defaultModerators) account.defaultModerators = object.defaultModerators.map((m: any) => Contact.from(m));
simon06527b02022-10-01 15:01:47 -040059 return account;
60 }
61
62 update(data: Account) {
63 this._details = data._details;
64 this._volatileDetails = data._volatileDetails;
65 }
66
67 async getObject() {
68 const hasModerators = this.defaultModerators && this.defaultModerators.length;
69 return {
70 id: this.id,
71 details: this._details,
72 defaultModerators: hasModerators
73 ? await Promise.all(this.defaultModerators.map(async (c) => await c.getObject()))
74 : undefined,
75 volatileDetails: this._volatileDetails,
76 };
77 }
78
79 getId() {
80 return this.id;
81 }
82
83 getType() {
84 return this._details['Account.type'];
85 }
86
87 getUri() {
88 return this._details['Account.username'];
89 }
90
91 getRegisteredName() {
92 return this._volatileDetails['Account.registeredName'];
93 }
94
95 isRendezVous() {
96 return this._details['Account.rendezVous'] === Account.BOOL_TRUE;
97 }
98
99 isPublicIn() {
100 return this._details['DHT.PublicInCalls'] === Account.BOOL_TRUE;
101 }
102
103 setDetail(detail: keyof AccountDetails, value: string) {
104 this._details[detail] = value;
105 }
106
107 updateDetails(details: Partial<AccountDetails>) {
108 return Object.assign(this._details, details);
109 }
110
111 getDetails() {
112 return this._details;
113 }
114
115 getSummary() {
116 return this.getObject();
117 }
118
119 getDisplayName() {
120 return this._details['Account.displayName'] || this.getDisplayUri();
121 }
122
123 getDisplayUri() {
124 return this.getRegisteredName() || this.getUri();
125 }
126
127 getDisplayNameNoFallback() {
128 return this._details['Account.displayName'] || this.getRegisteredName();
129 }
130
131 getConversationIds() {
132 return Object.keys(this.conversations);
133 }
134
135 getConversations() {
136 return this.conversations;
137 }
138
139 getConversation(conversationId: string) {
140 return this.conversations[conversationId];
141 }
142
143 addConversation(conversation: Conversation) {
144 const conversationId = conversation.getId();
145 if (conversationId != null) {
146 this.conversations[conversationId] = conversation;
147 } else {
148 throw new Error('Conversation ID cannot be undefined');
149 }
150 }
151
152 removeConversation(conversationId: string) {
153 delete this.conversations[conversationId];
154 }
155
156 getContactFromCache(uri: string) {
157 let contact = this.contactCache[uri];
158 if (!contact) {
159 contact = new Contact(uri);
160 this.contactCache[uri] = contact;
161 }
162 return contact;
163 }
164
165 getContacts() {
166 return this._contacts;
167 }
168
169 set contacts(contacts: Contact[]) {
170 this._contacts = contacts;
171 }
172
173 getDefaultModerators() {
174 return this.defaultModerators;
175 }
176
177 set details(value: AccountDetails) {
178 this._details = value;
179 }
180
181 set volatileDetails(value: VolatileDetails) {
182 this._volatileDetails = value;
183 }
184
185 get lookups(): Lookup[] {
186 return this._lookups;
187 }
188
189 set lookups(lookups: Lookup[]) {
190 this._lookups = lookups;
191 }
192
193 setDevices(devices: Devices) {
194 this.devices = { ...devices };
195 }
196
197 getDevices() {
198 return this.devices;
199 }
200
201 get registrationState(): RegistrationState | undefined {
202 return this._registrationState;
203 }
204
205 set registrationState(registrationState: RegistrationState | undefined) {
206 this._registrationState = registrationState;
207 }
208
209 get registeringName(): AccountRegisteringName | undefined {
210 return this._registeringName;
211 }
212
213 set registeringName(registeringName: AccountRegisteringName | undefined) {
214 this._registeringName = registeringName;
215 }
216}
217
218Account.TYPE_JAMI = 'RING';
219Account.TYPE_SIP = 'SIP';
220
221Account.BOOL_TRUE = 'true';
222Account.BOOL_FALSE = 'false';
223
224export default Account;