diff --git a/wai-server/api/channels/channel.controller.js b/wai-server/api/channels/channel.controller.js index 39c04e4..97f36bc 100644 --- a/wai-server/api/channels/channel.controller.js +++ b/wai-server/api/channels/channel.controller.js @@ -4,9 +4,6 @@ const { getConnection } = require('../../services/connections.service'); const { objectMapper, isEmpty } = require('../../utils/commons.util'); const { domain } = require('../../config').server; -const waInstance = { - wa: null, -}; exports.newConnect = async ctx => { try { const { phone } = ctx.query; @@ -16,15 +13,20 @@ exports.newConnect = async ctx => { const { sesson_id: sessonId, status } = findSession[0]; if (['open', 'connecting'].includes(status)) { const sock = sessionService.getSession(sessonId); - return sock; + if (!isEmpty(sock)) { + return sock; + } } } const whatsApp1 = await createWhatsApp(phone); - const qr = await whatsApp1.start(); - waInstance.wa = whatsApp1; + const existsSession = sessionService.getSession(phone); + let qr; + if (isEmpty(existsSession)) { + qr = await whatsApp1.start(); + const { sessionId } = sessionService.createSession(phone, whatsApp1); + } ctx.assert(whatsApp1, 503, 'No available connections'); - const { sessionId } = sessionService.createSession(phone, whatsApp1); - return { qr, phone, sessionId }; + return { qr, phone, sessionId: phone }; } catch (error) { console.error('create connection error', error); ctx.assert(null, 500, 'Failed to create connection or generate QR code.'); diff --git a/wai-server/api/messages/message.controller.js b/wai-server/api/messages/message.controller.js index 62cdfd4..b153516 100644 --- a/wai-server/api/messages/message.controller.js +++ b/wai-server/api/messages/message.controller.js @@ -22,6 +22,7 @@ exports.sendText = async ctx => { return; } const wsToSend = sessionService.getSession(from); + console.log('find wsToSend', wsToSend) if (!wsToSend) { ctx.assert(wsToSend, 400, 'Session not found'); // 404 return; diff --git a/wai-server/core/baileys/index.js b/wai-server/core/baileys/index.js index 0b64d90..5b86833 100644 --- a/wai-server/core/baileys/index.js +++ b/wai-server/core/baileys/index.js @@ -97,7 +97,10 @@ const createWhatsApp = async phone => { // maybe it closed, or we received all offline message or connection opened waSocket.ev.on('connection.update', async update => { console.log('connection update: ', update); - const { connection, lastDisconnect, qr } = update; + const { connection, lastDisconnect, qr, isOnline } = update; + if (isOnline === true) { + resolve(''); + } if (connection === 'close') { console.log('链接断开:', lastDisconnect); if (lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut) { @@ -113,6 +116,10 @@ const createWhatsApp = async phone => { waEmitter.emit('connection.open', { status: 'online', }); + waEmitter.emit('connection:open', { + status: 'open', phone + }); + resolve(''); } else if (qr !== undefined) { // WebSocket 创建成功等待扫码,如果没有扫码会更新 qr resolve(qr); diff --git a/wai-server/core/services/session.js b/wai-server/core/services/session.js index 88fd5cb..bbcf06d 100644 --- a/wai-server/core/services/session.js +++ b/wai-server/core/services/session.js @@ -5,7 +5,7 @@ module.exports = () => { const createSession = (sessionId, ws) => { sessions.set(ws, sessionId); - whatsappEvents.emit('connection:added', ws); + whatsappEvents.emit('connection:connect', ws); return { sessionId }; }; diff --git a/wai-server/core/services/whatsappHandler.js b/wai-server/core/services/whatsappHandler.js index a07c825..da7b404 100644 --- a/wai-server/core/services/whatsappHandler.js +++ b/wai-server/core/services/whatsappHandler.js @@ -1,12 +1,14 @@ const generateId = require('../../utils/generateId.util'); +const { domain } = require('../../config').server; const whatsappEvents = require('../emitter'); const { callWebhook } = require('../webhook'); -const { addConnection, updateConnection } = require('../../services/connections.service'); +const { addConnection, updateConnection, addCurrentConnection } = require('../../services/connections.service'); const { objectMapper } = require('../../utils/commons.util'); +const { sessionService } = require('..'); const logger = console; -const connectionEventNames = ['connection:open', 'connection:update', 'connection:close']; +const connectionEventNames = ['connection:connect', 'connection:open', 'connection:close']; const messageEventNames = ['message:received', 'message:updated']; const eeventTypeMapped = { @@ -28,10 +30,11 @@ const webhookBodyBuilder = (messageData, messageType) => { const setupConnectionHandler = () => { // connectionEventNames.forEach(eventName => { - whatsappEvents.on('connection:open', async connectionData => { - logger.info(`Setting up event ${'connection:open'}`); + logger.info(`Setting up event ${'connection:connect'}`); + whatsappEvents.on('connection:connect', async connectionData => { try { - await addConnection({ + // find Or create + await addCurrentConnection({ ...objectMapper(connectionData, { phone: [{ key: 'wa_id' }, { key: 'sesson_id' }], channelId: 'channel_id', createTimestamp: 'createtime' }), service_type: 'baileys', status: 'connecting', @@ -40,13 +43,30 @@ const setupConnectionHandler = () => { logger.error({ connectionData, error }, 'error add connection'); } }); - whatsappEvents.on('connection:update', async connectionData => { - logger.info(`Setting up event ${'connection:updated'}`); + logger.info(`Setting up event ${'connection:open'}`); + whatsappEvents.on('connection:open', async connectionData => { + logger.info(`event ${'connection:open'}`, connectionData); + try { + await updateConnection( + { + ...objectMapper(connectionData, { phone: [{ key: 'wa_id' }, { key: 'sesson_id' }], channelId: 'channel_id' }), + service_type: 'baileys', + }, + { connect_domain: domain }, + ); + } catch (error) { + logger.error({ connectionData, error }, 'error add connection'); + } + }); + logger.info(`Setting up event ${'connection:close'}`); + whatsappEvents.on('connection:close', async connectionData => { try { + sessionService.removeSession(connectionData.sesson_id); await updateConnection({ ...objectMapper(connectionData, { phone: [{ key: 'wa_id' }, { key: 'sesson_id' }], channelId: 'channel_id' }), service_type: 'baileys', }); + // todo: 通知前端: 重新扫码 } catch (error) { logger.error({ connectionData, error }, 'error add connection'); } diff --git a/wai-server/middleware/components/forward.middleware.js b/wai-server/middleware/components/forward.middleware.js index e6714ac..e0c74eb 100644 --- a/wai-server/middleware/components/forward.middleware.js +++ b/wai-server/middleware/components/forward.middleware.js @@ -8,9 +8,14 @@ module.exports = async (ctx, next) => { console.log('forward start ---------------'); // console.log(/^\/wai-server\/v\d{1}\/(?!channels|messages)/.test(ctx.path)); const { waisession } = ctx.headers; - const findSession = await getConnection({ sesson_id: waisession, connect_domain: domain }); - if (!isEmpty(findSession) && findSession.connect_domain === domain) { + if (isEmpty(waisession)) { await next(); + } else { + const findSession = await getConnection({ sesson_id: waisession, connect_domain: domain }); + if (!isEmpty(findSession)) { + // todo: 设置一个flag, 是否存在, 不用再查一遍 + await next(); + } } // todo: forward to target server diff --git a/wai-server/services/connections.service.js b/wai-server/services/connections.service.js index bf59224..0d3c426 100644 --- a/wai-server/services/connections.service.js +++ b/wai-server/services/connections.service.js @@ -14,14 +14,26 @@ const addConnection = async data => { return r; }; -const updateConnection = async data => { +/** + * Find or create connection to current server + */ +const addCurrentConnection = async data => { + const [r, createdId] = await ConnectionsModel.findOrCreate({ + where: { connect_domain: domain, connect_name: name, sesson_id: data.sesson_id }, + defaults: { ...data, connect_domain: domain, connect_name: name }, + }); + return r; +}; + +const updateConnection = async (data, where = {}) => { const r = await ConnectionsModel.update( { ...data, ...(data.status === 'open' ? { opentime: Sequelize.fn('NOW') } : {}), ...(data.status === 'close' ? { closetime: Sequelize.fn('NOW') } : {}), + updatetime: Sequelize.fn('NOW'), }, - { where: { channel_id: data.channel_id, sesson_id: data.sesson_id } }, + { where: { ...where, sesson_id: data.sesson_id } }, ); return r; }; @@ -31,4 +43,4 @@ const getConnection = async data => { return r; }; -module.exports = { addConnection, updateConnection, getConnection }; +module.exports = { addConnection, addCurrentConnection, updateConnection, getConnection };