Русский
Русский
English
Статистика
Реклама

Telebot

Из песочницы Бот Telegram для пиццерии на Python с помощью telebot

23.06.2020 12:07:45 | Автор: admin

Вступление


На Хабре уже есть статья о Telegram боте, написанном на Python с помощью telebot. Признаться, свое знакомство с чат-ботами в недавно разблокированном мессенджере я начинал с этой статьи. Моя писанина это дополнение, включающее в себя работу с Inline кнопками и базой данных.


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


Telebot библиотека для взаимодействия с Telegram API, которая привлекла меня простотой, поэтому я считаю, что для новичков она подходит на все 100%.


Чтобы установить библиотеку, введите в терминале следующую команду.


pip install pytelegrambotapi


Получение API-токена


Чтобы создать бота, обратимся к "отцу" всех ботов @BotFather. Отправьте команду /newbot, после чего введите имя бота, затем алиас, оканчивающийся на bot.


image

Пишем код


Лучше записывать API-токены, номера кошелька и тому подобное в отдельный файл, поэтому создадим файл config.py:


TOKEN = "1176585885:AAH-RA2kZym9E5tR8JFLtYYjNxrMHnsJr0o"

Основной код находится в bot.py


# импорт библиотекиimport telebot# Подтягиваем токен бота и все необходимое для получение средств за пиццуfrom config import TOKEN# Создание ботаbot = telebot.TeleBot(TOKEN)# Декоратор для обработки всех текстовых сообщений@bot.message_handler(content_types=['text'])def all_messages(msg):    # Получаем сообщение пользователя    message = msg.text    # Получаем Telegram id пользователя (очевидно, для каждого пользователя он свой)    user_id = msg.chat.id    # Отправляем сообщение    bot.send_message(user_id, f"Вы написали: {message}")# Запускаем бота, чтобы работал 24/7if __name__ == '__main__':    bot.polling(none_stop=True)

Мы создали эхо-бота. Подумаем, что будет в нашем боте:


  • База данных. В ней храним информацию по пользователям, а также создадим таблицу для хранения информации о пицце. Для взаимодействия с БД лучше написать отдельные классы для пользователя и пиццы.
  • Клавиатуры. Помогут сделать интерфейс удобным.
  • Оплата. Для этого будем использовать сервис QIWI.

База данных


Я пользуюсь SQLiteStudio для создания баз данных.


Структура таблицы для пользователя



  • id уникальный идентификатор пользователя. Таким выступает id пользователя в мессенджере, поэтому без зазрения совести будем использовать его.
  • stat статус работы с ботом. Запоминаем на каком шаге остановился пользователь.
  • ord. Здесь мы в виде строки храним заказ пользователя. Пока я не представляю как сделать по-другому, поэтому предлагайте идеи в комментариях.
  • random_code. В будущем будем генерировать рандомный код для оплаты через QIWI.
  • time. Пользователь выбирает, когда хочет получить заказ, а мы сохраняем в это поле.

Структура таблицы для пиццы



Данные по пиццам:



По name получаем описание пиццы и её стоимость.Осталось добавить фотографию. Создадим директорию data, поместим в нее img, а уже там будут храниться изображения.



Классы для взаимодействия с базой данных


Так, базу данных создали, теперь приступим к классам. Создадим файл user.py, в нём класс User. Сначала напишем пару функций для подключения к базе данных и закрытию соединения.


# Подключаем библиотекуimport sqlite3class User:    # Функция для соединения с БД    def connect_to_db(self):        self.connect = sqlite3.connect('PizzaApplication.db')        self.cursor = self.connect.cursor()    # Закрываем соединение с БД    def close(self):        self.connect.close()

Бота открыл пользователь, которого мы не знаем. Поэтому нужны функции добавления нового юзера и получения всех пользователей. Второе нужно для того, чтобы проверять наличие каждого написавшего "/start" в БД.


