wachan
Version:
Simpler way to code baileys.
154 lines (146 loc) • 6.5 kB
JavaScript
const { Message } = require("../classes/message")
const { Receiver } = require("../classes/receiver")
const { NextSignal } = require("../classes/next-signal")
const { getSocket } = require("./socket")
const { store: { messageStore, groupStore, userStore } } = require("./store")
const pendingMessages = []
const receivers = []
const connectedCallbacks = []
const readyCallbacks = []
const errorCallbacks = []
function setUpBehaviors({settings}) {
return {
onReceiveHandler: async (update) => {
if (update.type === "append") {
if (!settings.receiveOfflineMessages) return
pendingMessages.push(...update.messages)
return
}
await processMessages(update, settings)
},
onReceivePendingHandler: async () => {
await processMessages({type: "append", messages: pendingMessages}, settings)
},
onConnectedHandler: async () => {
for (const cb of connectedCallbacks) {
try {
await cb()
} catch (error) {
console.log("Error in onConnected callback:", error.message.red)
}
}
},
onReadyHandler: async () => {
for (const cb of readyCallbacks) {
try {
await cb()
} catch (error) {
console.log("Error in onReady callback:", error.message.red)
}
}
},
}
}
function addReceiver(input, response) {
const receiver = new Receiver(input)
receiver.remove = () => {
const index = receivers.findIndex(r => r.receiver.id === receiver.id)
if (index !== -1) receivers.splice(index, 1)
}
if (typeof response === "function" && response.length > 2) {
console.warn("Deprecation Warning: Receiver response functions' arguments will be simplified in the next major version. See documentation for details.".yellow)
}
receivers.push({receiver, response})
return receiver
}
function addConnectedCallback(callback) {
if (typeof callback !== "function") {
throw new Error("onConnected callback must be a function")
}
connectedCallbacks.push(callback)
}
function addReadyCallback(callback) {
if (typeof callback !== "function") {
throw new Error("onReady callback must be a function")
}
readyCallbacks.push(callback)
}
function addErrorCallback(callback) {
if (typeof callback !== "function") {
throw new Error("onError callback must be a function")
}
errorCallbacks.push(callback)
}
async function processMessages(update, settings) {
nextMessage: for (const m of update.messages) {
if (m.key.remoteJid === "status@broadcast") continue
messageStore.add(m)
const group = await groupStore.get(m.key.remoteJid)
const senderAsParticipant = group?.participants?.find(p => p.id === m.key.participant || p.id === m.key.remoteJid)
const senderIsAdmin = senderAsParticipant === undefined ? null : !!senderAsParticipant?.admin
const defaultBotName = settings.defaultBotName
const context = {
receivedOnline: update.type === "notify",
senderIsAdmin,
defaultBotName
}
const message = new Message(m, context)
userStore.add(message.sender.id, message.sender.name, message.sender.lid)
const groupChat = group
? {
id: group.id,
subject: group.subject,
description: group.desc,
getParticipants: () => group.participants.map(p => ({ id: p.phoneNumber, lid: p.id })),
getAdmins: () => group.participants.filter(p => p.admin).map(p => ({ id: p.phoneNumber, lid: p.id })),
getMembers: () => group.participants.filter(p => !p.admin).map(p => ({ id: p.phoneNumber, lid: p.id })),
getLink: async () => {
const code = await getSocket()?.groupInviteCode(group.id)
return code ? `https://chat.whatsapp.com/${await getSocket()?.groupInviteCode(group.id)}` : null
}
} : null
for (const { receiver, response } of receivers) {
const testResult = await receiver.test(message);
if (!testResult) continue
if (!response) continue
let value
const captures = testResult.captures || {}
const next = () => { throw new NextSignal() }
switch (typeof response) {
case "function": {
try {
// will be simplified next major version
// applying the new argument structure, while keeping backward compatibility
message.message = message
message.captures = captures
message.group = groupChat
const newNext = () => next()
Object.assign(newNext, captures)
value = await response(message, newNext, groupChat, next)
break
} catch (error) {
if (error instanceof NextSignal) continue
console.log("Error in receiver response function:", error.message.red)
for (const cb of errorCallbacks) {
const context = { message, captures, groupChat } // group chat will ber removed
const value = await cb(error, context)
await message.reply(value)
}
continue nextMessage
}
}
case "string": value = testResult.captures
? response.replace(/<<(.+)>>/g, (m,item)=>captures[item]||m)
: response; break;
default: value = response;
}
await message.reply(value)
continue nextMessage
}
}
}
module.exports = {
setUpBehaviors, addReceiver, addConnectedCallback,
addReadyCallback, addErrorCallback, processMessages, pendingMessages,
receivers, connectedCallbacks, readyCallbacks, errorCallbacks
}