Skip to content

Instantly share code, notes, and snippets.

@mallendeo
Last active July 16, 2023 03:22
Show Gist options
  • Save mallendeo/6de0f9f1eb9370117bd30d7814771974 to your computer and use it in GitHub Desktop.
Save mallendeo/6de0f9f1eb9370117bd30d7814771974 to your computer and use it in GitHub Desktop.
WhatsApp To MQTT
FROM node:20-alpine
ENV NPM_CONFIG_LOGLEVEL info
RUN apk update && apk add wget git unzip
USER node
WORKDIR /home/node
RUN wget -O app.zip https://codeload.github.com/gist/6de0f9f1eb9370117bd30d7814771974/zip/54b6c6d68949fd46968be4f9833cfcca67a8a349
RUN unzip app.zip -d tmp
COPY --chown=node:node . .
RUN mv tmp/6de0f9f1eb9370117bd30d7814771974-54b6c6d68949fd46968be4f9833cfcca67a8a349 app
WORKDIR /home/node/app
RUN npm install --loglevel verbose
RUN npx tsc --build
VOLUME /home/node/app/auth_info_baileys
CMD [ "node", "dist/wsp2mqtt.js" ]
{
"name": "wsp2mqtt",
"version": "1.0.0",
"main": "dist/wsp2mqtt.js",
"scripts": {
"watch": "npx tsx watch -r dotenv/config wsp2mqtt.ts",
"start": "node -r dotenv/config dist/wsp2mqtt.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@hapi/boom": "^10.0.1",
"@whiskeysockets/baileys": "^6.3.1",
"dotenv": "^16.3.1",
"mqtt": "^4.3.7",
"qrcode-terminal": "^0.12.0"
},
"devDependencies": {
"typescript": "^5.1.6"
}
}
{
"compilerOptions": {
"target": "es2022",
"module": "commonjs",
"experimentalDecorators": true,
"allowJs": false,
"checkJs": false,
"outDir": "dist",
"strict": false,
"strictNullChecks": true,
"skipLibCheck": true,
"noImplicitThis": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"declaration": true,
"lib": [
"es2020",
"DOM"
]
},
"include": [
"**/*.ts"
],
"exclude": [
"node_modules",
]
}
import makeWASocket, {
DisconnectReason,
useMultiFileAuthState,
} from '@whiskeysockets/baileys'
import { Boom } from '@hapi/boom'
import mqtt from 'mqtt'
const client = mqtt.connect(process.env.MQTT_BROKER || 'mqtt://localhost')
const allowList = process.env.WSP2MQTT_ALLOW_LIST?.split(',') || []
console.log('==== wsp2mqtt ====')
const main = async () => {
async function connectToWhatsApp() {
console.log('= connect to WhatsApp')
const { state, saveCreds } = await useMultiFileAuthState(
'auth_info_baileys',
)
const sock = makeWASocket({
printQRInTerminal: true,
auth: state,
})
sock.ev.on('creds.update', saveCreds)
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update
if (connection === 'close') {
const shouldReconnect =
(lastDisconnect?.error as Boom)?.output?.statusCode !==
DisconnectReason.loggedOut
console.log(
'connection closed due to ',
lastDisconnect?.error,
', reconnecting ',
shouldReconnect,
)
// reconnect if not logged out
if (shouldReconnect) {
connectToWhatsApp()
}
} else if (connection === 'open') {
console.log('opened connection')
}
})
const sendMessage = async (msg: string, jid: string) => {
return await sock.sendMessage(jid, { text: msg })
}
sock.ev.process(async (events) => {
if (events['messages.upsert']) {
const upsert = events['messages.upsert']
if (upsert.type === 'notify') {
for (const msg of upsert.messages) {
await sock.readMessages([msg.key])
if (!msg.message?.conversation || !msg.key.remoteJid) return
if (!allowList.includes(msg.key.remoteJid)) return
client.publish(
`whatsapp/in/${msg.key.remoteJid}`,
msg.message?.conversation,
)
}
}
}
})
client.on('message', async (topic, message) => {
// message is Buffer
console.log(topic, message.toString())
if (!topic.endsWith('@s.whatsapp.net')) return
const wspJid = topic.replace('whatsapp/out/', '')
if (!allowList.includes(wspJid)) return
await sendMessage(
message.toString(),
`${topic.replace('whatsapp/out/', '')}`,
)
})
}
client.on('error', console.error)
client.on('connect', () => {
connectToWhatsApp()
client.subscribe('whatsapp/out/+')
})
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment