Anonymous messaging in Telegram
I was starting an hour long commute home when my phone came abuzz. A friend was organizing the annual Angel & Mortal game for our residential college community and was interested in leveraging some online platform for anonymous communication between players. The rules of Angel & Mortal are simple:
- Each player is assigned a Mortal to whom they act as an Angel.
- The Angel must give gifts to or play pranks on their Mortal without being discovered.
Typically, players would send messages to the organizers to be manually forwarded to their Mortal or Angel, asking for their likes/dislikes or informing them of new gifts. I immediately found this project to be simple yet impactful and was compelled to help. Unfortunately the game was starting soon, in a week, so I had to work fast.
This bot was developed in Python using the python-telegram-bot package. This allows you to run a simple server that will poll for messages sent to your bot on telegram. Before starting, you will need to set up a bot using the BotFather and generate a token (instructions here). The initial player data are loaded from CSV.
Original code used when I was running the bot (sorry if it’s messy!) can be found here: https://github.com/kstonekuan/angel-mortal-bot
Before diving into the chatbot logic, it’s important to understand the theory of the game itself. Each player has an Angel and a Mortal. Furthermore, your Angel is another player in the game who has you as their Mortal and vice versa for your Mortal. From an OOP perspective, each player can be represented as an object that references other player objects. Along with some telegram attributes, this can be represented by a Player class.
Trending Bot Articles:
While not crucial, you might recognise this as a graph node from graph theory. In particular, the game is designed as a directed graph. Each node has two outgoing edges (to the Angel and Mortal) and two incoming edges (from the Angel and Mortal).
While it might be possible to use our system to generate Angel-Mortal mappings, organizers often have a more in-depth understanding of social dynamics within the group. I chose to load provided mappings from a CSV file, as opposed to using something more complex (but efficient at scale), as it was simpler for organizers to modify the data. After loading, players can be stored in a dictionary or hash map in memory, similar to an adjacency list
Note: I reference parts of the python-telegram-bot API without explaining them, please refer to their tutorials for this.
You might have noticed that our Player class includes a username and chat_id. The username is used to identify players and is provided by the organizers while chat_id is what is used to send messages. We cannot send messages directly to a username as it would be unclear how we want the bot to communicate such as in a private message or group chat. Each user needs to start a chat with the bot first in order to get the chat_id that is generated by Telegram. I also went one step further to reject users that do not appear as a key in the dictionary as they are not registered players in the game.
Conversation handlers can be used to create simple menus to guide users through your bot flow. For this bot the user must first choose either their Angel or Mortal before sending their messages across. They may cancel the conversation at any time to switch between the two. Thanks to the class created in previous steps, it is not difficult to find the reference to their Mortal or Angel and get their respective chat_id to forward messages.
The result should look something like this (with custom names for Angel and Mortal):
So far you might have been testing your bot locally but it is probably not a good idea to keep to run this on your own machine for the entire duration of such events. I personally made use of Microsoft Azure free student credits to host but there are many options available.
As this was built in a few days with little time for testing there are many improvements you may want to make.
- Common feedback from players was that they could not send pictures or emojis through the bot. I had forgotten to account for this which might have to do with the Filters module.
- For long term games that require modifications or continuity you may also consider building a proper backend database such as using SQL or NoSQL instead of a simple CSV.
- Using the Player class and directed graph design, you can develop advanced algorithms to generate, validate or even modify the player graph for larger games.
I really enjoyed building this bot and helping out my community. This is my first article about programming so I hope you enjoyed reading and am always open to feedback about my writing!
Don’t forget to give us your 👏 !