const WebSocket = require("ws"); const { URL } = require('url'); const sqlite3 = require('sqlite3'); const path = require('path'); require("dotenv").config(); const dbPath = process.env.DATABASE_PATH || '../'; const db = new sqlite3.Database(path.join(dbPath, 'database.sqlite')); const port = process.env.WS_PORT || 4001; const api_version = '1.0.0'; const wss = new WebSocket.Server({ port: port }, () => console.log(`Server started on port ${port}`)); wss.on('connection', async (ws, request) => { const url = new URL(request.url, `http://${request.headers.host}`) const params = Object.fromEntries(url.searchParams.entries()); const uuid = params.uuid; if (!uuid) return let check = await checkUUID(uuid); console.log(check); if (!check && check.possibilities.can_view_territory) return // Periodic ping to maintain a connection const pingInterval = setInterval(() => { if (ws.readyState === WebSocket.OPEN) { ws.ping('ping'); } }, 30000); ws.send(JSON.stringify({ "connection": "success", "api_version": api_version })); ws.on('message', (message) => { message = JSON.parse(message); console.log(message.username, check.name); switch (message.event) { case "connection": broadcastMessage(message); break; case "message": updateDatabase(message); broadcastMessage(message); break; }; }); ws.on('pong', (data) => { console.log('PONG received from the client:', data.toString()); }); ws.on('close', () => { console.log('Client close'); }); ws.on('error', (err) => { console.error('ERROR WebSocket:', err); }); }); function broadcastMessage(message) { wss.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(JSON.stringify(message)); } }); } function updateDatabase(message) { console.log(message.type); if (message.type === "apartment") { let sql = 'UPDATE apartments SET status = ?, description = ?, sheep_id = ?, updated_at = ? WHERE id = ?'; db.run(sql, [ Number(message.data.status), message.data.description, message.data.sheep_id, message.data.updated_at, message.data.id ], function (err) { if (err) { console.error(err.message); } else if (this.changes === 0) { console.error('Product not found'); } else { console.log({ "update": "ok", "id": message.data.id }); let sql = `INSERT INTO apartments_history (apartments_id, status, description, sheep_id, created_at) VALUES (?, ?, ?, ?, ?)`; db.run(sql, [ Number(message.data.id), Number(message.data.status), message.data.description, message.data.sheep_id, Math.floor(Date.now()) ], function (err) { if (err) { console.error(err.message); } else if (this.changes === 0) { console.error('Apartments not found'); } else { console.log({ "insert": "ok", "id": this.lastID }); } }); } }); } else if(message.type === "building") { let sql = 'UPDATE buildings SET status = ?, description = ?, sheep_id = ?, updated_at = ? WHERE id = ?'; db.run(sql, [ Number(message.data.status), message.data.description, message.data.sheep_id, message.data.updated_at, message.data.id ], function (err) { if (err) { console.error(err.message); } else if (this.changes === 0) { console.error('Product not found'); } else { console.log({ "update": "ok", "id": message.data.id }); let sql = `INSERT INTO buildings_history (buildings_id, status, description, sheep_id, created_at) VALUES (?, ?, ?, ?, ?)`; db.run(sql, [ Number(message.data.id), Number(message.data.status), message.data.description, message.data.sheep_id, Math.floor(Date.now()) ], function (err) { if (err) { console.error(err.message); } else if (this.changes === 0) { console.error('Apartments not found'); } else { console.log({ "insert": "ok", "id": this.lastID }); } }); } }); } } async function checkUUID(uuid) { return new Promise((res, rej) => { db.get(` SELECT sheeps.*, possibilities.can_view_territory AS can_view_territory FROM sheeps LEFT JOIN possibilities ON possibilities.sheep_id = sheeps.id WHERE sheeps.uuid_manager = ?`, [uuid], (err, moderator) => { if (moderator) { let data = { id: moderator.sheep_id, group_id: moderator.group_id, name: moderator.name, icon: moderator.icon, uuid: moderator.uuid, appointment: moderator.appointment, sheepRole: moderator.mode_title, possibilities: { can_view_territory: moderator.can_view_territory == 1 ? true : false } } return res(data); } db.get(` SELECT sheeps.*, possibilities.can_view_territory AS can_view_territory FROM sheeps LEFT JOIN possibilities ON possibilities.sheep_id = sheeps.id WHERE sheeps.uuid = ?`, [uuid], (err, sheep) => { if (sheep) { let data = { id: sheep.sheep_id, group_id: sheep.group_id, name: sheep.name, icon: sheep.icon, uuid: sheep.uuid, appointment: sheep.appointment, sheepRole: sheep.mode_title, possibilities: { can_view_territory: sheep.can_view_territory == 1 ? true : false } } return res(data); } return res(false); } ); } ); }); }