/* ---------------------------------------------------------------------------- Question Server GitLab: This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ------------------------------------------------------------------------- */ 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 } interface Message { id: number sender: number reciever: number msg: string type: string date: number unread: number } 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({ sender, reciever, }: { sender: number reciever: number }) { 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 socket.on('join', function (/*data*/) { socket.join(userid.toString()) const groups: number[] = 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: number[], x: { a: number }) => { if (x.a !== userid) acc.push(x.a) return acc }, []) socket.emit('prev messages', { prevMsgs: groups.map((to) => { const first: Message = 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: dbtools.sanitizeQuery(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) { 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) => { const user: User = req.session.user const userid: number = user.id 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: number[], x: { a: number }) => { if (x.a !== userid) acc.push(x.a) return acc }, []) const prevMsgs = groups.map((to: number) => { 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: number[], msg: Message) => { if (msg && msg.unread === 1 && msg.sender !== userid) { acc.push(msg.sender) } return acc }, []), }) }) } export default { setup: setup, }