Bot "Smart planner": understands perfectly

If you have ever wanted to have a personal servant who would remind you of everything you tell him about, but have not had the opportunity to hire one, then the bot I have developed will be a worthy replacement for him.







Do you want to test the functionality? Write to the bot using this link and he will answer you.



And for those who are interested in how it works and how a 16-year-old student was able to write it, I will gladly tell you everything in detail in this article.



Background



It all started with my other bot for VK on node js , which decrypted voice messages (and since such bots are a dime a dozen, I decided not to write an article about its development, although it also has several distinctive features). After I launched it, my father suggested that I develop another bot for our family chat via telegram. The essence of this bot was simple - to extract the date and time from a person's text message, and using telegram delayed messages, create reminders right in the family chat.



But soon I was disappointed. It turned out that bots cannot make deferred messages, so I decided to write my own system for storing and executing reminders.



Development of



General information



This bot is written in node js and lives on heroku .



It is capable of storing any text reminders accurate to the minute.



He can also work in group conversations.



At the moment, the bot recognizes the date and time only in Russian.



SmartScheduler is an open source project available on my github .



Extract date and time from message



I decided to start with the most difficult task: splitting a text reminder into a date and a reminder itself. To do this, we had to take into account all possible standards for writing the date by a person, from " at 12:00 " to " next Sunday at twenty-five to eight in the evening ."



A large database (constValues.js) was created, storing constant expressions and their properties that a person uses in his speech. Then functions were written to recognize each spelling of the time.



For example , a function is used to recognize a date in the form "through X % time_type %" FindAdditiveLiterals, and to find the day of the week FindDayOfWeek.



Each time designation option had its own priority.



As a result, the parser's algorithm looks like this:



  1. The original string is divided into words. The words in which the search for time is carried out cannot exceed 40.
  2. An array of words is passed through the word to number conversion function.
  3. All time indications are found in the message, and the words used in the instructions are also marked (for example, in the indication "alarm clock 8 o'clock" the words "8" and "hours" are marked).

  4. If some characteristic of time was not found (for example, month) in a text message, then the current value of this characteristic is taken.
  5. For the final verdict, the time indications with the highest priority and the adjacent indications that have the same source word are selected (for example, in the word "10:30" both hour and minute are indicated simultaneously).
  6. , , , .
  7. , .
  8. ,

    { string: answer, string: text, date: date }





    { string: answer, string: text }

    (answer – , text – , date – ).




The next questions were where to store all the reminders and how to keep track of their implementation.



Initially, I wanted to use the node-schedule library , but gave up this idea, since I did not want to clog the RAM with all the reminders.



Instead, I decided to study how SQL databases work and create my own.



After reading many articles on the Internet, I created a postgresql database on the heroku platform, since you can embed databases in your applications in it, which is very convenient.



To interact with the database, I wrote a small script (db.js) in which I implemented all the necessary functions, such as initializing the database, getting a list of reminders, etc.



There are two tables in my database: the first for storing reminders, and the second for storing users' time zones (more on that later).



After that, I implemented saving a parsed reminder from a text message to the database. The timer, which works once a minute, checks the time of the reminders. If the time has come for a reminder, then it is deleted from the database, and a message with the text from the reminder is sent to the user who made it.



I also added the display of all reminders via the / list command .







(there is a clickable / N command next to each reminder, which removes it when you click on it)



Time zone setting



Before I decided to write this article and put it on Habr, the Moscow time zone was hardcoded in the environment variables. This was enough for use within our family, but in order to take advantage of all the delights and conveniences of life with the SmartScheduler bot anyone could, I decided to add an individual time zone setting.



To complete the configuration, you need to write the / tz command , which the bot will warn the user about if he has not yet specified his time zone:







(due to the fact that the time zone is not specified, the response does not use local time, but Greenwich time)



When entering the / tz command the process of determining the time zone starts and a keyboard appears with three buttons:







  1. Using the user's location.
  2. Manual input.
  3. Cancel.



The first button asks the user for his location, based on which the time zone is calculated.



Usage example




The second button allows you to manually enter your time zone in the format Β± HH: MM ,

where Β± - plus or minus, HH - hours, MM - minutes.



Usage example




The third button cancels the definition process.



After the user has specified his time zone, the bot will correctly display and save the reminder time.



Final improvements



Having finished with the main functionality, I added the main keyboard with the main functions, corrected the answers for the / start and / help commands , and for the little things.



I also decided to replace the default time zone for all users with Moscow .



Result



The main advantage of the SmartScheduler bot is, of course, date parsing, which allows you to quickly and conveniently write down the necessary information or task in the form of a reminder even in the most unpredictable situations.



You no longer need to flip through the calendar in search of the right day and turn the clock to set the right time, it is enough to humanly tell the bot β€œwhat” and β€œwhen”, and then he will do everything himself.



Conclusion



Before developing bots on node js, I was completely unfamiliar with javascript, therefore, all the knowledge that I used in writing the code was taken from the Internet, where you can often find not exactly what you really need. Because of this, most likely, somewhere in my code there are very stupid errors, for which I still do not know much enough to determine.



Initially, my goal was not to create the most advanced and ideal from the point of view of the project structure, the most important thing for me was to gain new knowledge, learn a new programming language to improve understanding of computer science in general, and create an MVP product.



But if this development is in demand, then I will continue to improve it with pleasure, and if you have any ideas or find a bug, then welcome to the project's github. I already have ideas where and how to change what (for example, rewrite the terrible spaghetti code in the parsing module using the normal Visitor pattern), as well as plans to add support for the English language.



I hope this bot will help you as well as it helps me and my family in our daily activities.



Thank you for attention!



UPD: Added support for voice messages by popular demand.

UPD 2: The bot has received a major update since the article was published. List of changes .



All Articles