Всем привет! Наверняка вы видели в различных ботах реферальную ссылку типа 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
Надеюсь, что статья будет для вас полезна!