UNPKG

yekonga-server

Version:
436 lines (350 loc) 15 kB
// @ts-nocheck /*global Yekonga, global.serverLibrary */ const moment = global.serverLibrary.moment; const path = global.serverLibrary.path; const { setupMaster, setupWorker } = serverLibrary.socketSticky; const { createAdapter, setupPrimary } = serverLibrary.socketClusterAdapter; const Middleware = require('./middleware'); var ioAccount = null; var ioSync = null; class Socket { constructor() { this.namespace = null; this.roomId = null; this.socket = Yekonga.socketServer; this.connect = Yekonga.socketServer; } of(namespace) { this.namespace = namespace; return this; } to(id) { this.roomId = id; return this; } room(id) { return this.to(id); } emit(event, data) { try { var io = Yekonga.socketServer; if (this.namespace) io = io.of(this.namespace); if (this.roomId) io = io.to(this.roomId); io.emit(event, data); } catch (error) { console.error('Socket.emit', error.message); } } on(event, callback) { var io = Yekonga.socketServer; if (this.namespace) io = io.of(this.namespace); io.on(event, callback); } get broadcast() { return Yekonga.socketServer.broadcast; } } module.exports = async function(server) { if(Yekonga.socketServer) return console.warn('Socket server is already initialized'); Yekonga.socketServer = new global.serverLibrary.socketServer(server, { origin: '*', cors: { origin: '*', } }); if(!(serverLibrary.cluster.isPrimary || serverLibrary.cluster.isMaster)) { if(Yekonga.Config.localCluster) { Yekonga.socketServer.adapter(createAdapter()); setupWorker(Yekonga.socketServer); } } console.info('socket is process master?', `${serverLibrary.cluster.isMaster}`); if(Yekonga.Config.ports.redis) { const redisClient = global.serverLibrary.createClient({ url: `redis://localhost:${Yekonga.Config.ports.redis}` }); const subClient = redisClient.duplicate(); await redisClient.connect(); await subClient.connect(); Yekonga.socketServer.adapter(global.serverLibrary.createAdapter(redisClient, subClient)); } Yekonga.socketSystem = Yekonga.socketServer.of('/system'); Yekonga.pushNotification = Yekonga.socketServer.of('/pushNotification'); // Namespace Yekonga.socketServer.use(async function(socket, next) { socket.Yekonga = {} socket.headers = socket.handshake.headers; await Middleware.setYekonga(socket, {}, null); await Middleware.init(socket, {}, null); await Middleware.setToken(socket, {}, null); await Middleware.authorization(socket, {}, null); // console.debug('socket ======> ', socket); if(typeof next == 'function') { next(); } }).on('connection', function(socket) { // // console.debug(`socket connected`); socket.on('subscribe', async function(content) { // console.debug('subscribe', room); var deviceId = null; if(typeof content == "object") { deviceId = content.deviceId; if(content.userId) { socket.join(content.userId); } if(Yekonga.Helper.isNotEmpty(deviceId)) { var exists = await Yekonga.Model.UserDevice.findOne({ deviceUuid: deviceId, }); var body = { ...content, type: "phone", deviceUuid: deviceId, }; if(!exists) { Yekonga.Model.UserDevice.create(body, true) } else if(Yekonga.Helper.isNotEmpty(content.userId)) { Yekonga.Model.UserDevice.update(body, { userDeviceId: exists.userDeviceId }, true) } } } else if(typeof content == "string") { deviceId = content; } if(deviceId) { socket.join(deviceId); } Yekonga.Cloud.runOnMessage(null, 'subscribe', content); }) socket.on('unsubscribe', function(deviceId) { // console.debug('unsubscribe', room); socket.leave(deviceId); Yekonga.Cloud.runOnMessage(null, 'unsubscribe', deviceId); }) socket.on('run-on-server', function(content) { console.debug('data', content); Yekonga.Cloud.runOnMessage(null, 'run-on-server', content); }); socket.on('run-on-client', function(content) { console.debug('data', content); Yekonga.Cloud.runOnMessage(null, 'run-on-client', content); }); socket.on('run-on-desktop', function(content) { console.debug('data', content); Yekonga.Cloud.runOnMessage(null, 'run-on-desktop', content); }); socket.on('graphql-request', function({ room, listener, body, headers }) { var routeApi = (Yekonga.Config.graphql && Yekonga.Config.graphql.apiRoute) ? Yekonga.Config.graphql.apiRoute : `graphql`; Yekonga.Helper.request('post', { url: `http://127.0.0.1:${Yekonga.Config.ports.server}${routeApi}`, body: body, headers: headers, json: (typeof body == 'object') ? true : false }).then( (response) => { var responseBody = response.data; var content = (responseBody && responseBody.data) ? responseBody.data : responseBody; if (content) { Yekonga.Socket.to(room).emit('graphql-response', { listener: listener, body: content, }); } }, (error) => { console.error(error); } ); }); }); // Namespace Yekonga.socketSystem.use(function(socket, next) { if (!Yekonga.Auth) { if (socket.handshake.query && socket.handshake.query.token) { Middleware.setToken(socket.handshake); } else { // next(new Error('Authentication error')); } } next(); }).on('connection', function(socket) { // console.debug(`socket.of('/system') connected`); socket.on('subscribe', async function(content) { // console.debug('subscribe', room); var deviceId = null; if(typeof content == "object") { deviceId = content.deviceId; if(content.userId) { socket.join(content.userId); } if(Yekonga.Helper.isNotEmpty(deviceId)) { var exists = await Yekonga.Model.UserDevice.findOne({ deviceUuid: deviceId, }); var body = { ...content, type: "phone", deviceUuid: deviceId, }; if(!exists) { Yekonga.Model.UserDevice.create(body, true) } else if(Yekonga.Helper.isNotEmpty(content.userId)) { Yekonga.Model.UserDevice.update(body, { userDeviceId: exists.userDeviceId }, true) } } } else if(typeof content == "string") { deviceId = content; } if(deviceId) { socket.join(deviceId); } Yekonga.Cloud.runOnMessage('system', 'subscribe', content); }) socket.on('unsubscribe', function(content) { // console.debug('unsubscribe', room); socket.leave(content); Yekonga.Cloud.runOnMessage('system', 'unsubscribe', content); }) socket.on('run-on-server', function(content) { console.debug('data', content); Yekonga.Cloud.runOnMessage('system', 'run-on-server', content); }); socket.on('run-on-client', function(content) { console.debug('data', content); Yekonga.Cloud.runOnMessage('system', 'run-on-client', content); }); socket.on('run-on-desktop', function(content) { console.debug('data', content); Yekonga.Cloud.runOnMessage('system', 'run-on-desktop', content); }); socket.on('confirm', function(content) { console.debug('data', content); Yekonga.Cloud.runOnMessage('system', 'confirm', content); }); }); // Namespace Yekonga.pushNotification.use(function(socket, next) { if (!Yekonga.Auth) { if (socket.handshake.query && socket.handshake.query.token) { // Middleware.setToken(socket.handshake); } else { // next(new Error('Authentication error')); } } next(); }).on('connection', function(socket) { // console.debug(`socket.of('/pushNotification') connected`); socket.on('subscribe', async function(content) { // console.debug('subscribe to pushNotification - deviceId:', content); try { if(content) { var deviceId = content.deviceId; if(content.userId) { socket.join(content.userId); } if(deviceId) { socket.join(deviceId); // processPendingPushNotifications(deviceId); } if(Yekonga.Helper.isNotEmpty(deviceId)) { var exists = await Yekonga.Model.UserDevice.findOne({ deviceUuid: deviceId, }); var body = { ...content, type: "phone", deviceUuid: deviceId, }; if(!exists) { Yekonga.Model.UserDevice.create(body, true) } else if(Yekonga.Helper.isNotEmpty(content.userId)) { Yekonga.Model.UserDevice.update(body, { userDeviceId: exists.userDeviceId }, true) } } } } catch (error) { console.error("", error); } Yekonga.Cloud.runOnMessage('pushNotification', 'subscribe', content); }) socket.on('unsubscribe', function(room) { // console.debug('unsubscribe', room); socket.leave(room); Yekonga.Cloud.runOnMessage('pushNotification', 'unsubscribe', room); }) socket.on('disconnect', function(content) { // console.debug('unsubscribe', content); socket.leave(content); Yekonga.Cloud.runOnMessage('pushNotification', 'disconnect', content); }) socket.on('acknowledge', async function(id) { console.debug('acknowledge', id); await Yekonga.Model.PushNotification.update( { status: "delivered" }, { pushNotificationId: id }, true); Yekonga.Cloud.runOnMessage('pushNotification', 'acknowledge', id); }); }); if (typeof Yekonga.setPeer == 'function') { Yekonga.setPeer(Yekonga.socketServer); } if (typeof Yekonga.setChat == 'function') { Yekonga.setChat(Yekonga.socketServer); } setInterval(() => { processPushNotifications(); }, 5000); } var processStatus = false; async function processPushNotifications() { if(processStatus) return; processStatus = true; try { let timestamp = Yekonga.Helper.getMoment().format('YYYY-MM-DD HH:mm:ss'); let pastTimestamp = Yekonga.Helper.getMoment().subtract(5, 'minutes').format('YYYY-MM-DD HH:mm:ss'); let list = await Yekonga.Model.PushNotification.find({ status: ["waiting","pending"] }, true); for (const row of list) { row.id = row.pushNotificationId; await Yekonga.Model.PushNotification.update({ status: "sent", updatedAt: timestamp }, { pushNotificationId: row.pushNotificationId }, true); var s = null; if(Yekonga.Helper.isNotEmpty(row.namespace)) { s = Yekonga.socketServer.of(row.namespace); } else { s = Yekonga.pushNotification; } if (row.deviceUuid) { s.emit(`notification-${row.deviceUuid}`, row); s.to(`${row.deviceUuid}`).emit('notification', row); } else if (row.userId) { s.emit(`notification-${row.userId}`, row); s.to(`${row.userId}`).emit('notification', row); } else { s.emit('notification', row); } } } catch (error) { console.error('processPushNotifications', error) } processStatus = false; } async function processPendingPushNotifications(deviceId) { let pastTimestamp = Yekonga.Helper.getMoment().subtract(5, 'minutes').format('YYYY-MM-DD HH:mm:ss'); let sentList = await Yekonga.Model.PushNotification.find({ deviceUuid: deviceId, status: { in: ["sent", "waiting"]} }, true); for (const row of sentList) { row.id = row.pushNotificationId; var s = null; if(Yekonga.Helper.isNotEmpty(row.namespace)) { s = Yekonga.socketServer.of(row.namespace); } else { s = Yekonga.pushNotification; } // console.debug(`notification-${row.deviceUuid}`, row.namespace) s.emit(`notification-${row.deviceUuid}`, row); s.to(`${row.deviceUuid}`).emit('notification', row); } } Object.defineProperty(Yekonga, "Socket", { get: function() { return new Socket(); } });