From 51d867d3a5b16c6c250975603731586d9189f60e Mon Sep 17 00:00:00 2001 From: Lei OT Date: Thu, 6 Mar 2025 14:37:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(WAI):=20=E8=AE=BE=E7=BD=AEWhatsApp?= =?UTF-8?q?=E7=A6=BB=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wai-server/api/channels/channel.controller.js | 34 +++++++++++++++++++ wai-server/api/channels/channel.routes.js | 1 + wai-server/core/handler/whatsappHandler.js | 21 ++++++++++-- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/wai-server/api/channels/channel.controller.js b/wai-server/api/channels/channel.controller.js index 404c935..1b4817b 100644 --- a/wai-server/api/channels/channel.controller.js +++ b/wai-server/api/channels/channel.controller.js @@ -6,6 +6,7 @@ const { getConnection } = require('../../services/connections.service'); const { isEmpty } = require('../../utils/commons.util'); const { getUserLogger } = require('../../utils/logger.util'); const { domain } = require('../../config').server; +const waEmitter = require('../../core/emitter'); const newConnect = async ctx => { const { phone } = ctx.query; @@ -36,11 +37,44 @@ const getSessions = async () => { return Array.from(sessionStore.sessions); }; +const offline = async ctx => { + const { phone } = ctx.query; + const existsSession = sessionStore.getSession(phone); + ctx.assert(existsSession, 400, `WhatsApp ${phone} 已离线`); + try { + getUserLogger(phone).info(`WhatsApp ${phone} 准备离线`); + // existsSession.stop(); // todo: + // sessionStore.removeSession(existsSession.channelId); + waEmitter.emit('connection:close', { phone, whatsAppNo: phone, status: 'offline', channelId: existsSession.channelId }); + return ''; // { wsToSend, ret: 'Message sent successfully' }; + } catch (error) { + console.error('set offline error', error); + ctx.assert(null, 500, 'Failed to set offline'); + } +}; + +/** + * @deprecated + */ +const setStatus = async (ctx) => { + const { phone, status } = ctx.request.body; + const existsSession = sessionStore.getSession(phone); + ctx.assert(existsSession, 400, `WhatsApp ${phone} 已离线`); + try { + // existsSession.stop(); // todo: + waEmitter.emit('connection:close', { phone, status: 'offline', channelId: existsSession.channelId }); + } catch (error) { + console.error('close connection error', error); + ctx.assert(null, 500, 'Failed to close connection'); + } +}; + const test = async () => {}; module.exports = { newConnect, getAll, getSessions, + offline, test, }; diff --git a/wai-server/api/channels/channel.routes.js b/wai-server/api/channels/channel.routes.js index 92212b4..38db24d 100644 --- a/wai-server/api/channels/channel.routes.js +++ b/wai-server/api/channels/channel.routes.js @@ -12,6 +12,7 @@ module.exports = Router => { .get('/qrcode', controller.newConnect) // .get('/qrcode', controller.qrcode) .get('/sessions', controller.getSessions) + .get('/offline', controller.offline) .get('/test', controller.test) .get('/', controller.getAll); diff --git a/wai-server/core/handler/whatsappHandler.js b/wai-server/core/handler/whatsappHandler.js index 9ea1b62..c782034 100644 --- a/wai-server/core/handler/whatsappHandler.js +++ b/wai-server/core/handler/whatsappHandler.js @@ -8,10 +8,10 @@ const { callWebhook } = require('../webhook'); const { sessionStore } = require('..'); const { createWhatsApp } = require('../../core/baileys'); const { updateConnection, addCurrentConnection, resetConnection, getConnection } = require('../../services/connections.service'); -const { getOutboundMessage, upsertOutboundMessage } = require('../../services/outbound_messages.service'); +const { getOutboundMessage, upsertOutboundMessage, createOutboundMessage } = require('../../services/outbound_messages.service'); const { objectMapper, pick, isEmpty, omitEmpty } = require('../../utils/commons.util'); const { logger, getUserLogger } = require('../../utils/logger.util'); -const { DbData, waiContentToDB, uploadMediaFile } = require('../../helper/wai.msg.helper'); +const { DbData, waiContentToDB, uploadMediaFile, ctxToSendBuilder, ctxToDB } = require('../../helper/wai.msg.helper'); const connectionEventNames = ['connection:connect', 'connection:open', 'connection:close']; const messageEventNames = ['message:received', 'message:updated']; @@ -227,6 +227,9 @@ const setupMessageHandler = async () => { const readyUpsert = omitEmpty({ ...timeFields, ...pusher, ...waiContentFieldsToDB, ...record }); const msgRow = await upsertOutboundMessage({ ...upsertFields, ...readyUpsert, ...typeField, ...msgOrigin }, targetUpsert); + + whatsappEvents.emit(`user:${eventName}`, msgRow); + if (_type !== 'unresolvable') { // 把内容加上, 否则前端没显示 await callWebhook(webhookBodyFill(webhookBody, { ...msgRow, status: msgRow.msg_status || '' })); @@ -254,6 +257,18 @@ function setupWhatsappHandler() { setupMessageHandler(); } +/** + * 发送消息 + * @param {*} _data { from, to, msgtype, msgcontent: { body, image, }, actionId } + */ +async function sendMessage(_data) { + const { from } = _data; + const toUpsert = ctxToDB(_data); + await createOutboundMessage({ ...toUpsert }); + const messagePayload = ctxToSendBuilder(_data); + whatsappEvents.emit('request.' + from + '.send.message', messagePayload); +} + /** * 登出: 当前服务的所有连接 */ @@ -275,4 +290,4 @@ async function loginCurrentConnections() { } } -module.exports = { setupWhatsappHandler, resetCurrentConnections, loginCurrentConnections }; +module.exports = { setupWhatsappHandler, resetCurrentConnections, loginCurrentConnections, sendMessage };