- Published on
build a whatsapp bot to send news using node.js and whatsapp web api
- Authors
- Name
- Lahrasab Ramzan
- @lahrasab931
Have you ever wanted to create a WhatsApp bot that could send you news updates? In this tutorial, we will walk you through building a WhatsApp bot that fetches news from a website and sends it to a user when they send a specific message.
Prerequisites
1. A working knowledge of Node.js
2. An active WhatsApp account
3. An instance on Azure
4. A news website to scrape
5. WhatsApp Web API library
6. Axios library
7. Cheerio library
Step 1 : Scraping news data
We will use Axios and Cheerio libraries to scrape news data from a website. The website we will scrape is arynews.tv. We will use the following code to scrape the website and retrieve the title, thumbnail, source link, and description of each news article and then store this information in an array and that will be our API.
Import Required Modules
- Import required modules for the code to work. express to create an instance of the app,
axios
to make HTTP requests, and cheerio to scrape and manipulate HTML data.
// Import required modules
const express = require('express');
const axios = require('axios');
const cheerio = require('cheerio');
Create an Instance of Express App
- Create an instance of the Express app and set the port for the app to listen on.
// Create an instance of express app
const app = express();
const port = 8000;
Set URL to Scrape
- Set the URL to scrape data from.
// Set URL to scrape
const url = 'https://arynews.tv/category/pakistan/';
Create a GET Route
- Create a GET route that responds with JSON data of the scraped article information.
// Create a GET route
app.get('/', async (req, res) => {
try {
Make a Request to the URL and Load HTML Data into Cheerio Object
- Use
axios
to make a GET request to the URL and get the HTML data. - Load the HTML data into a Cheerio object using
cheerio
.
// Make a request to the URL and get the HTML data using axios
const response = await axios.get(url);
// Load the HTML data into a cheerio object to manipulate it using jQuery syntax
const $ = cheerio.load(response.data);
Create an Array to Hold the Scraped Article Data
- Create an empty array to hold the scraped article data.
// Create an array to hold the scraped article data
const articles = [];
Iterate Over Each Article Container on the Page
- Use
$('.td-module-container').each()
to iterate over each article container on the page. - Use jQuery syntax to scrape the article title, thumbnail, and source URL from each article container
- Create an article object with the scraped data and add it to the
articles
array.
// Iterate over each article container on the page
$('.td-module-container').each((index, element) => {
// Scrape the article title, thumbnail, and source URL from each article container
const title = $(element).find('.td-module-meta-info h3').text().trim();
const thumbnail = $(element).find('.entry-thumb').attr('data-img-url');
const source = $(element).find('.td-module-meta-info h3 a').attr('href');
// Create an article object and add it to the array
const article = { title, thumbnail, source, description: '' };
articles.push(article);
});
Visit Each Article Source to Get the Description
- Iterate over each
// Visit each article source to get the description
for (const article of articles) {
const sourceResponse = await axios.get(article.source);
const $source = cheerio.load(sourceResponse.data);
const description = $source('.tdb-block-inner p strong').text().trim();
article.description = description;
}
JSON response and error handling
- Data will be displayed in JSON form and error handling if anything goes wrong with the server. As we know code 500 indicates there's something wrong with server so we can identify the problem easily.
// Send articles as a JSON response
res.json(articles);
} catch (error) {
console.error(error);
res.status(500).send('Something went wrong');
}
});
API Starts Listening!!! YAAAYYYYYYY
- Congrats you have made your own API. You can even sell it on platforms like RAPID API
// Start the express app and listen for requests on the specified port
app.listen(port, () => {
console.log(`App listening at http://localhost:${port}`);
});
Step 2 : Building WhatsApp Bot
What the Bot will do
WhatsApp Web API and Node.js to build a WhatsApp chatbot that can send news articles to the user. When a user sends the keyword "news" to the bot, it makes an HTTP request to a server that returns a list of news articles. The bot then sends the first three articles to the user, with an option to request more. The code listens for other keywords like "more" and "help" to provide additional functionality.
Now we will code it. So lets get started:
Importing Libraries that will make API calls
- In this block, we are importing the
axios
library to make API calls andwhatsapp-web.js
library to create a client object. Then we create a new client object with theLocalAuth
authentication strategy.
const axios = require('axios');
const { Client, LocalAuth} = require('whatsapp-web.js');
const client = new Client({
authStrategy: new LocalAuth()
});
Setting up event listeners and QR code
- In this block, we are setting up event listeners for when the QR code needs to be scanned and when the client is ready. We also initialize the client object.
client.on('qr', (qr) => {
qrcode.generate(qr, {small: true});
});
client.on('ready', () => {
console.log('Client is ready!');
});
client.initialize();
Help Message
- In this block, we are defining a string variable that contains help message that will be sent as a reply when the user types "help" in WhatsApp.
const helpMessage = `Type 'news' to get the latest articles. Type 'more' to get more articles.`;
This code listens for incoming messages
- The code listens for incoming messages using the
client.on('message', async (message) => { ... })
function.
// This code runs when the bot receives a message
client.on('message', async (message) => {
...
write code here
...
})
Converts the commands case-insensitive
- This code will convert the message to lowercase to make it case-insensitive.
const lowerCase = message.body.toLowerCase();
NEWS
command
- If the message is
news
, the code makes an HTTP request to a server that returns a list of news articles.
// If the message says 'news', get the latest news and send the top 3 articles
if (lowerCase === 'news') {
try {
// Get the latest news from the server
const response = await axios.get('http://localhost:8000/');
const articles = response.data;
// Limit the number of articles to a maximum of 3
const articleCount = Math.min(3, articles.length);
let index = 0;
// Send each article to the user
for (let i = 0; i < articleCount; i++) {
const article = articles[index];
await message.reply(`*${article.title}*\n\n${article.description}\n\nSource: ${article.source}`);
index++;
}
MORE
command
- If the message is "more", the code retrieves the next three articles from the list and sends them to the user, with another prompt to request more if there are more articles available.
// If there are more articles, prompt the user to type 'more' to see them
if (articleCount < articles.length) {
await message.reply(`Type 'more' to get more articles.`);
}
} catch (error) {
// If there is an error getting the news, notify the user
console.error(error);
await message.reply('Sorry, an error occurred while fetching the latest news.');
}
}
// If the message says 'more', get the next 3 articles (if available)
else if (lowerCase === 'more') {
try {
// Get the latest news from the server
const response = await axios.get('http://localhost:8000/');
const articles = response.data;
// Get the next 3 articles (starting from index 3)
const articleCount = Math.min(3, articles.length - 3);
let index = 3;
// Send each article to the user
if (articleCount === 0) {
await message.reply(`There are no more articles available.`);
} else {
for (let i = 0; i < articleCount; i++) {
const article = articles[index];
await message.reply(`*${article.title}*\n\n${article.description}\n\nSource: ${article.source}`);
index++;
}
// If there are more articles, prompt the user to type 'more' to see them
if (articleCount < articles.length - 3) {
await message.reply(`Type 'more' to get more articles.`);
}
}
} catch (error) {
// If there is an error getting the news, notify the user
console.error(error);
await message.reply('Sorry, an error occurred while fetching the latest news.');
}
}
help
command
- If the message is "help", the bot sends a help message to the user.
- If the message is anything else, the bot sends a default message asking how it can help.
/ If the message says 'help', send the help message
else if (lowerCase === 'help') {
await message.reply(helpMessage);
}
// If the message doesn't match any of the above commands, send a generic message with the available commands
else {
await message.reply('Hi! How may I help you? Type *help* to see the available commands.');
}
});
This code is for a WhatsApp bot that sends news articles to users who message it. Here's what the code does:
When the bot receives a message, the client.on('message', ...)
function is called. This function takes a callback function with the message object as
Complete Code
FOR API
const express = require('express');
const axios = require('axios');
const cheerio = require('cheerio');
const app = express();
const port = 8000;
const url = 'https://arynews.tv/category/pakistan/';
app.get('/', async (req, res) => {
try {
const response = await axios.get(url);
const $ = cheerio.load(response.data);
const articles = [];
$('.td-module-container').each((index, element) => {
const title = $(element).find('.td-module-meta-info h3').text().trim();
const thumbnail = $(element).find('.entry-thumb').attr('data-img-url');
const source = $(element).find('.td-module-meta-info h3 a').attr('href');
const article = { title, thumbnail, source, description: '' };
articles.push(article);
});
// Visit each article source to get the description
for (const article of articles) {
const sourceResponse = await axios.get(article.source);
const $source = cheerio.load(sourceResponse.data);
const description = $source('.tdb-block-inner p strong').text().trim();
article.description = description;
}
// Send articles as a JSON response
res.json(articles);
} catch (error) {
console.error(error);
res.status(500).send('Something went wrong');
}
});
app.listen(port, () => {
console.log(`App listening at http://localhost:${port}`);
});
FOR WhatsApp BOT
const { Client, LocalAuth } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal');
const axios = require('axios');
const cheerio = require('cheerio');
const client = new Client({
authStrategy: new LocalAuth()
});
const newsApiUrl = 'http://url-of-the-api:8000/';
client.on('qr', (qr) => {
qrcode.generate(qr, { small: true });
});
client.on('ready', () => {
console.log('Client is ready!');
});
const helpMessage = `Type 'news' to get the latest articles. Type 'more' to get more articles.`;
client.on('message', async (msg) => {
const lowerCase = msg.body.toLowerCase();
if (msg.body === 'news') {
try {
const response = await axios.get(newsApiUrl);
const articles = response.data.slice(0, 3);
let articleIndex = 0;
for (const article of articles) {
const { title, source, description } = article;
const message = `*${title}*\n\n_${source}_\n\n${description}`;
await msg.reply(message);
articleIndex++;
}
if (articles.length === 0) {
await msg.reply('No news articles found');
} else if (articles.length < 3) {
await msg.reply('No more news articles available');
} else {
await msg.reply('Send "more" to get the next three news articles');
}
} catch (error) {
console.error(error);
await msg.reply('Failed to fetch news articles');
}
} else if (msg.body === 'help') {
const message = 'Available commands:\n\n- news: Get the latest news articles\n- help: Display this help message';
await msg.reply(message);
} else if (msg.body === 'more') {
try {
const response = await axios.get(newsApiUrl);
const articles = response.data.slice(3, 6);
let articleIndex = 0;
for (const article of articles) {
const { title, source, description } = article;
const message = `*${title}*\n\n_${source}_\n\n${description}`;
await msg.reply(message);
articleIndex++;
}
if (articles.length === 0) {
await msg.reply('No more news articles available');
} else {
await msg.reply('Send "more" to get the next three news articles');
}
} catch (error) {
console.error(error);
await msg.reply('Failed to fetch news articles');
}
}
});
client.initialize();
Conclusion
In conclusion, we have successfully built a WhatsApp bot to send news using Node.js and the WhatsApp Web API. This bot allows users to get the latest news by simply sending a message to the bot on WhatsApp. We used Axios to make HTTP requests to a remote API that returns news articles in JSON format. We then parsed the response and sent the articles to the user via WhatsApp. The bot also allows users to get more articles by sending the "more" command. With this bot, users can get the latest news without having to leave WhatsApp, making it a convenient and user-friendly solution.
In the wise words of Bugs Bunny, "Don't panic, just automate!" So go forth and automate with your new WhatsApp news bot!