python telegram bot api inlinekeyboardbutton not getting callback_data - python

python telegram bot api inlinekeyboardbutton not getting callback_data,
i'm using telebot libray,
this is how i created the buttons
markup = types.ReplyKeyboardMarkup(row_width=2)
b1 = types.InlineKeyboardButton("button 1", callback_data='1')
b2 = types.InlineKeyboardButton('Button 2', callback_data='2')
markup.add(b1, b2)
bot.send_message(cid, 'message', reply_markup=markup)
the buttons appear and i can press them but nothing returns to my callback_query_handler
#bot.callback_query_handler(func=lambda call: True)
def callback_button(call):
try:
if call.message:
cid = message.chat.id
if call.data == '1':
pass
elif call.data == '2':
pass
except:
pass

As it turned out, InlineKeyboardButton objects do not return callback as ReplyKeyboardButton objects.
InlineKeyboardButton are sent as a message and they will appear within the message_handler

Related

How to make author only click button

i want to make author only button if someone clicked and if this is not the author of the message, then the bot will send an error.but my code is not working
#bot.command()
async def button(ctx):
await ctx.send(content="test", components=[Button(style=ButtonStyle.blue, label="Default Button", custom_id="button")])
interaction = await bot.wait_for("button_click", check = lambda i: i.custom_id == "button")
if interaction.user == ctx.author:
await ctx.send("successful test")
Change the check function to this:
check = lambda i: i.custom_id == "button" and i.user == ctx.author
This checks if the user associated with the interaction is the author of the message.

How to execute definite handler-function in aiogram (Telegram API)?

I have got a Telegram-bot in AIOgram. My aim in this bot is to run it and if user writes secret phrase - bot must send secret message.
My code in main.py file:
from aiogram.dispatcher.filters import Text
from aiogram.dispatcher import FSMContext
from database import Database
from states import *
from aiogram import Bot, Dispatcher, executor, types
bot = Bot(token="my_token")
dp = Dispatcher(bot)
#dp.message_handler(commands="start")
async def start(message: types.Message):
keyboard1 = types.InlineKeyboardMarkup()
links = ["one", "two", "three"]
for row in links:
button = types.InlineKeyboardButton(text=row[0])
keyboard1.add(button)
await message.answer("Chose the phrase", reply_markup=keyboard1)
# options - is the next handler function
dp.register_message_handler(options, state="*")
async def options(message: types.Message):
if message.text == "Secret phrase":
keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True)
keyboard.add(types.KeyboardButton(text="Secret 1"),
types.KeyboardButton(text="Secret 2"),
types.KeyboardButton(text="Secret 3"),
types.KeyboardButton(text="Main menu"))
await message.answer("Chose the phrase", reply_markup=keyboard)
dp.register_message_handler(workingWithLinks, state="*")
else:
await message.answer("This command is error, for phrases update call command /update")
async def workingWithLinks(message: types.Message):
if message.text == "Secret 1":
await message.answer("This is secret number 1")
await SecretOne.step_one.set()
elif message.text == "Secret 2":
await SecretTwo.step_one.set()
await message.answer("This is secret 2")
elif message.text == "Secret 3":
await SecretThree.step_one.set()
await message.answer("This is secret 3")
else:
await message.answer("This command is error, for phrases update call command /update")
def register_handlers_common(dp: Dispatcher):
dp.register_message_handler(start, commands="start", state="*")
dp.register_message_handler(start, commands="update", state="*")
if __name__ == "__main__":
register_handlers_common(dp)
executor.start_polling(dp, skip_updates=True)
My code in states.py file:
from aiogram.dispatcher.filters.state import State, StatesGroup
class SecretOne(StatesGroup):
step_one = State()
step_two = State()
step_three = State()
class SecretTwo(StatesGroup):
step_one = State()
step_two = State()
step_three = State()
class SecretThree(StatesGroup):
step_one = State()
step_two = State()
step_three = State()
Scenario of my bot is next: I click command /start, and bot sends me message "Chose the phrase" with three inline-buttons - "one", "two" and "three". And if user don't click on one of this button and type "Secret phrase" - program link user to "options" handler-function. This is string, where linking is:
dp.register_message_handler(options, state="*")
"options" is handler-function. This link works. But, if in "options" I chose the phrase "Secret 1" - link on workingWithLinks handler-function doesn't work.
Linking on workingWithLinks handler-function:
dp.register_message_handler(workingWithLinks, state="*")
Also I tried to link on next handler-function with states as in this tutorial, but this also doesn't works.
How to link on workingWithLinks handler-function?
Don't register message handlers in message handlers!
dp.register_message_handler(options, state="*")
This string will add handler to the stack on every message call.
Answer
If you wanna get something from user - use states.
Look at the FSM example

