As of July 2023, @RemindMe_OfThis is dead, thanks to the Twitter API changes. 😢 Thanks for this lovely journey of 4.5 years, everyone!
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.
Just tweet:
@RemindMe_OfThis in three years
And when the time is right:
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!
- AWS Lambda with the Serverless Framework
- Firebase Messaging for push notifications
- Redis for data storage
- Node.js 14.x
- Chrono (pinned at v1) for parsing dates/times from text
The bot uses a number of AWS Lambda functions that work in tandem:
This function serves as the webhook registered to Twitter's Account 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.
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.
Renders the home page of http://remindmeofthis.app
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.🤔
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.
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.
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.
These are utility functions used only once: when verifying the webhook for Twitter (during setup). See here.
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.
See the contributing and development guide for details on working on this project.