Celebrate Anniversaries With Your Loved One Using Twilio Voice Calls

December 08, 2022
Written by
Dotun Jolaoso
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

This post was written by a third-party contributor as a part of our Twilio Voices program. It is no longer actively maintained. 

As humans, we generally tend to celebrate anniversaries in the life of a loved one. Examples of such anniversaries can include weddings, birthdays, or job anniversaries. And the frequency at which they occur varies, from yearly, to quarterly and even monthly for some of them.

In this tutorial, we’ll be building a NodeJS app that allows you to celebrate special anniversaries in the life of a loved one using Twilio Programmable Voice.

Prerequisites

To follow along, you’ll need the following:

Getting Started

First, create a directory where the project will reside. From the terminal, run the following command:

mkdir twilio_celebrate_anniversary

Next, change into the project directory and run the following command to create a new  package.json file in the root of your project directory.

npm init -y

Next, install all the dependencies the project will need. These are:

  • dotenv: A library for importing environment variables from a .env file.
  • twilio-node: A Twilio helper library for interacting with Twilio’s REST API.
  • moment: A Javascript date library for working with dates.
  • node-cron: A library that allows you to schedule task in Node.js

Run the following command to install all of the dependencies at once:

npm install dotenv moment node-cron twilio

Set up Twilio

You will need to obtain the Account SID, Auth Token and phone number associated with your Twilio account. These details can be obtained from the Keys & Credentials section on your Twilio Dashboard.

Twilio Credentials

Head back to the project’s directory and then create a file named .env. Then, add the following details to the file:

TWILIO_ACCOUNT_SID=xxxx
TWILIO_AUTH_TOKEN=xxxx
TWILIO_NUMBER=xxxx
PARTNER_NUMBER=xxxx

Don’t forget to replace "xxxx" with their corresponding values. The PARTNER_NUMBER field is the phone number of your partner or loved one you’ll be placing a phone call to.

Create an anniversary list

For the purpose of this tutorial, you’ll use a simple JSON file to keep track of all the important anniversaries you need to celebrate with your loved one. In your project directory, create a new file named anniversary.json, and paste the following into the file:

{
    "anniversary": "birthday"
}

Each anniversary entry contains the following details:

  • anniversary: The title of the particular anniversary you’re celebrating
  • day: The date for which this anniversary occurs
  • frequency: The celebration frequency for the anniversary, which can be monthly or yearly. Later down the line, the value of this field will be used to update the anniversary's date
  • message: The anniversary message you would like to be said to your partner during the voice call

You can modify the contents of the anniversary.json file to suit your own needs.

Creating Outbound Voice Calls

In the root of your project’s directory, create a new file named app.js and paste the following code into the file:

require("dotenv").config();
const fs = require("fs/promises");
const moment = require("moment");
const cron = require("node-cron");
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const twilioNumber = process.env.TWILIO_NUMBER;
const client = require("twilio")(accountSid, authToken);
const toNumber = process.env.PARTNER_NUMBER;

async function fetchAnniversaries() {
  return JSON.parse(await fs.readFile("./anniversary.json"));
}

async function writeAnniversaries(data) {
  return await fs.writeFile("./anniversary.json", JSON.stringify(data));
}

async function celebrateAnniversary() {
  const anniversaries = await fetchAnniversaries().catch(err => console.log(err));

    for (const [key, anniversary] of anniversaries.entries()) {
      const today = moment().utc().format("YYYY-MM-DD");
      const anniversaryDay = moment(anniversary.day).format("YYYY-MM-DD");

      if (anniversaryDay === today) {
        await placeCall(anniversary);

        //After making the call, update the anniversary date
        anniversary.day = updateAnniversaryDay(anniversary);
        anniversaries[key] = anniversary;
      }
    }

    writeAnniversaries(anniversaries).catch((err) => console.log(err));
}

async function placeCall(anniversary) {
  client.calls
    .create({
      twiml: `<Response><Say>${anniversary.message}</Say></Response>`,
      to: toNumber,
      from: twilioNumber,
    })
    .then((call) => console.log("Call SID:",call.sid))
    .catch((err) => console.log(err));
}

function updateAnniversaryDay(anniversary) {
  const days = moment().utc();

  if (anniversary.frequency === "monthly") {
    return days.add(moment.duration({ days: 30 })).format("YYYY-MM-DD");
  }

  if (anniversary.frequency === "yearly") {
    return days.add(moment.duration({ days: 365 })).format("YYYY-MM-DD");
  }
}

At the top of this file, all the dependencies the project will need are imported.

The require("dotenv").config() function loads the environment variables from the .env file you created earlier.

The celebrateAnniversary() function fetches all the anniversaries available in the anniversary.json file. Next, it loops through each of them. If there’s a match with an anniversary date and the current date, the placeCall() function is invoked, and then subsequently, the anniversary day is updated based on the anniversary’s frequency.

The fetchAnniversaries() and writeAnniversaries() functions are used to read from and write to the anniversary.json file respectively.

The placeCall() function is responsible for making the voice call to your loved one. A predefined message will speak to the receiver using the Twilio Markup Language (TwiML). At its core TwiML is an XML document with special tags defined by Twilio. The message to speak to them is obtained from the message attribute on the anniversary object.

Automate the application with Cron

Next, you're going to automate app.js to run everyday. Just below the updateAnniversaryDay() function, add the following function:

cron.schedule("0 8 * * *", async () => {
  console.log("Celebrating an anniversary");

  try {
    await celebrateAnniversary()
  } catch (error) {
    console.log(error);
  }
});

Using the node-cron library which you installed earlier, you’ve defined a Cron schedule that calls the celebrateAnniversary() function everyday at 8am.

Testing

To test that the app works as expected, you’ll need to make a few changes.

  • Update any of the anniversaries in the anniversary.json file to reflect the current date
  • Update the PARTNER_NUMBER environment variable to be your own, personal, phone number so you can receive the phone call
  • Update the Cron schedule in app.js to run every two minutes, by updating the call to cron.schedule to match the code below:
cron.schedule("*/2 * * * *", async () => {
  console.log("running a task");

  try {
    await celebrateAnniversary()
  } catch (error) {
    console.log(error);
  }
});

Finally, run the following command to start the application:

node app.js

Within two minutes, an outbound phone call should be placed to your number with the anniversary message being read to you.

Conclusion

In this tutorial, using Twilio Voice, we’ve seen how you can build an application that celebrates special anniversaries in the life of a loved one. This tutorial can serve as a starting point for you, if you’re looking to build something special for a loved one using any of Twilio’s product offerings such as Messaging, Video, etc.

Dotun is a backend software engineer who enjoys building awesome tools and products. He also enjoys technical writing in his spare time. Some of his favorite programming languages and frameworks include Go, PHP, Laravel, NestJS and Node.

Website: https://dotunj.dev/
Github: https://github.com/Dotunj
Twitter: https://twitter.com/Dotunj_

Image Credits