Динамические кнопки pytelegrambot
Я самоучка-новичок, сильно не бейте за кривой код :). Бьюсь уже 3ий день с проблемой. Хочу сделать динамические кнопки, что при нажатии на продукт, его кнопка моментально менялась(при call.data == edit_product) или моментально удалялась (при call.data == delete_product). При моей реализации клавиши удаляются или меняются только при выходе из меню по кнопке "назад" либо если отправить /show (т.е.показать список).
@bot.message_handler(commands=['show'])
def show_products(message):
if list_of_products:
keyboard = types.InlineKeyboardMarkup(row_width=2)
btn1 = types.InlineKeyboardButton(text='Редактировать ✏', callback_data='done')
btn2 = types.InlineKeyboardButton(text='Удалить ?', callback_data='delete')
keyboard.add(btn1, btn2)
bot.send_message(message.chat.id, ('Список покупок:\n' + line_print(list_of_products)), reply_markup=keyboard)
else:
bot.send_message(message.chat.id, "Список пуст")
@bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
if call.message:
if call.data == 'delete':
keyboard = types.InlineKeyboardMarkup(row_width=2)
btns = []
for product in list_of_products:
btn = types.InlineKeyboardButton(text=f'{product}', callback_data=f'delete_product {product}')
btns.append(btn)
btn1 = types.InlineKeyboardButton(text='Назад', callback_data='back')
btn2 = types.InlineKeyboardButton(text='Редактировать ✏', callback_data='edit')
keyboard.add(*btns)
keyboard.add(btn1, btn2)
bot.edit_message_text('Какой продукт хотите удалить?', call.message.chat.id, call.message.message_id,
reply_markup=keyboard)
elif call.data == 'edit':
keyboard = types.InlineKeyboardMarkup(row_width=2)
btns = []
for product in list_of_products:
if '\u0336' in product:
btn = types.InlineKeyboardButton(text=f'✖ {product}', callback_data=f'delete_product {product}')
else:
btn = types.InlineKeyboardButton(text=f'{product}', callback_data=f'edit_product {product}')
btns.append(btn)
btn1 = types.InlineKeyboardButton(text='Назад', callback_data='back')
btn2 = types.InlineKeyboardButton(text='Удалить ?', callback_data='delete')
keyboard.add(*btns)
keyboard.add(btn1, btn2)
bot.edit_message_text('Какой продукт хотите вычеркнуть?', call.message.chat.id, call.message.message_id,
reply_markup=keyboard)
elif call.data == 'back':
if list_of_products:
keyboard = types.InlineKeyboardMarkup(row_width=2)
btn1 = types.InlineKeyboardButton(text='Редактировать ✏', callback_data='edit')
btn2 = types.InlineKeyboardButton(text='Удалить ?', callback_data='delete')
keyboard.add(btn1, btn2)
bot.edit_message_text(line_print(list_of_products), call.message.chat.id, call.message.message_id,
reply_markup=keyboard)
else:
bot.send_message(call.message.chat.id, "Список пуст")
elif 'delete_product' in call.data:
if list_of_products:
product = call.data.split()[1]
list_of_products.remove(product)
# show alert
bot.answer_callback_query(callback_query_id=call.id, show_alert=False, text='Удалено')
print(list_of_products)
else:
bot.send_message(call.message.chat.id, "Список пуст")
elif 'edit_product' in call.data:
product = call.data.split()[1]
if '\u0336' in product:
uncross_product(product, list_of_products)
# show alert
bot.answer_callback_query(callback_query_id=call.id, show_alert=False, text='Отменил отметку')
else:
cross_product(product, list_of_products)
# show alert
bot.answer_callback_query(callback_query_id=call.id, show_alert=False, text='Отметил, что купил')
elif call.data == 'yes':
bot.edit_message_text(chat_id=call.message.chat.id, text='Список удален',
message_id=call.message.message_id,
reply_markup=None)
list_of_products.clear()
elif call.data == 'no':
bot.edit_message_text(chat_id=call.message.chat.id, text='А, ну хорошо...',
message_id=call.message.message_id,
reply_markup=None)
show_products(call.message)
def line_print(grocery_list):
new_line = ''
for i, item in enumerate(grocery_list):
new_line += (str(i + 1) + ') ' + item + '\n')
return new_line
def cross_product(product, grocery_list):
cross_product = ('\u0336'.join(product) + '\u0336')
for i in range(len(grocery_list)):
if grocery_list[i] == product:
grocery_list[i] = cross_product
def uncross_product(cross_product, grocery_list):
for i in range(len(grocery_list)):
if grocery_list[i] == cross_product:
grocery_list[i] = cross_product.replace('\u0336', '')
Ответы (2 шт):
def select_list():
kb = InlineKeyboardMarkup()
kb.row_width = 2
kb.add(InlineKeyboardButton(text='Симферополь', callback_data='simferopol'),
InlineKeyboardButton(text='Ялта', callback_data='yalta'))
return kb
@bot.callback_query_handler(func=lambda call: True)
def inline_kb(call):
if call.data == 'yalta':
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Выберите место', reply_markup=kb_yalta())
Таким образом, при нажатии на кнопку "Ялта" сообщение будет изменено на "Выберите место" с добавлением клавиатуры kb_yalta()
Спасибо всем, кто откликнулся на мой вопрос. Решил проблему топорным методом: после удаления, либо корректировки надписи на кнопке (вычеркивание из списка) формирую и вывожу новую клавиатуру. Извиняюсь за гигантизм кода, пока руки не дошли до рефакторинга.
elif 'delete_product' in call.data:
if list_of_products:
product = call.data.split()[1]
list_of_products.remove(product)
# show alert
bot.answer_callback_query(callback_query_id=call.id, show_alert=False, text='Удалено')
print(list_of_products)
else:
bot.send_message(call.message.chat.id, "Список пуст")
keyboard = types.InlineKeyboardMarkup(row_width=2)
products = []
for product in list_of_products:
if '\u0336' in product:
btn = types.InlineKeyboardButton(text=f'✖ {product}', callback_data=f'delete_product {product}')
else:
btn = types.InlineKeyboardButton(text=f'{product}', callback_data=f'delete_product {product}')
products.append(btn)
btn1 = types.InlineKeyboardButton(text='Назад', callback_data='back')
btn2 = types.InlineKeyboardButton(text='Редактировать ✏', callback_data='edit')
keyboard.add(*products)
keyboard.add(btn1, btn2)
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=keyboard)
elif 'edit_product' in call.data:
product = call.data.split()[1]
if '\u0336' in product:
uncross_product(product, list_of_products)
# show alert
bot.answer_callback_query(callback_query_id=call.id, show_alert=False, text='Отменил отметку')
else:
cross_product(product, list_of_products)
# show alert
bot.answer_callback_query(callback_query_id=call.id, show_alert=False, text='Отметил, что купил')
keyboard = types.InlineKeyboardMarkup(row_width=2)
products = []
for product in list_of_products:
if '\u0336' in product:
btn = types.InlineKeyboardButton(text=f'✖ {product}', callback_data=f'edit_product {product}')
else:
btn = types.InlineKeyboardButton(text=f'{product}', callback_data=f'edit_product {product}')
products.append(btn)
btn1 = types.InlineKeyboardButton(text='Назад', callback_data='back')
btn2 = types.InlineKeyboardButton(text='Удалить ?', callback_data='delete')
keyboard.add(*products)
keyboard.add(btn1, btn2)
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=keyboard)