started to convert to typescript

This commit is contained in:
grimhilt 2023-04-01 16:32:29 +02:00
parent aced3b8914
commit 90dd16ee0d
32 changed files with 1045 additions and 3897 deletions

View File

@ -1,8 +1,8 @@
const statusCode = require("../utils/statusCodes").statusCodes; import statusCode from "../utils/statusCodes";
const { registerAccount } = require("../db/api"); import { registerAccount } from "../db/api";
const { getAddresseId } = require("../db/mail"); import { getAddresseId } from "../db/mail";
async function addAccount(body, res) { export async function addAccount(body, res) {
const { email, pwd, xoauth, xoauth2, host, port, tls } = body; const { email, pwd, xoauth, xoauth2, host, port, tls } = body;
getAddresseId(email).then((addressId) => { getAddresseId(email).then((addressId) => {
registerAccount(addressId, pwd, xoauth, xoauth2, host, port, tls) registerAccount(addressId, pwd, xoauth, xoauth2, host, port, tls)
@ -15,8 +15,4 @@ async function addAccount(body, res) {
}); });
} }
module.exports = {
addAccount,
};
// todo change mailbox to account // todo change mailbox to account

View File

@ -1,8 +1,8 @@
const statusCode = require("../utils/statusCodes").statusCodes; import statusCode from "../utils/statusCodes";
const { getMembers } = require("../db/api.js"); import { getMembers } from "../db/api";
const { logger } = require("../system/Logger"); import logger from "../system/Logger";
async function members(body, res) { export async function members(body, res) {
const { roomId } = body; const { roomId } = body;
getMembers(roomId).then((addresses) => { getMembers(roomId).then((addresses) => {
res.status(statusCode.OK).json(addresses); res.status(statusCode.OK).json(addresses);
@ -11,7 +11,3 @@ async function members(body, res) {
res.status(statusCode.INTERNAL_SERVER_ERROR); res.status(statusCode.INTERNAL_SERVER_ERROR);
}); });
} }
module.exports = {
members,
};

View File

@ -1,17 +0,0 @@
const statusCode = require("../utils/statusCodes").statusCodes;
const { getMessages } = require("../db/api.js");
const { logger } = require("../system/Logger");
async function messages(body, res) {
const { roomId } = body;
getMessages(roomId).then((messages) => {
res.status(statusCode.OK).json(messages);
}).catch((err) => {
logger.err(err)
res.status(statusCode.INTERNAL_SERVER_ERROR);
});
}
module.exports = {
messages,
};

View File

@ -0,0 +1,13 @@
import statusCode from "../utils/statusCodes";
import { getMessages } from "../db/api";
import logger from "../system/Logger";
export async function messages(body, res) {
const { roomId } = body;
getMessages(roomId).then((messages) => {
res.status(statusCode.OK).json(messages);
}).catch((err) => {
logger.error(err)
res.status(statusCode.INTERNAL_SERVER_ERROR);
});
}

View File

@ -1,8 +1,8 @@
const statusCode = require("../utils/statusCodes").statusCodes; import statusCode from "../utils/statusCodes";
const { getRooms } = require("../db/api.js"); import { getRooms } from "../db/api";
const { logger } = require("../system/Logger"); import { logger } from "../system/Logger";
async function rooms(body, res) { export async function rooms(body, res) {
const { mailboxId, offset, limit } = body; const { mailboxId, offset, limit } = body;
getRooms(mailboxId).then((rooms) => { getRooms(mailboxId).then((rooms) => {
res.status(statusCode.OK).json(rooms); res.status(statusCode.OK).json(rooms);
@ -11,7 +11,3 @@ async function rooms(body, res) {
res.status(statusCode.INTERNAL_SERVER_ERROR); res.status(statusCode.INTERNAL_SERVER_ERROR);
}); });
} }
module.exports = {
rooms,
};

View File

@ -1,7 +1,7 @@
const { execQueryAsync, execQueryAsyncWithId } = require("./db.js"); import { execQueryAsync, execQueryAsyncWithId } from "./db";
const { queryCcId, queryToId, queryFromId } = require("./utils/addressQueries.js"); import { queryCcId, queryToId, queryFromId } from "./utils/addressQueries";
async function registerAccount(userId, pwd, xoauth, xoauth2, host, port, tls) { export async function registerAccount(userId, pwd, xoauth, xoauth2, host, port, tls) {
const query = ` const query = `
INSERT INTO app_account INSERT INTO app_account
(user_id, account_pwd, xoauth, xoauth2, host, port, tls) VALUES (?, ?, ?, ?, ?, ?, ?) (user_id, account_pwd, xoauth, xoauth2, host, port, tls) VALUES (?, ?, ?, ?, ?, ?, ?)
@ -10,7 +10,7 @@ async function registerAccount(userId, pwd, xoauth, xoauth2, host, port, tls) {
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }
async function getAccounts() { export async function getAccounts() {
// todo mailbox or account id ? // todo mailbox or account id ?
const query = ` const query = `
SELECT SELECT
@ -27,7 +27,7 @@ async function getAccounts() {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function getRooms(mailboxId) { export async function getRooms(mailboxId) {
const query = ` const query = `
SELECT SELECT
app_room.room_id AS id, app_room.room_id AS id,
@ -51,7 +51,7 @@ async function getRooms(mailboxId) {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function getMessages(roomId) { export async function getMessages(roomId) {
// todo attachements name // todo attachements name
const query = ` const query = `
SELECT SELECT
@ -97,7 +97,7 @@ async function getMessages(roomId) {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function getMembers(roomId) { export async function getMembers(roomId) {
const query = ` const query = `
SELECT SELECT
address.address_id, address.address_id,
@ -109,12 +109,4 @@ async function getMembers(roomId) {
`; `;
const values = [roomId]; const values = [roomId];
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
module.exports = {
registerAccount,
getAccounts,
getRooms,
getMessages,
getMembers
};

View File

@ -1,8 +1,9 @@
const mysql = require("mysql"); import mysql from "mysql";
const { logger } = require("../system/Logger"); import { logger } from "../system/Logger";
const MYSQL = require("./config.json").mysql; import MYSQL from "./config.json";
const db = mysql.createConnection({ // todo remove export
export const db = mysql.createConnection({
host: MYSQL.host, host: MYSQL.host,
user: MYSQL.user, user: MYSQL.user,
password: MYSQL.pwd, password: MYSQL.pwd,
@ -17,7 +18,7 @@ db.connect(function (err) {
} }
}); });
function execQueryAsync(query, values) { export function execQueryAsync(query, values) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.query(query, values, (err, results, fields) => { db.query(query, values, (err, results, fields) => {
if (err) { if (err) {
@ -29,7 +30,7 @@ function execQueryAsync(query, values) {
}); });
} }
function execQueryAsyncWithId(query, values) { export function execQueryAsyncWithId(query, values) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.query(query, values, (err, results, fields) => { db.query(query, values, (err, results, fields) => {
if (err) { if (err) {
@ -41,7 +42,7 @@ function execQueryAsyncWithId(query, values) {
}); });
} }
function execQuery(query, values) { export function execQuery(query, values) {
db.query(query, values, (err, results, fields) => { db.query(query, values, (err, results, fields) => {
if (err) { if (err) {
logger.error(err); logger.error(err);
@ -49,11 +50,4 @@ function execQuery(query, values) {
} }
return results; return results;
}); });
} }
module.exports = {
db, // todo remove this
execQuery,
execQueryAsync,
execQueryAsyncWithId
};

View File

@ -1,6 +1,6 @@
const { execQueryAsyncWithId, execQueryAsync, execQuery } = require("../db"); import { execQueryAsyncWithId, execQueryAsync, execQuery } from "../db";
async function getAllAccounts() { export async function getAllAccounts() {
const query = ` const query = `
SELECT SELECT
app_account.account_id AS id, app_account.account_id AS id,
@ -16,34 +16,26 @@ async function getAllAccounts() {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function getAllMailboxes(accountId) { export async function getAllMailboxes(accountId) {
const query = 'SELECT * FROM mailbox WHERE mailbox.account_id = ?'; const query = 'SELECT * FROM mailbox WHERE mailbox.account_id = ?';
const values = [accountId]; const values = [accountId];
return await execQueryAsync(query, values) return await execQueryAsync(query, values)
} }
async function registerMailbox(accountId, mailboxName) { export async function registerMailbox(accountId, mailboxName) {
const query = `INSERT INTO mailbox (account_id, mailbox_name) VALUES (?, ?)`; const query = `INSERT INTO mailbox (account_id, mailbox_name) VALUES (?, ?)`;
const values = [accountId, mailboxName]; const values = [accountId, mailboxName];
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }
async function getMailbox(mailboxId) { export async function getMailbox(mailboxId) {
const query = `SELECT * FROM mailbox WHERE mailbox_id = ?`; const query = `SELECT * FROM mailbox WHERE mailbox_id = ?`;
const values = [mailboxId]; const values = [mailboxId];
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
function updateMailbox(mailboxId, uidnext) { export function updateMailbox(mailboxId, uidnext) {
const query = `UPDATE mailbox SET uidnext = ? WHERE mailbox_id = ?`; const query = `UPDATE mailbox SET uidnext = ? WHERE mailbox_id = ?`;
const values = [uidnext, mailboxId]; const values = [uidnext, mailboxId];
execQuery(query, values); execQuery(query, values);
}
module.exports = {
getAllAccounts,
getAllMailboxes,
registerMailbox,
getMailbox,
updateMailbox
} }

View File

@ -1,6 +1,6 @@
const { execQueryAsync, execQueryAsyncWithId } = require("./db.js"); import { execQueryAsync, execQueryAsyncWithId } from "./db";
async function getAddresseId(email, name) { export async function getAddresseId(email, name) {
const localpart = email.split("@")[0]; const localpart = email.split("@")[0];
const domain = email.split("@")[1]; const domain = email.split("@")[1];
const query = `INSERT INTO address const query = `INSERT INTO address
@ -10,19 +10,19 @@ async function getAddresseId(email, name) {
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }
async function getFieldId(field) { export async function getFieldId(field) {
const query = `INSERT INTO field_name (field_name) VALUES (?) ON DUPLICATE KEY UPDATE field_id=LAST_INSERT_ID(field_id)`; const query = `INSERT INTO field_name (field_name) VALUES (?) ON DUPLICATE KEY UPDATE field_id=LAST_INSERT_ID(field_id)`;
const values = [field] const values = [field];
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }
async function findRoomByOwner(ownerId) { export async function findRoomByOwner(ownerId) {
const query = `SELECT room_id FROM app_room WHERE owner_id = ?`; const query = `SELECT room_id FROM app_room WHERE owner_id = ?`;
const values = [ownerId]; const values = [ownerId];
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function getUserIdOfMailbox(boxId) { export async function getUserIdOfMailbox(boxId) {
const query = ` const query = `
SELECT app_account.user_id SELECT app_account.user_id
FROM mailbox FROM mailbox
@ -32,10 +32,3 @@ async function getUserIdOfMailbox(boxId) {
const values = [boxId]; const values = [boxId];
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
module.exports = {
getAddresseId,
getFieldId,
findRoomByOwner,
getUserIdOfMailbox
};

View File

@ -1,7 +1,7 @@
const { transformEmojis } = require("../utils/string.js"); import { transformEmojis } from "../utils/string";
const { db, execQuery, execQueryAsync, execQueryAsyncWithId } = require("./db.js"); import { execQuery, execQueryAsync, execQueryAsyncWithId } from "./db";
async function registerMessage(timestamp, rfc822size, messageId) { export async function registerMessage(timestamp, rfc822size, messageId) {
const query = ` const query = `
INSERT INTO message INSERT INTO message
(idate, messageID, rfc822size) VALUES (?, ?, ?) (idate, messageID, rfc822size) VALUES (?, ?, ?)
@ -11,7 +11,7 @@ async function registerMessage(timestamp, rfc822size, messageId) {
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }
function registerMailbox_message(mailboxId, uid, messageId, modseq, seen, deleted) { export function registerMailbox_message(mailboxId, uid, messageId, modseq, seen, deleted) {
const query = ` const query = `
INSERT IGNORE INTO mailbox_message INSERT IGNORE INTO mailbox_message
(mailbox_id, uid, message_id, modseq, seen, deleted) VALUES (?, ?, ?, ?, ?, ?) (mailbox_id, uid, message_id, modseq, seen, deleted) VALUES (?, ?, ?, ?, ?, ?)
@ -20,7 +20,7 @@ function registerMailbox_message(mailboxId, uid, messageId, modseq, seen, delete
execQuery(query, values); execQuery(query, values);
} }
function registerBodypart(messageId, part, bodypartId, bytes, nbLines) { export function registerBodypart(messageId, part, bodypartId, bytes, nbLines) {
const query = ` const query = `
INSERT IGNORE INTO part_number INSERT IGNORE INTO part_number
(message_id, part, bodypart_id, bytes, nb_lines) VALUES (?, ?, ?, ?, ?) (message_id, part, bodypart_id, bytes, nb_lines) VALUES (?, ?, ?, ?, ?)
@ -29,14 +29,14 @@ function registerBodypart(messageId, part, bodypartId, bytes, nbLines) {
execQuery(query, values); execQuery(query, values);
} }
async function saveBodypart(bytes, hash, text, data) { export async function saveBodypart(bytes, hash, text, data) {
text = transformEmojis(text); text = transformEmojis(text);
const query = `INSERT IGNORE INTO bodypart (bytes, hash, text, data) VALUES (?, ?, ?, ?)`; const query = `INSERT IGNORE INTO bodypart (bytes, hash, text, data) VALUES (?, ?, ?, ?)`;
const values = [bytes, hash, text, data]; const values = [bytes, hash, text, data];
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }
async function saveHeader_fields(messageId, fieldId, bodypartId, part, value) { export async function saveHeader_fields(messageId, fieldId, bodypartId, part, value) {
value = transformEmojis(value); value = transformEmojis(value);
const query = ` const query = `
INSERT IGNORE INTO header_field INSERT IGNORE INTO header_field
@ -46,7 +46,7 @@ async function saveHeader_fields(messageId, fieldId, bodypartId, part, value) {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function saveAddress_fields(messageId, fieldId, addressId, number) { export async function saveAddress_fields(messageId, fieldId, addressId, number) {
const query = ` const query = `
INSERT IGNORE INTO address_field INSERT IGNORE INTO address_field
(message_id , field_id, address_id, number) VALUES (?, ?, ?, ?) (message_id , field_id, address_id, number) VALUES (?, ?, ?, ?)
@ -55,7 +55,7 @@ async function saveAddress_fields(messageId, fieldId, addressId, number) {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
function saveSource(messageId, content) { export function saveSource(messageId, content) {
content = transformEmojis(content); content = transformEmojis(content);
const query = ` const query = `
INSERT INTO source (message_id, content) VALUES (?, ?) INSERT INTO source (message_id, content) VALUES (?, ?)
@ -63,14 +63,4 @@ function saveSource(messageId, content) {
`; `;
const values = [messageId, content, content]; const values = [messageId, content, content];
execQuery(query, values); execQuery(query, values);
}
module.exports = {
registerMessage,
registerMailbox_message,
saveHeader_fields,
saveAddress_fields,
registerBodypart,
saveBodypart,
saveSource
} }

View File

@ -1,8 +1,8 @@
const { transformEmojis } = require("../utils/string.js"); import { transformEmojis } from "../utils/string";
const { db, execQueryAsync, execQueryAsyncWithId, execQuery } = require("./db.js"); import { db, execQueryAsync, execQueryAsyncWithId, execQuery } from "./db";
const { queryFromId, queryToId, queryCcId } = require("./utils/addressQueries.js"); import { queryFromId, queryToId, queryCcId } from "./utils/addressQueries";
async function getAllMembers(messageId) { export async function getAllMembers(messageId) {
const query = ` const query = `
SELECT GROUP_CONCAT(address.address_id) AS is SELECT GROUP_CONCAT(address.address_id) AS is
FROM address FROM address
@ -15,13 +15,13 @@ async function getAllMembers(messageId) {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function registerMember(roomId, memberId) { export async function registerMember(roomId, memberId) {
const query = `INSERT IGNORE INTO app_room_member (room_id, member_id) VALUES (?, ?)`; const query = `INSERT IGNORE INTO app_room_member (room_id, member_id) VALUES (?, ?)`;
const values = [roomId, memberId]; const values = [roomId, memberId];
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function createRoom(roomName, ownerId, messageId, roomType) { export async function createRoom(roomName, ownerId, messageId, roomType) {
if (!roomName) roomName = "No room name"; if (!roomName) roomName = "No room name";
roomName = transformEmojis(roomName); roomName = transformEmojis(roomName);
const query = `INSERT IGNORE INTO app_room (room_name, owner_id, message_id, room_type) VALUES (?, ?, ?, ?)`; const query = `INSERT IGNORE INTO app_room (room_name, owner_id, message_id, room_type) VALUES (?, ?, ?, ?)`;
@ -29,7 +29,7 @@ async function createRoom(roomName, ownerId, messageId, roomType) {
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }
async function registerMessageInRoom(messageId, roomId, isSeen, idate) { export async function registerMessageInRoom(messageId, roomId, isSeen, idate) {
const query = `INSERT IGNORE INTO app_room_message (message_id, room_id) VALUES (?, ?)`; const query = `INSERT IGNORE INTO app_room_message (message_id, room_id) VALUES (?, ?)`;
const values = [messageId, roomId]; const values = [messageId, roomId];
await execQueryAsync(query, values); await execQueryAsync(query, values);
@ -40,17 +40,17 @@ async function registerMessageInRoom(messageId, roomId, isSeen, idate) {
// } // }
} }
function updateLastUpdateRoom(roomId, idate) { export function updateLastUpdateRoom(roomId, idate) {
const query = `UPDATE app_room SET lastUpdate = ? WHERE room_id = ?`; const query = `UPDATE app_room SET lastUpdate = ? WHERE room_id = ?`;
const values = [idate, roomId]; const values = [idate, roomId];
execQuery(query, values); execQuery(query, values);
} }
function incrementNotSeenRoom(roomId) { export function incrementNotSeenRoom(roomId) {
// todo // todo
} }
async function getRoomInfo(messageID) { export async function getRoomInfo(messageID) {
const query = ` const query = `
SELECT SELECT
app_room.room_id app_room.room_id
@ -65,13 +65,13 @@ async function getRoomInfo(messageID) {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function registerThread(roomId, parentId, rootId) { export async function registerThread(roomId, parentId, rootId) {
const query = `INSERT IGNORE INTO app_thread (room_id, parent_id, root_id) VALUES (?, ?, ?)`; const query = `INSERT IGNORE INTO app_thread (room_id, parent_id, root_id) VALUES (?, ?, ?)`;
const values = [roomId, parentId, rootId]; const values = [roomId, parentId, rootId];
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function isRoomGroup(roomId) { export async function isRoomGroup(roomId) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const query = `SELECT isGroup FROM app_room WHERE room_id = '${roomId}'`; const query = `SELECT isGroup FROM app_room WHERE room_id = '${roomId}'`;
db.query(query, (err, results, fields) => { db.query(query, (err, results, fields) => {
@ -81,13 +81,13 @@ async function isRoomGroup(roomId) {
}); });
} }
async function findRoomsFromMessage(messageId) { export async function findRoomsFromMessage(messageId) {
const query = `SELECT room_id FROM app_room_message WHERE message_id = ? ORDER BY room_id`; const query = `SELECT room_id FROM app_room_message WHERE message_id = ? ORDER BY room_id`;
const values = [messageId]; const values = [messageId];
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function hasSameMembersAsParent(messageId, messageID) { export async function hasSameMembersAsParent(messageId, messageID) {
const query1 = ` const query1 = `
SELECT SELECT
GROUP_CONCAT(fromT.address_id) AS fromA, GROUP_CONCAT(fromT.address_id) AS fromA,
@ -129,16 +129,4 @@ async function hasSameMembersAsParent(messageId, messageID) {
addressesMsg1.length == addressesMsg2.length && addressesMsg1.length == addressesMsg2.length &&
addressesMsg1.reduce((a, b) => a && addressesMsg2.includes(b), true) addressesMsg1.reduce((a, b) => a && addressesMsg2.includes(b), true)
); );
} }
module.exports = {
getAllMembers,
registerMember,
createRoom,
registerMessageInRoom,
registerThread,
isRoomGroup,
findRoomsFromMessage,
hasSameMembersAsParent,
getRoomInfo
};

View File

@ -0,0 +1,5 @@
export interface User {
name: string,
mailbox: string,
host: string
}

View File

@ -1,9 +1,15 @@
const { getMailbox, updateMailbox } = require("../../db/imap/imap"); import { ImapMessageAttributes } from "imap";
const { logger } = require("../../system/Logger"); import { getMailbox, updateMailbox } from "../../db/imap/imap";
const { registerMessageInApp } = require("../saveMessage"); import logger from "../../system/Logger";
const { saveMessage } = require("../storeMessage"); import RegisterMessageInApp from "../saveMessage";
import { saveMessage } from "../storeMessage";
export default class Box {
imap: Imap;
boxName: string;
id: number;
box: Object;
class Box {
constructor(_imap, _boxId, _boxName) { constructor(_imap, _boxId, _boxName) {
this.imap = _imap; this.imap = _imap;
this.boxName = _boxName; this.boxName = _boxName;
@ -23,16 +29,18 @@ class Box {
} }
sync(savedUid, currentUid) { sync(savedUid, currentUid) {
const promises = []; const promises: Promise<unknown>[] = [];
const mails = []; const mails: ImapMessageAttributes[] = [];
logger.log(`Syncing from ${savedUid} to ${currentUid} uid`); logger.log(`Syncing from ${savedUid} to ${currentUid} uid`);
const f = this.imap.seq.fetch(`${savedUid}:${currentUid}`, { const f = this.imap.seq.fetch(`${savedUid}:${currentUid}`, {
// const f = this.imap.seq.fetch(`${savedUid}:${currentUid}`, {
size: true, size: true,
envelope: true, envelope: true,
}); });
f.on("message", (msg, seqno) => { f.on("message", (msg, seqno) => {
msg.once("attributes", (attrs) => { msg.once("attributes", (attrs: Attrs) => {
console.log(attrs.envelope)
mails.push(attrs); mails.push(attrs);
promises.push(saveMessage(attrs, this.id, this.imap)); promises.push(saveMessage(attrs, this.id, this.imap));
}); });
@ -44,14 +52,15 @@ class Box {
f.once("end", async () => { f.once("end", async () => {
let step = 20; let step = 20;
logger.log(promises.length)
for (let i = 0; i < promises.length; i += step) { for (let i = 0; i < promises.length; i += step) {
for (let j = i; j < (i + step && promises.length); j++) { for (let j = i; j < (i + step && promises.length); j++) {
console.log(j, promises.length, promises[j])
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
promises[j] promises[j]
.then(async (res) => { .then(async (res) => {
await registerMessageInApp(res, mails[j], this.id); const register = new RegisterMessageInApp(res, mails[j], this.id);
resolve(); await register.save();
resolve("");
}) })
.catch((err) => { .catch((err) => {
reject(err); reject(err);
@ -61,16 +70,7 @@ class Box {
logger.log(`Saved messages ${i + step > promises.length ? promises.length : i + step}/${mails.length}`); logger.log(`Saved messages ${i + step > promises.length ? promises.length : i + step}/${mails.length}`);
updateMailbox(this.id, mails[i].uid); updateMailbox(this.id, mails[i].uid);
} }
// await Promise.all(promises).then(async (res) => {
// for (let i = 0; i < mails.length; i++) {
// logger.log(`Saved message ${i}/${mails.length}`);
// }
// });
updateMailbox(this.id, currentUid); updateMailbox(this.id, currentUid);
}); });
} }
} }
module.exports = {
Box,
};

View File

@ -1,9 +1,15 @@
const Imap = require("imap"); import { Account } from "./ImapSync";
const { getAllMailboxes, registerMailbox } = require("../../db/imap/imap");
const { logger } = require("../../system/Logger"); import Imap from "imap";
const { Box } = require("./Box"); import { getAllMailboxes, registerMailbox } from "../../db/imap/imap";
import logger from "../../system/Logger";
import Box from "./Box";
export class ImapInstance {
imap: Imap;
account: Account;
boxes: Box[];
class ImapInstance {
constructor(account) { constructor(account) {
this.imap = new Imap({ this.imap = new Imap({
user: account.user, user: account.user,
@ -68,8 +74,4 @@ class ImapInstance {
if (!allBox.includes("/")) logger.warn("Did not find 'All' mailbox"); if (!allBox.includes("/")) logger.warn("Did not find 'All' mailbox");
return allBox; return allBox;
} }
} }
module.exports = {
ImapInstance,
};

View File

@ -1,28 +0,0 @@
const { getAllAccounts } = require("../../db/imap/imap");
const { logger } = require("../../system/Logger");
const { ImapInstance } = require("./ImapInstance");
class ImapSync {
constructor() {
this.instances = [];
}
init() {
getAllAccounts().then((accounts) => {
for (let i = 0; i < accounts.length; i++) {
accounts[i].password = accounts[i]?.password.toString().replace(/[\u{0080}-\u{FFFF}]/gu,"");
this.addInstance(accounts[i]);
}
}).catch((err) => {
logger.error(err);
});
}
addInstance(config) {
this.instances.push(new ImapInstance(config));
}
}
module.exports = {
ImapSync
}

View File

@ -0,0 +1,33 @@
import { getAllAccounts } from "../../db/imap/imap";
import logger from "../../system/Logger";
import { ImapInstance } from "./ImapInstance";
export interface Account {
id: number;
user: string
password?: string
}
export default class ImapSync {
instances: ImapInstance[]
constructor() {
this.instances = [];
}
init() {
getAllAccounts().then((accounts: Account[]) => {
for (let i = 0; i < accounts.length; i++) {
accounts[i].password = accounts[i]?.password?.toString().replace(/[\u{0080}-\u{FFFF}]/gu,"");
if (accounts[i].id == 2) continue; //debug_todo
this.addInstance(accounts[i]);
}
}).catch((err) => {
logger.error(err);
});
}
addInstance(config) {
this.instances.push(new ImapInstance(config));
}
}

View File

@ -1,19 +1,18 @@
const { import {
createRoom, createRoom,
registerMessageInRoom, registerMessageInRoom,
createThread,
registerMessageInThread,
isRoomGroup, isRoomGroup,
findRoomsFromMessage, findRoomsFromMessage,
hasSameMembersAsParent, hasSameMembersAsParent,
registerThread, registerThread,
registerMember, registerMember,
getAllMembers, getAllMembers,
} = require("../db/saveMessageApp"); } from "../db/saveMessageApp";
const { findRoomByOwner, getAddresseId, getUserIdOfMailbox } = require("../db/mail"); import { findRoomByOwner, getAddresseId, getUserIdOfMailbox } from "../db/mail";
const { nbMembers } = require("./utils/envelopeUtils"); import { nbMembers } from "./utils/envelopeUtils";
const { logger } = require("../system/Logger"); import logger from "../system/Logger";
import { ImapMessageAttributes } from "imap";
/** /**
* take object address and join mailbox and host to return mailbox@host * take object address and join mailbox and host to return mailbox@host
@ -22,22 +21,31 @@ function createAddress(elt) {
return `${elt.mailbox}@${elt.host}`; return `${elt.mailbox}@${elt.host}`;
} }
const roomType = { export const roomType = {
ROOM: 0, ROOM: 0,
CHANNEL: 1, CHANNEL: 1,
GROUP: 2, GROUP: 2,
DM: 3, DM: 3,
THREAD: 4 THREAD: 4,
} };
class registerMessageInApp { export default class RegisterMessageInApp {
messageId: number;
attrs: ImapMessageAttributes;
envelope?: ImapMessageAttributes.envelope;
messageID?: string;
boxId: number;
isSeen: boolean;
ownerId: number;
userId: number;
constructor(_messageId, _attrs, _boxId) { constructor(_messageId, _attrs, _boxId) {
this.messageId = _messageId; this.messageId = _messageId;
this.attrs = _attrs; this.attrs = _attrs;
this.envelope = this.attrs.envelope; this.envelope = this.attrs.envelope;
this.messageID = this.envelope.messageId; this.messageID = this.envelope?.messageId;
this.boxId = _boxId; this.boxId = _boxId;
this.isSeen = this.attrs.flags.includes("\\Seen") ? 1 : 0; this.isSeen = this.attrs.flags.includes("\\Seen") ? true : false;
this.ownerId; this.ownerId;
this.userId; this.userId;
} }
@ -55,7 +63,7 @@ class registerMessageInApp {
async registerMembers(roomId) { async registerMembers(roomId) {
getAllMembers(this.messageId).then((res) => { getAllMembers(this.messageId).then((res) => {
res[0].id.split(',').foreach(async (memberId) => { res[0].id.split(",").foreach(async (memberId) => {
await registerMember(roomId, memberId); await registerMember(roomId, memberId);
}); });
}); });
@ -89,8 +97,8 @@ class registerMessageInApp {
// find parent room infos // find parent room infos
await getRoomInfo(this.envelope.inReplyTo).then(async (room) => { await getRoomInfo(this.envelope.inReplyTo).then(async (room) => {
// todo room not lenght, reply to transfer ? // todo room not lenght, reply to transfer ?
let root_id = room[0].root_id let root_id = room[0].root_id;
if (!root_id) root_id = room[0].room_id if (!root_id) root_id = room[0].room_id;
await registerThread(roomId, room[0].room_id, root_id); await registerThread(roomId, room[0].room_id, root_id);
}); });
// impl register previous message ? // impl register previous message ?
@ -162,8 +170,3 @@ class registerMessageInApp {
}); });
} }
} }
module.exports = {
registerMessageInApp,
roomType
};

View File

@ -1,7 +1,7 @@
const { getAddresseId } = require("../db/mail"); import { getAddresseId } from "../db/mail";
const { simpleParser } = require("mailparser"); import mailParser from "mailparser";
const moment = require("moment"); import moment from "moment";
const { import {
registerMessage, registerMessage,
registerMailbox_message, registerMailbox_message,
saveHeader_fields, saveHeader_fields,
@ -9,12 +9,12 @@ const {
registerBodypart, registerBodypart,
saveBodypart, saveBodypart,
saveSource, saveSource,
} = require("../db/saveMessage"); } from "../db/saveMessage";
const { getFieldId } = require("../db/mail"); import { getFieldId } from "../db/mail";
const { logger } = require("../system/Logger"); import logger from "../system/Logger";
function saveMessage(attrs, mailboxId, imap) { export function saveMessage(attrs, mailboxId, imap) {
const envelope = attrs.envelope; const envelope = attrs.envelope;
const ts = moment(new Date(envelope.date).getTime()).format("YYYY-MM-DD HH:mm:ss"); const ts = moment(new Date(envelope.date).getTime()).format("YYYY-MM-DD HH:mm:ss");
const rfc822size = attrs.size; const rfc822size = attrs.size;
@ -41,7 +41,7 @@ function saveMessage(attrs, mailboxId, imap) {
// saveSource(messageId, buffer); // saveSource(messageId, buffer);
// parse data // parse data
simpleParser(buffer, async (err, parsed) => { mailParser(buffer, async (err, parsed) => {
saveFromParsedData(parsed, messageId) saveFromParsedData(parsed, messageId)
.then(() => { .then(() => {
resolve(messageId); resolve(messageId);
@ -118,9 +118,6 @@ async function saveFromParsedData(parsed, messageId) {
// todo when transfered // todo when transfered
} }
module.exports = {
saveMessage,
};
if (process.env["NODE_DEV"] == "TEST") { if (process.env["NODE_DEV"] == "TEST") {
module.exports = { module.exports = {

View File

@ -1,9 +1,9 @@
function nbMembers(envelope) { export function nbMembers(envelope) {
return getMembers(envelope).length; return getMembers(envelope).length;
} }
function getMembers(envelope) { export function getMembers(envelope) {
const members = []; const members: { mailbox: string; host: string }[] = [];
const fields = ["from", "to", "sender", "replyTo", "cc", "bcc"]; const fields = ["from", "to", "sender", "replyTo", "cc", "bcc"];
fields.forEach((field) => { fields.forEach((field) => {
if (!envelope[field]) return; if (!envelope[field]) return;
@ -14,8 +14,3 @@ function getMembers(envelope) {
}); });
return members; return members;
} }
module.exports = {
nbMembers,
getMembers,
};

1482
back/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,10 @@
{ {
"scripts": {
"build": "npx tsc",
"start": "node build/server.js",
"dev": "concurrently \"npx tsc --watch\" \"nodemon -q build/server.js\"",
"clean": "rm -rf build"
},
"dependencies": { "dependencies": {
"ajv": "^8.12.0", "ajv": "^8.12.0",
"ajv-formats": "^2.1.1", "ajv-formats": "^2.1.1",
@ -12,7 +18,16 @@
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
}, },
"devDependencies": { "devDependencies": {
"jest": "^29.5.0" "@types/express": "^4.17.17",
"@types/imap": "^0.8.35",
"@types/mailparser": "^3.0.2",
"@types/moment": "^2.13.0",
"@types/node": "^18.15.11",
"concurrently": "^8.0.1",
"jest": "^29.5.0",
"ts-node": "^10.9.1",
"ts-sql-plugin": "^0.9.0",
"typescript": "^5.0.3"
}, },
"jest": { "jest": {
"testMatch": [ "testMatch": [

View File

@ -1,16 +1,17 @@
const statusCodes = require("../utils/statusCodes.js").statusCodes; import statusCodes from "../utils/statusCodes";
const express = require("express"); import express from "express";
const router = express.Router(); const router = express.Router();
const Ajv = require("ajv"); import Ajv from "ajv";
const addFormats = require("ajv-formats"); import addFormats from "ajv-formats";
const ajv = new Ajv({ allErrors: true }); const ajv = new Ajv({ allErrors: true });
addFormats(ajv); addFormats(ajv);
const schema_account = require("../schemas/account_schema.json"); import schema_account from "../schemas/account_schema.json";
const { addAccount } = require("../controllers/addAccount.js"); import { addAccount } from "../controllers/addAccount";
const { getAccounts } = require("../db/api.js"); import { getAccounts } from "../db/api";
const { rooms } = require("../controllers/rooms.js"); import { rooms } from "../controllers/rooms";
const { messages } = require("../controllers/messages.js"); import { messages } from "../controllers/messages";
import { members } from "../controllers/members";
const validate_account = ajv.compile(schema_account); const validate_account = ajv.compile(schema_account);
@ -50,4 +51,4 @@ router.post("/account", async (req, res) => {
} }
}); });
module.exports = router; export default router;

View File

@ -1,7 +1,7 @@
const express = require("express"); import express from "express";
const cors = require("cors"); import cors from "cors";
const app = express(); const app = express();
const { ImapSync } = require("./mails/imap/ImapSync"); import ImapSync from "./mails/imap/ImapSync";
app.use(express.json()); app.use(express.json());
app.use( app.use(
@ -12,8 +12,8 @@ app.use(
app.use(cors()); app.use(cors());
app.listen(process.env.PORT || 5500); app.listen(process.env.PORT || 5500);
const mailRouter = require("./routes/mail"); import mailRouter from "./routes/mail";
app.use("/api/mail", mailRouter); app.use("/api/mail", mailRouter);
const imapSync = new ImapSync(); const imapSync = new ImapSync();
imapSync.init() imapSync.init();

View File

@ -3,19 +3,19 @@ class Logger {
} }
log(content) { log(...content): void {
console.log(this._prefix("log"), content); // console.log(this._prefix("log"), content);
} }
warn(content) { warn(...content): void {
console.warn(this._prefix("warn"), content); // console.warn(this._prefix("warn"), content);
} }
error(content) { error(...content): void {
console.error(this._prefix("err"), content); // console.error(this._prefix("err"), content);
} }
_prefix(type) { _prefix(type: string): string {
let typeStr = ""; let typeStr = "";
switch (type) { switch (type) {
case "log": case "log":
@ -39,7 +39,4 @@ class Logger {
} }
const logger = new Logger(); const logger = new Logger();
export default logger;
module.exports = {
logger,
}

View File

@ -1,6 +1,6 @@
const { getAddresseId, getUserIdOfMailbox } = require("../../db/mail"); const { getAddresseId, getUserIdOfMailbox } from ";
const { generateAttrs, generateUsers } = require("../test-utils/test-attrsUtils"); const { generateAttrs, generateUsers } = require("../test-utils/test-attrsUtils");
const { registerMessageInApp, roomType } = require("../../mails/saveMessage"); const { registerMessageInApp, roomType } from ";
jest.mock("../../db/mail"); jest.mock("../../db/mail");

View File

@ -1,4 +1,4 @@
const { nbMembers } = require("../../../mails/utils/envelopeUtils"); const { nbMembers } from ";
const { generateUsers } = require("../../test-utils/test-attrsUtils"); const { generateUsers } = require("../../test-utils/test-attrsUtils");
describe("envelopeUtils", () => { describe("envelopeUtils", () => {

View File

@ -0,0 +1,19 @@
// beforeAll(async () => {
// // const schema = fs.readFileSync('../../sql/structureV2.sql', 'utf8');
// // await setupDB(mysqlConfig, schema);
// });
// afterAll(async () => {
// global.db.query("DROP database mail_test");
// });
// describe('saveMessageApp', async () => {
// beforeEach(() => {
// });
// it("", () => {
// });
// });

View File

@ -1,4 +1,4 @@
const mysql = require("mysql"); const mysql from ";
export class TestDb { export class TestDb {
constructor (options) { constructor (options) {

View File

@ -1,4 +1,4 @@
const { names } = require("./names"); const { names } from ";
function generateAttrs(options) { function generateAttrs(options) {
const attrs = { const attrs = {

View File

@ -1,4 +1,4 @@
function removeDuplicates(array) { export function removeDuplicates(array: []) {
let unique = []; let unique = [];
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
if (!unique.includes(array[i])) { if (!unique.includes(array[i])) {
@ -7,7 +7,3 @@ function removeDuplicates(array) {
} }
return unique; return unique;
} }
module.exports = {
removeDuplicates,
};

View File

@ -1,5 +1,4 @@
// from https://github.com/prettymuchbryce/http-status-codes/blob/master/src/utils.ts // from https://github.com/prettymuchbryce/http-status-codes/blob/master/src/utils.ts
const statusCodes = { const statusCodes = {
"CONTINUE": 100, "CONTINUE": 100,
"SWITCHING_PROTOCOLS": 101, "SWITCHING_PROTOCOLS": 101,
@ -59,6 +58,4 @@ const statusCodes = {
"NETWORK_AUTHENTICATION_REQUIRED": 511, "NETWORK_AUTHENTICATION_REQUIRED": 511,
} }
module.exports = { export default statusCodes;
statusCodes: statusCodes
};

File diff suppressed because it is too large Load Diff