import { Server as socket, Socket } from 'socket.io' import utils from '../../../utils/utils' import dbtools from '../../../utils/dbtools' import logger from '../../../utils/logger' import { Request, SubmoduleData, User } from '../../../types/basicTypes' import socketAuth from '../../../middlewares/socketAuth.middleware' const msgDbPath = './data/dbs/msgs.db' const msgPaginationLimit = 15 interface ExtendedSocket extends Socket { user: User } function setup(data: SubmoduleData): void { const { app, httpServer, httpsServer, userDB, publicdirs } = data const msgDB = dbtools.GetDB(msgDbPath) const publicDir = publicdirs[0] const uloadFiles = publicDir + 'chatFiles' logger.Log(`Starting Socket.io Server on ${httpsServer ? 'https' : 'http'}`) // https://socket.io/docs/v4/handling-cors/#Configuration const io = new socket(httpsServer || httpServer, { cors: { credentials: true, origin: true, }, }) function chatMessageRead(data) { const { sender, reciever } = data dbtools.runStatement( msgDB, `update msgs set unread = 0 where sender = ${sender} and reciever = ${reciever}`, 'run' ) io.sockets.in(sender.toString()).emit('chat message read', { userReadMsg: reciever, }) } io.use(socketAuth({ userDB: userDB })) io.on('connection', (socket: ExtendedSocket) => { const userid = socket.user.id logger.Log(`Chat connect: ${userid}`, logger.GetColor('green')) socket.on('join', function (/*data*/) { socket.join(userid.toString()) const groups = dbtools .runStatement( msgDB, `select * from ( select sender as a from msgs where sender = ${userid} or reciever = ${userid} union select reciever from msgs where sender = ${userid} or reciever = ${userid} )t order by t.a asc` ) .reduce((acc, x) => { if (x.a !== userid) acc.push(x.a) return acc }, []) socket.emit('prev messages', { prevMsgs: groups.map((to) => { const first = dbtools.runStatement( msgDB, `select * from msgs where sender = ${userid} and reciever = ${to} or sender = ${to} and reciever = ${userid} order by date desc limit 1` )[0] return first }), }) socket.on('get chat messages', (data) => { const { chatPartner, from } = data const msgs = dbtools.runStatement( msgDB, `select * from msgs where (sender = ${userid} and reciever = ${chatPartner} or sender = ${chatPartner} and reciever = ${userid}) ${from ? `and date < ${from}` : ''} order by date desc limit ${msgPaginationLimit}` ) socket.emit('get chat messages', { requestsdMsgs: msgs, hasMore: msgs.length === msgPaginationLimit, }) // Read update chatMessageRead({ sender: chatPartner, reciever: userid }) }) socket.on('chat message read', (data) => { const { chatPartner } = data chatMessageRead({ sender: chatPartner, reciever: userid }) }) socket.on('chat message', (message) => { const { reciever, msg, type } = message const recieverUser = dbtools.Select(userDB, 'users', { id: reciever, })[0] if (!recieverUser) { socket.emit('chat message', { success: false, date: new Date().getTime(), sender: reciever, reciever: userid, type: 'text', msg: `A #${reciever} számú felhasználó nem létezik`, }) return } const msgObj = { sender: userid, reciever: parseInt(reciever), msg: msg, type: type || 'text', date: new Date().getTime(), unread: 1, } dbtools.Insert(msgDB, 'msgs', msgObj) if (userid !== reciever) { io.sockets.in(reciever.toString()).emit('chat message', msgObj) } }) }) // socket.on('disconnect', () => {}) // socket.on('close', () => {}) }) app.post('/postchatfile', function (req: Request, res: any) { logger.LogReq(req) utils .uploadFile(req, uloadFiles) .then((result) => { res.json({ success: true, path: result.filePath.replace(publicDir, ''), }) }) .catch(() => { res.json({ success: false, msg: 'error during uploading' }) return }) }) app.get('/hasNewMsg', (req: Request, res) => { let userid: any = req.query.userid if (!userid || isNaN(userid)) { res.json({ success: false, msg: 'Query "userid" (number) is required!', }) return } userid = parseInt(userid) const groups = dbtools .runStatement( msgDB, `select * from ( select sender as a from msgs where sender = ${userid} or reciever = ${userid} union select reciever from msgs where sender = ${userid} or reciever = ${userid} )t order by t.a asc` ) .reduce((acc, x) => { if (x.a !== userid) acc.push(x.a) return acc }, []) const prevMsgs = groups.map((to) => { const first = dbtools.runStatement( msgDB, `select * from msgs where sender = ${userid} and reciever = ${to} or sender = ${to} and reciever = ${userid} order by date desc limit 1` )[0] return first }) res.json({ unreads: prevMsgs.reduce((acc, msg) => { if (msg && msg.unread === 1 && msg.sender !== userid) { acc.push(msg.sender) } return acc }, []), }) }) } export default { setup: setup, }