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