WhatsApp Bot | Get Covid Data Daily on WhatsApp using Azure Functions and Twilio

This is the WhatsApp Bot that gets the COVID data daily to your WhatsApp number. I have scheduled the job to get executed daily at the scheduled time.

Pre-requisites

  1. Visual Studio
  2. Cloud Templates
  3. Twilio Account
  4. LUIS

Visual Studio links are available on the Download page.

Creating Azure Function in Visual Studio

Launch Visual Studio and Create a new project. Select Cloud as Project Type and choose Azure Function.

Give the name of the project “WhatsAppBot” and save it to the desired location. Select checkbox place solution and project in the same directory.

Select Azure Functions v3 (.NET Core) and Time Trigger. Keep the CRON expression default. You can change it to your convenience in the code.

Install the NuGet Package – Twilio. Replace the code with the below code.

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

namespace WhatsAppBot
{
    public static class Function1
    {
        
        private static readonly HttpClient httpClient = new HttpClient();

        [FunctionName("CovidDataSchedulerUpdates")]
        public static async Task RunAsync([TimerTrigger("47 14 * * *")] TimerInfo myTimer, ILogger log)
        {
            var accountSid = "<Twilio Acount SID>";
            var authToken = "<Twilio Authentication Token>";
            TwilioClient.Init(accountSid, authToken);

            var messageOptions = new CreateMessageOptions(
                new PhoneNumber("whatsapp:+<Your WhatsApp number>"));
            messageOptions.From = new PhoneNumber("whatsapp:+<Twilio Number>");

            List<string> messages = new List<string> { "Daily confirmed cases", "daily deceased", "daily recovered", "total confirmed cases", "total deceased", "total recovered" };
            for (int i = 0; i < messages.Count; i++)
            {
                messageOptions.Body = await evaluateMessage(messages[i]);
                var message = MessageResource.Create(messageOptions);
            }

        }

        private static async Task<string> evaluateMessage(string text)
        {
            HttpClient httpClient = new HttpClient();
            httpClient.BaseAddress = new Uri("https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/<LUIS App ID>?q=" + text);
            httpClient.DefaultRequestHeaders.Accept.Clear();
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //ACCEPT header
            httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "<LUIS Secret Key>");


            HttpRequestMessage luisRequest = new HttpRequestMessage(HttpMethod.Get, httpClient.BaseAddress);

            var luisResponse = await MakeRequestAsync(luisRequest, httpClient);

            var luisModel = JsonConvert.DeserializeObject<LuisModel>(luisResponse);

            
                var apiResponse = GetCovidData().GetAwaiter().GetResult();
                Root root = JsonConvert.DeserializeObject<Root>(apiResponse);

                if (luisModel.topScoringIntent.intent == "DailyConfirmedTSD")
                {
                    return $"Daily Confirmed cases on  {root.cases_time_series[root.cases_time_series.Count - 1].date} is {root.cases_time_series[root.cases_time_series.Count - 1].dailyconfirmed}.";
                }
                else if (luisModel.topScoringIntent.intent == "DailyDeceasedTSD")
                {
                    return $"Daily Deaceased on  {root.cases_time_series[root.cases_time_series.Count - 1].date} is {root.cases_time_series[root.cases_time_series.Count - 1].dailydeceased}.";
                }
                else if (luisModel.topScoringIntent.intent == "DailyRecoveredTSD")
                {
                    return $"Daily Recovered on  {root.cases_time_series[root.cases_time_series.Count - 1].date} is {root.cases_time_series[root.cases_time_series.Count - 1].dailyrecovered}.";
                }
                else if (luisModel.topScoringIntent.intent == "TotalConfirmedTSD")
                {
                    return $"Total Confirmed cases as of  {root.cases_time_series[root.cases_time_series.Count - 1].date} is {root.cases_time_series[root.cases_time_series.Count - 1].totalconfirmed}.";
                }
                else if (luisModel.topScoringIntent.intent == "TotalDeceasedTSD")
                {
                    return $"Total Deceased as of  {root.cases_time_series[root.cases_time_series.Count - 1].date} is {root.cases_time_series[root.cases_time_series.Count - 1].totaldeceased}.";
                }
                else if (luisModel.topScoringIntent.intent == "TotalRecoveredTSD")
                {
                    return $"Total Recovered as of  {root.cases_time_series[root.cases_time_series.Count - 1].date} is {root.cases_time_series[root.cases_time_series.Count - 1].totalrecovered}.";
                }
                else
                {
                    return "I am sorry, I am having difficulty in getting the latest data. Kindly try again.";
                }
            
            
        }