PyTelegramBotApi - how to stop one function if other function is running?

I am trying to do an optional input, and have this code
bot.send_chat_action(message.from_user.id, 'typing')
markup = types.InlineKeyboardMarkup()
markup.add(types.InlineKeyboardButton("Лечу только в одну сторону", callback_data="one_way"))
msg = bot.send_message(message.from_user.id, '✅Хорошо. Теперь введите дату возвращения:', reply_markup=markup)
bot.register_next_step_handler(msg, get_return_date)
This code sends user a message with button to skip this step, and registers function get_return_date(), that waits for a date value. Message
And if user clicks the button, query handler register another function get_adults(), that waits for numeric value:
#bot.callback_query_handler(func=lambda call: call.data == "one_way")
def is_one_way(call):
msg = bot.send_message(call.from_user.id,
'✅Хорошо. Сколько взрослых (пассажиров старше 12-ти лет на момент полёта) полетят 🤵👩‍💼?')
bot.register_next_step_handler(msg, get_adults)
return
And, trouble is that - if user clicks the button to skip, both get_return_date() and get_adults() are waiting for a value and work at one time:
Problem
Any ideas what should i do?
You can do this:
bot.send_chat_action(message.from_user.id, 'typing')
msg = bot.send_message(message.from_user.id, '✅Хорошо. Теперь введите дату возвращения: (you can skip this passage with /skip)')
bot.register_next_step_handler(msg, get_return_date)
def get_retourn_date(message):
if message.text == '/skip':
get_adults()
return
# write here the actual function code
i use query callbacks and i put this func at the begining of the callback:
bot.clear_step_handler_by_chat_id(call.message.chat.id)
u can use it like this
def gen_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton("Button 1", callback_data="one"),
InlineKeyboardButton("Button 2", callback_data="two"))
def ButtonOneFunc(message):
#do whatever u want here
def ButtonTwoFunc(message):
#do whatever u want here
#bot.callback_query_handler(func=lambda call: True)
def callback_query(call):
bot.clear_step_handler_by_chat_id(call.message.chat.id)
if call.data == "one":
sent= bot.reply_to(call.message, "This is Button 1")
bot.register_next_step_handler(sent, ButtonOneFunc)
elif call.data == "two":
sent= bot.reply_to(call.message, "This is Button 2")
bot.register_next_step_handler(sent, ButtonTwoFunc)
what will happen here is, whenever the user will click a button, it will clear all next_register_handler that were open
and then enter the new call.data and set the handler which the user clicked on

Python Telegram Bot (Telebot)

