diff --git a/wai-server/api/channels/call.controller.js b/wai-server/api/channels/call.controller.js new file mode 100644 index 0000000..2b19fa7 --- /dev/null +++ b/wai-server/api/channels/call.controller.js @@ -0,0 +1,67 @@ +const { websocketService, websocketManager } = require('../../core'); // Import from core/index.js +const generateId = require('../../utils/generateId.util'); +// const { createConnection, getConnection } = require('../../core/whatsapp/connection'); +// const { getAvailableConnection } = require('../../core/whatsapp/sessionStore'); + +exports.newConnect = async ctx => { + // try { + // const socketId = generateId(); + // const { qr } = await createConnection(socketId); // Await the Promise here + // return { socketId, qr, message: 'Connection initiated. QR code provided.' }; // Return the QR code + // } catch (error) { + // console.error('create connection error', error); + // ctx.assert(null, 500, 'Failed to create connection or generate QR code.'); + // } +}; + +exports.getIn = async ctx => { + // Wait for at least one connection to be established (or handle the case where no connections are available) + // await new Promise(resolve => { + // const checkConnections = () => { + // if (websocketManager.getConnections().length > 0) { + // resolve(); + // } else { + // setTimeout(checkConnections, 100); // Check again after 100ms + // } + // }; + // checkConnections(); + // }); + + const availableWs = websocketManager.getAvailableConnection(); + + if (!availableWs) { + // ctx.status = 503; + // ctx.body = { message: 'No available connections' }; + ctx.assert(availableWs, 503, 'No available connections'); + return; + } + // return availableWs; + + const { sessionId, url } = websocketService.createSession(availableWs); + return { sessionId, url, message: 'Connection established' }; // availableWs +}; + +exports.sendMsg = ctx => { + const { sessionId, message } = ctx.request.body; + if (!sessionId || !message) { + // ctx.status = 400; + // ctx.body = { message: 'Session ID and message are required' }; + ctx.assert(sessionId, 400, 'Session ID and message are required'); + return; + } + const wsToSend = websocketService.getSession(sessionId); + if (!wsToSend) { + // ctx.status = 404; + // ctx.body = { message: 'Session not found' }; + ctx.assert(wsToSend, 400, 'Session not found'); + return; + } + try { + wsToSend.send(message); + ctx.body = { message: 'Message sent' }; + } catch (error) { + console.error('Error sending message:', error); + ctx.status = 500; + ctx.body = { message: 'Failed to send message' }; + } +}; diff --git a/wai-server/api/channels/channel.controller.js b/wai-server/api/channels/channel.controller.js new file mode 100644 index 0000000..2c250b6 --- /dev/null +++ b/wai-server/api/channels/channel.controller.js @@ -0,0 +1,52 @@ +'use strict'; + +const generateId = require('../../utils/generateId.util'); + +/** + * Mock database, replace this with your db models import, required to perform query to your database. + */ +const db = { + channels: [ + { + channelId: 1, + phone: 'string', + formattedPhone: 'string', + profilePicture: 'string', + name: 'string', + connectStatus: 'string', + channelStatus: 'string', + createTime: 0, + }, + ], +}; +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} +exports.qrcode = async ctx => { + return `data:image/png;base64,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`; +}; +exports.getOne = async ctx => { + const { id } = ctx.params; + const channel = db.channels.find(channel => channel.channelId === Number(id)); + await sleep(500); + ctx.assert(channel, 200, "The requested channel doesn't exist"); + return channel; +}; + +exports.getAll = async ctx => { + return db.channels; +}; + +exports.createOne = async ctx => { + const { name } = ctx.request.body; + ctx.assert(name, 200, 'The channel info is malformed!'); + const id = generateId(); + const newChannel = { + id, + name, + timestamp: Date.now(), + }; + db.channels.push(newChannel); + const createdChannel = db.channels.find(channel => channel.id === id); + return createdChannel; +}; diff --git a/wai-server/api/channels/channel.routes.js b/wai-server/api/channels/channel.routes.js new file mode 100644 index 0000000..9bfb760 --- /dev/null +++ b/wai-server/api/channels/channel.routes.js @@ -0,0 +1,22 @@ +'use strict'; + +const controller = require('./channel.controller'); +const callController = require('./call.controller'); + +module.exports = Router => { + const router = new Router({ + prefix: `/channels`, + }); + + router + .get('/qrcode', callController.newConnect) + .get('/qrcode0', callController.getIn) + // .get('/qrcode', controller.qrcode) + .get('/:id', controller.getOne) + .get('/', controller.getAll) + .post('/', controller.createOne); + // router.post('/get-in', callController.getIn); + // router.post('/send-msg', callController.sendMsg); + + return router; +}; diff --git a/wai-server/api/channels/index.js b/wai-server/api/channels/index.js new file mode 100644 index 0000000..c358233 --- /dev/null +++ b/wai-server/api/channels/index.js @@ -0,0 +1 @@ +module.exports = require('./channel.routes'); diff --git a/wai-server/api/contacts/contact.controller.js b/wai-server/api/contacts/contact.controller.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/wai-server/api/contacts/contact.controller.js @@ -0,0 +1 @@ +'use strict'; diff --git a/wai-server/api/contacts/contact.routes.js b/wai-server/api/contacts/contact.routes.js new file mode 100644 index 0000000..819110d --- /dev/null +++ b/wai-server/api/contacts/contact.routes.js @@ -0,0 +1,20 @@ +'use strict'; + +// const controller = require('./contact.controller'); + +module.exports = Router => { + const router = new Router({ + prefix: `/contacts`, + }); + + // router + // .get('/qrcode', callController.getIn) + // // .get('/qrcode', controller.qrcode) + // .get('/:id', controller.getOne) + // .get('/', controller.getAll) + // .post('/', controller.createOne); + // router.post('/get-in', callController.getIn); + // router.post('/send-msg', callController.sendMsg); + + return router; +}; diff --git a/wai-server/api/contacts/index.js b/wai-server/api/contacts/index.js new file mode 100644 index 0000000..ca67d2a --- /dev/null +++ b/wai-server/api/contacts/index.js @@ -0,0 +1 @@ +module.exports = require('./contact.routes'); diff --git a/wai-server/api/group/group.controller.js b/wai-server/api/group/group.controller.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/wai-server/api/group/group.controller.js @@ -0,0 +1 @@ +'use strict'; diff --git a/wai-server/api/group/group.routes.js b/wai-server/api/group/group.routes.js new file mode 100644 index 0000000..7050e93 --- /dev/null +++ b/wai-server/api/group/group.routes.js @@ -0,0 +1,20 @@ +'use strict'; + +// const controller = require('./channel.controller'); + +module.exports = Router => { + const router = new Router({ + prefix: `/group`, + }); + + // router + // .get('/qrcode', callController.getIn) + // // .get('/qrcode', controller.qrcode) + // .get('/:id', controller.getOne) + // .get('/', controller.getAll) + // .post('/', controller.createOne); + // router.post('/get-in', callController.getIn); + // router.post('/send-msg', callController.sendMsg); + + return router; +}; diff --git a/wai-server/api/group/index.js b/wai-server/api/group/index.js new file mode 100644 index 0000000..1c4317e --- /dev/null +++ b/wai-server/api/group/index.js @@ -0,0 +1 @@ +module.exports = require('./group.routes'); diff --git a/wai-server/api/index.js b/wai-server/api/index.js index 67a8a19..06822fa 100644 --- a/wai-server/api/index.js +++ b/wai-server/api/index.js @@ -9,7 +9,7 @@ const baseName = path.basename(__filename); function applyApiMiddleware(app) { const router = new Router({ - prefix: `/api/${apiVersion}`, + prefix: `/api/${apiVersion}/whatsapp`, }); // Require all the folders and create a sub-router for each feature api diff --git a/wai-server/api/messages/index.js b/wai-server/api/messages/index.js new file mode 100644 index 0000000..163eadf --- /dev/null +++ b/wai-server/api/messages/index.js @@ -0,0 +1 @@ +module.exports = require('./message.routes'); diff --git a/wai-server/api/messages/message.controller.js b/wai-server/api/messages/message.controller.js new file mode 100644 index 0000000..47c553b --- /dev/null +++ b/wai-server/api/messages/message.controller.js @@ -0,0 +1,62 @@ +'use strict'; + +const generateId = require('../../utils/generateId.util'); + +/** + * Mock database, replace this with your db models import, required to perform query to your database. + */ +const db = { + users: [ + { + id: 'bff28903-042e-47c2-b9ee-07c3954989ec', + name: 'Marco', + created_at: 1558536830937, + }, + { + id: 'dca01a32-36e6-4886-af75-8e7caa0162a9', + name: 'Leonardo', + created_at: 1558536843742, + }, + { + id: 'dca01a32-36e6-4886-af75-8e7caa0162a9', + name: 'Berta', + created_at: 1558536863550, + }, + ], +}; +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} +exports.getOne = async ctx => { + const { id } = ctx.params; + const user = db.users.find(user => user.id === id); + await sleep(500); + ctx.assert(user, 404, "The requested user doesn't exist"); + return user; +}; + +exports.getAll = async ctx => { + return db.users; +}; + +exports.createOne = async ctx => { + const { name } = ctx.request.body; + ctx.assert(name, 400, 'The user info is malformed!'); + const id = generateId(); + const newUser = { + id, + name, + timestamp: Date.now(), + }; + db.users.push(newUser); + const createdUser = db.users.find(user => user.id === id); + return createdUser; +}; + +exports.sendText = async ctx => { + const { type } = ctx.params; + const body = ctx.request.body; + ctx.assert(null, 400, `debug: content: {${type}} {${body.content}}`); + ctx.assert(null, 400, 'The message info is malformed!'); + return body; +}; diff --git a/wai-server/api/messages/message.routes.js b/wai-server/api/messages/message.routes.js new file mode 100644 index 0000000..0561e27 --- /dev/null +++ b/wai-server/api/messages/message.routes.js @@ -0,0 +1,16 @@ +'use strict'; + +const controller = require('./message.controller'); + +module.exports = Router => { + const router = new Router({ + prefix: `/messages`, + }); + + router + .get('/:id', controller.getOne) + .get('/', controller.getAll) + .post('/:type', controller.sendText); + + return router; +}; diff --git a/wai-server/config/components/websocket.config.js b/wai-server/config/components/websocket.config.js new file mode 100644 index 0000000..ee873da --- /dev/null +++ b/wai-server/config/components/websocket.config.js @@ -0,0 +1,26 @@ +'use strict'; + +const serverNodes = Array.from({ length: 2 }, (_, i) => ({ + name: `wai-server-${i + 1}`, + port: 8080 + i, + // host: `ws://remote-websocket-service-${i + 1}.com`, + host: `wss://p9axztuwd7x8a7.mycht.cn/whatsapp_server?opisn=${i ? '383' : '404'}&_spam=${Date.now().toString()}`, + protocol: 'WhatsApp', + // path: '/ws', + // protocol: 'ws', + // subprotocol: 'protoo', + // maxPayload: 1048576, // 1MB + // allowRequest: (req, next) => next(null, true), + // compression: true, + // json: true, + // binary: true, + // heartbeatInterval: 5000, + // heartbeatTimeout: 10000, + // closeTimeout: 5000, +})); + +const config = { + websockets: serverNodes, +}; + +module.exports = config; diff --git a/wai-server/config/components/whatsapp.baileys.config.js b/wai-server/config/components/whatsapp.baileys.config.js new file mode 100644 index 0000000..b031af3 --- /dev/null +++ b/wai-server/config/components/whatsapp.baileys.config.js @@ -0,0 +1,12 @@ +'use strict'; + +const serverNodes = Array.from({ length: 2 }, (_, i) => ({ + name: `wai-server-${i + 1}`, + // host: `ws://remote-websocket-service-${i + 1}.com`, +})); + +const config = { + whatsappBaileys: serverNodes, +}; + +module.exports = config; diff --git a/wai-server/core/index.js b/wai-server/core/index.js new file mode 100644 index 0000000..2e41585 --- /dev/null +++ b/wai-server/core/index.js @@ -0,0 +1,12 @@ +// core/index.js +const websocketServicesI = require('./websocket/services/session'); +const websocketConnectionI = require('./websocket/connection'); + +// Create the instances here +const websocketService = websocketServicesI(); +const websocketManager = websocketConnectionI(websocketService); + +module.exports = { + websocketService, + websocketManager, +}; diff --git a/wai-server/core/websocket/connection.js b/wai-server/core/websocket/connection.js new file mode 100644 index 0000000..3961253 --- /dev/null +++ b/wai-server/core/websocket/connection.js @@ -0,0 +1,60 @@ +const WebSocket = require('ws'); +const websocketServerNodes = require('../../config').websockets; + +module.exports = callService => { + let connections = []; + + const connect = () => { + websocketServerNodes.forEach((node, index) => { + createConnection(node, index); + }); + }; + + const createConnection = (node, index) => { + try { + const ws = new WebSocket(node.host, [node.protocol]); + ws.on('open', () => { + console.log(`Connected to WebSocket ${index}: ${node.protocol} ${node.host}`); + // connections.push(ws); + connections = [...connections, ws]; + console.log('Current connections:', connections.length); + }); + + ws.on('close', () => { + console.log(`WebSocket ${index} disconnected. Reconnecting...`); + connections.splice(connections.indexOf(ws), 1); + setTimeout(() => createConnection(node, index), 3000); + }); + + ws.on('error', error => { + console.error(`WebSocket ${index} error:`, error); + }); + + ws.on('message', message => { + console.log(`Received from WebSocket ${index}: ${message}`); + }); + } catch (error) { + console.error(`Error connecting to WebSocket ${index}:`, error); + } + }; + + const getAvailableConnection = () => { + // console.log('Available connections length:', connections.length); + for (const ws of connections) { + // console.log('Session has ws:', callService.sessions.has(ws)); + if (!callService.sessions.has(ws)) { + // console.log('Found available ws:', ws); // Add this line + return ws; + } + } + console.log('No available connections found.'); + return null; + }; + const getConnections = () => connections; // Add this getter + + return { + connect, + getAvailableConnection, + getConnections, + }; +}; diff --git a/wai-server/core/websocket/services/session.js b/wai-server/core/websocket/services/session.js new file mode 100644 index 0000000..b3744ee --- /dev/null +++ b/wai-server/core/websocket/services/session.js @@ -0,0 +1,31 @@ +const generateId = require('../../../utils/generateId.util'); + +module.exports = () => { + const sessions = new Map(); + + const createSession = ws => { + const sessionId = generateId(); + sessions.set(ws, sessionId); + return { sessionId, url: ws.url }; + }; + + const getSession = sessionId => { + for (const [ws, storedSessionId] of sessions) { + if (storedSessionId === sessionId) { + return ws; + } + } + return null; + }; + + const removeSession = ws => { + sessions.delete(ws); + }; + + return { + createSession, + getSession, + removeSession, + sessions, + }; +}; diff --git a/wai-server/index.js b/wai-server/index.js index 15176f2..e33169a 100644 --- a/wai-server/index.js +++ b/wai-server/index.js @@ -4,6 +4,7 @@ const http = require('http'); const server = require('./server'); const { port } = require('./config').server; +const { websocketService, websocketManager } = require('./core'); async function bootstrap() { /** @@ -15,7 +16,10 @@ async function bootstrap() { } bootstrap() - .then(server => console.log(`🚀 Server listening on port ${server.address().port}!`)) + .then(server => { + console.log(`🚀 Server listening on port ${server.address().port}!`); + websocketManager.connect(); // connect websocket after server start + }) .catch(err => { setImmediate(() => { console.error('Unable to run the server because of the following error:'); diff --git a/wai-server/middleware/request.middleware.js b/wai-server/middleware/request.middleware.js index 374cc24..074f295 100644 --- a/wai-server/middleware/request.middleware.js +++ b/wai-server/middleware/request.middleware.js @@ -11,10 +11,11 @@ module.exports = async (ctx, next) => { } } catch (err) { console.log('Error handler:', err); - ctx.status = err.status || 500; + // ctx.status = 200; // err.status || 500; ctx.body = { errcode: 1, errmsg: err.message || 'Internal server error', + statuscode: err.status, result: null, }; } diff --git a/wai-server/server.js b/wai-server/server.js index a06b9cf..e927807 100644 --- a/wai-server/server.js +++ b/wai-server/server.js @@ -14,7 +14,7 @@ const applyApiMiddleware = require('./api'); * Add here only development middlewares */ if (isDevelopment) { - server.use(logger); + // server.use(logger); // Logger server.use(async (ctx, next) => { const start = new Date();