const express = require('express'); const { createServer } = require('node:http'); const { join } = require('node:path'); const { Server } = require('socket.io'); const mysql = require('mysql2/promise'); const dotenv = require('@dotenvx/dotenvx'); const { PoolConnection } = require('mysql2'); const app = express(); const server = createServer(app); const io = new Server(server, { 'path': '/io' }); dotenv.config(); const db = mysql.createPool({ host: process.env.DB_HOST || '127.0.0.1', user: process.env.DB_USER || 'mariadb', password: process.env.DB_PASSWORD || '', database: process.env.DB_NAME || '', port: process.env.DB_PORT || 3306, }); const app_port = process.env.APP_PORT || 3000; io.on('connection', (socket) => { let pollPPOB = null; let pollSuper = null; let pollMonitor = null; // get ip address const forwardedIp = socket.handshake.headers["x-forwarded-for"]; //const cloudflareIp = socket.handshake.headers["cf-connecting-ip"]; const clientIp = forwardedIp ? forwardedIp.split(',')[0] : socket.handshake.address; //console.log("Real Client IP:", clientIp); // PPOB socket.on('ppob-check', (ajson) => { if (!ajson || typeof ajson !== 'object') return socket.emit('ppob-error', { 'message': 'Invalid payload format' }); const { CabID, UserID } = ajson; if (!CabID || !UserID) return socket.emit('ppob-error', { 'message': 'Missing required CabID and UserID' }); if (pollPPOB) clearInterval(pollPPOB); pollPPOB = setInterval(async () => { try { const [rows, fields] = await db.query("SELECT No_TX,Status FROM ppob_tx WHERE No_TX IN (SELECT No_TX FROM ppob_pend WHERE CabID=? AND UserID=?)", [ CabID, UserID ]); socket.emit('ppob-data', { 'prabayar': rows }); } catch (error) { console.error("db query failed :", error); } }, 1500); }); socket.on('ppob-update', (ajson) => { if (!ajson || typeof ajson !== 'object') return socket.emit('ppob-error', { 'message': 'Invalid payload format' }); const { CabID, UserID } = ajson; if (!CabID || !UserID) return socket.emit('ppob-error', { 'message': 'Missing required CabID and UserID' }); try { db.execute("DELETE FROM ppob_pend WHERE Status=4 AND CabID=? AND UserID=?", [ CabID, UserID ]); } catch (error) { console.error("db execute failed :", error); } }); socket.on('ppob-done', () => { if (pollPPOB) clearInterval(pollPPOB); pollPPOB = null; }); // SUPERVISI socket.on('super-check', (ajson) => { if (pollSuper) return; pollSuper = setInterval(async () => { try { const [rows, fields] = await db.query({sql: "SELECT A.AuthID,O.Nama Nama_User,A.Tanggal,M.Judul,A.Catatan,A.REQ,'' Aksi FROM (SELECT AuthID,UserID,Kode,DATE_FORMAT(Tanggal,'%d-%m-%Y %H:%i:%s') Tanggal,REQ,Catatan FROM app_auth WHERE Auth=0) A LEFT JOIN app_operator O ON (A.UserID=O.UserID) LEFT JOIN app_menu M ON (A.Kode=M.Kode)", rowsAsArray: true}); socket.emit('super-data', { 'data': rows }); } catch (error) { console.error("db query failed :", error); } }, 1500); }); socket.on('super-done', () => { if (pollSuper) clearInterval(pollSuper); pollSuper = null; }); // MONITOR socket.on('monitor-check', (ajson) => { if (!ajson || typeof ajson !== 'object') return socket.emit('monitor-error', { 'message': 'Invalid payload format' }); const { CabID, UserID } = ajson; if (pollMonitor) return; pollMonitor = setInterval(async () => { try { const adata = { 'total': 0, 'thank': 0 }; const [row_pos, fields_pos] = await db.query("SELECT * FROM disp_login WHERE CabID=? AND IP=? ORDER BY Date DESC", [ CabID, clientIp ]); if (row_pos.length) { const [row_total, fields_total] = await db.query("SELECT SUM(-Qty*(Harga_Jual-Disk_Rupiah)) Total FROM tmp_inv_detail WHERE No_Ref=? AND Unix=?", [ row_pos[0].No_Pos, row_pos[0].Unix ]); const [row_thank, fields_thank] = await db.query("SELECT IF(No_Cetak='',0,1) Ada FROM disp_login WHERE CabID=? AND UserID=? AND Unix=?", [ CabID, row_pos[0].UserID, row_pos[0].Unix ]); if (row_total.length) adata.total = row_total[0].Total || 0; if (row_thank.length) adata.thank = row_thank[0].Ada || 0; } socket.emit('monitor-data', { 'data': adata }); } catch (error) { console.error("db query failed :", error); } }, 1500); }); socket.on('monitor-done', () => { if (pollMonitor) clearInterval(pollMonitor); pollMonitor = null; }); // DISCONNECT socket.on('disconnect', () => { if (pollPPOB) clearInterval(pollPPOB); if (pollSuper) clearInterval(pollSuper); if (pollMonitor) clearInterval(pollMonitor); }); }); app.get('/', (req, res) => { res.sendFile(join(__dirname, 'public', 'index.html')); }); app.use(express.static('public')); server.listen(app_port, () => { console.log('Server running at http://localhost:' + app_port); });