I'm building a Telegram bot with the library https://github.com/eternnoir/pyTelegramBotAPI
I'm trying to make when I press a menu button, it sends a message to the user.
How could I do it?
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
TELEGRAM_TOKEN = '<TOKEN>'
bot = telebot.TeleBot(TELEGRAM_TOKEN)
def gen_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton("Yes", callback_data="cb_yes"),
InlineKeyboardButton("No", callback_data="cb_no"))
return markup
#bot.callback_query_handler(func=lambda call: True)
def callback_query(call):
if call.data == "cb_yes":
bot.answer_callback_query(call.id, "Answer is Yes")
elif call.data == "cb_no":
bot.answer_callback_query(call.id, "Answer is No")
#bot.message_handler(func=lambda message: True)
def message_handler(message):
bot.send_message(message.chat.id, "Yes/no?", reply_markup=gen_markup())
bot.polling(none_stop=True)
You can use data of your call object as the user id(call.from_user.id) of the sender to send a message:
if call.data == "cb_yes":
bot.answer_callback_query(call.id, "Answer is Yes")
bot.send_message(call.from_user.id,"Your answer was Yes!")
elif call.data == "cb_no":
bot.answer_callback_query(call.id, "Answer is No")
bot.send_message(call.from_user.id,"Your answer was No!")

Python telebot not working with different users

I'm new in development and python too. I tried to write a simple telegram bot using Telebot. The scenario is to show inline keyboard to user when user click on button do some logic. In Example below I cut the code but it showing the problem. And the problem is:
When first user start working he gets correct and all notifications. But when second user starts to work with bot he gets correct keyboard but notification will send to First user.
Here is a code example:
import telebot
import datetime
bot = telebot.TeleBot(insert_token_here)
keyboard1 = telebot.types.ReplyKeyboardMarkup(True)
keyboard1.row('Choose date', 'dont push it')
#bot.message_handler(commands=['start'])
def start_message(message):
bot.send_message(message.chat.id, 'Welcome', reply_markup=keyboard1)
def dates_inline():
current_date = datetime.datetime.today()
# Inline keyboard
keyboard_dates = telebot.types.InlineKeyboardMarkup()
key_now = telebot.types.InlineKeyboardButton(text=current_date.strftime('%d.%m.%Y') + ' (Today)',
callback_data=current_date.strftime('%Y-%m-%d'))
keyboard_dates.add(key_now)
return keyboard_dates
#bot.message_handler(content_types=['text'])
def choose_message(message):
if message.text == "Choose date":
bot.send_message(message.chat.id, 'Choose date:', reply_markup=dates_inline())
#bot.callback_query_handler(func=lambda call: True)
def choose_date(call):
dt = call.data
print('chose_date dt: %s' % dt)
bot.send_message(message.chat.id, 'All done')
print('end')
else:
print('smth else')
def main():
bot.polling(none_stop=True)
if __name__ == '__main__':
main()
I also faced a similar problem.
Do not create a handler/decorator inside another one. It doesn't work like that. I'm also relatively new to python, so I don't know the exact reason. I also learned it from my mistake.
Do not send messages back to message.chat.id . send it to call.from_user.id so that it'll always send the reply back to the user from whom the call came.
#bot.message_handler(content_types=['text'])
def choose_message(message):
if message.text == "Choose date":
bot.send_message(message.chat.id, 'Choose date:', reply_markup=dates_inline())
else:
print('smth else')
#bot.callback_query_handler(func=lambda call: True)
def choose_date(call):
dt = call.data
print('chose_date dt: %s' % dt)
bot.send_message(call.from_user.id, 'All done')
print('end')
I am also in the development of a bot right now and this is working fine for me.
You need to move following code to top-level indentation. Otherwise it works not as you intended.
#bot.callback_query_handler(func=lambda call: True)
def choose_date(call):
dt = call.data
print('chose_date dt: %s' % dt)
bot.send_message(message.chat.id, 'All done')
#wowkin2 Here is a sample code:
#bot.message_handler(content_types=['text'])
def choose_message(message):
if message.text == "Choose date":
bot.send_message(message.chat.id, 'Choose date:', reply_markup=dates_inline())
print('end')
else:
print('smth else')
#bot.callback_query_handler(func=lambda call: True)
def choose_date(call):
dt = call.data
bot.send_message(message.chat.id, 'All done')

Categories

Resources