# Получаем id всех пользователей, позже будем проверять наличие пользователя в этом списке    def get_all_id(self):        self.connect_to_db()        request = "SELECT id FROM user"        result = self.cursor.execute(request).fetchall()        self.close()        return [i[0] for i in result]    # Добавляем нового пользователя    def add_id_to_db(self, user_id):        self.connect_to_db()        request = "INSERT INTO user(id, stat) VALUES(?, ?)"        self.cursor.execute(request, (user_id, "start"))        self.connect.commit()        self.close()

Для получения и обновления данных можно написать по две функции на каждое из полей, но я предлагаю поступить по-другому. Структура таких функций будет идентичная, за исключением названия столбца, поэтому в функцию будем передавать поле.


    # Получаем заданное поле по пользователю    def get_field(self, user_id, field):        self.connect_to_db()        request = f"SELECT {field} FROM user WHERE id=?"        result = self.cursor.execute(request, (user_id,)).fetchone()        self.close()        return result[0]    # Меняем значение поля    def set_field(self, user_id, field, value):        self.connect_to_db()        request = f"UPDATE user SET {field}=? WHERE id=?"        self.cursor.execute(request, (value, user_id))        self.connect.commit()        self.close()

Основные функции для пользователя написаны. Позже будем возвращаться к этому классу, а пока приступим к пицце. Создадим файл pizza.py, в нём класс Pizza. Начальные функции такие же, как у User.


import sqlite3class Pizza:    # Подключение к базе данных    def connect_to_db(self):        self.connect = sqlite3.connect('PizzaApplication.db')        self.cursor = self.connect.cursor()    # Закрытие базы данных    def close(self):        self.connect.close()

Нужно получать данные из БД.


    def get_field(self, pizza_name, field):        self.connect_to_db()        request = f"SELECT {field} FROM pizza WHERE name=?"        result = self.cursor.execute(request, (pizza_name,)).fetchone()        self.close()        return result[0]

Для админ-панели потребуется функция set_field (подобная есть в классе User), но её я пока не предусмотрел.


В следующей статье разберём клавиатуры и начнём писать код в bot.py. Спасибо за внимание!

Подробнее..

Реферальная система в Telegram ботах (telebot)

04.06.2021 20:14:20 | Автор: admin

Всем привет! Наверняка вы видели в различных ботах реферальную ссылку типа https://t.me/<юзернейм_бота>?start=<число>. Обычно в качестве числа указывается Telegram ID реферера. В этой статье я расскажу как обрабатывать такие ссылки в своем боте.

Для разработки ботов я использую Python библиотеку pytelegrambotapi.

Процесс создания бота через @BotFatherопущу, приступлю сразу к коду. Есть файл config.py с переменной TOKEN, в которой хранится токен бота. В файле bot.py будем "химичить". Напишем обработчик команды /start и выведем все, что хранится в объекте сообщения.

import telebotimport configbot = telebot.TeleBot(config.TOKEN)@bot.message_handler(commands=["start"])def start_command_handler(msg):    print(msg)if __name__ == '__main__':    bot.polling(none_stop=True)

Нас интересует строчка 'text': '/start'. Попробуем теперь перейти по ссылке вида https://t.me/<юзернейм_бота>?start=test и изменим 10-ю строчку на print(msg.text)

В консоли вывелось/start test. Делаем вывод, что в msg.text хранится необходимая нам информация из реферальной ссылки, которую необходимо обработать.

Приступим к обработке. Учитываем, что не всегда пользователь нажимает /start по реферальной ссылке, поэтому текста после /start может и не быть. Отличительным символом служит пробел (вспоминаем /start test). Значит будем проверять наличие ID реферера по нему.

@bot.message_handler(commands=["start"])def start_command_handler(msg):    user_id = msg.from_user.id    # Проверяем наличие хоть какой-то дополнительной информации из ссылки    if " " in msg.text:        referer = msg.text.split()[1]    else:        referer = None

Если пользователь перейдет по ссылке https://t.me/<юзернейм_бота>?start=test test2, То test2 не попадет в msg.text, потому что там имеется пробел, который говорит, что test2 не является частью ссылки. Именно поэтому в msg.text находится только один символ пробела. А значит если он имеется, то и есть некоторая информация из реферальной ссылки. Поэтому в первой ветке мы создаем список (msg.text.split()), и берем его второй элемент (всем ведь известно, что нумерация списка идет с нуля, да?).