        public static async Task<string> GetCovidData()
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("https://api.covid19india.org/data.json");
            client.DefaultRequestHeaders.Accept.Clear();

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, client.BaseAddress);

            var response = await MakeRequestAsync(request, client);
            return response;
        }

        private static async Task<string> MakeRequestAsync(HttpRequestMessage getRequest, HttpClient client)
        {
            var response = await client.SendAsync(getRequest).ConfigureAwait(false);
            var responseString = string.Empty;
            try
            {
                response.EnsureSuccessStatusCode();
                responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            }
            catch (HttpRequestException)
            {

            }

            return responseString;
        }
    }

    public class Root
    {
        public List<Cases_Time_Series> cases_time_series { get; set; }
        public List<Statewise> statewise { get; set; }
        public List<Tested> tested { get; set; }
    }

    public class Cases_Time_Series
    {
        public string dailyconfirmed { get; set; }
        public string dailydeceased { get; set; }
        public string dailyrecovered { get; set; }
        public string date { get; set; }
        public string totalconfirmed { get; set; }
        public string totaldeceased { get; set; }
        public string totalrecovered { get; set; }
    }

    public class Statewise
    {
        public string active { get; set; }
        public string confirmed { get; set; }
        public string deaths { get; set; }
        public string deltaconfirmed { get; set; }
        public string deltadeaths { get; set; }
        public string deltarecovered { get; set; }
        public string lastupdatedtime { get; set; }
        public string migratedother { get; set; }
        public string recovered { get; set; }
        public string state { get; set; }
        public string statecode { get; set; }
        public string statenotes { get; set; }
    }

    public class Tested
    {
        public string individualstestedperconfirmedcase { get; set; }
        public string positivecasesfromsamplesreported { get; set; }
        public string samplereportedtoday { get; set; }
        public string source { get; set; }
        public string source1 { get; set; }
        public string testedasof { get; set; }
        public string testpositivityrate { get; set; }
        public string testsconductedbyprivatelabs { get; set; }
        public string testsperconfirmedcase { get; set; }
        public string testspermillion { get; set; }
        public string totalindividualstested { get; set; }
        public string totalpositivecases { get; set; }
        public string totalsamplestested { get; set; }
        public string updatetimestamp { get; set; }
    }

    public class LuisModel
    {
        public string query { get; set; }
        public TopScoringIntent topScoringIntent { get; set; }
        public List<Intent> intents { get; set; }
    }

    public class TopScoringIntent
    {
        public string intent { get; set; }
        public double score { get; set; }
    }

    public class Intent
    {
        public string intent { get; set; }
        public double score { get; set; }
    }
}

Replace the configuration details in the code – Twilio Account SID, Twilio Authentication Token, Your WhatsApp number, Twilio Number, LUIS App ID, and LUIS Secret Key.

To get the Twilio configuration details, go to my post on Create WhatsApp Bot -> Configure Twilio Channel. SID and Authentication are available on the Console Dashboard page.

To get the LUIS configuration details. Import the LUIS app from the below JSON.

