diff --git a/wai-server/core/baileys/helper.js b/wai-server/core/baileys/helper.js index 4b208bd..ad684ea 100644 --- a/wai-server/core/baileys/helper.js +++ b/wai-server/core/baileys/helper.js @@ -50,7 +50,31 @@ const formatTimestamp = timestamp => { return `${datetime.getFullYear()}-${datetime.getMonth() + 1}-${datetime.getDate()} ${datetime.getHours()}:${datetime.getMinutes()}:${datetime.getSeconds()}`; }; +const getFileExtension = mimeType => { + switch (mimeType) { + case 'image/jpeg': + return '.jpg'; + case 'image/png': + return '.png'; + case 'image/gif': + return '.gif'; + case 'image/bmp': + return '.bmp'; + case 'image/webp': + return '.webp'; + default: + return 'unknown'; + } +} + +const uint8ArrayToBase64 = uint8Array => { + const binaryString = String.fromCharCode(...uint8Array); + return btoa(binaryString); +} + module.exports = { + uint8ArrayToBase64, + getFileExtension, formatTimestamp, formatStatus, encodeJid, diff --git a/wai-server/core/baileys/index.js b/wai-server/core/baileys/index.js index 28b9ec8..9e33ab7 100644 --- a/wai-server/core/baileys/index.js +++ b/wai-server/core/baileys/index.js @@ -15,7 +15,7 @@ const { writeFile } = require('fs/promises'); const waEmitter = require('../emitter'); const serverConfig = require('../../config').server; -const { encodeJid, decodeJid, formatStatus, formatTimestamp } = require('./helper'); +const { encodeJid, decodeJid, formatStatus, formatTimestamp, getFileExtension, uint8ArrayToBase64 } = require('./helper'); const generateId = require('../../utils/generateId.util'); const NodeCache = require('node-cache'); const P = require('pino'); @@ -43,152 +43,6 @@ const createWhatsApp = async phone => { const { version, isLatest } = await fetchLatestBaileysVersion(); const waVersion = version.join('.') + ', ' + (isLatest ? 'latest' : 'out'); - const handleMessagesUpsert = async upsert => { - console.info('messages.upsert: ', JSON.stringify(upsert, undefined, 2)); - - if (upsert.type === 'notify') { - for (const msg of upsert.messages) { - - // 没有类型的消息,先忽略 - if (!msg.message) { - continue; - } - - const messageType = Object.keys(msg.message)[0]; - console.log('messageType', messageType); - // TODO: 待处理图片消息 - - const fromWhatsAppNo = decodeJid(msg.key.remoteJid); - - if (msg.message?.conversation || msg.message?.extendedTextMessage?.text) { - - const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text; - const externalId = externalIdCache.get(msg.key.id); - - if (msg.key.fromMe) { - waEmitter.emit('message:updated', { - id: msg.key.id, - externalId, - status: formatStatus(msg.status), - direction: 'outbound', - from: whatsAppNo, - to: fromWhatsAppNo, - type: 'text', - text: { - body: text, - }, - conversation: { - type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', - }, - customerProfile: { - id: decodeJid(msg.key.participant), - name: msg.pushName, - }, - whatsAppNo, - fromMe: msg.key.fromMe, - eventSource: serverConfig.name + '.messages.upsert.notify', - updateTime: formatTimestamp(msg.messageTimestamp), - }); - } else { - waEmitter.emit('message:received', { - id: msg.key.id, - externalId, - status: '', - direction: 'inbound', - from: fromWhatsAppNo, - to: whatsAppNo, - type: 'text', - text: { - body: text, - }, - conversation: { - type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', - }, - customerProfile: { - id: decodeJid(msg.key.participant), - name: msg.pushName, - }, - whatsAppNo, - fromMe: msg.key.fromMe, - eventSource: serverConfig.name + '.messages.upsert.notify', - createTime: formatTimestamp(msg.messageTimestamp), - }); - } - } - } - } else if (upsert.type === 'append') { - for (const msg of upsert.messages) { - if (msg.message?.conversation || msg.message?.extendedTextMessage?.text) { - const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text; - const fromWhatsAppNo = decodeJid(msg.key.remoteJid); - - const externalId = externalIdCache.get(msg.key.id); - if (msg.key.fromMe) { - waEmitter.emit('message:updated', { - id: msg.key.id, - externalId, - status: formatStatus(msg.status), - direction: 'outbound', - from: whatsAppNo, - to: fromWhatsAppNo, - type: 'text', - text: { - body: text, - }, - conversation: { - type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', - }, - customerProfile: { - id: decodeJid(msg.participant), - name: msg.pushName, - }, - whatsAppNo, - fromMe: msg.key.fromMe, - eventSource: serverConfig.name + '.messages.upsert.append', - updateTime: formatTimestamp(msg.messageTimestamp), - }); - } - } - } - } - } - - const handleMessagesUpdate = async messageUpdate => { - console.info('messages.update: ', JSON.stringify(messageUpdate, undefined, 2)); - - for (const msg of messageUpdate) { - - // 没有明确标识状态的更新,忽略 - const ignore = msg.update === undefined || msg.update.status === undefined; - - if (ignore) continue; - - const externalId = externalIdCache.get(msg.key.id); - waEmitter.emit('message:updated', { - id: msg.key.id, - externalId, - status: formatStatus(msg.update?.status), - direction: msg.key.fromMe ? 'outbound' : 'inbound', - from: msg.key.fromMe ? whatsAppNo : decodeJid(msg.key.remoteJid), - to: msg.key.fromMe ? decodeJid(msg.key.remoteJid) : whatsAppNo, - conversation: { - type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', - }, - customerProfile: { - id: decodeJid(msg.key.participant), - name: msg.pushName, - }, - whatsAppNo, - fromMe: msg.key.fromMe, - eventSource: serverConfig.name + '.messages.updated', - updateTime: formatTimestamp(new Date().getTime() / 1000), - }); - } - } - - const handleCredsUpdate = async () => { - await saveCreds(); - } const start = () => { @@ -213,6 +67,188 @@ const createWhatsApp = async phone => { store?.bind(waSocket.ev); + const handleMessagesUpsert = async upsert => { + console.info('messages.upsert: ', JSON.stringify(upsert, undefined, 2)); + + if (upsert.type === 'notify') { + for (const msg of upsert.messages) { + + // 没有类型的消息,先忽略 + if (!msg.message) { + continue; + } + + const messageType = Object.keys(msg.message)[0]; + const remoteNo = decodeJid(msg.key.remoteJid); + const externalId = externalIdCache.get(msg.key.id); + + if (msg.message?.conversation || msg.message?.extendedTextMessage?.text) { + + const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text; + + if (msg.key.fromMe) { + waEmitter.emit('message:updated', { + id: msg.key.id, + externalId, + status: formatStatus(msg.status), + direction: 'outbound', + from: whatsAppNo, + to: remoteNo, + type: 'text', + text: { + body: text, + }, + conversation: { + type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', + }, + customerProfile: { + id: decodeJid(msg.key.participant), + name: msg.pushName, + }, + whatsAppNo, + fromMe: msg.key.fromMe, + eventSource: serverConfig.name + '.messages.upsert.notify', + updateTime: formatTimestamp(msg.messageTimestamp), + }); + } else { + waEmitter.emit('message:received', { + id: msg.key.id, + externalId, + status: '', + direction: 'inbound', + from: remoteNo, + to: whatsAppNo, + type: 'text', + text: { + body: text, + }, + conversation: { + type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', + }, + customerProfile: { + id: decodeJid(msg.key.participant), + name: msg.pushName, + }, + whatsAppNo, + fromMe: msg.key.fromMe, + eventSource: serverConfig.name + '.messages.upsert.notify', + createTime: formatTimestamp(msg.messageTimestamp), + }); + } + } else if (messageType === 'imageMessage') { + console.info('image message: ', msg) + const imageMessage = msg.message.imageMessage; + const fileExtension = getFileExtension(imageMessage.mimetype); + const imageBuffer = await downloadMediaMessage( + msg, 'buffer', {}, { logger, reuploadRequest: waSocket.updateMediaMessage, }, + ); + const imageFilename = './temp/image_' + whatsAppNo + '_' + msg.key.id + fileExtension; + await writeFile(imageFilename, imageBuffer); + if (msg.key.fromMe) { + waEmitter.emit('message:updated', { + id: msg.key.id, + externalId, + status: formatStatus(msg.status), + direction: 'outbound', + from: whatsAppNo, + to: remoteNo, + type: 'image', + image: { + mimetype: imageMessage.mimetype, + sha256: uint8ArrayToBase64(imageMessage.fileSha256), + caption: '', // 暂时为空 + filename: imageFilename, + link_original: imageMessage.url, + }, + conversation: { + type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', + }, + customerProfile: { + id: decodeJid(msg.key.participant), + name: msg.pushName, + }, + whatsAppNo, + fromMe: msg.key.fromMe, + eventSource: serverConfig.name + '.messages.upsert.notify', + updateTime: formatTimestamp(msg.messageTimestamp), + }); + } + } + } + } else if (upsert.type === 'append') { + for (const msg of upsert.messages) { + if (msg.message?.conversation || msg.message?.extendedTextMessage?.text) { + const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text; + const fromWhatsAppNo = decodeJid(msg.key.remoteJid); + + const externalId = externalIdCache.get(msg.key.id); + if (msg.key.fromMe) { + waEmitter.emit('message:updated', { + id: msg.key.id, + externalId, + status: formatStatus(msg.status), + direction: 'outbound', + from: whatsAppNo, + to: fromWhatsAppNo, + type: 'text', + text: { + body: text, + }, + conversation: { + type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', + }, + customerProfile: { + id: decodeJid(msg.participant), + name: msg.pushName, + }, + whatsAppNo, + fromMe: msg.key.fromMe, + eventSource: serverConfig.name + '.messages.upsert.append', + updateTime: formatTimestamp(msg.messageTimestamp), + }); + } + } + } + } + } + + const handleMessagesUpdate = async messageUpdate => { + console.info('messages.update: ', JSON.stringify(messageUpdate, undefined, 2)); + + for (const msg of messageUpdate) { + + // 没有明确标识状态的更新,忽略 + const ignore = msg.update === undefined || msg.update.status === undefined; + + if (ignore) continue; + + const externalId = externalIdCache.get(msg.key.id); + waEmitter.emit('message:updated', { + id: msg.key.id, + externalId, + status: formatStatus(msg.update?.status), + direction: msg.key.fromMe ? 'outbound' : 'inbound', + from: msg.key.fromMe ? whatsAppNo : decodeJid(msg.key.remoteJid), + to: msg.key.fromMe ? decodeJid(msg.key.remoteJid) : whatsAppNo, + conversation: { + type: isJidUser(msg.key.remoteJid) ? 'individual' : 'group', + }, + customerProfile: { + id: decodeJid(msg.key.participant), + name: msg.pushName, + }, + whatsAppNo, + fromMe: msg.key.fromMe, + eventSource: serverConfig.name + '.messages.updated', + updateTime: formatTimestamp(new Date().getTime() / 1000), + }); + } + } + + const handleCredsUpdate = async () => { + await saveCreds(); + } + const sendMessageHandler = (event) => { const { to: number, externalId, ...content } = event; const jid = encodeJid(number); @@ -264,7 +300,7 @@ const createWhatsApp = async phone => { eventSource: serverConfig.name + '.connection.update.open', }); - waEmitter.on('request.' + whatsAppNo + '.send.text', sendMessageHandler); + waEmitter.on('request.' + whatsAppNo + '.send.message', sendMessageHandler); } else if (qr !== undefined) { // WebSocket 创建成功等待扫码,如果没有扫码会更新 qr // 第一次一分钟,后面是 20 秒更新一次