blob: ce529c0af0dfde7643ee85845e7ba0102b10393a [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;
28 private contactCache: Record<string, Contact> = {};
29 private _contacts: Contact[] = [];
30 private conversations: Record<string, Conversation> = {};
31 private defaultModerators: Contact[] = [];
32 private _lookups: Lookup[] = [];
33 private devices: Devices = {};
34 private _registrationState: RegistrationState | undefined = undefined;
35 private _registeringName: AccountRegisteringName | undefined = undefined;
36
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;
44 this._details = details;
45 this._volatileDetails = volatileDetails;
46 }
47
48 static from(object: Account) {
49 const account = new Account(object.id, object._details, object._volatileDetails);
50 if (object.defaultModerators) account.defaultModerators = object.defaultModerators.map((m) => Contact.from(m));
51 return account;
52 }
53
54 update(data: Account) {
55 this._details = data._details;
56 this._volatileDetails = data._volatileDetails;
57 }
58
59 async getObject() {
60 const hasModerators = this.defaultModerators && this.defaultModerators.length;
61 return {
62 id: this.id,
63 details: this._details,
64 defaultModerators: hasModerators
65 ? await Promise.all(this.defaultModerators.map(async (c) => await c.getObject()))
66 : undefined,
67 volatileDetails: this._volatileDetails,
68 };
69 }
70
71 getId() {
72 return this.id;
73 }
74
75 getType() {
76 return this._details['Account.type'];
77 }
78
79 getUri() {
80 return this._details['Account.username'];
81 }
82
83 getRegisteredName() {
84 return this._volatileDetails['Account.registeredName'];
85 }
86
87 isRendezVous() {
88 return this._details['Account.rendezVous'] === Account.BOOL_TRUE;
89 }
90
91 isPublicIn() {
92 return this._details['DHT.PublicInCalls'] === Account.BOOL_TRUE;
93 }
94
95 setDetail(detail: keyof AccountDetails, value: string) {
96 this._details[detail] = value;
97 }
98
99 updateDetails(details: Partial<AccountDetails>) {
100 return Object.assign(this._details, details);
101 }
102
103 getDetails() {
104 return this._details;
105 }
106
107 getSummary() {
108 return this.getObject();
109 }
110
111 getDisplayName() {
112 return this._details['Account.displayName'] || this.getDisplayUri();
113 }
114
115 getDisplayUri() {
116 return this.getRegisteredName() || this.getUri();
117 }
118
119 getDisplayNameNoFallback() {
120 return this._details['Account.displayName'] || this.getRegisteredName();
121 }
122
123 getConversationIds() {
124 return Object.keys(this.conversations);
125 }
126
127 getConversations() {
128 return this.conversations;
129 }
130
131 getConversation(conversationId: string) {
132 return this.conversations[conversationId];
133 }
134
135 addConversation(conversation: Conversation) {
136 const conversationId = conversation.getId();
137 if (conversationId != null) {
138 this.conversations[conversationId] = conversation;
139 } else {
140 throw new Error('Conversation ID cannot be undefined');
141 }
142 }
143
144 removeConversation(conversationId: string) {
145 delete this.conversations[conversationId];
146 }
147
148 getContactFromCache(uri: string) {
149 let contact = this.contactCache[uri];
150 if (!contact) {
151 contact = new Contact(uri);
152 this.contactCache[uri] = contact;
153 }
154 return contact;
155 }
156
157 getContacts() {
158 return this._contacts;
159 }
160
161 set contacts(contacts: Contact[]) {
162 this._contacts = contacts;
163 }
164
165 getDefaultModerators() {
166 return this.defaultModerators;
167 }
168
169 set details(value: AccountDetails) {
170 this._details = value;
171 }
172
173 set volatileDetails(value: VolatileDetails) {
174 this._volatileDetails = value;
175 }
176
177 get lookups(): Lookup[] {
178 return this._lookups;
179 }
180
181 set lookups(lookups: Lookup[]) {
182 this._lookups = lookups;
183 }
184
185 setDevices(devices: Devices) {
186 this.devices = { ...devices };
187 }
188
189 getDevices() {
190 return this.devices;
191 }
192
193 get registrationState(): RegistrationState | undefined {
194 return this._registrationState;
195 }
196
197 set registrationState(registrationState: RegistrationState | undefined) {
198 this._registrationState = registrationState;
199 }
200
201 get registeringName(): AccountRegisteringName | undefined {
202 return this._registeringName;
203 }
204
205 set registeringName(registeringName: AccountRegisteringName | undefined) {
206 this._registeringName = registeringName;
207 }
208}
209
210Account.TYPE_JAMI = 'RING';
211Account.TYPE_SIP = 'SIP';
212
213Account.BOOL_TRUE = 'true';
214Account.BOOL_FALSE = 'false';
215
216export default Account;