Сегодня, мы будем писать Telegram Bot с заявкой. Например: Пользователи заполняют анкеты и после эти данные отправляются Администратору.

Для этого мы будем использовать библиотеку pyTelegramBotAPI (telebot).

pyTelegramBotAPI - это легкая и хорошая библиотека для написания Telegram Bot!

Установка библиотеки

Для установки на Windows самой библиотеки telebot нам понадобиться открыть cmd или терминал и написать:

pip install pyTelegramBotAPI

Для установки на macOS нужно написать:

pip3 install pyTelegramBotAPI

Начало кода

Для начало необходимо получить наш токен бота. Для этого нужно перейти в @BotFather и создать бота. После вы получите токен и его нужно вставить его в переменную TOKEN которую мы сейчас создадим, вставить нужно вместо YOUR_TOKEN .

И так, импортируем сначала саму библиотеку:

import telebot

TOKEN = 'YOUR_TOKEN'
ADMIN_ID = 'YOUR_ID'

В переменной TOKEN мы будем хранить наш токен полученный от BotFather

В переменной ADMIN_ID нам нужно вставить наш айди от аккаунта телеграм. Ваш ID можно узнать через бота @getmyid_bot

Теперь давайте напишем приветствие бота:

import telebot

TOKEN = 'YOUR_TOKEN'
ADMIN_ID = 'YOUR_ID'

bot = telebot.TeleBot(TOKEN)

name = None
username = None
user1_mess = None
user2_mess = None
user3_mess = None

@bot.message_handler(commands=['start'])
def start_message(message):
    global name, username
    name = message.from_user.first_name
    username = message.from_user.username
    bot.send_message(message.chat.id, "Привет! Это бот для заявок. Чтобы подать заявку, заполните анкеты")

bot.polling()

У нас есть 4 переменных. Переменные name и username делаем глобальными и в них нужно хранить username пользователя от телеграмма и имя. Теперь давайте проверим, работает ли наш бот. Для этого сначала нужно в конце кода написать:

bot.polling()

Как мы видим, бот работает!

Теперь давайте приступим к анкетам:

import telebot

TOKEN = 'YOUR_TOKEN'
ADMIN_ID = 'YOUR_ID'

bot = telebot.TeleBot(TOKEN)

name = None
username = None
user1_mess = None
user2_mess = None
user3_mess = None


@bot.message_handler(commands=['start'])
def start_message(message):
    global name, username
    name = message.from_user.first_name
    username = message.from_user.username
    bot.send_message(message.chat.id, "Привет! Это бот для заявок. Чтобы подать заявку, заполните анкеты")
    form1(message)

И да, в функции start_message в конце не забываем написать form1(message) благодаря которому после приветствия перекидывает нас на следующую функцию, которую мы сейчас и создадим.

Давайте напишем первый вопрос:

def form1(message):
    bot.send_message(message.chat.id, "1. Как вас зовут?")
    bot.register_next_step_handler(message, form2)

Благодаря коду bot.register_next_step_handler(message, form2) бот ждет, пока пользователь не отправит сообщение, и после его отправки переходит к следующей функции form2, сейчас мы его и создадим

Делаем вторую функцию:

def form2(message):
    global user1_mess
    user1_mess = message.text
    bot.send_message(message.chat.id, "2. Сколько вам лет?")
    bot.register_next_step_handler(message, form3)

Делаем переременную user1_mess глобальным и меняем его значение на message.text. В нем будет храниться текст пользователя. Эта переменная хранит текст введенный в предыдущей фукции.

Также делаем и с третьей функцией:

def form3(message):
    global user2_mess
    user2_mess = message.text
    bot.send_message(message.chat.id, "3. Укажите номер телефона:")
    bot.register_next_step_handler(message, result)

Вы наверное заметили, что в коде bot.register_next_step_handler(message, result) на этот раз указывает на функцию result. Давайте его создадим

Делаем функцию result:

def result(message):
    global user3_mess
    user3_mess = message.text
    bot.send_message(message.chat.id, "Спасибо за заявку! Скоро наш менеджер свяжется с вами. Всего доброго!")
    admin_app(ADMIN_ID)

Здесь просто пишем сообщение и код admin_app(ADMIN_ID) который перекидывает к функции admin_app.

Напомню, что Переменные user3_mess, user2_mess и user1_mess хранят тексты введенные в предыдущей функции.

И так, создаем функцию для отправки введенных данных пользователя Администратору/Менеджеру

Делаем функцию admin_app для отправки данных Админу:

def admin_app(ADMIN_ID):
    ankets = f'''Новая заявка от {name}!
Имя: {user1_mess}
Возраст: {user2_mess}
Номер телефона: {user3_mess}

Telegram:
Name: {name}
Username: @{username}'''

    bot.send_message(ADMIN_ID, ankets)

Создаем переменную ankets где будут заполненные анкеты пользователя и отправляем Админу. Вы помните, что мы создавали переменную ADMIN_ID? Так вот, на этот аккаунт с таким айди будут отправляться заявки пользователей.

