Inlinekeyboardbutton как определить нажатие url кнопки


Скачай курс
в приложении
Перейти в приложение
Открыть мобильную версию сайта
© 2013 — 2023. Stepik
Наши условия использования и конфиденциальности

Public user contributions licensed under cc-wiki license with attribution required
Как отследить нажатие кнопки InlineKeyboard при использовании параметра url без callback?
Недавно просто хотел создать кнопку с url, и для ослеживания её нажатия использовать callback_data, что-то по типу types.InlineKeyboardButton(text=’Нажми’, url = ‘https://example.com’, callback_data = ‘test’), но проблема в том, что при нажатии хоть и вылазит окно, о предложении перейти по ссылке, но буд-то не идёт.
@bot.callback_query_handler(func=lambda call: True) def callback_worker(call): if call.data == 'test': print('Нажата кнопка')
Вся картина
@bot.message_handler(content_types=['text']) def start(message): if message.text.lower() == '/test': keyboard = types.InlineKeyboardMarkup() key_note = types.InlineKeyboardButton(text='Нажми', url = 'https://example.com', callback_data = 'test') keyboard.add(key_note) bot.send_message(message.from_user.id, 'Нажми.', reply_markup = keyboard) @bot.callback_query_handler(func=lambda call: True) def callback_worker(call): if call.data == 'test': print('Нажата кнопка')
- Вопрос задан более двух лет назад
- 841 просмотр
Клавиатура как способ взаимодействия с ботом
Очень полезная возможность, которая упрощает взаимодействие пользователя с ботом. Рассмотрим этот объект пользовательской клавиатуры с опциями ответа, какие типы нам доступны на текущую версию API.
Еще раз про кнопки и клавиатуру
id — уникальный идентификатор пользователя в Telegram
last_name — значение поля фамилия, может быть пустым
first_name — значение поля имя, может быть пустым
username — уникальное значение текстовый идентификатор, может быть пустым
language_code — кодовое обозначение выбранного языка интерфейса приложения (en, ru . )
is_bot — флаг, определяющий пользователя как бота, в случае с ботом равен 1, в случае с пользователем пустое значение
Полезный инструмент
У каждого бота есть ссылка, которая открывает диалог с ним в Telegram — https://telegram.me/ИМЯ_БОТА . К этой ссылке можно добавить параметры start или startgroup со значениями. Значение может быть длиной от 1 до 64 символов и состоять из букв латинского алфавита (больших — A-Z и маленьких — a-z), цифр — 0-9, нижнего подчеркивания _ и тире -.
https://telegram.me/ИМЯ_БОТА?start=ВАШЕ_ЗНАЧЕНИЕ
Telegram Bot API рекомендует использовать base64url для кодирования параметров с двоичным и другими типами контента.
По ссылке с параметром start будет открыт диалог с ботом, с кнопкой Старт в месте поля ввода. Если используется параметр startgroup, пользователю будет предложено выбрать группу для добавления бота.
Как только пользователь подтвердит действие (нажмет кнопку Пуск в своем приложении или выберет группу для добавления бота), ваш бот получит сообщение от этого пользователя в таком формате:
/start ВАШЕ_ЗНАЧЕНИЕ
Для удобства пользователя, можно через настройки Commands вашего бота у @BotFather, задать список поддерживаемых ботом команд. Тогда при вводе знака слеш / , пользователь увидит все команды и сможет сразу их отправить, просто нажав на одну из них. Каждая команда состоит из собственно командного слова, начинающегося со слеша и короткого описания:
/invoice Выписать счет
Клавиатуры и их возможности
Для управления ботом вы как создатель бота предполагаете какой-то сценарий. Пользователю чтобы получить от бота желаемый результат нужно отправить команду. Бот, когда получит команду обработает ее и отреагирует по установленному вами сценарию. Но представьте, что пользователь написал команду с ошибкой, бот в этом случае должен предупредить что команда не распознана и попросить попробовать еще раз. Это не совсем удобно пользователю, и он может пойти искать другого бота с аналогичными возможностями. Вы можете потерять потенциального клиента, это не совсем хорошо.
В этом случае нам помогут клавиатуры. Ее нужно просто после старта диалога с ботом вывести на экран пользователю, и когда тот нажмет на нужную ему кнопку, боту отправиться заложенная вами правильная команда. В этом случае уходим от возможных ошибок, интерфейс бота выглядит более приветливо и профессионально. Качество бота повышается.
С каждым сообщением бот может отправлять разный набор кнопок как по количеству, так и по назначению. Кнопки можно расположить непосредственно под сообщением (InlineKeyboardButton), или зафиксировать под тестовым полем для ввода сообщения (KeyboardButton). Различия в них очень существенные на мой взгляд. Давайте рассмотрим некоторые их возможности.
KeyboardButton
Этот объект представляет одну кнопку клавиатуры, располагающуюся под текстовым полем для отправки сообщения. Поставляется она в интерфейс приложения в наборе с другими аналогичными кнопками через объект ReplyKeyboardMarkup. В качестве параметров с ним можно передать:
text — текст который будет на отображен на кнопке, обязательный параметр, поддерживает текст и смайлики (эмодзи)
request_contact — если параметр установлен в true, пользователь отправит в бот свой номер телефона на который зарегистрирован аккаунт
request_location — если параметр установлен в true, пользователь отправит в бот свое текущее местоположение
Если будет заполнен только обязательный параметр text , то при нажатии на кнопку будет отправлено текстовое сообщение с содержанием из этого параметра. Если будет включено дополнительно одно из необязательных параметров или локация, или контакт, то будет отправлен или контакт, или локация соответственно. Необязательные параметры взаимоисключающие.
Помимо набора кнопок в объект ReplyKeyboardMarkup можно передать еще ряд параметров:
keyboard — массив кнопок (объекты KeyboardButton)
resize_keyboard — если предать true, то клавиатура подгонится по высоте до возможного минимума.
one_time_keyboard — возможность скрывать клавиатуру после ее использования
selective — если надо показать клавиатуру только определенным пользователям
При необходимости удалить клавиатуру используйте объект ReplyKeyboardRemove.
InlineKeyboardButton
Это объект одной кнопки встроенной клавиатуры. Располагается набор таких кнопок сразу под сообщением. С помощью этого объекта можно передать кнопке url , или использовать его для голосования как одним из вариантов. В любом случае можно сделать много интересного и полезного. Рассмотрим его возможности на практике чуть ниже. Передается в наборе с другими аналогичными кнопками через объект InlineKeyboardMarkup. Принимает параметры:
text — текст который будет на отображен на кнопке, обязательный параметр, поддерживает текст и смайлики (эмодзи)
url — адрес на который будет направлен пользователь
callback_data — строка 1-64 символа будет передан боту через объект CallbackQuery
switch_inline_query — после нажатия будет предложен выбор чата где будет использован бот во встроенном режиме, пример @gif dog
switch_inline_query_current_chat — после нажатия вставит команду для использования бота во встроенном режиме в текущем чате
callback_game — описание игры, которая будет запущена при нажатии пользователем кнопки.
pay — кнопка будет использована как кнопка оплаты
Теперь немного практики
Предлагаю рассмотреть поближе возможности клавиатур. Для примера я сделаю 4 кнопки: 2 KeyboardButton и 2 InlineKeyboardButton. Для этого будем работать с теми же инструментами, которые были в предыдущей статье. Добавим только несколько новых методов.
Логика скрипта будет простая, при старте бот будет выводить сообщение о готовности и 2 кнопки Голосовать и Помощь. При нажатии на кнопку Помощь — выведется сообщение с небольшой инструкцией, а при нажатии на кнопку Голосовать на экране появиться сообщение и под ним 2 кнопки, при нажатии на которые произойдет увеличения счетчика.

Чтобы обрабатывать команды от всех типов кнопок нам надо составить условия проверки. В моем примере от кнопки KeyboardButton команда приходит в виде обычного текстового сообщения вместе с объектом Message под ключом text, а от кнопки InlineKeyboardButton в объекте CallbackQuery под ключом data.
elseif (array_key_exists('callback_query', $arrData)) < $chat_id = $arrData['callback_query']['message']['chat']['id']; $message = $arrData['callback_query']['data']; >?>
Кнопки будем отправлять в параметре reply_markup в методе sendMessage. Набор кнопок идет в таком формате:
Массив данных ( 'Тип клавиатуры' => Массив строк кнопок ( Массив кнопок строки ( Массив параметров кнопки ( ) ) ), // если предусмотрено 'Дополнительный параметр', )
Создадим два метода для разных клавиатур, на входе принимают массив строк кнопок, на выходе строку в формате JSON.
$data, ); return json_encode($inlineKeyboard); > private function getKeyBoard($data) < $keyboard = array( "keyboard" =>$data, "one_time_keyboard" => false, "resize_keyboard" => true ); return json_encode($keyboard); > ?>
Сам набор кнопок будет выглядеть вот так.
getKeyBoard([[["text" => "Голосовать"], ["text" => "Помощь"]]]); $inlineKeyboard = $this->getInlineKeyBoard([[ ['text' => hex2bin('F09F918D') . ' 0', 'callback_data' => 'vote_1_0_0'], ['text' => hex2bin('F09F918E') . ' 0', 'callback_data' => 'vote_0_0_0'] ]]); ?>
Во встроенных кнопках (inlineKeyboardButton) в качестве значения параметра callback_data будем передавать служебную информацию в виде action_type_count1_count2 , где
action — действие, в нашем случае это vote
type — тип кнопки: 1 — левая, 0 — правая
count1 — текущее значение левой кнопки
count2 — текущее состояние правой кнопки
В значении параметра text передаем бинарный код эмодзи в кодировке UTF-8 (список эмодзи), которые преобразуются из шестнадцатеричных данных в двоичные данные функцией hex2bin, и еще выведем текущее числовое значение счетчика кнопки.
Теперь нам остается только описать механизм определения команды и механизм ее обработки. Поэтому в методе init() создадим конструкцию оператора switch
"Приветствую, давайте начнем нашу практику. Нажмите на кнопку Голосовать.", 'chat_id' => $chat_id, // отправляем клавиатуру 'reply_markup' => $justKeyboard, ); $this->requestToTelegram($dataSend, "sendMessage"); break; // если пришла команда Голосовать case 'Голосовать': $dataSend = array( 'text' => "Выберите один из вариантов", 'chat_id' => $chat_id, // отправляем встроенную клавиатуру 'reply_markup' => $inlineKeyboard, ); $this->requestToTelegram($dataSend, "sendMessage"); break; // если запросили Помощь case 'Помощь': $dataSend = array( 'text' => "Просто нажмите на кнопку Голосовать.", 'chat_id' => $chat_id, ); $this->requestToTelegram($dataSend, "sendMessage"); break; // если вызвана встроенная кнопка case (preg_match('/^vote/', $message) ? true : false): // получаем новую клавиатуру $params = $this->setParams($message); $dataSend = array( 'reply_markup' => $params[0], 'message_id' => $arrData['callback_query']['message']['message_id'], 'chat_id' => $chat_id, ); // изменяем клавиатуру под выбранным сообщением $this->changeVote($dataSend, $params[1], $arrData['callback_query']['id']); break; // незапланированное действие обрабатываем как поумолчанию default: $dataSend = array( 'text' => "Не запланированная реакция, может просто нажмете на кнопку Голосовать.", 'chat_id' => $chat_id, ); $this->requestToTelegram($dataSend, "sendMessage"); break; > ?>
Давайте разберемся, что в этом коде происходит. Оператор switch принимает значение $message , которое может быть, как просто текст сообщения (в том числе команды), так и значение объекта callbackQuery .
При получении команды /start — мы выводим приветственное слово и набор кнопок: Голосовать, Помощь.
При получении команды Помощь, выводим простое текстовое сообщение.
При получении команды Голосовать, выводим текстовое сообщение и набор встроенных кнопок с параметром callback_data .
При получении не запланированного значения, выводим текстовое сообщение.
И самое интересное это когда принимаем значение в начале которого стоит action , в нашем случае это vote . Мы формируем новую клавиатуру изменяем в ней текстовое значение, увеличиваем счетчик у нажатой кнопки и подставляем новую служебную информацию в параметрах callback_data .
Для создания новой клавиатуры мы используем метод setParams() , а для отправки изменений мы используем метод changeVote(). Здесь остановим внимание на методах Bot API
editMessageReplyMarkup — меняем клавиатуру у заданного сообщения
answerCallbackQuery — позволяет выводить уведомление о проделанной работе CallbackQuery, мы его используем, уведомляя пользователя что он удачно проголосовал.
requestToTelegram($data, "editMessageReplyMarkup") ? "Вы проголосовали " . hex2bin($emoji) : "Непредвиденная ошибка, попробуйте позже."; // отправляем уведомление при любом результате $this->requestToTelegram([ 'callback_query_id' => $callback_query_id, 'text' => $text, 'cache_time' => 3, ], "answerCallbackQuery"); > private function setParams($data) < // разбиваем в массив по знаку _ $params = explode("_", $data); // увеличиваем значение или левой или правой кнопки $params[1] ? $params[2]++ : $params[3]++; // готови клавиатуру с новыми значениями callback_data $arr[] = $this->getInlineKeyBoard([[ [ 'text' => hex2bin('F09F918D') . ' ' . $params[2], 'callback_data' => 'vote_1_' . $params[2] . '_' . $params[3] ], [ 'text' => hex2bin('F09F918E') . ' ' . $params[3], 'callback_data' => 'vote_0_' . $params[2] . '_' . $params[3] ] ]]); // готовим эмодзи для уведомления $arr[] = $params[1] ? 'F09F918D' : 'F09F918E'; return $arr; > ?>
Подводим итоги
Мы рассмотрели некоторые способы взаимодействия между пользователем и ботом, в основном это элементы интерфейса бота.
Как обратиться к inline кнопкам которые находятся в функции
Как мне отловить нажатие этих кнопок в коде? Я знаю как работать с кнопками вне функции (то бишь кнопка просто создана и находится вне функции) Допустим если инлайн кнопка создана не в функции, ее нажатие можно отследить, например так: Так создана кнопка:
btn_pay = InlineKeyboardButton(text='=какой-то текст', callback_data='pay')
Так я отслеживаю ее нажатие:
@dp.callback_query_handler(lambda c: c.data == 'pay') async def process_callback_button_pay(callback_query: types.CallbackQuery): await bot.answer_callback_query(callback_query.id)
В общем сейчас я не понимаю как сделать тоже самое, но для инлайн кнопок которые находятся в def Если что плохо объяснил/написал спрашивайте. Я только учусь так что я гриб на данном этапе Использую aiogram
Отслеживать
задан 27 сен 2022 в 17:04
3 1 1 бронзовый знак
url кнопки ты не отследишь никак
27 сен 2022 в 17:23
по факту мне не нужно отслеживать url, нужно просто отловить нажатие кнопки которая находится внутри функции
28 сен 2022 в 6:47
Нет, вам нужно отследить нажатие на кнопку, которая является ссылкой. И это реализовать невозможно средствами BotAPI
28 сен 2022 в 6:54
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Приветик! Я так понимаю, нужно проверить статус чека? Я бы сделал отдельный хендлер и в нем проверял бы статус чека.
Как-то так:
from pyqiwip2p import QiwiP2P p2p = QiwiP2P(auth_key='ТОКЕН КИВИ') def buy_menu(url:str, bill_id:str) -> types.InlineKeyboardMarkup: qiwi_menu = InlineKeyboardMarkup(row_width=2) if url: btn_url_qiwi = InlineKeyboardButton(text="Ссылка на оплату", url=url) qiwi_menu.insert(btn_url_qiwi) btn_check_qiwi_ = InlineKeyboardButton(text="какой-то текст", callback_data="check_" + bill_id) qiwi_menu.insert(btn_check_qiwi_) return qiwi_menu @dp.callback_query_handler(text_startswith='check_') async def checkpayment(call: types.CallbackQuery): bill_id=call.data.split('_')[1] #БЕРЕМ ID ЧЕКА bill=p2p.check(bill_id) if bill.status == 'PAID': billinfo=int(float(bill.amount)) else: billinfo=False if billinfo == False: await call.answer('Оплата еще не получена!', True) else: await bot.send_message(call.message.chat.id, 'Мы получили оплату') #делаем действие
Решение рассчитано на: aiogram + pyqiwip2p Данные для buy_menu можно создать так:
bill=p2p.bill(amount='цена', lifetime='жизнь ссылки', comment='коммент') keyboard=buy_menu(bill.pay_url, bill.bill_id) #цена и жизнь - числа
