HYPER-LINK

HYPER-LINK

LaravelMySQL
I was contacted by Next Gen Futures to develop a Telegram chat bot to help automate their curator network. Their old system involved collecting and recording users in the network's discoveries manually which was becoming unwieldy. I needed to build a chat bot that could collect links from users every week and then distribute them through the network in a secret Santa like fashion.

A Curator network

HYPER-LINK is a project set up by Jack Fancy and Harry Eastham with the aim of linking creative individuals to allow them to share their discoveries throughout the week. The premise is that members of the network would send 5 articles, post casts, videos etc. to the pair on WhatsApp a week. Jack and Harry would then send these sets of links to another member based on their interests, the process is very similar to a secret Santa set up. Inevitably, as their network grew, managing so many people was becoming quite difficult to they decided they required a chat bot to automate it. Telegram has become a more popular platform after WhatsApp was bought by Facebook so they would use it as their platform.


They came into contact with me through a family friend who had seen my work and I agreed to build the chatbot as I was curious about the development process and thought it would be a good project to learn from.

Learning about Telegram

Learning about Telegram

Telegram has an established SDK for PHP with some support for Laravel which I used. The process of making a bot works by using web hooks sent from Telegram's servers. If a bot is present in a chat, the user can send it a message and this triggers a web hook to be sent to an endpoint specified by the developer. This endpoint would receive the data about that message as an 'update' object. This object holds the message content, the chat ID along with various other stats about it. However, these objects do not hold information about what message was sent previously so you would have no idea about the context of a reply or message.


To get around this issue, my solution was to store message logs against a chat ID. This way, when the next message comes through, the previous message could be looked at so the bot would know how to process the new message. This technique would allow my bot to ask questions and store responses or handle messages without any prior instruction.

Testing the bot

Testing the bot

The bot requires a https domain to function which is an issue when working locally. Luckily, there is a program called Ngrok that creates a https tunnel to your localhost. This meant that I could assign the bot the Ngrok link as the webhook which would then route to my app running locally. This also meant that users testing the bot could use it as normal and I'd be able to look at data and debug on my local development environment as errors pop up.

The First Iteration

The First Iteration

I wanted to start by establishing all of the base functionality the chatbot would need first so started by building a chain of questions to collect details about a user. This data includes a name, location, age and list of interests the administrators could use to match people with similar interests. However, before any of that, I needed to start with '/start'. All bots on Telegram require a command a user can send through /start. In this app's case, it would register the sender by saving their sender ID, welcome the person to network with an explanation and finally ask for their name.


Commands can be built using the Telegram SDK's Telegram\Bot\Commands\Command class that uses:

  • A name variable, basically the word after / in a command, with this one being start.
  • A description to be shown when the user lists available commands.
  • A function called handle which will run when the command is received by the bot.


When starting to build the bot I didn't actually use the solution I explained before, I was trying to force a reply state which allows the bot to see the previous message. However this could not be used along side the custom keyboard API so was scrapped. That was not the only thing that changed during development as originally the network was called M.One. This had to be changed due to the reveal of Apple's new M1 chips.

Saving the name

Here is an example of handling a question response. In this example, the content of the user's message is saved as the name in their record and the bot then asks what interests the user has ready for the next response.

Custom Keyboards

Custom Keyboards

With some questions, the response needs to be limited. For example, user interests would need to be limited to a number of categories so it would be easier to match people. The first way of doing this is to send the user a list of interests with numbers and ask them to type the number or the name of the interest. While this can work, it is a bad experience for the user and can result in errors such as spelling. The second, better way is to use Telegram's custom keyboards. These can be created by providing a JSON encoded list of items to create a keyboard. In this example, each row would be an interest from a database model created by the administrators.

Custom keyboards continued

The Matcher

The Matcher

Once links have been collected from the user, the admins would need to match people up. To do this, I built a simplistic user interface using Vue that presents each user one by one. The admin can then choose from a list of the other users whose links they would like to be sent to the person. Each card shows the basic info about the person, their interests and the links they have collected so far on that week.


As a note, when links are saved by the bot, they are saved against the timestamp of the coming Friday so there is no confusion as to which week the bot is focusing on.

Scheduling Tasks

Scheduling Tasks

There are various tasks that need to be done by the bot at certain times in the week. For example, sending out reminders, asking the users for ratings of their last 5 discoveries and sending out emails. These are done using Laravel's scheduler in which times can be specified to run artisan commands, a cron task can then be created on the server which checks if any of the scheduled tasks need to be run and execute them if they do.

Sign up process

Sign up process

The creators of the network wanted the bot to be exclusive to a select group of members that they could curate at first. This was to ensure that users in the network were submitting quality content so that it works at its best. My solution for this was to have a sign up form that would create a new signup request in the admin panel. The admins could then accept or deny the request and an email would be sent to the person. This email would contain a link that opens up the box with a token query parameter. This token would verify the user and would be assigned to their telegram sender id allowing them to interact with the bot.

Start