blob: 7b55de93889386acfbb06f82f39e4aebd72e4f0c [file] [log] [blame]
simon26e79f72022-10-05 22:16:08 -04001/*
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 */
simon20076982022-10-11 15:04:13 -040018import { Contact } from './Contact.js';
simond8ca2f22022-10-11 23:30:55 -040019import { PromiseExecutor } from './util.js';
simon06527b02022-10-01 15:01:47 -040020
21export interface ConversationMember {
22 contact: Contact;
23 role?: 'admin' | 'member' | 'invited' | 'banned' | 'left';
24}
25
26type ConversationInfos = Record<string, unknown>;
27
28export type Message = Record<string, string>;
29type ConversationRequest = PromiseExecutor<Message[]>;
30
31type ConversationListeners = Record<
32 string,
33 {
simond8ca2f22022-10-11 23:30:55 -040034 socket: any; // TODO: Improve typing
35 session: any;
simon06527b02022-10-01 15:01:47 -040036 }
37>;
38
simon20076982022-10-11 15:04:13 -040039export class Conversation {
simon06527b02022-10-01 15:01:47 -040040 private readonly id: string | undefined;
41 private readonly accountId: string;
42 private readonly members: ConversationMember[];
simon5e32f742022-10-04 18:03:12 -040043 private messages: Message[];
44 private _infos: ConversationInfos;
45 private _requests: Record<string, ConversationRequest>;
46 private _listeners: ConversationListeners;
simon06527b02022-10-01 15:01:47 -040047
48 constructor(id: string | undefined, accountId: string, members?: ConversationMember[]) {
49 this.id = id;
50 this.accountId = accountId;
51 this.members = members || [];
simon5e32f742022-10-04 18:03:12 -040052
53 this.messages = [];
54 this._infos = {};
55 this._requests = {};
56 this._listeners = {};
simon06527b02022-10-01 15:01:47 -040057 }
58
simon5e32f742022-10-04 18:03:12 -040059 static from(accountId: string, object: any) {
simon06527b02022-10-01 15:01:47 -040060 const conversation = new Conversation(
61 object.id,
62 accountId,
simon5e32f742022-10-04 18:03:12 -040063 object.members.map((member: any) => {
simon06527b02022-10-01 15:01:47 -040064 member.contact = Contact.from(member.contact);
65 return member;
66 })
67 );
68 conversation.messages = object.messages;
69 return conversation;
70 }
71 static fromSingleContact(accountId: string, contact: Contact) {
72 return new Conversation(undefined, accountId, [{ contact }]);
73 }
74
75 getId() {
76 return this.id;
77 }
78
79 getAccountId() {
80 return this.accountId;
81 }
82
83 getDisplayName() {
84 if (this.members.length !== 0) {
85 return this.members[0].contact.getDisplayName();
86 }
87 return this.getDisplayUri();
88 }
89
90 getDisplayNameNoFallback() {
91 if (this.members.length !== 0) {
92 return this.members[0].contact.getDisplayNameNoFallback();
93 }
94 }
95
96 async getObject(params?: {
97 memberFilter: (value: ConversationMember, index: number, array: ConversationMember[]) => boolean;
98 }) {
99 const members = params?.memberFilter ? this.members.filter(params.memberFilter) : this.members;
100 return {
101 id: this.id,
102 messages: this.messages,
103 members: await Promise.all(
104 members.map(async (member) => {
105 //Object.assign({}, member);
106 return {
107 role: member.role,
108 contact: await member.contact.getObject(),
109 };
110 })
111 ),
112 };
113 }
114
115 getSummary() {
116 return this.getObject();
117 }
118
119 getDisplayUri() {
120 return this.getId() || this.getFirstMember().contact.getUri();
121 }
122
123 getFirstMember() {
124 return this.members[0];
125 }
126
127 getMembers() {
128 return this.members;
129 }
130
131 addMessage(message: Message) {
132 if (this.messages.length === 0) this.messages.push(message);
133 else if (message.id === this.messages[this.messages.length - 1].linearizedParent) {
134 this.messages.push(message);
135 } else if (message.linearizedParent === this.messages[0].id) {
136 this.messages.unshift(message);
137 } else {
138 console.log("Can't insert message " + message.id);
139 }
140 }
141
142 addLoadedMessages(messages: Message[]) {
143 messages.forEach((message) => this.addMessage(message));
144 }
145
146 getMessages() {
147 return this.messages;
148 }
149
150 set infos(infos: ConversationInfos) {
151 this._infos = infos;
152 }
153
154 get requests(): Record<string, ConversationRequest> {
155 return this._requests;
156 }
157
158 set requests(value: Record<string, ConversationRequest>) {
159 this._requests = value;
160 }
161
162 get listeners(): ConversationListeners {
163 return this._listeners;
164 }
165
166 set listeners(listeners: ConversationListeners) {
167 this._listeners = listeners;
168 }
169}