208 lines
7.5 KiB
TypeScript
208 lines
7.5 KiB
TypeScript
import {
|
|
createRoom,
|
|
registerMessageInRoom,
|
|
getRoomType,
|
|
findRoomsFromMessage,
|
|
hasSameMembersAsParent,
|
|
registerThread,
|
|
registerMember,
|
|
getAllMembers,
|
|
getThreadInfo,
|
|
incrementNotSeenRoom,
|
|
getThreadInfoOnId,
|
|
} from "../db/saveMessage-db";
|
|
|
|
import { findRoomByOwner, getAddresseId, getUserIdOfMailbox } from "../db/utils/mail";
|
|
import { nbMembers } from "./utils/envelopeUtils";
|
|
import logger from "../system/Logger";
|
|
import { Attrs, Envelope, User } from "../interfaces/mail/attrs.interface";
|
|
|
|
/**
|
|
* take object address and join mailbox and host to return mailbox@host
|
|
*/
|
|
function createAddress(elt: User): string {
|
|
return `${elt.mailbox}@${elt.host}`;
|
|
}
|
|
|
|
export enum RoomType {
|
|
ROOM = 0,
|
|
CHANNEL = 1,
|
|
GROUP = 2,
|
|
DM = 3,
|
|
THREAD = 4,
|
|
}
|
|
|
|
export default class RegisterMessageInApp {
|
|
messageId: number;
|
|
attrs: Attrs;
|
|
envelope: Envelope;
|
|
messageID?: string;
|
|
boxId: number;
|
|
isSeen: boolean;
|
|
ownerId: number;
|
|
userId: number;
|
|
inReplyTo: string;
|
|
|
|
constructor(_messageId: number, _attrs: Attrs, _boxId: number) {
|
|
this.messageId = _messageId;
|
|
this.attrs = _attrs;
|
|
if (!this.attrs.envelope) throw new Error("Envelope must exist in attributes");
|
|
this.envelope = this.attrs.envelope;
|
|
this.messageID = this.envelope?.messageId;
|
|
this.boxId = _boxId;
|
|
this.isSeen = this.attrs.flags.includes("\\Seen") ? true : false;
|
|
this.ownerId = -1;
|
|
this.userId = -1;
|
|
this.inReplyTo = "";
|
|
}
|
|
|
|
async init() {
|
|
if (this.envelope.from) {
|
|
this.ownerId = await getAddresseId(createAddress(this.envelope.from[0])); // todo use sender or from ?
|
|
} else {
|
|
throw new Error("Envelope must have a 'from' field");
|
|
}
|
|
}
|
|
|
|
isDm = () => nbMembers(this.envelope) == 2;
|
|
|
|
async isFromUs() {
|
|
if (this.userId == -1) {
|
|
await getUserIdOfMailbox(this.boxId).then((res) => {
|
|
this.userId = res[0]?.user_id;
|
|
});
|
|
}
|
|
return this.ownerId == this.userId;
|
|
}
|
|
|
|
async incrementNotSeen(roomId: number) {
|
|
if (!this.isSeen) {
|
|
await incrementNotSeenRoom(roomId);
|
|
}
|
|
}
|
|
|
|
async registerMembers(roomId: number) {
|
|
getAllMembers(this.messageId).then((res) => {
|
|
if (res.lenght == 0) return;
|
|
const data = res[0].id.split(",");
|
|
data.forEach(async (memberId: number) => {
|
|
await registerMember(roomId, memberId);
|
|
});
|
|
});
|
|
}
|
|
|
|
async initiateRoom(owner: number, roomType: RoomType) {
|
|
try {
|
|
const roomId = await createRoom(this.envelope.subject, owner, this.messageId, roomType);
|
|
await registerMessageInRoom(this.messageId, roomId, this.envelope.date);
|
|
await this.incrementNotSeen(roomId);
|
|
await this.registerMembers(roomId);
|
|
return roomId;
|
|
} catch (err) {
|
|
logger.err(err);
|
|
}
|
|
}
|
|
|
|
async createOrRegisterOnExistence(owner: number, roomType: RoomType) {
|
|
await findRoomByOwner(owner).then(async (res) => {
|
|
if (res.length == 0) {
|
|
// first message with this sender
|
|
await this.initiateRoom(owner, roomType);
|
|
} else {
|
|
// not a reply, add to the list of message if this sender
|
|
await registerMessageInRoom(this.messageId, res[0].room_id, this.envelope.date);
|
|
await this.incrementNotSeen(res[0].room_id);
|
|
}
|
|
});
|
|
}
|
|
|
|
async initiateThread() {
|
|
await createRoom(this.envelope.subject, this.ownerId, this.messageId, RoomType.THREAD).then(
|
|
async (threadId: number) => {
|
|
// find parent room infos
|
|
let roomId: number;
|
|
let root_id: number;
|
|
await getThreadInfo(this.inReplyTo).then(async (room) => {
|
|
// todo room not lenght, reply to transfer ?
|
|
roomId = room[0].room_id;
|
|
root_id = room[0].root_id;
|
|
if (root_id === undefined) root_id = roomId;
|
|
await registerThread(threadId, roomId, root_id);
|
|
});
|
|
// impl register previous message or go back
|
|
await registerMessageInRoom(this.messageId, threadId, this.envelope.date);
|
|
await this.incrementNotSeen(root_id);
|
|
await this.incrementNotSeen(threadId);
|
|
await this.registerMembers(threadId);
|
|
},
|
|
);
|
|
}
|
|
|
|
async createOrRegisterOnMembers(roomId: number, isThread?: boolean) {
|
|
const hasSameMembers = await hasSameMembersAsParent(this.messageId, this.inReplyTo);
|
|
if (hasSameMembers) {
|
|
await registerMessageInRoom(this.messageId, roomId, this.envelope.date);
|
|
await this.incrementNotSeen(roomId);
|
|
if (isThread) {
|
|
await getThreadInfoOnId(roomId).then(async (res) => {
|
|
let root_id = res[0].root_id;
|
|
if (root_id == undefined) root_id = res[0].room_id;
|
|
await this.incrementNotSeen(res[0].root_id);
|
|
});
|
|
}
|
|
} else {
|
|
await this.initiateThread();
|
|
}
|
|
}
|
|
|
|
async save() {
|
|
await this.init();
|
|
if (this.envelope.inReplyTo) {
|
|
this.inReplyTo = this.envelope.inReplyTo;
|
|
await this.saveReply();
|
|
} else {
|
|
if (await this.isFromUs()) {
|
|
if (this.isDm()) {
|
|
// create or add new message to DM
|
|
if (!this.envelope.to) throw new Error("Who send a DM and put the recipient in cc ?");
|
|
const userTo = await getAddresseId(createAddress(this.envelope.to[0]));
|
|
await this.createOrRegisterOnExistence(userTo, RoomType.DM);
|
|
} else {
|
|
// it is not a reply and not a dm
|
|
// so it is a channel, which can be possibly a group
|
|
await this.initiateRoom(this.ownerId, RoomType.ROOM);
|
|
}
|
|
} else {
|
|
await this.createOrRegisterOnExistence(this.ownerId, RoomType.ROOM);
|
|
}
|
|
}
|
|
}
|
|
|
|
async saveReply() {
|
|
await findRoomsFromMessage(this.inReplyTo).then(async (rooms) => {
|
|
if (rooms.length < 1) {
|
|
// no rooms, so is a transfer
|
|
// todo test if members of transferred message are included
|
|
} else if (rooms.length === 1) {
|
|
// only one room so message is only in a room and not in a thread
|
|
// as a thread is associated to a room
|
|
const roomType = (await getRoomType(rooms[0].room_id))[0].room_type;
|
|
if (roomType == RoomType.GROUP || roomType == RoomType.THREAD) {
|
|
await this.createOrRegisterOnMembers(rooms[0].room_id, roomType == RoomType.THREAD);
|
|
} else {
|
|
// reply from CHANNEL or DM or ROOM
|
|
await this.initiateThread();
|
|
// todo
|
|
// if (sender == owner) { // correction from the original sender
|
|
// // leave in the same channel
|
|
// }
|
|
}
|
|
} else if (rooms.length > 1) {
|
|
// get the lowest thread (order by room_id)
|
|
const roomId = rooms[rooms.length - 1].room_id;
|
|
await this.createOrRegisterOnMembers(roomId);
|
|
}
|
|
});
|
|
}
|
|
}
|