Не забываем в конце кода написать:

bot.polling()

Полный код:

import telebot

TOKEN = 'YOUR_TOKEN'
ADMIN_ID = 'YOUR_ID'

bot = telebot.TeleBot(TOKEN)

name = None
username = None
user1_mess = None
user2_mess = None
user3_mess = None


@bot.message_handler(commands=['start'])
def start_message(message):
    global name, username
    name = message.from_user.first_name
    username = message.from_user.username
    bot.send_message(message.chat.id, "Привет! Это бот для заявок. Чтобы подать заявку, заполните анкеты")
    form1(message)


def form1(message):
    bot.send_message(message.chat.id, "1. Как вас зовут?")
    bot.register_next_step_handler(message, form2)

def form2(message):
    global user1_mess
    user1_mess = message.text
    bot.send_message(message.chat.id, "2. Сколько вам лет?")
    bot.register_next_step_handler(message, form3)

def form3(message):
    global user2_mess
    user2_mess = message.text
    bot.send_message(message.chat.id, "3. Укажите номер телефона:")
    bot.register_next_step_handler(message, result)

def result(message):
    global user3_mess
    user3_mess = message.text
    bot.send_message(message.chat.id, "Спасибо за заявку! Скоро наш менеджер свяжется с вами. Всего доброго!")
    admin_app(ADMIN_ID)

def admin_app(ADMIN_ID):
    ankets = f'''Новая заявка от {name}!
Имя: {user1_mess}
Возраст: {user2_mess}
Номер телефона: {user3_mess}

Telegram:
Name: {name}
Username: @{username}'''

    bot.send_message(ADMIN_ID, ankets)

    
bot.polling()

Запускаем и проверяем:

Ура! Все работает прекрасно!

Также вы можете в переменной ADMIN_ID указать айди вашей группы, куда нужно отправлять уведомления о новых заявок (не забудьте добавить бота в группу).

Комментарии (12)


  1. rusik2293
    08.08.2023 01:36
    +1

    user3_mess - беспорядок юзера 3?


  1. rSedoy
    08.08.2023 01:36
    +1

    А вы хотя бы понимаете проблему такого использования глобальных переменных в подобных конкурентных средах?


  1. theurus
    08.08.2023 01:36

    А как юзеру отменить режим ожидания ввода сообщения :) пока он возраст не напишет его не отпустит?


  1. fedorov0av
    08.08.2023 01:36
    +1

    мммм... для таких целей есть FSM. Советую ознакомиться. Можно обойтись без глобальных переменных.


  1. iantoshkai
    08.08.2023 01:36

    telebot в 2023 -__-
    использование global -____-
    нейминг на уровне(user3_mess, user2_mess, ...)
    советую почитать за aiogram, fsm


    1. twistfire92
      08.08.2023 01:36

      Конкретно для задачи описанной в статье telebot подходит более чем. И FSM от aiogram тут тоже не нужен. Слишком простой сценарий, реализация которого легко ложится на плечи register_next_step_handler, просто автор не все возможности этой функции знает. Вот если бы появились Inline кнопки, было бы чуть сложнее, но тоже решаемо.
      Автор - новичок, и прыгать сразу в aiogram с FSM только потому что aiogram достаточно попсовый - не самая удачная идея.


  1. crushilov
    08.08.2023 01:36

    Это конечно все круто, что можно кинуть боту сообщение и он тебе ответит другим сообщением, но хотелось бы уже что-то поинтереснее про на эту тему, чем просто краткий User Guide.


  1. twistfire92
    08.08.2023 01:36

    Я правильно понимаю, что на одновременной работе нескольких пользователей это все не тестировалось? Попробуйте использовать несколько аккаунтов, попросите друзей.
    Шаги следующие:

    • Первый начнет заполнять анкету, доходит до вопроса с номером телефона и ждет

    • Второй заполняет анкету полностью

    • Первый вводит номер телефона

    Какой результат получит первый пользователь?

    Собранную информацию на каждом шаге лучше пробрасывать в register_next_step_handler дополнительными параметрами, а не хранить в глобальных переменных


  1. MaxSoft
    08.08.2023 01:36

    А что будет, если 2 и более пользователя одновременно начнут писать в этого бота? Мне кажется, что будет Race Condition на глобальные переменные и всё сломается. Или я ошибаюсь?


  1. lex08275
    08.08.2023 01:36

    А в чем смысл глобальных переменных?

    2 человека одновременно заполняют форму, админу придет солянка из двух анкет?

    Почему бы не генерить объект и передавать его по цепочке?


  1. nameisBegemot
    08.08.2023 01:36

    А как в этом коде обстоит дело с асинхронным выполнением? Не будет ли блокировать после первого же подключения юзера?


    1. theurus
      08.08.2023 01:36

      Будет блокироваться. Ну видно же что это просто пример а не рабочий бот.