Хорошо, на этом этапе мы имеем текст из ссылки. Мы подразумеваем, что там число, но от пользователя можно поджидать чего угодно. Вдруг кому-то захочется "сломать" бота, указав в ссылке вместо ID реферера какой-то текст. Для этого проверим данные.

@bot.message_handler(commands=["start"])def start_command_handler(msg):    user_id = msg.from_user.id    # Проверяем наличие хоть какой-то дополнительной информации из ссылки    if " " in msg.text:        referer = msg.text.split()[1]        # Пробуем преобразовать строку в число        try:            referer = int(referer)        except ValueError:            referer = None    else:        referer = None

Здесь, используя try... except мы преобразуем при помощи int() информацию в число. Если в переменной referer хранится не число, то int() вызовет ошибку ValueError

Теперь в referer записано число. Но тут появляется загвоздка: функция int() может перевести строку "-101" в число -101. То есть на данном этапе в referer может храниться отрицательное число. Почему это не важно, расскажу чуть позднее.

Пользователь может вставить в ссылку свой TG ID. Реферальная система подразумевает под собой некий бонус за переход, поэтому таким образом можно выдать самому себе бонус. Предусмотрим это. ID пользователя получаем, используя user_id = msg.from_user.id

@bot.message_handler(commands=["start"])def start_command_handler(msg):    user_id = msg.from_user.id    # Проверяем наличие хоть какой-то дополнительной информации из ссылки    if " " in msg.text:        referer = msg.text.split()[1]        # Пробуем преобразовать строку в число        try:            referer = int(referer)            # Проверяем на несоответствие TG ID пользователя TG ID реферера            if user_id != referer:                pass            else:                referer = None        except ValueError:            referer = None    else:        referer = None

Допустим, что имеется функция get_all_users(), которая возвращает список всех пользователей бота. Делаем это для того, чтобы не назначить в качестве реферера пользователя, которого не существует.

@bot.message_handler(commands=["start"])def start_command_handler(msg):    user_id = msg.from_user.id    # Проверяем наличие хоть какой-то дополнительной информации из ссылки    if " " in msg.text:        referer = msg.text.split()[1]        # Пробуем преобразовать строку в число        try:            referer = int(referer)            # Проверяем на несоответствие TG ID пользователя TG ID реферера            if user_id != referer:                                # Проверяем, есть ли такой реферер в базе данных                if referer in get_all_users():                # Здесь, используя самописную функцию, закрепим за пользователем реферера                    pass                else:                    referer = None            else:                referer = None        except ValueError:            referer = None    else:        referer = None

Что необходимо делать в случае, если у пользователя и так уже есть реферер? Не будем ведь при каждом использовании реферальной ссылки выдавать бонус за приведенного реферала, это нас попросту разорит. Поэтому необходимо написать проверку. Напишем функцию check_if_has_a_referer(), которая вернет True при наличии у пользователя реферера и False при его отсутствии. Логично ее написать в начале для оптимизации.

@bot.message_handler(commands=["start"])def start_command_handler(msg):    user_id = msg.from_user.id    # Проверяем наличие хоть какой-то дополнительной информации из ссылки    if " " in msg.text:        # Проверяем наличие закрепленного реферера за пользователем        if not check_if_has_a_referer():            referer = msg.text.split()[1]                # Пробуем преобразовать строку в число            try:                referer = int(referer)                    # Проверяем на несоответствие TG ID пользователя TG ID реферера                if user_id != referer:                        # Проверяем, есть ли такой реферер в базе данных                    if referer in get_all_users():                        # Здесь, используя самописную функцию, закрепим за пользователем реферера                        pass                    else:                        referer = None                    else:                    referer = None                except ValueError:                referer = None        else:            referer = None    else:        referer = None

Надеюсь, что статья будет для вас полезна!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru