Github GitHub - orkestral/venom: Venom the more complete javascript library for...
source link: https://github.com/orkestral/venom
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Venom the more complete javascript library for Whatsapp, 100% Open Source
Venom is a high-performance system developed with JavaScript to create a bot for WhatsApp, support for creating any interaction, such as customer service, media sending, sentence recognition based on artificial intelligence and all types of design architecture for WhatsApp.
Getting Started • Basic Function • Documentation
Grupo de Suporte do Venom em português do Brasil | R$ 30 Mensais
Functions Venom
Automatic QR Refresh Send text, image, video, audio, files Get contacts, chats, groups, group members, Block List Send contacts & Multples Contacts Send Location Send Link Preview Send stickers Send stickers GIF Send stories text, image, video Multiple Sessions Forward Messages Receive message insert user section Send location!! and much moreDocumentation at https://orkestral.github.io/venom/index.html
Installation
> npm i --save venom-bot
or for Nightly releases:
> npm i --save https://github.com/orkestral/venom/releases/download/nightly/venom-bot-nightly.tgz
Getting started
// Supports ES6 // import { create, Whatsapp } from 'venom-bot'; const venom = require('venom-bot'); venom .create() .then((client) => { let time = 0; client.onStreamChange((state) => { console.log('Connection status: ', state); clearTimeout(time); if(state === 'CONNECTED'){ start(client); } // DISCONNECTED when the mobile device is disconnected if (state === 'DISCONNECTED' || state === 'SYNCING') { time = setTimeout(() => { client.close(); // process.exit(); //optional function if you work with only one session }, 80000); } }) .catch((erro) => { console.log('There was an error in the bot',erro); }); function start(client) { let inchat = await client.isInsideChat(); //wait until the page is in whatsapp chat if (inchat) { client.onMessage((message) => { if (message.body === 'Hi' && message.isGroupMsg === false) { client .sendText(message.from, 'Welcome Venom 🕷') .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); } }); } }
After executing create()
function, venom will create an instance of whatsapp web. If you are not logged in, it will print a QR code in the terminal. Scan it with your phone and you are ready to go!
Venom will remember the session so there is no need to authenticate everytime.
Multiples sessions can be created at the same time by pasing a session name to create()
function:
// Init sales whatsapp bot venom.create('sales').then((salesClient) => {...}); // Init support whatsapp bot venom.create('support').then((supportClient) => {...});
Optional create parameters
Venom create()
method third parameter can have the following optional parameters:
const venom = require('venom-bot'); venom .create( //session 'sessionName', //Pass the name of the client you want to start the bot //catchQR (base64Qrimg, asciiQR, attempts, urlCode) => { console.log('Number of attempts to read the qrcode: ', attempts); console.log('Terminal qrcode: ', asciiQR); console.log('base64 image string qrcode: ', base64Qrimg); console.log('urlCode (data-ref): ', urlCode); }, // statusFind (statusSession, session) => { console.log('Status Session: ', statusSession); //return isLogged || notLogged || browserClose || qrReadSuccess || qrReadFail || autocloseCalled || desconnectedMobile || deleteToken //Create session wss return "serverClose" case server for close console.log('Session name: ', session); }, // options { folderNameToken: 'tokens', //folder name when saving tokens mkdirFolderToken: '', //folder directory tokens, just inside the venom folder, example: { mkdirFolderToken: '/node_modules', } //will save the tokens folder in the node_modules directory headless: true, // Headless chrome devtools: false, // Open devtools by default useChrome: true, // If false will use Chromium instance debug: false, // Opens a debug session logQR: true, // Logs QR automatically in terminal browserWS: '', // If u want to use browserWSEndpoint browserArgs: [''], // Parameters to be added into the chrome browser instance puppeteerOptions: {}, // Will be passed to puppeteer.launch disableSpins: true, // Will disable Spinnies animation, useful for containers (docker) for a better log disableWelcome: true, // Will disable the welcoming message which appears in the beginning updatesLog: true, // Logs info updates automatically in terminal autoClose: 60000, // Automatically closes the venom-bot only when scanning the QR code (default 60 seconds, if you want to turn it off, assign 0 or false) createPathFileToken: false, //creates a folder when inserting an object in the client's browser, to work it is necessary to pass the parameters in the function create browserSessionToken }, // BrowserSessionToken // To receive the client's token use the function await client.getSessionTokenBrowser() { WABrowserId: '"UnXjH....."', WASecretBundle: '{"key":"+i/nRgWJ....","encKey":"kGdMR5t....","macKey":"+i/nRgW...."}', WAToken1: '"0i8...."', WAToken2: '"1@lPpzwC...."', } ) .then((client) => { let time = 0; client.onStreamChange((state) => { console.log('Connection status: ', state); clearTimeout(time); if(state === 'CONNECTED'){ start(client); } // DISCONNECTED when the mobile device is disconnected if (state === 'DISCONNECTED' || state === 'SYNCING') { time = setTimeout(() => { client.close(); // process.exit(); //optional function if you work with only one session }, 80000); } }) .catch((erro) => { console.log('There was an error in the bot',erro); });
Callback Status Session
Gets the return if the session is isLogged
or notLogged
or browserClose
or qrReadSuccess
or qrReadFail
or autocloseCalled
or desconnectedMobile
or deleteToken
or Create session wss return "serverClose" case server for close
isLogged
When the user is already logged in to the browser
notLogged
When the user is not connected to the browser, it is necessary to scan the QR code through the cell phone in the option WhatsApp Web
browserClose
If the browser is closed this parameter is returned
qrReadSuccess
If the user is not logged in, the QR code is passed on the terminal a callback is returned. After the correct reading by cell phone this parameter is returned
qrReadFail
If the browser stops when the QR code scan is in progress, this parameter is returned
autocloseCalled
The browser was closed using the autoClose command
desconnectedMobile
Client has desconnected in to mobile
serverClose
Client has desconnected in to wss
deleteToken
If you pass true within the function client.getSessionTokenBrowser(true)
const venom = require('venom-bot'); venom .create( 'sessionName', undefined, (statusSession, session) => { console.log('Status Session: ', statusSession); //return isLogged || notLogged || browserClose || qrReadSuccess || qrReadFail || autocloseCalled || desconnectedMobile || deleteToken //Create session wss return "serverClose" case server for close console.log('Session name: ', session); }, undefined ) .then((client) => { let time = 0; client.onStreamChange((state) => { console.log('Connection status: ', state); clearTimeout(time); if(state === 'CONNECTED'){ start(client); } // DISCONNECTED when the mobile device is disconnected if (state === 'DISCONNECTED' || state === 'SYNCING') { time = setTimeout(() => { client.close(); // process.exit(); //optional function if you work with only one session }, 80000); } }) .catch((erro) => { console.log('There was an error in the bot', erro); });
Exporting QR Code
By default QR code will appear on the terminal. If you need to pass the QR somewhere else heres how:
const fs = require('fs'); const venom = require('venom-bot'); venom .create( 'sessionName', (base64Qr, asciiQR, attempts, urlCode) => { console.log(asciiQR); // Optional to log the QR in the terminal var matches = base64Qr.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/), response = {}; if (matches.length !== 3) { return new Error('Invalid input string'); } response.type = matches[1]; response.data = new Buffer.from(matches[2], 'base64'); var imageBuffer = response; require('fs').writeFile( 'out.png', imageBuffer['data'], 'binary', function (err) { if (err != null) { console.log(err); } } ); }, undefined, { logQR: false } ) .then((client) => { let time = 0; client.onStreamChange((state) => { console.log('Connection status: ', state); clearTimeout(time); if(state === 'CONNECTED'){ start(client); } // DISCONNECTED when the mobile device is disconnected if (state === 'DISCONNECTED' || state === 'SYNCING') { time = setTimeout(() => { client.close(); // process.exit(); //optional function if you work with only one session }, 80000); } }) .catch((erro) => { console.log('There was an error in the bot', erro); });
Downloading Files
Puppeteer takes care of the file downloading. The decryption is being done as fast as possible (outruns native methods). Supports big files!
import fs = require('fs'); import mime = require('mime-types'); client.onMessage( async (message) => { if (message.isMedia === true || message.isMMS === true) { const buffer = await client.decryptFile(message); // At this point you can do whatever you want with the buffer // Most likely you want to write it into a file const fileName = `some-file-name.${mime.extension(message.mimetype)}`; await fs.writeFile(fileName, buffer, (err) => { ... }); } });
Basic Functions (usage)
Not every available function is listed, for further look, every function available can be found in here and here
Chatting
Here, chatId
could be <phoneNumber>@c.us
or <phoneNumber>-<groupId>@g.us
//send an image in Status (history) await client.sendStatusImg("https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Alan_Turing_Aged_16_%28cropped%29.jpg/300px-Alan_Turing_Aged_16_%28cropped%29.jpg", "test") .then((result) => { console.log('Result image: ', result); //return object success }).catch((erro) => { console.error('Error when sending image: ', erro); //return object error }); //send an text in Status (history) await client.sendStatusText("Água mole em pedra dura tanto bate até que fura").then((result) => { console.log('Result text', result); //return object success }) .catch((erro) => { console.error('Error when sending text: ', erro);//return object error }); //send an video in Status (history) await client.sendStatusVideo("test.mp4", "test").then((result) => { console.log('Result video', result); }) .catch((erro) => { console.error('Error when sending video: ', erro); }); // Send contact await client .sendContactVcard('[email protected]', '[email protected]', 'Name of contact') .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Send a list of contact cards await client .sendContactVcardList('[email protected]', [ '[email protected]', '[email protected]', ]) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Send basic text await client .sendText('[email protected]', '👋 Hello from venom!') .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Send location await client .sendLocation('[email protected]', '-13.6561589', '-69.7309264', 'Brasil') .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Automatically sends a link with the auto generated link preview. You can also add a custom message to be added. await client .sendLinkPreview( '[email protected]', 'https://www.youtube.com/watch?v=V1bFr2SWP1I', 'Kamakawiwo ole' ) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Send image (you can also upload an image using a valid HTTP protocol) await client .sendImage( '[email protected]', 'path/to/img.jpg', 'image-name', 'Caption text' ) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Send file (venom will take care of mime types, just need the path) // you can also upload an image using a valid HTTP protocol await client .sendFile( '[email protected]', 'path/to/file.pdf', 'file_name', 'See my file in pdf' ) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Sends file // base64 parameter should have mime type already defined await client .sendFileFromBase64( '[email protected]', base64PDF, 'file_name.pdf', 'See my file in pdf' ) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Generates sticker from the provided animated gif image and sends it (Send image as animated sticker) // image path imageBase64 A valid gif and webp image is required. You can also send via http/https (http://www.website.com/img.gif) await client .sendImageAsStickerGif('[email protected]', './image.gif') .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Generates sticker from given image and sends it (Send Image As Sticker) // image path imageBase64 A valid png, jpg and webp image is required. You can also send via http/https (http://www.website.com/img.jpg) await client .sendImageAsSticker('[email protected]', './image.jpg') .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Send @tagged message await client.sendMentioned( '[email protected]', 'Hello @5218113130740 and @5218243160777!', ['5218113130740', '5218243160777'] ); // Reply to a message await client.reply( '[email protected]', 'This is a reply!', message.id.toString() ); // Reply to a message with mention await client.reply( '[email protected]', 'Hello @5218113130740 and @5218243160777! This is a reply with mention!', message.id.toString(), ['5218113130740', '5218243160777'] ); // Send message with options await client. .sendMessageOptions( '[email protected]', 'This is a reply!', { quotedMessageId: reply, } ) .then((retorno) => { resp = retorno; }) .catch((e) => { console.log(e); }); // Send gif await client.sendVideoAsGif( '[email protected]', 'path/to/video.mp4', 'video.gif', 'Gif image file' ); // Forwards messages await client.forwardMessages( '[email protected]', [message.id.toString()], true ); // Send seen ✔️✔️ await client.sendSeen('[email protected]'); // Start typing... await client.startTyping('[email protected]'); // Stop typing await client.stopTyping('[email protected]'); // Set chat state (0: Typing, 1: Recording, 2: Paused) await client.setChatState('[email protected]', 0 | 1 | 2);
Retrieving Data
//Retrieves all grups const groups = await client.getAllChatsGroups(); //Retrieves all chats Contacts const contacts = await client.getAllChatsContacts(); //Retrieves all chats Transmission list const transmission = await client.getAllChatsTransmission(); //Retrieve all contacts new messages const contactNewMsg = await client.getChatContactNewMsg(); //Retrieve all groups new messages const groupNewMsg = await client.getChatGroupNewMsg(); // Returns a list of mute and non-mute users // "all" List all mutes // "toMute" List all silent chats // "noMute" List all chats without silence const listMute = await client.getListMute('all'); // Retrieve the browser session token // if you want to delete the token file -> const browserSessionToken = await client.getSessionTokenBrowser(true); const browserSessionToken = await client.getSessionTokenBrowser(); // Calls your list of blocked contacts (returns an array) const getBlockList = await client.getBlockList(); // Retrieve contacts const contacts = await client.getAllContacts(); // Retrieve messages in chat const Messages = await client.getAllMessagesInChat('[email protected]'); // Retrieve more chat message const moreMessages = await client.loadEarlierMessages('[email protected]'); // Retrieve all messages in chat const allMessages = await client.loadAndGetAllMessagesInChat( '[email protected]' ); // Retrieve contact status const status = await client.getStatus('[email protected]'); // Retrieve user profile const user = await client.getNumberProfile('[email protected]'); // Retrieve all unread message const messages = await client.getAllUnreadMessages(); // Retrieve all chats const chats = await client.getAllChats(); // Retrieve all groups const chats = await client.getAllGroups(); // Retrieve profile fic (as url) const url = await client.getProfilePicFromServer('[email protected]'); // Retrieve chat/conversation const chat = await client.getChat('[email protected]'); // Check if the number exists const chat = await client.checkNumberStatus('[email protected]');
Group Functions
// groupId or chatId: leaveGroup [email protected] // Leave group await client.leaveGroup('[email protected]'); // Get group members await client.getGroupMembers('[email protected]'); // Get group members ids await client.getGroupMembersIds('[email protected]'); // Generate group invite url link await client.getGroupInviteLink('[email protected]'); // Create group (title, participants to add) await client.createGroup('Group name', [ '[email protected]', '[email protected]', ]); // Remove participant await client.removeParticipant('[email protected]', '[email protected]'); // Add participant await client.addParticipant('[email protected]', '[email protected]'); // Promote participant (Give admin privileges) await client.promoteParticipant('[email protected]', '[email protected]'); // Demote particiapnt (Revoke admin privileges) await client.demoteParticipant('[email protected]', '[email protected]'); // Get group admins await client.getGroupAdmins('[email protected]'); // Return the group status, jid, description from it's invite link await client.getGroupInfoFromInviteLink(InviteCode); // Join a group using the group invite code await client.joinGroup(InviteCode);
Profile Functions
// Set client status await client.setProfileStatus('On vacations! ✈️'); // Set client profile name await client.setProfileName('Venom bot'); // Set client profile photo await client.setProfilePic('path/to/image.jpg');
Device Functions
// Delete the Service Worker await client.killServiceWorker(); // Load the service again await client.restartService(); // Get device info await client.getHostDevice(); // Get connection state await client.getConnectionState(); // Get battery level await client.getBatteryLevel(); // Is connected await client.isConnected(); // Get whatsapp web version await client.getWAVersion();
Events
// Listen to messages client.onMessage(message => { ... }) // Listen to state changes client.onStateChange(state => { ... }); // Listen to ack's // See the status of the message when sent. // When receiving the confirmation object, "ack" may return a number, look {@link AckType} for details: // -7 = MD_DOWNGRADE, // -6 = INACTIVE, // -5 = CONTENT_UNUPLOADABLE, // -4 = CONTENT_TOO_BIG, // -3 = CONTENT_GONE, // -2 = EXPIRED, // -1 = FAILED, // 0 = CLOCK, // 1 = SENT, // 2 = RECEIVED, // 3 = READ, // 4 = PLAYED = client.onAck(ack => { ... }); // Listen to live location // chatId: '[email protected]' client.onLiveLocation("[email protected]", (liveLocation) => { ... }); // chatId looks like this: '[email protected]' // Event interface is in here: https://github.com/s2click/venom/blob/master/src/api/model/participant-event.ts client.onParticipantsChanged("[email protected]", (event) => { ... }); // Listen when client has been added to a group client.onAddedToGroup(chatEvent => { ... });
Other
// Pin chat and Unpin chat messages with true or false // Pin chat, non-existent (optional) await client .pinChat(chatId, true, false) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); ///mute a contact await client .sendMute( '[email protected]', //contact mute 30, //duration of silence, example: 30 minutes 'minutes' ///kind of silence "hours" "minutes" "year" ) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); ///unmute contact await client .sendMute( '[email protected]' //contact unmute ) .then((result) => { console.log('Result: ', result); //return object success }) .catch((erro) => { console.error('Error when sending: ', erro); //return object error }); // Change the theme // string types "dark" or "light" await client.setTheme('dark'); // Receive the current theme // returns string light or dark await client.getTheme(); // Delete chat await client.deleteChat('[email protected]'); // Clear chat messages await client.clearChat('[email protected]'); // Archive and unarchive chat messages with true or false await client.archiveChat(chatId, true); // Delete message (last parameter: delete only locally) await client.deleteMessage('[email protected]', message.id.toString(), false); // Mark chat as not seen (returns true if it works) await client.markUnseenMessage('[email protected]'); // Blocks a user (returns true if it works) await client.blockContact('[email protected]'); // Unlocks contacts (returns true if it works) await client.unblockContact('[email protected]'); // Retrieve a number profile / check if contact is a valid whatsapp number const profile = await client.getNumberProfile('[email protected]');
There are some tricks for a better usage of venom.
Keep session alive:
// function to detect conflits and change status // Force it to keep the current session // Possible state values: // CONFLICT // CONNECTED // DEPRECATED_VERSION // OPENING // PAIRING // PROXYBLOCK // SMB_TOS_BLOCK // TIMEOUT // TOS_BLOCK // UNLAUNCHED // UNPAIRED // UNPAIRED_IDLE client.onStateChange((state) => { console.log('State changed: ', state); // force whatsapp take over if ('CONFLICT'.includes(state)) client.useHere(); // detect disconnect on whatsapp if ('UNPAIRED'.includes(state)) console.log('logout'); }); // DISCONNECTED // SYNCING // RESUMING // CONNECTED let time = 0; client.onStreamChange((state) => { console.log('State Connection Stream: ' + state); clearTimeout(time); if (state === 'DISCONNECTED' || state === 'SYNCING') { time = setTimeout(() => { client.close(); }, 80000); } }); // function to detect incoming call client.onIncomingCall(async (call) => { console.log(call); client.sendText(call.peerJid, "Sorry, I still can't answer calls"); });
Closing (saving) sessions
Close the session properly to ensure the session is saved for the next time you log in (So it won't ask for QR scan again). So instead of CTRL+C,
// Catch ctrl+C process.on('SIGINT', function() { client.close(); }); // Try-catch close try { ... } catch (error) { client.close(); }
Auto closing unsynced sessions
The auto close is enabled by default and the timeout is set to 60 sec. Receives the time in milliseconds to countdown until paired.
Use "autoClose: 0 | false" to disable auto closing.
Debugging
Development
Building venom is really simple altough it contains 3 main projects inside
- Wapi project
> npm run build:wapi
- Middleware
> npm run build:middleware > npm run build:jsQR
- Venom
> npm run build:venom
To build the entire project just run
> npm run build
Maintainers
Maintainers are needed, I cannot keep with all the updates by myself. If you are interested please open a Pull Request.
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK