How to create a Telegram bot to send messages from a Python program
Perfect for long running bits of code that need to be passively monitored
Author’s Note: This is a long tutorial. If you are viewing it in email inbox, you may have a better experience in your web browser.
Introduction
When trying to solve complex mathematical problems or running simulations, my time was better used doing other things (like reading the backlog of papers in my citation manager). I created a Telegram bot to message me with information on the status of these projects, progress, and issues that arise. This tutorial will guide you in setting up a bot with Python and Telegram’s API to have your code message you of your program's progress.
The full project can be found on GitHub.
The Case
Consider that we have two simulations SIMULATION_01
and SIMULATION_02
. Simulation 1 takes a uniformally random amount of time to complete, Simulation 2 takes a Beta distribution random amount of time to complete. Let us say this project we want to compare the execution time of these simulations.
def SIMULATION_01(lb, ub):
"""
Takes a uniformly random amount of time
to complete between :param lb: and :param ub:
"""
t = random.randint(lb, ub)
time.sleep(t)
return 0
def SIMULATION_02(lb, ub, alpha=2, beta=5):
"""
Takes the Beta [betavariate()] distribution of
:param alpha: and :param beta:.
Then takes the proportion between :param lb:
and :param ub: to complete the simualtion
"""
p = random.betavariate(alpha, beta)
t = round(lb + ((ub - lb) * p))
time.sleep(t)
return 0
def main(n_sims):
""" This is the main testing block, we run
each simulation n_sims times"""
for i in range(n_sims):
t_start_sim_1 = time.time()
# Takes between 1 and 3 minutes to complete
SIMULATION_01(60, 180)
t_end_sim_1 = time.time()
t_start_sim_2 = time.time()
# between 1 and 3 minutes also, beta distribution
SIMULATION_02(60, 180)
t_end_sim_2 = time.time()
log_data(i, t_end_sim_1 - t_start_sim_1,
t_end_sim_2 - t_start_sim_2,
file="./results/results.csv")
Creating the Bot
To create this bot, you’ll have to open a free Telegram account. As of November 2, 2022, creating both the account and the bot is free. An account is created similarly to WhatsApp. You’ll need a phone number and access to some form of wireless data service (mobile data, wi-fi).
After you have created and verified your account, you will need to message an account called BotFather. If you click the magnifying glass near the top of the app, you can Search for BotFather. Alternatively you can go to the URL t.me/BotFather.
You can scan its QR Code here:
Telegram has both a web browser app or a downloadable desktop app, both of which I find easier to use given that you will have to copy-paste secret keys between your chat with BotFather and your code.
Your first message to BotFather should be /start
. BotFather will respond with a series of commands you can send BotFather. Next, send /newbot
. You’ll be prompted for a bot name, for this tutorial I will name the bot SeanGroganTutorsBot. Next, you’ll be prompted for a username. This must be unique and end in “bot” (case insensitive). Here, I have also named the bot SeanGroganTutorsBot. For the purpose of this tutorial I am leaving the HTTP API key visible; However, it will be changed before publication of this tutorial. Your chat should look similar to below.
How you store and use your key is up to you. One of the more secure ways to store API keys is in your computer’s environment variables. However a personal preference is to store API keys in my personal research projects is a plaintext JSON file outside the working folder of my project to avoid the risk of committing an API key to Git/GitHub. In addition to the API Key, I store other bot parameters in this file. There will be other relevant Telegram parameters I can store in the parameter file.
There are a few ways to tackle the next step. You can set up the bot to message your account directly. However given our objective, I think this creates complications and overhead to both deployment of the code and managing the code. I believe the easier path will be to create a Telegram channel as this will reduce the coding overhead and allow other stakeholders to easily receive status updates.
Creating the Channel
If you are unfamiliar, telegram channels are one-way messaging platforms where channel administrators send messages to theit subscribers. For example, Bloomberg and the New York Times have channels where they send news articles to their subscribers.
To create a channel, click the new chat icon:
Next, you need to select “New Channel”
Next, you need to give your channel a name and description:
Finally, you’ll need to give the channel a unique username:
You have now created a Telegram channel. Now you’ll need to add the bot you made as a Channel administrator. Click the chat header (here, Sean telegram tutorial channel)
Click “Administrators”
Click “Add Admin”. Find and add your bot. Finally, I recommend you only give your bot “Posting Messages” privileges.
Creating the Bot in Your Code
Next, if you’re in Python, you’ll install the python-telegram-bot
package/API wrapper from here.
As indicated before, I have put my API key in a JSON File. In addition to the API key, you’ll need the Chat ID of your channel. If your channel is public, it will be the username/link you created earlier with a leading at (@) character1. I have set up my JSON file as follows:
{
"api_key": "5666889990:AAGZKEXd-AvUhqbTFSOfIgKfp5CvsjHmS8M",
"chat_id": "@seantelegramtutorial"
}
I like JSON as once it is read into a Python program, it can be used/manipulated like a dictionary.
Next, insert this code into your program:
def telegram_bot_send_message(
message,
telegram_pars= "" # Path to your api file
):
with open(telegram_pars) as f:
pars = json.load(f)
bot = telegram.Bot(pars["api_key"])
bot.sendMessage(
chat_id=pars["chat_id"],
text=message,
)
Finally, run the code/function:
telegram_bot_send_message(f"Hello World")
and you should see this:
Next Steps
Now that you have created the messaging bot, you have to insert it into your simulation tests. The naive entry is to put it at the end of each loop:
def main(n_sims):
for i in range(n_sims):
t_start_sim_1 = time.time()
# Takes between 1 and 3 minutes to complete
SIMULATION_01(60, 180)
t_end_sim_1 = time.time()
t_start_sim_2 = time.time()
# Takes between 1 and 3 minutes to complete, beta dist
SIMULATION_02(60, 180)
t_end_sim_2 = time.time()
log_data(i, t_end_sim_1 - t_start_sim_1,
t_end_sim_2 - t_start_sim_2,
file="./results/results.csv")
if i%10 == 0: #Sends every 10 simulations
telegram_bot_send_message(
f"Completed iteration {i} of {n_sims}"
)
There is a chance that you may fail to send the Telegram message. After you have tested to ensure that your Telegram bot works, I would put the the contents of the telegram_bot_send_message() function into a try except block as follows:
def telegram_bot_send_message(
message,
telegram_pars=# Path to your api file
):
try:
with open(telegram_pars) as f:
pars = json.load(f)
bot = telegram.Bot(pars['api_key'])
bot.sendMessage(
chat_id=pars["chat_id"],
text=message,
)
except:
print("Telegram struggled to send a message, continuing...")
This would allow the simulation to continue in case your computer has network connectivity issues, that way your program doesn’t get caught and exited on a Telegram error.
On the scope of errors, it would be helpful to know if your code has error and what that error is.
If we place the main() function into a try
- except
- else
block, we can send a message that there is an error, and using the traceback library we can also send the traceback to your Channel!
def main(n_sims):
telegram_bot_send_message(f"Starting Simulations!")
try:
for i in trange(n_sims):
t_start_sim_1 = time.time()
# Takes between 1 and 3 minutes to complete
SIMULATION_01(60, 180)
t_end_sim_1 = time.time()
t_start_sim_2 = time.time()
# Takes between 1 and 3 minutes to complete, beta dist
SIMULATION_02(60, 180)
t_end_sim_2 = time.time()
log_data(i, t_end_sim_1 - t_start_sim_1,
t_end_sim_2 - t_start_sim_2,
file="./results/results.csv")
if i % 10 == 0:
telegram_bot_send_message(
f"Completed iteration {i} of {n_sims}"
)
except:
traceback.print_exc()
telegram_bot_send_message(f"Error in Simulations!")
telegram_bot_send_message(f"TRACEBACK : {traceback.format_exc()}")
else:
telegram_bot_send_message(f"Completed Simulations!")
Yielding:
Conclusion
I hope that this is a complete and comprehensive guide for incorporating a telegram bot into a Python program. We have 1) created a personal Telegram account, 2) created a bot with botfather 3) created a Telegram channel for your bot to post messages 4) used the python-telegram-bot
package/wrapper to send messages to the Telegram channel 5) ensured that the Telegram bot in your code/simulation would not affect the execution of your code overall 6) send information about errors in the code/simulation to your Telegram channel.
If you have found this tuuorial useful, consider sharing this post!
And if you would like to see more tutorials, consider subscibing.
Thanks and happy coding!