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

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

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

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

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

import telebot

import config

bot = 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

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

Источник: https://habr.com/ru/post/561112/


Интересные статьи

Интересные статьи

В основном, про Firebase рассказывают в контексте создания приложений под IOS или Android. Однако, данный инструмент можно использовать и в других областях разработки, на...
Хочу поделиться опытом автоматизации экспорта заказов из Aliexpress в несколько CRM. Приведенные примеры написаны на PHP, но библиотеки для работы с Aliexpress есть и для...
Приветики-омлетики, как-то недавно у меня появилась идея написать Telegram бота на Ruby на специфическую тематику, в двух словах этот бот должен был поднимать онлайн чатах по ср...
Есть несколько способов добавить водяной знак в Битрикс. Рассмотрим два способа.
Этап 0: Начало пути В реалиях современного мира, когда ведется повсеместная цифровизация и накопление данных обо всем и о каждом, возникает резонный вопрос, а как этими данными воспользоваться? ...