This repository has been archived by the owner on Sep 10, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
bot.js
138 lines (122 loc) · 4.95 KB
/
bot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Init requires and imports
require('dotenv').config()
const express = require("express");
const mongoose = require("mongoose");
const cron = require("node-cron");
const axios = require("axios").default;
const {sendMessage, sendMessages, sendMessagesToDiffClients, checkPincodeValidity} = require("./utils");
const app = express();
app.use(express.urlencoded({extended: false}));
// Common data for query URL
const today = new Date();
const day = today.getDate();
const month = ((today.getMonth() < 10) ? "0" : "") + (today.getMonth() + 1);
const year = today.getFullYear();
const DATE = `${day}-${month}-${year}`;
const CONFIG = {
headers: {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
}
// Create MongoDB schema and connect with MongoDB Atlas
const taskSchema = new mongoose.Schema({pinCode: Number, clientNumber: Number});
const Task = mongoose.model('Task', taskSchema);
mongoose.connect(process.env.DB_URI, {useNewUrlParser: true, useUnifiedTopology: true}).catch(err => console.log(err));
// Root route
app.get("/", (req, res) => {
res.send("Roses are red, Violets are blue, There's nothing to see here, What will you do?");
});
// Starts the bot
app.listen(process.env.PORT || 8000, () => {
console.log("Server started.");
});
// Handles incoming messages
app.post("/incoming", async (req) => {
// Parse user query
// Key Body & From stores client's message & WhatsApp number respectively
const query = req.body.Body.split(' ');
let action = query[0];
let pinCode = query[1];
let clientNumber = req.body.From.split(':')[1];
let isValidPincode = checkPincodeValidity(pinCode);
// Create new tracking task
if (action === "track" && isValidPincode === true) {
// Create new task
const taskInfo = new Task({pinCode: pinCode, clientNumber: clientNumber});
// Save the task
const afterSave = await taskInfo.save();
if (afterSave === taskInfo)
sendMessage(`Tracking empty vaccination slots for *${pinCode}*`, clientNumber);
}
// Handle checking
else if (action === "check" && isValidPincode === true) {
const URL = `https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByPin?pincode=${pinCode}&date=${DATE}`
// Send GET request to CoWIN API and process it
let response = await axios.get(URL, CONFIG);
try {
// Cherrypick data, create the message and store them
let data = response.data.centers;
let messages = data.map((center) => {
let sessionsInfo = ``;
center.sessions.forEach((session, index) => {
let msg = `\n${index + 1}. ${session.date}:\nDose 1 = ${session.available_capacity_dose1}\nDose 2 = ${session.available_capacity_dose2}\nMin Age = ${session.min_age_limit}\n`;
sessionsInfo = sessionsInfo + msg;
});
return `\`\`\`Name: ${center.name}\nFee Type: ${center.fee_type}\nSessions: \n${sessionsInfo}\`\`\``;
})
// Send the stored messages
sendMessages(messages, clientNumber);
} catch (err) {
console.log(err);
}
}
// Remove a tracking task for a given clientNumber & pinCode
else if (action === "stop" && isValidPincode === true) {
await Task.deleteOne({pinCode: pinCode, clientNumber: clientNumber});
sendMessage(`Tracking for ${pinCode} stopped`, clientNumber)
}
// Handle invalid input
else
sendMessage(`I can't understand your query 🙁. Please check that you typed it correctly`, clientNumber);
});
// Cron task to check availability for saved tasks
// */30 * * * * -> Every 30th minute
cron.schedule('*/30 * * * *', () => {
console.log("Searching...");
Task.find({}, (err, tasks) => {
if (!err) {
tasks.forEach(async (task) => {
let messagesForDiffClients = [];
let URL = `https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByPin?pincode=${task.pinCode}&date=${DATE}`
let response = await axios.get(URL, CONFIG)
try {
// If any center in the region can administer a dose, inform client
let data = response.data.centers;
data.every(center => {
let regionCanServe = false;
center.sessions.every(session => {
if (session.available_capacity_dose1 !== 0 || session.available_capacity_dose2 !== 0) {
regionCanServe = true;
return false;
}
return true;
})
if (regionCanServe === true) {
var msg = `A session may be available at ${task.pinCode}. Please visit https://www.cowin.gov.in/home for more details`;
messagesForDiffClients.push({
message: msg,
clientNumber: task.clientNumber
});
return false;
}
return true;
})
sendMessagesToDiffClients(messagesForDiffClients);
} catch (err) {
console.log(err);
}
})
}
console.log("Search ended!")
})
})