Skip to content

Instantly share code, notes, and snippets.

@LucasSaud
Forked from igortrinidad/WhatsappManager.ts
Created December 16, 2024 11:38
Show Gist options
  • Save LucasSaud/1a3563288fcc773a397a8cfb991b8824 to your computer and use it in GitHub Desktop.
Save LucasSaud/1a3563288fcc773a397a8cfb991b8824 to your computer and use it in GitHub Desktop.
Manager wpp instances with workers
import { Worker } from 'worker_threads'
import path from 'path'
import Instance from '#models/Instance'
import app from '@adonisjs/core/services/app'
export class WhatsappManager {
isBooted = false
workers = new Map()
constructor() {
if (this.isBooted) {
return this
}
this.boot()
return this
}
boot() {
this.isBooted = true
}
async connectInstance(instance: Instance) {
const instance_id = instance.id
if (this.workers.has(instance_id)) {
console.log(`Instance ${instance_id} is already connected`)
return
}
const workerPath = path.join(app.appRoot.toString(), 'app/services/Whatsapp/util', 'worker.js').replace('file:', '')
const worker = new Worker(workerPath)
this.workers.set(instance_id, worker)
worker.on('message', (msg) => {
console.log(`Worker for instance ${instance_id} sent message:`, msg)
if (msg.status === 'connection_open') {
console.log(`Instance ${instance_id} connected successfully`)
} else if (msg.status === 'message') {
console.log(`Message for instance ${msg.instanceId}:`, msg.messages)
}
})
worker.on('error', (err) => {
console.error(`Worker for instance ${instance_id} encountered an error:`, err)
})
worker.on('exit', (code) => {
console.log(`Worker for instance ${instance_id} exited with code ${code}`)
this.workers.delete(instance_id)
})
worker.postMessage({ action: 'connect', instance_id })
}
disconnectInstance(instanceId: string) {
const worker = this.workers.get(instanceId)
if (!worker) {
console.log(`Instance ${instanceId} is not connected`)
return
}
worker.postMessage({ action: 'disconnect' })
worker.terminate()
this.workers.delete(instanceId)
}
}
export default new WhatsappManager()
import { parentPort } from 'worker_threads'
import { makeWASocket, DisconnectReason } from '@whiskeysockets/baileys'
import { useMongoAuthState } from './useMongoAuthState.js'
import { Boom } from '@hapi/boom'
let client = null
parentPort.on('message', async (message) => {
const { action, instance_id } = message
try {
if (action === 'connect') {
await connectInstance(instance_id)
parentPort.postMessage({ status: 'connected', instance_id })
} else if (action === 'disconnect') {
if (client) {
client.end()
client = null
parentPort.postMessage({ status: 'disconnected', instance_id })
}
}
} catch (error) {
parentPort.postMessage({ status: 'error', error: error.message, instance_id })
}
})
async function connectInstance(instance_id) {
const { state, saveCreds } = await useMongoAuthState(instance_id)
client = makeWASocket({ auth: state, printQRInTerminal: true })
client.ev.on('creds.update', saveCreds)
client.ev.on('connection.update', async (update) => {
const { connection, lastDisconnect } = update
if (connection === 'close') {
const shouldReconnect = (lastDisconnect.error instanceof Boom) &&
lastDisconnect.error.output.statusCode !== DisconnectReason.loggedOut
if (shouldReconnect) {
await connectInstance(instance_id)
}
} else if (connection === 'open') {
parentPort.postMessage({ status: 'connection_open', instance_id })
}
})
client.ev.on('messages.upsert', async (messages) => {
console.log(messages)
parentPort.postMessage({ status: 'message', instance_id, messages })
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment