Compare commits

..

10 Commits

Author SHA1 Message Date
raweee
c8f6454512 Minor updates 2023-10-05 02:03:23 +05:30
raweee
176b51ec9a base64 Image support added 2023-10-01 02:57:17 +05:30
raweee
dcf46cde9c minor update 2023-09-30 20:22:32 +05:30
raweee
d5d7d0e9fb Whatsapp Web & Lite fixed 2023-09-30 19:16:41 +05:30
raweee
0a272da620 Whatsapp-Web Working 2023-09-30 17:43:27 +05:30
raweee
d39e56525d Whatsapp-Lite Fixed 2023-09-30 15:15:04 +05:30
raweee
483e4461e1 Whiskey 2023-09-30 14:55:27 +05:30
raweee
b0b83f6587 update 2023-09-30 14:46:15 +05:30
raweee
8c904fe703 updating packages 2023-09-30 02:45:42 +05:30
Ravi Mishra
936deb39bc
Whatsapp Lite 2023-09-30 01:27:40 +05:30
10 changed files with 789 additions and 1958 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
node_modules node_modules
removed.rm

View File

@ -1 +1,2 @@
node_modules node_modules
removed.rm

View File

@ -1,6 +1,7 @@
# 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:
@ -65,12 +66,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.
`A-reply-to-All.json` example is avilable in examples to import. `ImageMessage.json` example is avilable in examples to import.
MultiMedia Message: Requirments- MultiMedia Message: Requirments-
| Input | Description | | Input | Description |
|--------|-------------| |--------|-------------|
| `msg.image` | Base64 (encoded image) | | `msg.image` | Base64 (encoded image), [`image-tool`](https://flows.nodered.org/node/node-red-contrib-image-tools) node work fine for incoding base64|
| `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) |
@ -85,65 +86,7 @@ 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.
## Button, List and TemplateButton `A-reply-to-All.json` example is avilable in examples to import.
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)
@ -163,6 +106,7 @@ 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 -

View File

@ -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,16 +126,21 @@ 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){
var qrImageWithID = {}; printQrCode(url);
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){
@ -144,20 +149,16 @@ 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);
var {connection} = updates
//Setting conncetion status indication //Setting conncetion status indication
var {connection} = updates
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'){

View File

@ -5,7 +5,8 @@ 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});
@ -83,12 +84,14 @@ module.exports = function(RED) {
} }
else { else {
numb = await socNubmerSeteing(numb) numb = await socNubmerSeteing(numb)
const imageMessage = {
text: whatsappCaption, let imageToSend = Buffer.from(whatsappImageBase64, "base64");
footer: null, const imageMessage = {
templateButtons: null, // image: {url : whatsappImage},
image: {url : whatsappImage } image: imageToSend,
}; 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);
} }

139
examples/ImageMessage.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -76,21 +76,23 @@ 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 = {
text: whatsappCaption, let imageToSend = Buffer.from(whatsappImageBase64, "base64");
footer: null, const imageMessage = {
templateButtons: null, // image: {url : whatsappImage},
image: {url : whatsappImage } image: imageToSend,
}; 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);
} }

2430
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "node-red-contrib-whatsapp-link", "name": "node-red-contrib-whatsapp-link",
"version": "0.1.37", "version": "0.1.39C",
"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": {
"@adiwajshing/baileys": "latest", "@whiskeysockets/baileys": "latest",
"whatsapp-web.js": "latest", "pino": "latest",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",
"pino": "latest" "whatsapp-web.js": "^1.22.2-alpha.1"
}, },
"engines": { "engines": {
"node": ">=8.0.0" "node": ">=8.0.0"

View File

@ -29,7 +29,10 @@ module.exports = function(RED) {
}), }),
puppeteer : { puppeteer : {
headless : true, headless : true,
args : ['--no-sandbox', '--disable-setuid-sandbox', '--user-data-dir=' + WAnode.id] args : ['--no-sandbox',
'--disable-setuid-sandbox',
'--user-data-dir=' + WAnode.id
]
} }
}); });
@ -43,8 +46,7 @@ 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){
@ -86,17 +88,19 @@ 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);
}); });
@ -109,7 +113,7 @@ module.exports = function(RED) {
}; };
if (clientType === "waSocketClient"){ if (clientType === "waSocketClient"){
const makeWASocket = require('@adiwajshing/baileys'); const makeWASocket = require('@whiskeysockets/baileys');
const { useMultiFileAuthState } = makeWASocket; const { useMultiFileAuthState } = makeWASocket;
const pino = require('pino'); const pino = require('pino');
@ -149,7 +153,14 @@ 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 &&
@ -164,12 +175,13 @@ 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("Error : " + lastDisconnect?.error) WAnode.log(`ErrorCode: ${lastDisconnect?.error?.output.statusCode} | ${lastDisconnect?.error}`)
} }
} }
} }