{
  "luis_schema_version": "7.0.0",
  "intents": [
    {
      "name": "DailyConfirmedTSD",
      "features": []
    },
    {
      "name": "DailyDeceasedTSD",
      "features": []
    },
    {
      "name": "DailyRecoveredTSD",
      "features": []
    },
    {
      "name": "None",
      "features": []
    },
    {
      "name": "TotalConfirmedTSD",
      "features": []
    },
    {
      "name": "TotalDeceasedTSD",
      "features": []
    },
    {
      "name": "TotalRecoveredTSD",
      "features": []
    }
  ],
  "entities": [],
  "hierarchicals": [],
  "composites": [],
  "closedLists": [],
  "prebuiltEntities": [],
  "utterances": [
    {
      "text": "count of daily confirmed cases",
      "intent": "DailyConfirmedTSD",
      "entities": []
    },
    {
      "text": "count of people daily recovering",
      "intent": "DailyRecoveredTSD",
      "entities": []
    },
    {
      "text": "daily confirmed cases",
      "intent": "DailyConfirmedTSD",
      "entities": []
    },
    {
      "text": "daily confirmed count",
      "intent": "DailyConfirmedTSD",
      "entities": []
    },
    {
      "text": "daily deaths",
      "intent": "DailyDeceasedTSD",
      "entities": []
    },
    {
      "text": "daily deaths count",
      "intent": "DailyDeceasedTSD",
      "entities": []
    },
    {
      "text": "daily deceased",
      "intent": "DailyDeceasedTSD",
      "entities": []
    },
    {
      "text": "daily recovered",
      "intent": "DailyRecoveredTSD",
      "entities": []
    },
    {
      "text": "get me the count of total confirmed cases",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "get me the daily confirmed count",
      "intent": "DailyConfirmedTSD",
      "entities": []
    },
    {
      "text": "how many people deceased",
      "intent": "TotalDeceasedTSD",
      "entities": []
    },
    {
      "text": "how many people died as of today",
      "intent": "TotalDeceasedTSD",
      "entities": []
    },
    {
      "text": "how many people dying daily",
      "intent": "DailyDeceasedTSD",
      "entities": []
    },
    {
      "text": "how many people got affected",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "how many people got recovered",
      "intent": "TotalRecoveredTSD",
      "entities": []
    },
    {
      "text": "how many people got recovered in total",
      "intent": "TotalRecoveredTSD",
      "entities": []
    },
    {
      "text": "how many people recovered daily",
      "intent": "DailyRecoveredTSD",
      "entities": []
    },
    {
      "text": "how many positive cases as of today",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "people daily recovering",
      "intent": "DailyRecoveredTSD",
      "entities": []
    },
    {
      "text": "people recovered today",
      "intent": "DailyRecoveredTSD",
      "entities": []
    },
    {
      "text": "total cases",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "total confirmed cases",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "total covid cases",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "total covid cases count",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "total deaths",
      "intent": "TotalDeceasedTSD",
      "entities": []
    },
    {
      "text": "total deaths due to coronavirus",
      "intent": "TotalDeceasedTSD",
      "entities": []
    },
    {
      "text": "total deceased count",
      "intent": "TotalDeceasedTSD",
      "entities": []
    },
    {
      "text": "total people died",
      "intent": "TotalDeceasedTSD",
      "entities": []
    },
    {
      "text": "total positive cases",
      "intent": "TotalConfirmedTSD",
      "entities": []
    },
    {
      "text": "total recovered",
      "intent": "TotalRecoveredTSD",
      "entities": []
    },
    {
      "text": "total recovered as of today",
      "intent": "TotalRecoveredTSD",
      "entities": []
    },
    {
      "text": "what is the daily confirmed count",
      "intent": "DailyConfirmedTSD",
      "entities": []
    }
  ],
  "versionId": "0.1",
  "name": "CovidBot",
  "desc": "",
  "culture": "en-us",
  "tokenizerVersion": "1.0.0",
  "patternAnyEntities": [],
  "regex_entities": [],
  "phraselists": [],
  "regex_features": [],
  "patterns": [],
  "settings": []
}

To learn how to import and get the LUIS App ID and Secret Key, go to my post on Create Azure Resource Manager Bot -> Creating a LUIS App.

Now run the project in Visual Studio using Cntrl+F5. Before running change the CRON expression based on your schedule. My scheduled time is Daily at 14:47 PM.

Below is the output you will get on WhatsApp. Also, you can check the next occurrence of execution in Console output.

Thank you All!!! Hope you find this useful. You can publish the function in Azure. Refer the article here.

If you liked our content and it was helpful, you can buy us a coffee or a pizza. Thank you so much.


One thought on “WhatsApp Bot | Get Covid Data Daily on WhatsApp using Azure Functions and Twilio

Add yours

Up ↑

%d bloggers like this: