So much has already been said about bots on Habr, and not only there, that it's almost too much. But having become interested in this topic a couple of weeks ago, I couldn't find any decent material: all the articles were either for complete beginners and limited to sending a message in response to a user's message, or they were outdated. This is what prompted me to write an article that would explain to a beginner like me how to write and launch a more or less meaningful bot (with the possibility of expanding its functionality).

Part 1: Registering the bot


The simplest and most described part. Very briefly: you need to find the @BotFather bot, send it /start, or /newbot, fill in the fields it asks for (the bot's name and its short name), and receive a message with the bot's token and a link to the documentation. The token needs to be saved, preferably securely, as it is the only key for authorizing the bot and interacting with it.

Part 2: Preparing to write code


As mentioned in the title, we will be writing the bot in Python. This article will describe working with the PyTelegramBotAPI (Telebot) library. If you don't have Python installed, you need to do that first: in a Linux terminal, you need to enter

sudo apt-get install python python-pip

If you are using Windows, you need to download Python from the official website.

Afterward, in a Linux terminal or Windows command prompt, enter

pip install pytelegrambotapi

Now everything is ready for writing code.

Part 3: Receiving messages and saying “Hello”


A small digression. Telegram can inform a bot about user actions in two ways: through a response to a server request (Long Poll), and through a Webhook, when the Telegram server itself sends a message that someone has written to the bot. The second method clearly looks better, but it requires a dedicated IP address and an installed SSL certificate on the server. In this article, I want to talk about writing a bot, not configuring a server, so we will be using Long Poll.

Open your favorite text editor, and let's write the bot's code!

The first thing to do is to import our library and connect the bot's token:

import telebot;
bot = telebot.TeleBot('%your token%');

Now let's declare a method for receiving text messages:

@bot.message_handler(content_types=['text'])
def get_text_messages(message):

In this piece of code, we have declared a listener for text messages and a method for processing them. The content_types field can take different values, and not just one, for example

@bot.message_handler(content_types=['text', 'document', 'audio'])

Will react to text messages, documents, and audio. You can read more details in the official documentation

Now let's add some functionality to our method: if a user writes “Hello” to us, we'll say “Hello, how can I help you?”, and if they write the “/help” command, we'll tell the user to write “Hello”:

if message.text == "Hello":
    bot.send_message(message.from_user.id, "Hello, how can I help you?")
elif message.text == "/help":
    bot.send_message(message.from_user.id, "Write hello")
else:
    bot.send_message(message.from_user.id, "I don't understand you. Write /help.")

This piece of code doesn't require comments, I think. Now we just need to add one more line to our code (outside of all methods).

bot.polling(none_stop=True, interval=0)

Now our bot will constantly ask the Telegram server, “Has anyone written to me?”, and if we write to our bot, Telegram will pass our message to it. Save the entire file, and type in the console

python bot.py

Where bot.py is the name of our file.

Now you can write to the bot and see the result:

image

Part 4: Buttons and message branches


Sending messages is undoubtedly fun, but it's even more fun to have a dialogue with the user: asking them questions and getting answers. Let's say our bot will now ask the user for their first name, last name, and age in sequence. To do this, we will use the bot's register_next_step_handler method:

name = '';
surname = '';
age = 0;
@bot.message_handler(content_types=['text'])
def start(message):
    if message.text == '/reg':
        bot.send_message(message.from_user.id, "What is your name?");
        bot.register_next_step_handler(message, get_name); #next step is the get_name function
    else:
        bot.send_message(message.from_user.id, 'Write /reg');

def get_name(message): #get the last name
    global name;
    name = message.text;
    bot.send_message(message.from_user.id, 'What is your last name?');
    bot.register_next_step_handler(message, get_surnme);

def get_surname(message):
    global surname;
    surname = message.text;
    bot.send_message('How old are you?');
    bot.register_next_step_handler(message, get_age);

def get_age(message):
    global age;
    while age == 0: #check that the age has changed
        try:
             age = int(message.text) #check that the age is entered correctly
        except Exception:
             bot.send_message(message.from_user.id, 'In numbers, please');
      bot.send_message(message.from_user.id, 'You are '+str(age)+' years old, and your name is '+name+' '+surname+'?')

And so, we have recorded the user's data. This example shows a very simplified case; ideally, intermediate data and user states should be stored in a database, but today we are working with a bot, not with databases. The final touch – let's ask the user for confirmation that everything is entered correctly, and not just in any way, but with buttons! To do this, let's edit the code of the get_age method a bit

def get_age(message):
    global age;
    while age == 0: #check that the age has changed
        try:
             age = int(message.text) #check that the age is entered correctly
        except Exception:
             bot.send_message(message.from_user.id, 'In numbers, please');
      keyboard = types.InlineKeyboardMarkup(); #our keyboard
      key_yes = types.InlineKeyboardButton(text='Yes', callback_data='yes'); #the "Yes" button
      keyboard.add(key_yes); #add the button to the keyboard
      key_no= types.InlineKeyboardButton(text='No', callback_data='no');
      keyboard.add(key_no);
      question = 'You are '+str(age)+' years old, and your name is '+name+' '+surname+'?';
      bot.send_message(message.from_user.id, text=question, reply_markup=keyboard)

And now our bot sends a keyboard, but if you press it, nothing will happen. That's because we haven't written a handler method. Let's write one:

@bot.callback_query_handler(func=lambda call: True)
def callback_worker(call):
    if call.data == "yes": #call.data is the callback_data we specified when declaring the button
        .... #code to save or process data
        bot.send_message(call.message.chat.id, 'Got it : )');
    elif call.data == "no":
         ... #ask again

All that's left is to add one line to the beginning of the file:

from telebot import types

That's it, save and run our bot:

image