How to create a simple Telegram bot in python

The basic idea was to starting handling some python code and having fun, that lead me to create a Telegram bot with the ability to send simple text mesage into a group to bother my friends.

The documentation about python Telegram library to create a bot is available in the official site https://python-telegram-bot.org/, here you can find any information with a bunch of example.

To keep things simple in this stage I decided to avoid DB and others cool stuff, all the phrases that the bot will use are saved in text files and picked up randomly.

Requirement

  • A text editor or a dev IDE, I used Visual Studio Code
  • Python3 installed on your machine
  • python-telegram-bot
    • pip install python-telegram-bot

Create a BOT with BotFather

The first step that is already well explained on the web is to create our bot in Telegram with BotFather (@botfather) following their instrucion.

Once you have the TOKEN to access via HTTP the API, save it in a safe place and be aware do not share it, as advised from BotFather itself: “Keep your token secure and store it safely, it can be used by anyone to control your bot.”

Code and files structure

  • data – The folder where to store the text files
  • main.py – The core fo the bot
  • constants.py – The file that containt constants
  • sources.py – The file that containt the sourses path (It will disappear in a near future :D)

I edited the file constants.py creating the variabile TOKEN that refer to the ID provided from BotFather:

TOKEN = 'my:secrettockenfrombothfather'
chatID= numberOfChatIDwithoutQuote

I created four text file into the data folder containing the phrases:

  • complains_list.txt
  • quotes_list.txt
  • secrets_list.txt
  • tips_list.txt

In the sources.py file a specified the file path:

complains = "/opt/tl_bot/data/complains_list.txt"
quotes = "/opt/tl_bot/data/quotes_list.txt"
tips = "/opt/tl_bot/data/tips_list.txt"
secrets = "/opt/tl_bot/data/secrets_list.txt"

The file main.py is where the code that run the bot are:

from telegram.ext.updater import Updater
from telegram.update import Update
from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.commandhandler import CommandHandler
from telegram.ext.filters import Filters
import constants as keys
import logging
import random
import sources as data

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)

def lineFromFile(sorgente):
        with open(sorgente,"r") as sourceFile:
                lines = sourceFile.read().splitlines()
        return (random.choice(lines))

def help_command(update: Update, context: CallbackContext):
        update.message.reply_text("""/quote - For random quote
        /tip - When do you need a tip
        /secrets - Reveal one of the secret of the gang
        """)

def complain_command(update: Update, context: CallbackContext):
        update.message.reply_text(lineFromFile(data.complains))

def quote_command(update: Update, context: CallbackContext):
        update.message.reply_text(lineFromFile(data.quotes))

def tip_command(update: Update, context: CallbackContext):
        update.message.reply_text(lineFromFile(data.tips))

def secrets_command(update: Update, context: CallbackContext):
        update.message.reply_text(lineFromFile(data.secrets))

def main():
        updater = Updater(keys.TOKEN, use_context=True)
        dp = updater.dispatcher
        dp.add_handler(CommandHandler('complain', complain_command, Filters.user(username="@MyNickname")))
        dp.add_handler(CommandHandler('help', help_command, Filters.chat(keys.chatID)))
        dp.add_handler(CommandHandler('quote', quote_command, Filters.chat(keys.chatID)))
        dp.add_handler(CommandHandler('tip', tip_command, Filters.chat(keys.chatID)))
        dp.add_handler(CommandHandler('secrets', secrets_command, Filters.chat(keys.chatID)))
        ## Polling command, you can specify a value if you want define a fixed delayin seconds.
        updater.start_polling(clean=True)

        ## Run the bot until you press Ctrl-C or the process receives SIGINT,
        ## SIGTERM or SIGABRT. This should be used most of the time, since
        ## start_polling() is non-blocking and will stop the bot gracefully.
        updater.idle()

main()

main.py drill down

The firt part of the fail contain the import of all the need function.

A little tip is to avoid to import all the stuff with * but to select the needed library and import them one by one.

From the telegram bot I got:

from telegram.ext.updater import Updater
from telegram.update import Update
from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.commandhandler import CommandHandler
from telegram.ext.filters import Filters

Please, refer to the official documentation for a detailed explanation of them https://docs.python-telegram-bot.org/en/v20.0b0/index.html

I imported the logging and the random function and my files constants.py and sources.py.

import constants as keys
import logging
import random
import sources as data

About the logging funtion there are no more to add.

The lineFromFile function pickup a random line for a text file, I decide to use with open to read the file to avoid issues in case of error and be sure that the file don’t remain openend for any reason:

def lineFromFile(sorgente):
        with open(sorgente,"r") as sourceFile:
                lines = sourceFile.read().splitlines()
        return (random.choice(lines))

The function read the file, split the lines of the file and return a random line back.

The other funtions are related to the “different commands” that use the lineFromFile function with different source files.

The main function is where the magic happen! 😀

Use of our bot token and shorted the updater.dispatcher:

        updater = Updater(keys.TOKEN, use_context=True)
        dp = updater.dispatcher

Defined the handler of the available command of the bot:

        dp.add_handler(CommandHandler('complain', complain_command, Filters.user(username="@MyNickname")))
        dp.add_handler(CommandHandler('help', help_command, Filters.chat(keys.chatID)))
        dp.add_handler(CommandHandler('quote', quote_command, Filters.chat(keys.chatID)))
        dp.add_handler(CommandHandler('tip', tip_command, Filters.chat(keys.chatID)))
        dp.add_handler(CommandHandler('secrets', secrets_command, Filters.chat(keys.chatID)))

I decided to keep for myself the command “complain” filtering it with my username, whereas the other commands are filtered for the chat ID to limit the use to the group where the bot is in.

The start of the bot:

        updater.start_polling(clean=True)

        updater.idle()

The execution of the main function:

main()

Run the bot as a Linux service on a Raspberry Pi

After the creation of the bot I decide to run it on a general purpose Raspberry that I have at home.

Create a group and a user without a home and that is not able to login into the system.

Use chown to grant the ownership of the files of the bot to the new user.

Install python and the telegram-bot library, than create the bot folder tl_bot into /opt and copy all the files in.

After being sure that the bot is working properly we can step into the creation of the linux service by creating the botname.service in /etc/systemd/system containing the following information:

[Unit]
Description=BotName Telegram Bot
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/bin/python3 main.py
KillSignal=SIGINT
WorkingDirectory=/opt/tl_bot
StandardOutput=inherit
StandardError=inherit
Restart=always
User=NewUserCreatedForTheBot

[Install]
WantedBy=multi-user.target

To automatically startup the service on reboot of the Pi run:

sudo systemctl enable botname.service

Conclusion

Those are the step that I followed to create a basic telegram bot in python, this can be a good starting point to create something that match your needs.

Remember to:

  • Never share your bot TOKEN, who have the tocken can control it
  • Import only the needed function from the library trying to avoid the * when possible
  • Create a specific user to run the bot
  • Last but not least, to have fun!
Advertisement

One thought on “How to create a simple Telegram bot in python

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s