Bot “Smart Scheduler” — quick in the uptake
Usage of reminders becomes more and more valuable thing, because human time tends to be more valuable as well. And services for planning your schedule can be really handy for this task.
That’s why I’ve came up with an idea to create Telegram bot for jotting down users’ affairs and remind of them. Main feature of this bot is it’s ability to create reminders directly from natural language.
In addition to it, this bot can also:
- Understand words with errors.
- Understand voice messages.
- Pin files to your reminders.
- Be integrated to your Trello board.
If you want to try it out right now here’s link to the bot.
For everyone else who’s interested how 16 year old schoolboy happened to write it, I will tell small story of development and how “Smart Scheduler” parsing system works behind the scenes.
Brief history of creation
There are 3 reasons why I’ve decided to create bot in Telegram messenger:
- Huge users base
- Many companies locate their work chats in this messenger
- There are many guides in internet how to set up bot in Telegram
How it all started
First version of “Smart Scheduler” had a very different technical side, but served the same purpose — creating reminders from natural speech. It was just a pilot project to see if my hypothesis was correct, so I didn’t bother myself about the quality of code. Main goal was to create MVP, so the whole application was nothing but a monolith. I presented it at russian IT-themed web-site Habrahabr. Then, after seeing that people appreciate the idea of project, I decided to improve code structure and continue on developing the bot.
I won’t tell you about this awkward clumsy first version, which was created almost a year ago, because it’s add no relevant information. Better let’s get directly to the current version.
Bot application architecture
The operating algorithm is as follows:
Checking of reminders is made using one minute timer. On the diagram this part is named “Tasks Scheduler”. It loads all reminders from data base, checks their time, and if their time is up, executes them. Expired reminders are deleted.
Originally bot was planned to understand both Russian and English, so I wrote each bot reply in two languages. To determine user’s language bot counts number of cyrillic and latin letters in message’s text. If there are more cyrillic letters than the latin, then the language is Russian, otherwise English.
Just to keep things safer I added text encryption using default Node.js library crypto.
Data base: PostgreSQL
Choice of DBMS is due to the fact that it’s already integrated to Heroku, where the bot is hosted, and it’s free. There are 3 tables in bot’s DB: User IDs, Chats and Schedules.
Also I’ve made ORM tool from scratch. I know, that it has definitely been done already, but I wanted to make it on my own and thus create fewer dependencies.
To extract time from natural language message, we first need to replace all numbers written in words with real numbers. For this I’ve made npm library parse-word-to-number. It takes a string and returns a string in which all possible words were replaced with numbers.
For matching words from source string with corresponding words from dictionary I’ve used Damerau-Levenshtein distance. This allows the library to understand words even with few mistakes.
The library works this way:
- Select the next word and search for it in dictionary.
- If it’s found in dictionary, then:
⠀⠀If previous word is number:
⠀⠀⠀⠀If previous number rank is bigger than current, then sum current number with previous and merge them.
⠀⠀⠀⠀Else if current number can be multiplied by previous number, then multiply it and merge with previous number.
- Otherwise write it to string.
It also supports russian language.
Time and text parsing
After all numbers in message were replaced with actual numbers, we can finally extract time definitions. For that I’ve made another npm library date-parser. It takes a string and returns array of objects of class ParsedDate (more information about in readme). Each of this objects represents one event with it’s time and text description. Thereby library can extract multiple reminders from string with one call.
This library also supports recurring reminders and time limits for them, for example: “Warm-up every 30 minutes until 20:00”.
Process of parsing is divided in three stages: simplifying, finding and forming.
To make search for human time definition patterns easier, we need first to simplify source string. This is done by creating reduced string, in which all words from source string are replaced with corresponding symbols from dictionary. Let’s take a look at the message “Pick up parcel tomorrow at 3 p.m.” and see how library shortens it.
(Word “tomorrow” corresponds to symbol A, “at” — p, “3” — n, “p.m.” — O. All not found words are replaced with dots.)
Now we can just apply different regular expressions to this shortened string to find time definitions. This allows us to handle every possible pattern, even the most complex ones! All we need to do is just write enough regular expressions:
In the end we form event’s description from the left words:
This is the most basic, but also most important part of parsing. The actual date-parser library is way more complex. I haven’t covered other technical nuances, such as contexts processing, validation levels and search for suitable time definitions. But for very simple parser this algorithm is more than enough.
Last but not least part of creating reminders is user’s timezone. It’s necessary to allow every people on globe to use bot correctly. To adjust timezone I’ve made two options, both of them are started via /tz command.
If you’re chatting with bot from smartphone, then you can set up your timezone in 1 click: just send your geolocation and bot will automatically determine your timezone.
To determine timezone by longitude and latitude bot uses web-site GeoNames.
Or, if you’re using telegram from PC, you can simply write your timezone GMT offset in “±HH:MM” format.
This is valid for mobile version as well.
Even with so many usefull features, Smart Scheduler is still can be much better. My main tasks for improving this bot are:
- Adding ability to integrate bot with user’s Google calendar.
- Adding ability to define time for common words, such as “morning, day, evening, night”.
- Improvement of user-bot interface by removing most of text commands and replacing them with convenient inline buttons.
Other minor tasks are listed in project’s issues on GitHub.
“Smart Scheduler” is an open-source project, so feel free to report any bugs or suggest improvements, I will greatly appreciate it.
Thank you for attention, hope you’ll have more free time with my bot!