I'm currently on holiday from work because of Lebaran and, after the food and festivities had passed, I quickly grew restless. The creeping feeling of "I should be doing something" made it impossible to spend the rest of my holiday working through the Netflix shows I had saved but never got around to watching.
No, I decided.
I would make a chatbot.
And I would do it in 24 hours.
Okay, that sounds cooler than it is, but I figured that making a chatbot for Line (the messaging app I currently use most), could be both useful and educational.
After some time brainstorming, I decided I would make a chatbot that would record a goal that you would set yourself with some deadline in the future. That bot would later email you (or your friend, or some arbitrary person) when the deadline came to remind you (or them) of that goal. That way, you could track if you met your goal or not!
Super simple and only kind of useful. The perfect project.
I started out by making a channel in my Line Developers console. I'd done this once before in my time at a conversational chatbot startup, so the process was pretty familiar to me already. Then, I set up the webhook URL to an ngrok public URL that pointed to a basic Express app on my localhost.
The JSON objects that Line were sending through were pretty nice and self-explanatory, so extracting the data was really simple and convenient. I managed to POST back a reply message, and then I had already made myself an echo bot!
I then I got to thinking - how do I build out a user flow that were >1 message?
After a few moments Googling and straining to remember half-heard conversations from people smarter than me, I decided to implement a flow with sessions.
I would set up a session for every new user that chatted with the bot. Depending on the user's reply to each message, I could set the current conversational context or state and store it in the user session. Based on the current state, the message sent by the server would be different, thus allowing a chain of messages as part of a flow. If the user completes the flow, the session would be stored somewhere. If the user didn't complete the flow, the session would expire.
But wait, how can these sessions be made unique, given that they're all being set on the same program running on the same instance of the same server?
After more Googling, I decided on Redis as a solution. I'd never used Redis before or really understood it before this project, so it was really fun getting to know how it worked and learning how to use it correctly.
I would store sessions in Redis with a unique key so they would be unique among users, and I would retrieve session information for the appropriate user on every step in the flow. Pretty good so far!
I implemented the whole flow, storing and retrieving the sessions along the way. Then it came to the end of the flow, where the data would have to be stored somewhere persistently.
Since I decided on Heroku way before this to host the project, I decided to store the relevant information in the session in a PostgreSQL database, which comes as an addon. I built that out quickly, wrote the right queries, and voila!
...Bugs.
I took some more time to build out basic input validation and test out the whole flow and all the different branches. Less bugs!
Now that the data could be stored in the database, it was time for me to figure out how I was going to email people when the deadline of their goals or pledges came.
I looked up how to set up a cron job on Heroku. Apparently there's an addon called Heroku Scheduler and, while not perfect, it seemed to be enough for a small project like this.
I wrote a script that would check for any pledges whose deadlines equalled the date today and emailed the stored email address if true. Then, I set the scheduler on Heroku to run it once a day.
It's alive!
So yeah, that's the story of how I made a janky (but operational) Line chatbot in 24 hours.
It was really fun to try out new things like Redis in this project, and I'm really happy to release my projects to the world - even if they're not perfect. After all, it's all about getting out there and starting.