/RemindMeOfThisTweet

πŸ€– Twitter bot to set reminders for tweets.

Primary LanguageJavaScriptMIT LicenseMIT

RemindMeOfThisTweet

The Problem

Some guy on Twitter tweets:

In three years, humans will have established a colony on Uranus.

And of course, naturally, you want to check back in three years to see if he was right. But you likely won't remember by that time.

The Solution

Just tweet:

@RemindMe_OfThis in three years

Reminder request screenshot

And when the time is right:

Reminder screenshot

Of course, that's not all you can do! You can set reminders for your own tweets (New Year's Resolutions, anyone?πŸ‘€), too, for instance.

Note that the bot will assume all absolute times are in UTC, so if you want to specify an absolute time, you need to specify a timezone if you're not in UTC/GMT. For instance, "11:30 pm WAT" (West African Time), "10:20 am UTC+0300", "10:20 am GMT-0900". Better yet, sign in on https://remindmeofthis.app and set your timezone.πŸ™‚

PS: I also made @this_vid!

How This Works

Stack

Implementation

The bot uses a number of AWS Lambda functions that work in tandem:

handleAccountActivity

This function serves as the webhook registered to Twitter's Accout Activity API. Whenever anyone mentions the bot (or likes or retweets a tweet by the bot), Twitter hits this URL with a payload containing details of the events.

This function iterates through all the mentions and looks for any possible reminder requests (or reminder cancellations). If it finds any requests, it sets a reminder by storing the relevant data (tweet, author, etc) in Redis, with the Redis key being the timestamp (ISO8601β€”can't remmber why I went with that instead of the UNIX timestamp, but possibly human-readability).

Cancellations (reply "cancel" to the bot's reply) work by storing a Redis entry with the reminder request tweet ID as value and the ID of the bot's response as key. SO when a user replies cancel to a Tweet, we look up the ID of the tweet they're replying to, fetch their original reminder Tweet from there, and then delete th reminder from that Tweet from the datetime-key containing it in Redis.

checkForRemindersAndSend

This function runs once every minute (this means reminders can only have minute precision) and checks for any reminders scheduled for the current time. Assuming the time is 2019-05-03, 11:23, it will check for a Redis key 2019-05-03T11:23:00Z, which should hold all the reminders for that time. Then it iterates over them and dispatches any tweets or push notifications.

getHomePage

Renders the home page of http://remindmeofthis.app

getPage

Renders all other pages on http://remindmeofthis.app. Why are getHomePage and getPage separate, you ask? I honestly do not remember. Maybe I wasn't sure if I could make path parameters optional.πŸ€”

startTwitterSignIn

When you click "Sign in With Twitter" on the website, you're redirected to the URL of this function. It retrieves the necessary tokens and passes on to Twitter API to start the sign in process.

completeTwitterSignIn

The URL Twitter redirects you to after you complete the sign in process. This function fetches your profile info from the Twitter API and creates a session for you on the website.

updateSettings

HTTP handler that the form submits to when you update your settings on the website (set a timezone or enable/disable push notifications). Settings are stored in redis, with the user's Twitter handle forming part of the key.

handleTwitterCrc

These are utility functions used only once: when verifying the webhook for Twitter (during setup). See here.

retryFailedTasks

This re-publishes failed tasks (stored in Redis) and attempts to set reminders for them. It can only be triggered manually.

This architecture isn't perfect, and I'm open to criticism and suggestions. It's unlikely I'll change things much (because time, work, etc), but I'm interested in hearing your thoughts.

Development

See the contributing and development guide for details on working on this project.