Created
October 19, 2025 11:08
-
-
Save ZTRdiamond/5cc2a28df784f42d875a398ce161c748 to your computer and use it in GitHub Desktop.
Baileys Shard example usage.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import makeWASocket, { useMultiFileAuthState, DisconnectReason } from "baileys"; | |
| import { ShardManager } from "baileys-shard"; | |
| import { Boom } from "@hapi/boom"; | |
| import Pino from "pino"; | |
| console.log(await import("baileys-shard")) | |
| const manager = new ShardManager(); | |
| function parseArgs(input = "") { | |
| const args = (input || "").match(/--\w+(?:[= ](?:[^\s"']+|".+?"|'.+?'))?/g) || []; | |
| const result = {}; | |
| const argRegex = /--(\w+)(?:[= ]((?:[^\s"']+)|(?:"[^"]*")|(?:'[^']*')))?/; | |
| args.forEach(arg => { | |
| const match = arg.match(argRegex); | |
| if (match) { | |
| const key = match[1]; | |
| let value = match[2]; | |
| if (value == undefined) { | |
| result[key] = true; // flag tanpa nilai | |
| } else if (/^["']/.test(value)) { | |
| value = value.slice(1, -1); // hapus tanda kutip di sekitar nilai | |
| } | |
| result[key] = value; | |
| } | |
| }); | |
| return result; | |
| } | |
| let timeout = 0; | |
| const logger = Pino( | |
| { | |
| level: "info", | |
| formatters: { | |
| level(label) { | |
| return { level: label }; | |
| }, | |
| }, | |
| timestamp: () => `,"time":"${new Date().toISOString()}"`, | |
| base: { pid: false, hostname: false }, | |
| }, | |
| Pino.destination("./baileys-logs.txt") | |
| ); | |
| manager.on("messages.upsert", async({ shardId, sock, data }) => { | |
| const m = data.messages[0] | |
| if(!m) return; | |
| const sender = m?.key?.remoteJid; | |
| const body = m?.message?.conversation; | |
| if(body && body.startsWith(".sayhi")) { | |
| return sock.sendMessage(sender, { | |
| text: `Hello, from ${shardId}` | |
| }) | |
| } else return; | |
| }) | |
| async function start() { | |
| const { state, saveCreds } = await useMultiFileAuthState("./session"); | |
| const sock = makeWASocket({ | |
| printQRInTerminal: false, | |
| logger, | |
| auth: state | |
| }); | |
| // pairing jika belum registered | |
| if (!sock.authState.creds.registered) { | |
| const botNumber = "628xxx" // phone number | |
| console.log("Request new session:"); | |
| console.log("> Bot Number:", botNumber); | |
| setTimeout(async function () { | |
| const pairingCode = await sock.requestPairingCode(botNumber); | |
| console.log("> Pairing Code:", pairingCode); | |
| }, 5000); | |
| } | |
| // update creds | |
| sock.ev.on("creds.update", saveCreds); | |
| // update koneksi | |
| sock.ev.on("connection.update", async (update) => { | |
| const { lastDisconnect, connection } = update; | |
| if (connection) { | |
| console.log(`[Session] Connecting session... (${connection})`); | |
| } | |
| if (connection == "close") { | |
| const closeReason = new Boom(lastDisconnect?.error)?.output?.statusCode; | |
| switch (closeReason) { | |
| case DisconnectReason.badSession: | |
| console.log("[Session] Bad session file, delete old session and login again."); | |
| break; | |
| case DisconnectReason.connectionClosed: | |
| timeout++; | |
| console.log("[Session] Connection closed, Reconnecting..."); | |
| await start(); | |
| break; | |
| case DisconnectReason.connectionLost: | |
| timeout++; | |
| console.log("[Session] Connection lost, Reconnecting..."); | |
| await start(); | |
| break; | |
| case DisconnectReason.connectionReplaced: | |
| console.log("[Session] Connection replaced, please logout from other device."); | |
| break; | |
| case DisconnectReason.loggedOut: | |
| console.log("[Session] Logged out, please login again."); | |
| break; | |
| case DisconnectReason.restartRequired: | |
| timeout++; | |
| console.log("[Session] Restart required, reconnecting..."); | |
| await start(); | |
| break; | |
| case DisconnectReason.connectionTimedOut: | |
| timeout++; | |
| console.log("[Session] Connection timeout, reconnecting..."); | |
| await start(); | |
| break; | |
| case DisconnectReason.multideviceMismatch: | |
| console.log("[Session] Multi device mismatch, please login again."); | |
| break; | |
| default: | |
| timeout++; | |
| console.log("[Session] Unknown disconnect reason, reconnecting..."); | |
| await start(); | |
| } | |
| if (timeout > 10) { | |
| console.log("[Session] Stopped after 10 retries."); | |
| process.exit(1); | |
| } | |
| } | |
| if (connection == "open") { | |
| console.log("[Session] sock connected on:", (sock?.user?.id.split(":")[0] || global.botNumber)); | |
| } | |
| }); | |
| sock.ev.on("messages.upsert", async(raw) => { | |
| const m = raw.messages[0]; | |
| if(!m) return; | |
| const sender = m?.key?.remoteJid; | |
| const body = m?.message?.conversation || null; | |
| if (!body || !body.startsWith('/')) return; // Hanya proses command dengan prefix / | |
| const args = parseArgs(body); | |
| const botId = args.id; | |
| const command = body.split(' ')[0].replace("/", ""); // Hapus prefix / dan ambil command | |
| console.log("debug:", command, args) | |
| if (command == 'new') { | |
| const botNumber = args.number; | |
| if (!botId || !botNumber) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /new --id=shardId --number=phoneNumber` | |
| }); | |
| return; | |
| } | |
| try { | |
| manager.createShard({ | |
| id: botId, | |
| phoneNumber: botNumber | |
| }); | |
| manager.on("login.update", async({ shardId, state, type, code, image }) => { | |
| if (state == "connecting") { | |
| if (type == "qr") { | |
| sock.sendMessage(sender, { | |
| caption: "Scan this QR image to login device!", | |
| image | |
| }); | |
| } else if (type == "pairing") { | |
| sock.sendMessage(sender, { | |
| text: `Pairing code ${shardId}: ${code}` | |
| }); | |
| } | |
| } else if (state == "connected") { | |
| sock.sendMessage(sender, { | |
| text: `β ${shardId} successfully connected` | |
| }); | |
| } else if (state == "disconnected") { | |
| sock.sendMessage(sender, { | |
| text: `β οΈ ${shardId} disconnected, will reconnect...` | |
| }); | |
| } else if (state == "logged_out") { | |
| sock.sendMessage(sender, { | |
| text: `β ${shardId} logged out, session cleared` | |
| }); | |
| } else if (state == "creds_saved") { | |
| sock.sendMessage(sender, { | |
| text: `πΎ Credentials ${shardId} saved` | |
| }); | |
| } | |
| }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to create shard: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'stop') { | |
| if (!botId) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /stop --id=shardId` | |
| }); | |
| return; | |
| } | |
| try { | |
| const stopStatus = await manager.stopShard(botId); | |
| sock.sendMessage(sender, { | |
| text: `π Shard ${botId} stopped successfully!` | |
| }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to stop shard ${botId}: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'socket') { | |
| if (!botId) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /socket --id=shardId` | |
| }); | |
| return; | |
| } | |
| const shardSocket = manager.socket(botId); | |
| if (shardSocket) { | |
| const socketInfo = `π± *Socket Info for ${botId}:*\n\n` + | |
| `User ID: ${shardSocket?.user?.id || 'N/A'}\n` + | |
| `User Name: ${shardSocket?.user?.name || 'N/A'}\n` + | |
| `Connection State: ${shardSocket?.ws?.readyState == 1 ? 'Connected' : 'Disconnected'}\n` + | |
| `Auth Registered: ${shardSocket?.authState?.creds?.registered ? 'β ' : 'β'}`; | |
| sock.sendMessage(sender, { text: socketInfo }); | |
| } else { | |
| sock.sendMessage(sender, { | |
| text: `β Socket not found for shard ${botId}` | |
| }); | |
| } | |
| } | |
| else if (command == 'info') { | |
| if (!botId) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /info --id=shardId` | |
| }); | |
| return; | |
| } | |
| const shardInfo = manager.getShardInfo(botId); | |
| if (shardInfo) { | |
| const infoText = `βΉοΈ *Shard Info: ${botId}*\n\n` + | |
| `ID: ${shardInfo.id}\n` + | |
| `Index: ${shardInfo.index}\n` + | |
| `Total Shards: ${shardInfo.total}\n` + | |
| `Phone Number: ${shardInfo.phoneNumber || 'N/A'}\n` + | |
| `Status: ${shardInfo.status}\n` + | |
| `Created: ${shardInfo.createdAt || 'N/A'}\n` + | |
| `Last Update: ${shardInfo.updatedAt || 'N/A'}`; | |
| sock.sendMessage(sender, { text: infoText }); | |
| } else { | |
| sock.sendMessage(sender, { | |
| text: `β Shard info not found for ${botId}` | |
| }); | |
| } | |
| } | |
| else if (command == 'listall') { | |
| const allShardInfo = manager.getAllShardInfo(); | |
| if (allShardInfo.length == 0) { | |
| sock.sendMessage(sender, { | |
| text: `π No active shards found.` | |
| }); | |
| } else { | |
| let listText = `π *All Active Shards (${allShardInfo.length}):*\n\n`; | |
| allShardInfo.forEach((shard, index) => { | |
| listText += `*${index + 1}. ${shard.id}*\n`; | |
| listText += ` Status: ${shard.status}\n`; | |
| listText += ` Phone: ${shard.phoneNumber || 'N/A'}\n`; | |
| listText += ` Index: ${shard.index}/${shard.total}\n\n`; | |
| }); | |
| sock.sendMessage(sender, { text: listText }); | |
| } | |
| } | |
| else if (command == 'connect') { | |
| if (!botId) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /connect --id=shardId` | |
| }); | |
| return; | |
| } | |
| try { | |
| const connectResult = await manager.connect(botId); | |
| sock.sendMessage(sender, { | |
| text: `π Attempting to connect shard ${connectResult.id}...` | |
| }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to connect shard ${botId}: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'recreate') { | |
| const clearSession = args.clear == 'true'; | |
| const forceRecreate = args.force == 'true'; | |
| if (!botId) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /recreate --id=shardId [--clear=true] [--force=true]` | |
| }); | |
| return; | |
| } | |
| try { | |
| const recreateResult = await manager.recreateShard({ | |
| id: botId, | |
| clearSession, | |
| forceRecreate | |
| }); | |
| sock.sendMessage(sender, { | |
| text: `β»οΈ Shard ${recreateResult.id} recreated successfully!\n` + | |
| `Clear Session: ${clearSession ? 'β ' : 'β'}\n` + | |
| `Force Recreate: ${forceRecreate ? 'β ' : 'β'}` | |
| }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to recreate shard ${botId}: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'session') { | |
| if (!botId) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /session --id=shardId` | |
| }); | |
| return; | |
| } | |
| try { | |
| const sessionInfo = await manager.getSessionInfo(botId); | |
| const sessionText = `πΎ *Session Info for ${botId}:*\n\n` + | |
| `Exists: ${sessionInfo.exists ? 'β ' : 'β'}\n` + | |
| `Registered: ${sessionInfo.registered ? 'β ' : 'β'}\n` + | |
| `Valid: ${sessionInfo.valid ? 'β ' : 'β'}\n` + | |
| `Reason: ${sessionInfo.reason || 'N/A'}`; | |
| sock.sendMessage(sender, { text: sessionText }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to get session info for ${botId}: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'loadall') { | |
| try { | |
| sock.sendMessage(sender, { | |
| text: `π Loading all existing sessions...` | |
| }); | |
| const loadedIds = await manager.loadAllShards(); | |
| if (loadedIds.length == 0) { | |
| sock.sendMessage(sender, { | |
| text: `β No sessions were loaded.` | |
| }); | |
| } else { | |
| let loadText = `β *Loaded ${loadedIds.length} sessions:*\n\n`; | |
| loadedIds.forEach((id, index) => { | |
| loadText += `${index + 1}. ${id}\n`; | |
| }); | |
| sock.sendMessage(sender, { text: loadText }); | |
| } | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to load sessions: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'cleanup') { | |
| try { | |
| sock.sendMessage(sender, { | |
| text: `π§Ή Starting session cleanup...` | |
| }); | |
| await manager.cleanupCorruptSessions(); | |
| sock.sendMessage(sender, { | |
| text: `β Session cleanup completed!` | |
| }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Cleanup failed: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'send') { | |
| const targetJid = args.to; | |
| const message = args.message; | |
| if (!botId || !targetJid || !message) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /send --id=shardId --to=targetNumber --message="your message"` | |
| }); | |
| return; | |
| } | |
| try { | |
| const shardSocket = manager.socket(botId); | |
| if (!shardSocket) { | |
| throw new Error(`Shard ${botId} not found`); | |
| } | |
| await shardSocket.sendMessage(targetJid + "@s.whatsapp.net", { text: message }); | |
| sock.sendMessage(sender, { | |
| text: `β Message sent from shard ${botId} to ${targetJid}` | |
| }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to send message from ${botId}: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'events') { | |
| if (!botId) { | |
| sock.sendMessage(sender, { | |
| text: `β Usage: /events --id=shardId` | |
| }); | |
| return; | |
| } | |
| try { | |
| const shardEmitter = manager.shard(botId); | |
| if (shardEmitter) { | |
| let eventCount = 0; | |
| const eventTypes = []; | |
| const tempListener = (event, payload) => { | |
| if (!eventTypes.includes(event)) { | |
| eventTypes.push(event); | |
| } | |
| eventCount++; | |
| }; | |
| manager.onAny(tempListener); | |
| setTimeout(() => { | |
| const eventText = `π‘ *Events for Shard ${botId}:*\n\n` + | |
| `Total Events (30s): ${eventCount}\n` + | |
| `Event Types: ${eventTypes.join(', ') || 'None'}\n\n` + | |
| `Available Events:\n` + | |
| `β’ messages.upsert\nβ’ connection.update\nβ’ creds.update\n` + | |
| `β’ chats.upsert\nβ’ contacts.upsert\nβ’ groups.upsert`; | |
| sock.sendMessage(sender, { text: eventText }); | |
| }, 30000); | |
| sock.sendMessage(sender, { | |
| text: `π Monitoring events for shard ${botId} for 30 seconds...` | |
| }); | |
| } else { | |
| sock.sendMessage(sender, { | |
| text: `β Event emitter not found for shard ${botId}` | |
| }); | |
| } | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Failed to get events for ${botId}: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'health') { | |
| try { | |
| const allShards = manager.getAllShardInfo(); | |
| let healthyCount = 0; | |
| let connectedCount = 0; | |
| let disconnectedCount = 0; | |
| let errorCount = 0; | |
| for (const shard of allShards) { | |
| const sessionInfo = await manager.getSessionInfo(shard.id); | |
| if (sessionInfo.valid && shard.status == 'connected') { | |
| healthyCount++; | |
| connectedCount++; | |
| } else if (shard.status == 'disconnected') { | |
| disconnectedCount++; | |
| } else { | |
| errorCount++; | |
| } | |
| } | |
| const healthText = `π₯ *Shard Health Report:*\n\n` + | |
| `Total Shards: ${allShards.length}\n` + | |
| `Healthy & Connected: ${healthyCount} β \n` + | |
| `Disconnected: ${disconnectedCount} β οΈ\n` + | |
| `Errors/Issues: ${errorCount} β\n\n` + | |
| `Overall Health: ${healthyCount == allShards.length ? 'Perfect' : | |
| healthyCount >= (allShards.length * 0.8) ? 'Good' : | |
| healthyCount >= (allShards.length * 0.5) ? 'Fair' : 'Poor'}`; | |
| sock.sendMessage(sender, { text: healthText }); | |
| } catch (error) { | |
| sock.sendMessage(sender, { | |
| text: `β Health check failed: ${error.message}` | |
| }); | |
| } | |
| } | |
| else if (command == 'help') { | |
| const helpText = `π€ *Shard Manager Commands:*\n\n` + | |
| `*Basic Management:*\n` + | |
| `β’ /new --id=botId --number=phoneNumber - Create new shard\n` + | |
| `β’ /stop --id=botId - Stop shard\n` + | |
| `β’ /connect --id=botId - Connect/reconnect shard\n` + | |
| `β’ /recreate --id=botId [--clear=true] [--force=true] - Recreate shard\n\n` + | |
| `*Information & Status:*\n` + | |
| `β’ /info --id=botId - Get shard information\n` + | |
| `β’ /session --id=botId - Get session status\n` + | |
| `β’ /socket --id=botId - Get socket information\n` + | |
| `β’ /listall - List all active shards\n\n` + | |
| `*Session Management:*\n` + | |
| `β’ /loadall - Load all existing sessions\n` + | |
| `β’ /cleanup - Clean up corrupt sessions\n` + | |
| `β’ /health - Overall health check\n\n` + | |
| `*Messaging & Events:*\n` + | |
| `β’ /send --id=botId --to=target --message="text" - Send message\n` + | |
| `β’ /events --id=botId - Monitor shard events\n\n` + | |
| `β’ /help - Show this help message`; | |
| sock.sendMessage(sender, { text: helpText }); | |
| } | |
| else { | |
| // Command tidak dikenali | |
| sock.sendMessage(sender, { | |
| text: `β Command "${command}" not recognized. Type /help for available commands.` | |
| }); | |
| } | |
| }); | |
| return sock; | |
| } | |
| start(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment