Задать вопрос
@IvanSSP

Игнорируются запросы callback от инлайн-кнопок. Как это можно исправить?

Писал код для телеграмм бота. По ТЗ суб. подрядчик может задать вопрос ген. подрядчику (его представителям), а тот (те) на него ответить. Также вшита "защита" от повторных ответов.

Через ChatGPT написал основу этого механизма:

import telebot
import threading
from telebot import types
bot = telebot.TeleBot("тут токен") # токен бота (на данный момент тест)
genpod_id = "genpod_id.txt" # Файл с ID зарегестрированных представителей ген. подрядчика.

# Кнопки
def choise_markup(): 
    markup = types.InlineKeyboardMarkup(row_width=True)
    gen_key = types.InlineKeyboardButton(text="Ген. Подрядчик", callback_data="gen_key_check")
    sub_key = types.InlineKeyboardButton(text="Суб. Подрядчик", callback_data="sub_key_check")
    markup.add(gen_key, sub_key)
    return markup
def sub_func_markup(): 
    markup = types.InlineKeyboardMarkup(row_width=True)
    report_key = types.InlineKeyboardButton(text="Оставить отчет", callback_data="report_key")
    callback_key = types.InlineKeyboardButton(text="Задать вопрос", callback_data="callback_key")
    markup.add(report_key, callback_key)
    return markup
def callback_markup(): 
    markup = types.InlineKeyboardMarkup(row_width=True)
    ask_question_key = types.InlineKeyboardButton(text="Написать вопрос", callback_data="ask_question")
    markup.add(ask_question_key)
    return markup

# Комманды
@bot.message_handler(commands=["start"])
def start(message):
    bot.send_message(message.chat.id, "Добрый день!\nПредставьтесь, пожалуйста:", reply_markup=choise_markup())

# Вывод функционала по выбору
def sub_functional(message):
    bot.delete_message(message.chat.id, message.message_id)
    bot.send_message(message.chat.id, "Что вы хотите сделать?", reply_markup=sub_func_markup())

# Обработка callback и вывод конкретного функционала
@bot.callback_query_handler(func= lambda call: True)
def callback(call):      
    if call.data == "sub_key_check":
        thread = threading.Thread(target=sub_functional, args=(call.message,))
        thread.start()
    if call.data == "callback_key":
        thread = threading.Thread(target=get_callback, args=(call.message,))
        thread.start()
    # if call.data == "ask_question":
    #     thread = threading.Thread(target=write_callback, args=(call.message,))
    #     thread.start()

# Вопросы
def get_callback(message):
    bot.send_message(message.chat.id, "Вы можете задать вопрос Ген. Подрядчику.", reply_markup=callback_markup())

@bot.callback_query_handler(func=lambda call: call.data == 'ask_question')
def write_callback(call):
    chat_id = call.message.chat.id
    bot.send_message(chat_id, "Введите наименование вашей организации:")
    bot.register_next_step_handler_by_chat_id(chat_id, get_company_name)

def get_company_name(message):
    chat_id = message.chat.id
    company_name = message.text
    bot.send_message(chat_id, "Напишите вопрос:")
    bot.register_next_step_handler(message, get_question, company_name)

def get_question(message, company_name):
    chat_id = message.chat.id
    question = message.text
    
    # Сохраним информацию о вопросе для последующего ответа
    if not hasattr(bot, 'questions'):
        bot.questions = {}
    question_id = len(bot.questions) + 1
    bot.questions[question_id] = {'chat_id': chat_id, 'company_name': company_name, 'question': question, 'answered': False}

    with open(genpod_id, 'r') as file:
        genpod_ids = [int(line.strip()) for line in file.readlines()]

    for genpod in genpod_ids:
        markup = types.InlineKeyboardMarkup()
        button_reply = types.InlineKeyboardButton("Ответить", callback_data=f'reply_{question_id}')
        markup.add(button_reply)
        bot.send_message(genpod, f" Новый вопрос от {company_name}.\n{question}", reply_markup=markup)

    bot.send_message(chat_id, "✅ Ваш вопрос принят.")

@bot.callback_query_handler(func=lambda call: call.data.startswith('reply_'))
def reply_to_question(call):
    question_id = int(call.data.split('_')[1])

    question_data = bot.questions.get(question_id)
    if not question_data:
        bot.answer_callback_query(call.id, "⚠️ Вопрос не найден!", show_alert=True)
        return

    if question_data['answered']:
        bot.answer_callback_query(call.id, "⚠️ На этот вопрос уже ответили!", show_alert=True)
        return

    bot.send_message(call.message.chat.id, "Напишите ответ на вопрос:")
    bot.register_next_step_handler_by_chat_id(call.message.chat.id, send_answer, question_id)

def send_answer(message, question_id):
    answer = message.text
    question_data = bot.questions.get(question_id)

    if question_data and not question_data['answered']:
        original_chat_id = question_data['chat_id']
        bot.send_message(original_chat_id, f" Ответ от генерального подрядчика:\n{answer}")
        question_data['answered'] = True
    else:
        bot.send_message(message.chat.id, "⚠️ На этот вопрос уже ответили!")

bot.polling(none_stop=True)


Проблема в том, что при нажатии инлайн-кнопок "Написать вопрос" и "Ответить", от них игнорируется call: call.data == 'ask_question' (и, как потом выяснил, call: call.data.startswith('reply_')). Не понимаю, из-за чего это происходит.

Как это можно исправить?
  • Вопрос задан
  • 30 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
Wispik
@Wispik
потому что все обрабатывает вот это:
@bot.callback_query_handler(func= lambda call: True)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы