blob: 5776c59e0609734b0f5a0d121adb490618f0d494 [file] [log] [blame]
/*
* Copyright (C) 2022 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
import { Contact } from './Contact.js';
import { PromiseExecutor } from './util.js';
export interface ConversationMember {
contact: Contact;
role?: 'admin' | 'member' | 'invited' | 'banned' | 'left';
}
type ConversationInfos = Record<string, unknown>;
export type Message = {
id: string;
author: string;
timestamp: string;
type:
| 'application/call-history+json'
| 'application/data-transfer+json'
| 'application/update-profile'
| 'initial'
| 'member'
| 'merge'
| 'text/plain'
| 'vote';
linearizedParent: string;
parents: string;
body?: string;
duration?: string;
to?: string;
invited?: string;
};
type ConversationRequest = PromiseExecutor<Message[]>;
type ConversationListeners = Record<
string,
{
socket: any; // TODO: Improve typing
session: any;
}
>;
export class Conversation {
private readonly id: string | undefined;
private readonly accountId: string;
private readonly members: ConversationMember[];
private messages: Message[];
private _infos: ConversationInfos;
private _requests: Record<string, ConversationRequest>;
private _listeners: ConversationListeners;
constructor(id: string | undefined, accountId: string, members?: ConversationMember[]) {
this.id = id;
this.accountId = accountId;
this.members = members || [];
this.messages = [];
this._infos = {};
this._requests = {};
this._listeners = {};
}
static from(accountId: string, object: any) {
const conversation = new Conversation(
object.id,
accountId,
object.members.map((member: any) => {
member.contact = Contact.from(member.contact);
return member;
})
);
conversation.messages = object.messages;
conversation.infos = object.infos;
return conversation;
}
static fromSingleContact(accountId: string, contact: Contact) {
return new Conversation(undefined, accountId, [{ contact }]);
}
getId() {
return this.id;
}
getAccountId() {
return this.accountId;
}
getDisplayName() {
if (this.members.length !== 0) {
return this.members[0].contact.getDisplayName();
}
return this.getDisplayUri();
}
getDisplayNameNoFallback() {
if (this.members.length !== 0) {
return this.members[0].contact.getDisplayNameNoFallback();
}
}
async getObject(params?: {
memberFilter: (value: ConversationMember, index: number, array: ConversationMember[]) => boolean;
}) {
const members = params?.memberFilter ? this.members.filter(params.memberFilter) : this.members;
return {
id: this.id,
messages: this.messages,
members: await Promise.all(
members.map(async (member) => {
//Object.assign({}, member);
return {
role: member.role,
contact: await member.contact.getObject(),
};
})
),
infos: this._infos,
};
}
getSummary() {
return this.getObject();
}
getDisplayUri() {
return this.getId() || this.getFirstMember().contact.getUri();
}
getFirstMember() {
return this.members[0];
}
getMembers() {
return this.members;
}
addMessage(message: Message) {
if (this.messages.length === 0) this.messages.push(message);
else if (message.id === this.messages[this.messages.length - 1].linearizedParent) {
this.messages.push(message);
} else if (message.linearizedParent === this.messages[0].id) {
this.messages.unshift(message);
} else {
console.log("Can't insert message " + message.id);
}
}
addLoadedMessages(messages: Message[]) {
messages.forEach((message) => this.addMessage(message));
}
getMessages() {
return this.messages;
}
get infos() {
return this._infos;
}
set infos(infos: ConversationInfos) {
this._infos = infos;
}
get requests(): Record<string, ConversationRequest> {
return this._requests;
}
set requests(value: Record<string, ConversationRequest>) {
this._requests = value;
}
get listeners(): ConversationListeners {
return this._listeners;
}
set listeners(listeners: ConversationListeners) {
this._listeners = listeners;
}
}