From e924508b1d8e4fc2369ec90e0de44652226d9bcd Mon Sep 17 00:00:00 2001 From: LiaoYijun Date: Mon, 23 Dec 2024 13:33:24 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=20WA=20=E6=89=AB?= =?UTF-8?q?=E7=A0=81=E5=90=8E=E6=97=A0=E6=B3=95=E5=8F=91=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wai-server/api/channels/channel.controller.js | 23 +- wai-server/api/channels/channel.routes.js | 3 +- wai-server/core/baileys/index.js | 204 ++++++++++-------- 3 files changed, 130 insertions(+), 100 deletions(-) diff --git a/wai-server/api/channels/channel.controller.js b/wai-server/api/channels/channel.controller.js index 4a9a654..27b0e64 100644 --- a/wai-server/api/channels/channel.controller.js +++ b/wai-server/api/channels/channel.controller.js @@ -4,15 +4,24 @@ const generateId = require('../../utils/generateId.util'); // const { createConnection, getConnection } = require('../../core/whatsapp/connection'); // const { getAvailableConnection } = require('../../core/whatsapp/sessionStore'); +const waInstance = { + wa: null, +}; exports.newConnect = async ctx => { try { const { phone } = ctx.query; - // return phone; - const connectId = generateId(); - const whatsApp1 = await createWhatsApp(connectId, phone); + const whatsApp1 = await createWhatsApp(phone); + // console.info(whatsApp1); + whatsApp1.on('connection.open', async sock => { + console.info('收到:connection.open'); + // await sock.sendMessage('8617607730395' + '@s.whatsapp.net', { text: '收到事件,发送消息' }); + await whatsApp1.sendTextMessage('8617607730395', '收到事件,发送消息'); + }); + const qr = await whatsApp1.start(); + waInstance.wa = whatsApp1; ctx.assert(whatsApp1, 503, 'No available connections'); const { sessionId } = websocketService.createSession(phone, whatsApp1); - return { sessionId, whatsApp1 }; + return { qr }; } catch (error) { console.error('create connection error', error); ctx.assert(null, 500, 'Failed to create connection or generate QR code.'); @@ -22,6 +31,12 @@ exports.newConnect = async ctx => { } }; +exports.testSend = async ctx => { + const { from, to, content } = ctx.request.body; + waInstance.wa.sendTextMessage(to, content); + return { waInstance, ret: 'Message sent successfully' }; +}; + exports.getAll = async ctx => { const sessions = websocketService.sessions; return Array.from(sessions); diff --git a/wai-server/api/channels/channel.routes.js b/wai-server/api/channels/channel.routes.js index 8ea4d89..8e7e87d 100644 --- a/wai-server/api/channels/channel.routes.js +++ b/wai-server/api/channels/channel.routes.js @@ -13,7 +13,8 @@ module.exports = Router => { // .get('/qrcode0', callController.getIn) // .get('/qrcode', controller.qrcode) // .get('/:id', controller.getOne) - .get('/', controller.getAll); + .get('/', controller.getAll) + .post('/test', controller.testSend); // .post('/', controller.createOne) // router.post('/get-in', callController.getIn); // router.post('/send-msg', callController.sendMsg); diff --git a/wai-server/core/baileys/index.js b/wai-server/core/baileys/index.js index 712b671..4e550f6 100644 --- a/wai-server/core/baileys/index.js +++ b/wai-server/core/baileys/index.js @@ -8,9 +8,10 @@ const { useMultiFileAuthState, downloadMediaMessage } = require('@whiskeysockets/baileys'); - +const EventEmitter = require('events'); const { writeFile } = require('fs/promises'); +const generateId = require('../../utils/generateId.util'); const NodeCache = require('node-cache'); const P = require('pino'); @@ -31,26 +32,38 @@ setInterval(() => { }, 10_000) // start a connection -const createWhatsApp = async (channelId, phone) => { - - const { state, saveCreds } = await useMultiFileAuthState('baileys_auth_info_' + channelId + '_' + phone) +const createWhatsApp = async (phone) => { + const channelId = generateId() + const { state, saveCreds } = await useMultiFileAuthState('baileys_auth_info_' + phone + '_' + channelId) // fetch latest version of WA Web const { version, isLatest } = await fetchLatestBaileysVersion() const waVersion = version.join('.') + ', ' + (isLatest ? 'latest' : 'out') + const myEmitter = new EventEmitter(); + myEmitter.on('connection.open', (p) => { + console.info('EventEmitter: connection.open') + }); + + const on = (eventName, listener) => { + myEmitter.on(eventName, listener); + } + + const sendTextMessage = (whatsAppNo, content) => { + waSocket.sendMessage(whatsAppNo + '@s.whatsapp.net', { text: content }) + } + + const sendImageMessage = (whatsAppNo, imageUrl) => { + waSocket.sendMessage(whatsAppNo + '@s.whatsapp.net', { + image: { url: imageUrl}, + }) + } - return new Promise((resolve, reject) => { + let waSocket = null - const sendTextMessage = (whatsAppNo, content) => { - sock.sendMessage(whatsAppNo + '@s.whatsapp.net', { text: content }) - } + const start = () => { - const sendImageMessage = (whatsAppNo, imageUrl) => { - sock.sendMessage(whatsAppNo + '@s.whatsapp.net', { - image: { url: imageUrl}, - }) - } - const sock = makeWASocket({ + return new Promise((resolve, reject) => { + waSocket = makeWASocket({ version, logger, auth: { @@ -63,96 +76,97 @@ const createWhatsApp = async (channelId, phone) => { }) // something about the connection changed - // maybe it closed, or we received all offline message or connection opened - sock.ev.on('connection.update', async (update) => { - console.log('connection update: ', update) - const { connection, lastDisconnect, qr } = update - if(connection === 'close') { - console.log('链接断开:', lastDisconnect) - if (lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut) { - createWhatsApp(channelId, phone) - } else { - sock.end((error) => console.error('end.error: ', error)) - sock.logout((msg) => console.error('logout.msg: ', msg)) - console.log('Connection closed. You are logged out.') - reject('Connection closed. You are logged out.') + // 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 + if(connection === 'close') { + console.log('链接断开:', lastDisconnect) + if (lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut) { + start() + } else { + waSocket.end((error) => console.error('end.error: ', error)) + waSocket.logout((msg) => console.error('logout.msg: ', msg)) + console.log('Connection closed. You are logged out.') + } + } else if(connection === 'open') { + console.info('链接成功') + myEmitter.emit('connection.open', waSocket); + await waSocket.sendMessage('8617607730395' + '@s.whatsapp.net', { text: 'OPEN: ' + new Date().toString() }) + } else if(qr !== undefined) { + // WebSocket 创建成功等待扫码,如果没有扫码会更新 qr + resolve(qr) } - } else if(connection === 'open') { - console.info('链接成功') - await sock.sendMessage('8617607730395' + '@s.whatsapp.net', { text: 'OPEN: ' + new Date().toString() }) - } else if(qr !== undefined) { - // WebSocket 创建成功等待扫码,如果没有扫码会更新 qr - resolve({ - qrCode: qr, - version: waVersion, - createTimestamp: Date.now(), - status: 'connecting', - channelId : channelId, - phone: phone, - sendTextMessage, - sendImageMessage - }) - } - }) - - sock.ev.on('messages.upsert', async (upsert) => { - console.log('收到消息:', JSON.stringify(upsert, undefined, 2)) - - if (upsert.type === 'notify') { - for (const msg of upsert.messages) { - - const messageType = Object.keys(msg.message)[0] - - console.log('messageType', messageType) - if (messageType === 'imageMessage') { - // download the message - const buffer = await downloadMediaMessage( - msg, - 'buffer', - { }, - { - logger, - // pass this so that baileys can request a reupload of media - // that has been deleted - reuploadRequest: sock.updateMediaMessage - } - ) - // save to file - await writeFile('d:/my-download.jpeg', buffer) + }) - console.log('writeFile', messageType) - } + waSocket.ev.on('messages.upsert', async (upsert) => { + console.log('收到消息:', JSON.stringify(upsert, undefined, 2)) + + if (upsert.type === 'notify') { + for (const msg of upsert.messages) { + + const messageType = Object.keys(msg.message)[0] + + console.log('messageType', messageType) + if (messageType === 'imageMessage') { + // download the message + const buffer = await downloadMediaMessage( + msg, + 'buffer', + { }, + { + logger, + // pass this so that baileys can request a reupload of media + // that has been deleted + reuploadRequest: sock.updateMediaMessage + } + ) + // save to file + await writeFile('d:/my-download.jpeg', buffer) + + console.log('writeFile', messageType) + } - const fromWhatsAppNo = msg.key.remoteJid.split('@')[0] + const fromWhatsAppNo = msg.key.remoteJid.split('@')[0] - if (msg.message?.conversation || msg.message?.extendedTextMessage?.text) { - const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text + if (msg.message?.conversation || msg.message?.extendedTextMessage?.text) { + const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text - if (text.indexOf('图片') > -1){ - sendImageMessage(fromWhatsAppNo, 'https://images.asiahighlights.com/allpicture/2022/07/8a7d9ced5936463bb904c82a_cut_750x850_349.webp') - } else if (text.indexOf('文本') > -1){ - sendTextMessage(fromWhatsAppNo, '文本消息' + new Date().toString()) + if (text.indexOf('图片') > -1){ + sendImageMessage(fromWhatsAppNo, 'https://images.asiahighlights.com/allpicture/2022/07/8a7d9ced5936463bb904c82a_cut_750x850_349.webp') + } else if (text.indexOf('文本') > -1){ + sendTextMessage(fromWhatsAppNo, '文本消息' + new Date().toString()) + } } } } - } - }) + }) - // 不绑定不会影响扫码登录 - store?.bind(sock.ev) - - // the process function lets you process all events that just occurred - // efficiently in a batch - sock.ev.process( - // events is a map for event name => event data - async (events) => { - // credentials updated -- save them - if (events['creds.update']) { - await saveCreds() - } - }, - ) - }) + // 不绑定不会影响扫码登录 + store?.bind(waSocket.ev) + + // the process function lets you process all events that just occurred + // efficiently in a batch + waSocket.ev.process( + // events is a map for event name => event data + async (events) => { + // credentials updated -- save them + if (events['creds.update']) { + await saveCreds() + } + }, + ) + }) + } + + return { + createTimestamp: Date.now(), + status: 'offline', + version: waVersion, + channelId : channelId, + phone: phone, + start, on,sendTextMessage,sendImageMessage + } } module.exports = {