Compare commits
No commits in common. "c8f6454512e2cab5bfaa98889eb3f3c2662abb02" and "8b733b9365c0431bfb6c1ea9d1314fa06c93aac9" have entirely different histories.
c8f6454512
...
8b733b9365
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
node_modules
|
node_modules
|
||||||
removed.rm
|
|
||||||
@ -1,2 +1 @@
|
|||||||
node_modules
|
node_modules
|
||||||
removed.rm
|
|
||||||
66
README.md
66
README.md
@ -1,7 +1,6 @@
|
|||||||
# Whatsapp Link :iphone:
|
# Whatsapp Link :iphone:
|
||||||
|
|
||||||
Simple node for connecting Node-Red to Whatsapp :iphone:
|
Simple node for connecting Node-Red to Whatsapp :iphone:
|
||||||
Send and Receive Whatsapp Image/Text.
|
|
||||||
|
|
||||||
Currently in developing mode, Continous updated may encounter. :sweat_smile:
|
Currently in developing mode, Continous updated may encounter. :sweat_smile:
|
||||||
|
|
||||||
@ -66,12 +65,12 @@ Admin Node generate QR Code just below the node for easy connection with whatsap
|
|||||||
|
|
||||||
|
|
||||||
3. **Chats / Group Out** : As simple as mention on name, node will send `msg.payload` recived at input to the number mentioned in node.
|
3. **Chats / Group Out** : As simple as mention on name, node will send `msg.payload` recived at input to the number mentioned in node.
|
||||||
`ImageMessage.json` example is avilable in examples to import.
|
`A-reply-to-All.json` example is avilable in examples to import.
|
||||||
|
|
||||||
MultiMedia Message: Requirments-
|
MultiMedia Message: Requirments-
|
||||||
| Input | Description |
|
| Input | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `msg.image` | Base64 (encoded image), [`image-tool`](https://flows.nodered.org/node/node-red-contrib-image-tools) node work fine for incoding base64|
|
| `msg.image` | Base64 (encoded image) |
|
||||||
| `msg.payload` | Image Caption |
|
| `msg.payload` | Image Caption |
|
||||||
| `msg.toNumber` | Reciver number (if number not provided in node) |
|
| `msg.toNumber` | Reciver number (if number not provided in node) |
|
||||||
|
|
||||||
@ -86,7 +85,65 @@ Admin Node generate QR Code just below the node for easy connection with whatsap
|
|||||||
|
|
||||||
The node will send recived `msg.payload` to a group chat.
|
The node will send recived `msg.payload` to a group chat.
|
||||||
|
|
||||||
`A-reply-to-All.json` example is avilable in examples to import.
|
## Button, List and TemplateButton
|
||||||
|
Supported in Whatsapp-Lite only, `TODO for Whatsapp-Web`.
|
||||||
|
A Complete Button-Bot example is avilable in Node examples.
|
||||||
|
|
||||||
|
* <b>Simple Button </b>For simple 3 Bottons your `msg.paylod` should be...
|
||||||
|
|
||||||
|
```js
|
||||||
|
msg.payload = {
|
||||||
|
text: "Hi it's button message", //String
|
||||||
|
footer: 'Hello World', //String
|
||||||
|
headerType: 1, //keep it "1" only.
|
||||||
|
buttons: [ // Array of buttons.
|
||||||
|
{buttonId: 'id1', buttonText: {displayText: 'Button 1'}, type: 1},
|
||||||
|
{buttonId: 'id2', buttonText: {displayText: 'Button 2'}, type: 1},
|
||||||
|
{buttonId: 'id3', buttonText: {displayText: 'Button 3'}, type: 1}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* <b>TemplateButton</b> combination of <b>link button</b>, <b>Call button</b> and Normal buttons. Your `msg.paylod` should look similar to--
|
||||||
|
|
||||||
|
```js
|
||||||
|
msg.payload = {
|
||||||
|
text: "Hi it's a template message by Node-RED 👍 to Test",
|
||||||
|
footer: 'Hello I am footer of message.',
|
||||||
|
templateButtons: [
|
||||||
|
{index: 1, urlButton: {displayText: '⭐ Vist Node-RED', url: 'https://nodered.org/'}},
|
||||||
|
{index: 2, callButton: {displayText: 'Call me!', phoneNumber: '+1 (234) 5678-901'}},
|
||||||
|
{index: 3, quickReplyButton: {displayText: 'Click me I am Button', id: 'I-am-button-id-without-space'}},
|
||||||
|
{index: 4, quickReplyButton: {displayText: '🖱️ Sample Button 2', id: 'button-2-was-clicked'}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* <b>List Message</b> combination of <b>link button</b>, <b>List button</b> and Selectors. Your `msg.paylod` should look similar to--
|
||||||
|
|
||||||
|
```js
|
||||||
|
msg.payload = {
|
||||||
|
text: "This is a list",
|
||||||
|
footer: "nice footer, link: https://google.com",
|
||||||
|
title: "Amazing boldfaced list title",
|
||||||
|
buttonText: "Required, Tap to see List",
|
||||||
|
sections : [{
|
||||||
|
title: "Section 1",
|
||||||
|
rows: [
|
||||||
|
{title: "Option 1", rowId: "option1"},
|
||||||
|
{title: "Option 2", rowId: "option2", description: "This is a description"}
|
||||||
|
]},
|
||||||
|
{
|
||||||
|
title: "Section 2",
|
||||||
|
rows: [
|
||||||
|
{title: "Option 3", rowId: "option3"},
|
||||||
|
{title: "Option 4", rowId: "option4", description: "This is a description V2"}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
Yes its lot require for buttons, A node will come soon to minimize these effors.
|
||||||
|
You may direct import these test buttons from the Node Examples.
|
||||||
|
|
||||||
|
|
||||||
5. **Reply Node** : In Beta mode. (Chats-out Node can be used instead of reply node)
|
5. **Reply Node** : In Beta mode. (Chats-out Node can be used instead of reply node)
|
||||||
|
|
||||||
@ -106,7 +163,6 @@ Issues and Suggestions are welcome [here.](https://github.com/raweee/node-red-co
|
|||||||
* `Ver-0.1.34` : Multiple Events reading options are added in Chats-In Node.
|
* `Ver-0.1.34` : Multiple Events reading options are added in Chats-In Node.
|
||||||
* `Ver-0.1.36` : Check box added to show status as `Online/Offline` in Whatsapp-Link Node, to get push notifications. Ping-Interval added to keep whatsapp alive for long time. Multiple examples added.
|
* `Ver-0.1.36` : Check box added to show status as `Online/Offline` in Whatsapp-Link Node, to get push notifications. Ping-Interval added to keep whatsapp alive for long time. Multiple examples added.
|
||||||
* `Ver-0.1.37` : Changes for correction of send message with images and use Chromium profiles in Puppeteer.
|
* `Ver-0.1.37` : Changes for correction of send message with images and use Chromium profiles in Puppeteer.
|
||||||
* `Ver-0.1.39B` : Broken "Whatsapp-Web & Lite" fixed. Able to `Send/Receive` whatsapp `Image/Text` in both Whatsapp-Lite & Web. working on easy to use nodes.
|
|
||||||
|
|
||||||
## Future Nodes
|
## Future Nodes
|
||||||
Currently working on more Whatsapp Node and will be avilable soon -
|
Currently working on more Whatsapp Node and will be avilable soon -
|
||||||
|
|||||||
29
admin.js
29
admin.js
@ -72,7 +72,7 @@ module.exports = function(RED) {
|
|||||||
msg.type = notification.type;
|
msg.type = notification.type;
|
||||||
msg.notification = notification;
|
msg.notification = notification;
|
||||||
node.send(msg);
|
node.send(msg);
|
||||||
// notification.reply('!Node-Red joined');
|
notification.reply('!Node-Red joined');
|
||||||
});
|
});
|
||||||
|
|
||||||
node.client.on('group_leave', async (notification)=>{
|
node.client.on('group_leave', async (notification)=>{
|
||||||
@ -126,21 +126,16 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
if(node.client.clientType === "waSocketClient"){
|
if(node.client.clientType === "waSocketClient"){
|
||||||
var client = null
|
var client = null
|
||||||
|
|
||||||
|
|
||||||
async function clientFromWhatsappLite(){
|
async function clientFromWhatsappLite(){
|
||||||
client = await node.client;
|
client = await node.client;
|
||||||
client.ev.on('connection.update', (updates)=>{
|
client.ev.on('connection.update', (updates)=>{
|
||||||
function printQrCode(urlQr) {
|
|
||||||
var qrImageWithID = {};
|
|
||||||
qrImageWithID.id = node.id;
|
|
||||||
qrImageWithID.image = urlQr;
|
|
||||||
RED.comms.publish("whatsappLinkQrCode", qrImageWithID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(updates.qr){
|
if(updates.qr){
|
||||||
QRCode.toDataURL(updates.qr, function(err, url){
|
QRCode.toDataURL(updates.qr, function(err, url){
|
||||||
printQrCode(url);
|
var qrImageWithID = {};
|
||||||
|
qrImageWithID.id = node.id;
|
||||||
|
qrImageWithID.image = url;
|
||||||
|
RED.comms.publish("whatsappLinkQrCode", qrImageWithID);
|
||||||
});
|
});
|
||||||
|
|
||||||
QRCode.toString(updates.qr, {type : 'terminal', small:true }, function(err, QRTerminal){
|
QRCode.toString(updates.qr, {type : 'terminal', small:true }, function(err, QRTerminal){
|
||||||
@ -149,16 +144,20 @@ module.exports = function(RED) {
|
|||||||
console.log(QRTerminal);
|
console.log(QRTerminal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (connection === 'open') {
|
||||||
|
var qrImageWithID = {};
|
||||||
|
qrImageWithID.id = node.id;
|
||||||
|
qrImageWithID.image = null;
|
||||||
|
RED.comms.publish("whatsappLinkQrCode", qrImageWithID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(updates);
|
||||||
//Setting conncetion status indication
|
|
||||||
var {connection} = updates
|
var {connection} = updates
|
||||||
|
//Setting conncetion status indication
|
||||||
if(connection === 'open'){
|
if(connection === 'open'){
|
||||||
printQrCode(null);
|
|
||||||
SetStatus("Connected", "green");
|
SetStatus("Connected", "green");
|
||||||
}
|
}
|
||||||
else if(updates.isOnline){
|
else if(updates.isOnline){
|
||||||
printQrCode(null);
|
|
||||||
SetStatus("Connected", "green");
|
SetStatus("Connected", "green");
|
||||||
}
|
}
|
||||||
else if(connection === 'close'){
|
else if(connection === 'close'){
|
||||||
|
|||||||
17
chats-out.js
17
chats-out.js
@ -5,8 +5,7 @@ module.exports = function(RED) {
|
|||||||
node.number = config.number;
|
node.number = config.number;
|
||||||
var whatsappLinkNode = RED.nodes.getNode(config.whatsappLink);
|
var whatsappLinkNode = RED.nodes.getNode(config.whatsappLink);
|
||||||
node.waClient = whatsappLinkNode.client;
|
node.waClient = whatsappLinkNode.client;
|
||||||
const { MessageMedia, Buttons } = require('whatsapp-web.js');
|
const { MessageMedia, Buttons } = require('whatsapp-web.js')
|
||||||
const {Mimetype} = require(`@whiskeysockets/baileys`);
|
|
||||||
|
|
||||||
let SetStatus = function(WAStatus, color){
|
let SetStatus = function(WAStatus, color){
|
||||||
node.status({fill:color,shape:"dot",text:WAStatus});
|
node.status({fill:color,shape:"dot",text:WAStatus});
|
||||||
@ -84,14 +83,12 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
numb = await socNubmerSeteing(numb)
|
numb = await socNubmerSeteing(numb)
|
||||||
|
const imageMessage = {
|
||||||
let imageToSend = Buffer.from(whatsappImageBase64, "base64");
|
text: whatsappCaption,
|
||||||
const imageMessage = {
|
footer: null,
|
||||||
// image: {url : whatsappImage},
|
templateButtons: null,
|
||||||
image: imageToSend,
|
image: {url : whatsappImage }
|
||||||
caption: whatsappCaption
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let client = await node.waClient;
|
let client = await node.waClient;
|
||||||
const msgStatus = await client.sendMessage(numb, imageMessage);
|
const msgStatus = await client.sendMessage(numb, imageMessage);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
18
group-out.js
18
group-out.js
@ -76,23 +76,21 @@ module.exports = function(RED) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function whatsappMultiMediaMessage(numb, whatsappImage, whatsappCaption){
|
async function whatsappMultiMediaMessage(numb, whatsappImage, whatsappCaption){
|
||||||
|
var whatsappImageBase64 = whatsappImage.split(',')[1] || whatsappImage;
|
||||||
try {
|
try {
|
||||||
if (node.waClient.clientType === "waWebClient"){
|
if (node.waClient.clientType === "waWebClient"){
|
||||||
numb = await webNubmerSeteing(node.number)
|
numb = await webNubmerSeteing(node.number)
|
||||||
var whatsappImageBase64 = whatsappImage.split(',')[1] || whatsappImage;
|
|
||||||
var myMessage = new MessageMedia('image/png', whatsappImageBase64, null, null);
|
var myMessage = new MessageMedia('image/png', whatsappImageBase64, null, null);
|
||||||
node.waClient.sendMessage(numb, myMessage, {caption : whatsappCaption || "Image from Node-Red"});
|
node.waClient.sendMessage(numb, myMessage, {caption : whatsappCaption || "Image from Node-Red"});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
numb = await socNubmerSeteing(node.number);
|
numb = await socNubmerSeteing(node.number)
|
||||||
|
const imageMessage = {
|
||||||
let imageToSend = Buffer.from(whatsappImageBase64, "base64");
|
text: whatsappCaption,
|
||||||
const imageMessage = {
|
footer: null,
|
||||||
// image: {url : whatsappImage},
|
templateButtons: null,
|
||||||
image: imageToSend,
|
image: {url : whatsappImage }
|
||||||
caption: whatsappCaption
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let client = await node.waClient;
|
let client = await node.waClient;
|
||||||
const msgStatus = await client.sendMessage(numb, imageMessage);
|
const msgStatus = await client.sendMessage(numb, imageMessage);
|
||||||
}
|
}
|
||||||
|
|||||||
2428
package-lock.json
generated
2428
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red-contrib-whatsapp-link",
|
"name": "node-red-contrib-whatsapp-link",
|
||||||
"version": "0.1.39C",
|
"version": "0.1.37",
|
||||||
"description": "Node to send and receive whatsapp messages in groups and chats. | No third party APIs",
|
"description": "Node to send and receive whatsapp messages in groups and chats. | No third party APIs",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -30,10 +30,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@whiskeysockets/baileys": "latest",
|
"@adiwajshing/baileys": "latest",
|
||||||
"pino": "latest",
|
"whatsapp-web.js": "latest",
|
||||||
"qrcode": "^1.5.1",
|
"qrcode": "^1.5.1",
|
||||||
"whatsapp-web.js": "^1.22.2-alpha.1"
|
"pino": "latest"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
|
|||||||
@ -29,10 +29,7 @@ module.exports = function(RED) {
|
|||||||
}),
|
}),
|
||||||
puppeteer : {
|
puppeteer : {
|
||||||
headless : true,
|
headless : true,
|
||||||
args : ['--no-sandbox',
|
args : ['--no-sandbox', '--disable-setuid-sandbox', '--user-data-dir=' + WAnode.id]
|
||||||
'--disable-setuid-sandbox',
|
|
||||||
'--user-data-dir=' + WAnode.id
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -46,7 +43,8 @@ module.exports = function(RED) {
|
|||||||
return webClient ;
|
return webClient ;
|
||||||
};
|
};
|
||||||
client = WAConnect();
|
client = WAConnect();
|
||||||
|
WAnode.connectionSetupID = setInterval(connectionSetup, 10000);
|
||||||
|
|
||||||
async function pressenceUpdate(OLS){
|
async function pressenceUpdate(OLS){
|
||||||
try {
|
try {
|
||||||
if (!OLS){
|
if (!OLS){
|
||||||
@ -88,19 +86,17 @@ module.exports = function(RED) {
|
|||||||
WAnode.log(`Error : Waiting for Initializion...`);
|
WAnode.log(`Error : Waiting for Initializion...`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
WAnode.connectionSetupID = setInterval(connectionSetup, 10000);
|
|
||||||
|
|
||||||
//QR-Code on Terminal and Ready Status.
|
//QR-Code on Terminal and Ready Status.
|
||||||
client.on(`qr`, (qr)=>{
|
client.on("qr", (qr)=>{
|
||||||
// clearInterval(WAnode.connectionSetupID);
|
clearInterval(WAnode.connectionSetupID);
|
||||||
QRCode.toString(qr, {type : 'terminal', small:true }, function(err, QRTerminal){
|
QRCode.toString(qr, {type : 'terminal', small:true }, function(err, QRTerminal){
|
||||||
WAnode.log(`To Connect, Scan the QR Code through your Whatsapp Mobile App.`)
|
WAnode.log(`To Connect, Scan the QR Code through your Whatsapp Mobile App.`)
|
||||||
console.log("");
|
console.log("");
|
||||||
console.log(QRTerminal);
|
console.log(QRTerminal);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
client.on("ready", ()=>{
|
||||||
client.on(`ready`, ()=>{
|
|
||||||
WAnode.log(`Status : Whatsapp Connected`);
|
WAnode.log(`Status : Whatsapp Connected`);
|
||||||
pressenceUpdate(onlineStatus);
|
pressenceUpdate(onlineStatus);
|
||||||
});
|
});
|
||||||
@ -113,7 +109,7 @@ module.exports = function(RED) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (clientType === "waSocketClient"){
|
if (clientType === "waSocketClient"){
|
||||||
const makeWASocket = require('@whiskeysockets/baileys');
|
const makeWASocket = require('@adiwajshing/baileys');
|
||||||
const { useMultiFileAuthState } = makeWASocket;
|
const { useMultiFileAuthState } = makeWASocket;
|
||||||
const pino = require('pino');
|
const pino = require('pino');
|
||||||
|
|
||||||
@ -153,14 +149,7 @@ module.exports = function(RED) {
|
|||||||
const { connection, lastDisconnect } = update
|
const { connection, lastDisconnect } = update
|
||||||
if (connection === 'close') {
|
if (connection === 'close') {
|
||||||
// reconnect if not logged out
|
// reconnect if not logged out
|
||||||
|
|
||||||
// console.log(lastDisconnect, lastDisconnect?.error?.data?.content)
|
|
||||||
// if (lastDisconnect.error.output.statusCode === 401 ||
|
|
||||||
// lastDisconnect.error.output.statusCode === 440){
|
|
||||||
// console.log(`logged Out by User. StatusCode : ${lastDisconnect?.error?.output.statusCode}`)
|
|
||||||
// FS.rmSync(whatsappLinkDirSocket, {recursive : true, force: true})
|
|
||||||
// }
|
|
||||||
// connectSocketClient();
|
|
||||||
if (
|
if (
|
||||||
lastDisconnect &&
|
lastDisconnect &&
|
||||||
lastDisconnect.error &&
|
lastDisconnect.error &&
|
||||||
@ -175,13 +164,12 @@ module.exports = function(RED) {
|
|||||||
lastDisconnect &&
|
lastDisconnect &&
|
||||||
lastDisconnect.error &&
|
lastDisconnect.error &&
|
||||||
lastDisconnect.error.output &&
|
lastDisconnect.error.output &&
|
||||||
lastDisconnect.error.output.statusCode === 401 &&
|
lastDisconnect.error.output.statusCode === 401
|
||||||
lastDisconnect.error.output.statusCode === 440
|
|
||||||
) {
|
) {
|
||||||
FS.rmSync(whatsappLinkDirSocket, {recursive : true, force: true})
|
FS.rmSync(whatsappLinkDirSocket, {recursive : true, force: true})
|
||||||
connectSocketClient()
|
connectSocketClient()
|
||||||
} else {
|
} else {
|
||||||
WAnode.log(`ErrorCode: ${lastDisconnect?.error?.output.statusCode} | ${lastDisconnect?.error}`)
|
WAnode.log("Error : " + lastDisconnect?.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user