·4 min read

Building Reminders for WhatsApp (GPT Online) using QStash

Bilal TahirBilal TahirFront-end developer (Guest Author)

QStash is a task scheduler and message queue system designed for serverless environments. It's a valuable tool for developers as it allows them to set up automated workflows that run at specific intervals, either once or repeatedly, without having to worry about managing state.

You can play around on the QStash console to get a feel of how to build a request:

The Use Case

My product GPT Hotline is essentially ChatGPT on WhatsApp (we use the same underlying model). You can text the bot on a dedicated number just like you would on the ChatGPT app.

GPT Hotline offers additional features beyond just texting, such as image search, video search, and news. Additionally, I wanted to add a reminders feature, which would allow users to text the bot to receive a message at a specified time.

A simple flow where you could text the bot to send you a message at a certain time. It would look something like this:

I had used Upstash for serverless Redis before so I was vaguely aware of QStash and this seemed like the perfect opportunity to learn more!

Let's Dive In

The high-level workflow we want to code up is

User sends reminder message -> QStash job is set up -> QStash triggers API at specified time -> Message sent to user

To keep things simple, I'll only focus on the QStash code. GPT Hotline has "Power Commands" that override the bot's default response, and the command to set a reminder is in the following format:

sudo reminder <TIME-INTERVAL> <MY-MESSAGE>
sudo reminder <TIME-INTERVAL> <MY-MESSAGE>

For example, if you text:

sudo reminder 3h go for a walk
sudo reminder 3h go for a walk

The "sudo reminder" command will trigger the reminder code, and the "3h" indicates that you want the reminder ("go for a walk") to be sent in 3 hours.

GPT Hotline is built using Next.js so we can trigger QStash in a couple of ways. They have a verifySignature function you can use to authenticate but we will use the REST API approach to keep things simple.

// Note: There are CURL Command examples available in the QStash docs.
const YOUR_API_URL = "https://api.example.com";
const MY_MESSAGE = "go for a walk";
const REMINDER_TIME = "3h";
const MESSENGER = "1800-MCDONALDS";
 
await fetch(`https://qstash.upstash.io/v1/publish/${YOUR_API_URL}`, {
  headers: {
    Authorization: `Bearer ${process.env.QSTASH_TOKEN}`,
    "Upstash-Delay": REMINDER_TIME,
    "Content-Type": "application/json",
  },
  method: "POST",
  body: JSON.stringify({
    message: MY_MESSAGE,
    messenger: MESSENGER,
  }),
});
// Note: There are CURL Command examples available in the QStash docs.
const YOUR_API_URL = "https://api.example.com";
const MY_MESSAGE = "go for a walk";
const REMINDER_TIME = "3h";
const MESSENGER = "1800-MCDONALDS";
 
await fetch(`https://qstash.upstash.io/v1/publish/${YOUR_API_URL}`, {
  headers: {
    Authorization: `Bearer ${process.env.QSTASH_TOKEN}`,
    "Upstash-Delay": REMINDER_TIME,
    "Content-Type": "application/json",
  },
  method: "POST",
  body: JSON.stringify({
    message: MY_MESSAGE,
    messenger: MESSENGER,
  }),
});

This is an example of a fetch request we can send to QStash. I have hardcoded values and removed extra fields, but this is a good representation of our actual fetch request in the app.

QStash requires a URL to send the message to. This would be our API URL which we want to trigger at the specified time.

The Upstash-Delay value determines the time to send the message. Upstash-Delay can take values in seconds (s), minutes (m), hours (h), and days (d). For example, 30m is 30 minutes and 2d is 2 days, etc. If we wanted to set up a job that runs periodically rather than just once, we would use the Upstash-Cron field with cron logic*.*

We'll also send the message in the body, along with the recipient's number (messenger), and authenticate using our QSTASH_TOKEN which is set as an environment variable.

And that's it! If everything works as expected, we'll receive a confirmation that the reminder has been set, and QStash will trigger the API at the set time with the message and messenger values (which would in turn send the reminder to the recipient).

Conclusion

I had been putting off this feature because I thought it would be a bit complicated to implement, but with the help of QStash, I was able to knock it out in just one evening!

I highly recommend you check it out. They have a generous Free Tier of 500 messages/day you can start using, and only pay once your application scales, so there is no reason not to give it a shot.

Cheers, Bilal

sudo reminder 1m Good Luck!
sudo reminder 1m Good Luck!