mirror of
https://github.com/cheveguerra/whatsapp-api-tutorial.git
synced 2026-04-17 19:36:59 +00:00
Add new feature: multiple whatsapp client (dynamic)
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
node_modules
|
node_modules
|
||||||
whatsapp-session.json
|
whatsapp-session-*.json
|
||||||
174
app-multiple-device.js
Normal file
174
app-multiple-device.js
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
const { Client, MessageMedia } = require('whatsapp-web.js');
|
||||||
|
const express = require('express');
|
||||||
|
const socketIO = require('socket.io');
|
||||||
|
const qrcode = require('qrcode');
|
||||||
|
const http = require('http');
|
||||||
|
const fs = require('fs');
|
||||||
|
const { phoneNumberFormatter } = require('./helpers/formatter');
|
||||||
|
const axios = require('axios');
|
||||||
|
const port = process.env.PORT || 8000;
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const server = http.createServer(app);
|
||||||
|
const io = socketIO(server);
|
||||||
|
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.urlencoded({
|
||||||
|
extended: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
res.sendFile('index.html', {
|
||||||
|
root: __dirname
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const sessions = [];
|
||||||
|
const createSession = function(id, description, io) {
|
||||||
|
const SESSION_FILE_PATH = `./whatsapp-session-${id}.json`;
|
||||||
|
let sessionCfg;
|
||||||
|
if (fs.existsSync(SESSION_FILE_PATH)) {
|
||||||
|
sessionCfg = require(SESSION_FILE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
restartOnAuthFail: true,
|
||||||
|
puppeteer: {
|
||||||
|
headless: true,
|
||||||
|
args: [
|
||||||
|
'--no-sandbox',
|
||||||
|
'--disable-setuid-sandbox',
|
||||||
|
'--disable-dev-shm-usage',
|
||||||
|
'--disable-accelerated-2d-canvas',
|
||||||
|
'--no-first-run',
|
||||||
|
'--no-zygote',
|
||||||
|
'--single-process', // <- this one doesn't works in Windows
|
||||||
|
'--disable-gpu'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
session: sessionCfg
|
||||||
|
});
|
||||||
|
|
||||||
|
client.initialize();
|
||||||
|
|
||||||
|
client.on('qr', (qr) => {
|
||||||
|
console.log('QR RECEIVED', qr);
|
||||||
|
qrcode.toDataURL(qr, (err, url) => {
|
||||||
|
io.emit('qr', { id: id, src: url });
|
||||||
|
io.emit('message', { id: id, text: 'QR Code received, scan please!' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('ready', () => {
|
||||||
|
io.emit('ready', { id: id });
|
||||||
|
io.emit('message', { id: id, text: 'Whatsapp is ready!' });
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('authenticated', (session) => {
|
||||||
|
io.emit('authenticated', { id: id });
|
||||||
|
io.emit('message', { id: id, text: 'Whatsapp is authenticated!' });
|
||||||
|
sessionCfg = session;
|
||||||
|
fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function(err) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('auth_failure', function(session) {
|
||||||
|
io.emit('message', { id: id, text: 'Auth failure, restarting...' });
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('disconnected', (reason) => {
|
||||||
|
io.emit('message', { id: id, text: 'Whatsapp is disconnected!' });
|
||||||
|
fs.unlinkSync(SESSION_FILE_PATH, function(err) {
|
||||||
|
if(err) return console.log(err);
|
||||||
|
console.log('Session file deleted!');
|
||||||
|
});
|
||||||
|
client.destroy();
|
||||||
|
client.initialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tambahkan client ke sessions
|
||||||
|
sessions.push({
|
||||||
|
id: id,
|
||||||
|
description: description,
|
||||||
|
client: client
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Socket IO
|
||||||
|
io.on('connection', function(socket) {
|
||||||
|
socket.on('create-session', function(data) {
|
||||||
|
console.log('Create session: ' + data.id);
|
||||||
|
createSession(data.id, data.description, io);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// io.on('connection', function(socket) {
|
||||||
|
// socket.emit('message', 'Connecting...');
|
||||||
|
|
||||||
|
// client.on('qr', (qr) => {
|
||||||
|
// console.log('QR RECEIVED', qr);
|
||||||
|
// qrcode.toDataURL(qr, (err, url) => {
|
||||||
|
// socket.emit('qr', url);
|
||||||
|
// socket.emit('message', 'QR Code received, scan please!');
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// client.on('ready', () => {
|
||||||
|
// socket.emit('ready', 'Whatsapp is ready!');
|
||||||
|
// socket.emit('message', 'Whatsapp is ready!');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// client.on('authenticated', (session) => {
|
||||||
|
// socket.emit('authenticated', 'Whatsapp is authenticated!');
|
||||||
|
// socket.emit('message', 'Whatsapp is authenticated!');
|
||||||
|
// console.log('AUTHENTICATED', session);
|
||||||
|
// sessionCfg = session;
|
||||||
|
// fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function(err) {
|
||||||
|
// if (err) {
|
||||||
|
// console.error(err);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// client.on('auth_failure', function(session) {
|
||||||
|
// socket.emit('message', 'Auth failure, restarting...');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// client.on('disconnected', (reason) => {
|
||||||
|
// socket.emit('message', 'Whatsapp is disconnected!');
|
||||||
|
// fs.unlinkSync(SESSION_FILE_PATH, function(err) {
|
||||||
|
// if(err) return console.log(err);
|
||||||
|
// console.log('Session file deleted!');
|
||||||
|
// });
|
||||||
|
// client.destroy();
|
||||||
|
// client.initialize();
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
app.post('/send-message', (req, res) => {
|
||||||
|
const sender = req.body.sender;
|
||||||
|
const number = phoneNumberFormatter(req.body.number);
|
||||||
|
const message = req.body.message;
|
||||||
|
|
||||||
|
const client = sessions.find(sess => sess.id == sender).client;
|
||||||
|
|
||||||
|
client.sendMessage(number, message).then(response => {
|
||||||
|
res.status(200).json({
|
||||||
|
status: true,
|
||||||
|
response: response
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
res.status(500).json({
|
||||||
|
status: false,
|
||||||
|
response: err
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(port, function() {
|
||||||
|
console.log('App running on *: ' + port);
|
||||||
|
});
|
||||||
65
index.html
65
index.html
@@ -2,15 +2,43 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Whatsapp API by Ngekoding</title>
|
<title>Whatsapp API by Ngekoding</title>
|
||||||
|
<style>
|
||||||
|
.client {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.hide {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<h1>Whatsapp API</h1>
|
<h1>Whatsapp API</h1>
|
||||||
<p>Powered by Ngekoding</p>
|
<p>Powered by Ngekoding</p>
|
||||||
<img src="" alt="QR Code" id="qrcode">
|
<div class="form-container">
|
||||||
<h3>Logs:</h3>
|
<label for="client-id">ID</label><br>
|
||||||
<ul class="logs"></ul>
|
<input type="text" id="client-id" placeholder="Masukkan ID">
|
||||||
|
<br><br>
|
||||||
|
<label for="client-description">Deskripsi</label><br>
|
||||||
|
<textarea rows="3" id="client-description" placeholder="Masukkan deskripsi"></textarea>
|
||||||
|
<br><br>
|
||||||
|
<button class="add-client-btn">Tambah Client</button>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="client-container">
|
||||||
|
<div class="client hide">
|
||||||
|
<h3 class="title"></h3>
|
||||||
|
<p class="description"></p>
|
||||||
|
<img src="" alt="QR Code" id="qrcode">
|
||||||
|
<h3>Logs:</h3>
|
||||||
|
<ul class="logs"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
|
||||||
@@ -19,21 +47,38 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var socket = io();
|
var socket = io();
|
||||||
|
|
||||||
socket.on('message', function(msg) {
|
// Ketika button tambah diklik
|
||||||
$('.logs').append($('<li>').text(msg));
|
$('.add-client-btn').click(function() {
|
||||||
|
var clientId = $('#client-id').val();
|
||||||
|
var clientDescription = $('#client-description').val();
|
||||||
|
var template = $('.client').first().clone()
|
||||||
|
.removeClass('hide')
|
||||||
|
.addClass(clientId);
|
||||||
|
template.find('.title').html(clientId);
|
||||||
|
template.find('.description').html(clientDescription);
|
||||||
|
$('.client-container').append(template);
|
||||||
|
|
||||||
|
socket.emit('create-session', {
|
||||||
|
id: clientId,
|
||||||
|
description: clientDescription
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('qr', function(src) {
|
socket.on('message', function(data) {
|
||||||
$('#qrcode').attr('src', src);
|
$(`.client.${data.id} .logs`).append($('<li>').text(data.text));
|
||||||
$('#qrcode').show();
|
});
|
||||||
|
|
||||||
|
socket.on('qr', function(data) {
|
||||||
|
$(`.client.${data.id} #qrcode`).attr('src', data.src);
|
||||||
|
$(`.client.${data.id} #qrcode`).show();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('ready', function(data) {
|
socket.on('ready', function(data) {
|
||||||
$('#qrcode').hide();
|
$(`.client.${data.id} #qrcode`).hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('authenticated', function(data) {
|
socket.on('authenticated', function(data) {
|
||||||
$('#qrcode').hide();
|
$(`.client.${data.id} #qrcode`).hide();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"ignore": ["whatsapp-session.json"]
|
"ignore": ["whatsapp-session-*.json"]
|
||||||
}
|
}
|
||||||
54
package-lock.json
generated
54
package-lock.json
generated
@@ -25,9 +25,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "14.14.6",
|
"version": "14.14.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.10.tgz",
|
||||||
"integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==",
|
"integrity": "sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@types/yauzl": {
|
"@types/yauzl": {
|
||||||
@@ -550,9 +550,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.2.0",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||||
"integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
|
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
}
|
}
|
||||||
@@ -594,9 +594,9 @@
|
|||||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||||
},
|
},
|
||||||
"devtools-protocol": {
|
"devtools-protocol": {
|
||||||
"version": "0.0.809251",
|
"version": "0.0.818844",
|
||||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.809251.tgz",
|
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz",
|
||||||
"integrity": "sha512-pf+2OY6ghMDPjKkzSWxHMq+McD+9Ojmq5XVRYpv/kPd9sTMQxzEt21592a31API8qRjro0iYYOc3ag46qF/1FA=="
|
"integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg=="
|
||||||
},
|
},
|
||||||
"dicer": {
|
"dicer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
@@ -827,11 +827,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"express-validator": {
|
"express-validator": {
|
||||||
"version": "6.6.1",
|
"version": "6.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.7.0.tgz",
|
||||||
"integrity": "sha512-+MrZKJ3eGYXkNF9p9Zf7MS7NkPJFg9MDYATU5c80Cf4F62JdLBIjWxy6481tRC0y1NnC9cgOw8FuN364bWaGhA==",
|
"integrity": "sha512-sLnTFlyKEvesC2Fyn1TY4Q05cWCZHQQ1ijQOVbBG7hFeTKt4CNzttoF4t6CqrYroKa+2DOzj0E09odPIYDTbRg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.20",
|
||||||
"validator": "^13.1.1"
|
"validator": "^13.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1593,12 +1593,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"puppeteer": {
|
"puppeteer": {
|
||||||
"version": "5.4.1",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.5.0.tgz",
|
||||||
"integrity": "sha512-8u6r9tFm3gtMylU4uCry1W/CeAA8uczKMONvGvivkTsGqKA7iB7DWO2CBFYlB9GY6/IEoq9vkI5slJWzUBkwNw==",
|
"integrity": "sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"devtools-protocol": "0.0.809251",
|
"devtools-protocol": "0.0.818844",
|
||||||
"extract-zip": "^2.0.0",
|
"extract-zip": "^2.0.0",
|
||||||
"https-proxy-agent": "^4.0.0",
|
"https-proxy-agent": "^4.0.0",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
@@ -1995,14 +1995,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tar-fs": {
|
"tar-fs": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||||
"integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==",
|
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chownr": "^1.1.1",
|
"chownr": "^1.1.1",
|
||||||
"mkdirp-classic": "^0.5.2",
|
"mkdirp-classic": "^0.5.2",
|
||||||
"pump": "^3.0.0",
|
"pump": "^3.0.0",
|
||||||
"tar-stream": "^2.0.0"
|
"tar-stream": "^2.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tar-stream": {
|
"tar-stream": {
|
||||||
@@ -2176,9 +2176,9 @@
|
|||||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||||
},
|
},
|
||||||
"validator": {
|
"validator": {
|
||||||
"version": "13.1.17",
|
"version": "13.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.1.17.tgz",
|
"resolved": "https://registry.npmjs.org/validator/-/validator-13.5.1.tgz",
|
||||||
"integrity": "sha512-zL5QBoemJ3jYFb2/j38y7ljhwYGXVLUp8H6W1nVxadnAOvUOytec+L7BHh1oBQ82/TzWXHd+GSaxUWp4lROkLg=="
|
"integrity": "sha512-s+7LW1Xi0OzPNfGN7Hb2vk0YB/epp9KFHHGC5JtqZOE1dUkN4ULPFZAQ1inCu7ceAsWmOJu6sn9cnwm3R+ghWQ=="
|
||||||
},
|
},
|
||||||
"vary": {
|
"vary": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@@ -2186,9 +2186,9 @@
|
|||||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||||
},
|
},
|
||||||
"whatsapp-web.js": {
|
"whatsapp-web.js": {
|
||||||
"version": "1.11.0",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/whatsapp-web.js/-/whatsapp-web.js-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatsapp-web.js/-/whatsapp-web.js-1.11.1.tgz",
|
||||||
"integrity": "sha512-gI9Lm1KmmBimNVL8yviJkfkI5qHaKBM47PYtTY2M97RityARmncLwXwss35aKLirQynOjpFxsFEVo4FhMB+3CQ==",
|
"integrity": "sha512-tlRpZBLtBIqVvf9y6dCq3A7rbLu2ttc+D55JwCoNvPniiiZyFLVV4LUAA40g0hEpapkwFbiYdHv5eAV2Gubw3g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@pedroslopez/moduleraid": "^4.1.0",
|
"@pedroslopez/moduleraid": "^4.1.0",
|
||||||
"jsqr": "^1.3.1",
|
"jsqr": "^1.3.1",
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
"axios": "^0.20.0",
|
"axios": "^0.20.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-fileupload": "^1.2.0",
|
"express-fileupload": "^1.2.0",
|
||||||
"express-validator": "^6.6.1",
|
"express-validator": "^6.7.0",
|
||||||
"http": "0.0.1-security",
|
"http": "0.0.1-security",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.4.4",
|
||||||
"socket.io": "^2.3.0",
|
"socket.io": "^2.3.0",
|
||||||
"whatsapp-web.js": "^1.11.0"
|
"whatsapp-web.js": "^1.11.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "v12.10.0"
|
"node": "v12.10.0"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Watch the tutorials:
|
|||||||
- <a href="https://youtu.be/uBu7Zfba1zA">Whatsapp API Tutorial: Tips & Tricks</a>
|
- <a href="https://youtu.be/uBu7Zfba1zA">Whatsapp API Tutorial: Tips & Tricks</a>
|
||||||
- <a href="https://youtu.be/ksVBXF-6Jtc">Whatsapp API Tutorial: Sending Media File</a>
|
- <a href="https://youtu.be/ksVBXF-6Jtc">Whatsapp API Tutorial: Sending Media File</a>
|
||||||
- <a href="https://youtu.be/uSzjbuaHexk">Whatsapp API Tutorial: Deploy to Heroku</a>
|
- <a href="https://youtu.be/uSzjbuaHexk">Whatsapp API Tutorial: Deploy to Heroku</a>
|
||||||
|
- <a href="https://youtu.be/5VfM9PvrYcE">Whatsapp API Tutorial: Multiple Device</a>
|
||||||
|
|
||||||
### How to use?
|
### How to use?
|
||||||
- Clone or download this repo
|
- Clone or download this repo
|
||||||
|
|||||||
Reference in New Issue
Block a user