Не знаю, как обрабатывать несколько обратных вызовов в pyTelegramBotApi - PullRequest
0 голосов
/ 09 апреля 2020

Я с нетерпением жду создания какого-нибудь телеграммного шахматного бота. Так что он основан на встроенной клавиатуре. Пользователь должен нажать на ilnlineButton, чтобы выбрать шахматного игрока, а затем нажать кнопку, куда поставить шахматного игрока. Я не знаю, как выбрать свободную ячейку на «доске» в inlineKeyboard после выбора пешки, только пока. Я пытался сделать bot.register_next_step_handler, но он не дает того, что я ожидал.

@bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
    try:
        if call.message:
            if call.data == "suck":
                bot.send_message(call.message.chat.id, "Just wait a bit, OK?")
            elif call.data == "frick":
                bot.send_message(call.message.chat.id, "No, frick you")
            elif call.data == "sad":
                bot.send_message(call.message.chat.id, "Well, shit happens")
            elif call.data == "good":
                bot.send_message(call.message.chat.id, "I am soulless robot. How do      you think I can feel?")
            elif call.data.partition('pawn')[1] == "pawn":
                bot.register_next_step_handler(call.data, process_move_step)

else:
                bot.send_message(call.message.chat.id, call.data)
                bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=
                                                                                                      "some_text",reply_markup=None)

    except Exception as e:
        print(repr(e))


def process_move_step(call):
    try:
        if call.message:
            if call.data.partition('empty')[1] == "empty":
                next_move = new_board.get_chessman(call.data)
                new_board.move(call, next_move.X, next_move.Y)
                bot.send_message(call.message.chat.id, "Moved to "+str(next_move.X+str(next_move.Y)))
                print(new_board)

    except Exception as e:
        print(repr(e))

, поэтому я надеялся, что процесс переходит к process_move_step и ждет нового обратного вызова и проверяет его там, но после получения обратного вызова pawn и затем, получив «пустой» обратный вызов, я получил результат из else: part вместо того, чтобы получить его, если

if call.data.partition('empty')[1] == "empty":

Итак, как я могу получить «пешечную» ячейку, затем «пустую» ячейку из обратных вызовов и затем завершить функции. Для «пустых» стоит объект EmptyCell и он имеет атрибуты X и Y, поэтому я могу переместить пешку в точное место в Board obj и редактировать встроенную клавиатуру. Я видел нечто подобное в @TrueMafiaBot. Когда сотрудника полиции спрашивают, хочет ли он кого-нибудь проверить или застрелить, он выбирает игрока для выполнения выбранного действия.

Ответы [ 2 ]

1 голос
/ 11 апреля 2020

Это не работает, как вы ожидали. Каждый запрос всегда передается вашей основной функции (callback_inline). Поэтому, если вы попытаетесь поймать следующий шаг после выбора пешки, вам следует сохранить текущий статус пользователя. Если пользователь выбирает пешку, его статус устанавливается is_pawn_selected = true. После этого вы можете добавить некоторые логи c для обработки этого статуса. В вашем случае это должно быть примерно так:

 if (users.get(user_ID).is_pawn_selected) { 
    user.is_pawn_selected = false
    process_move_step 
}
0 голосов
/ 12 апреля 2020

Самый простой способ - удерживать некоторое состояние при запуске бота и выполнять if-else проверку ответа на запрос обратного вызова. Например, вы можете сделать что-то вроде:

from enum import Enum
from dataclasses import dataclass


class Color(Enum):
    WHITE = 0
    BLACK = 1


@dataclass
class GameState:
    chat_id: int
    turn: Color
    holding_chessman: Chessman
    # ...another useful data for game flow


# data is your callback data received from users
# gamestate is local instanse of GameState on server (or database)

# inside callback answer handling:
if gamestate.turn != data.user.color:
    return error('Not your turn, hold on!')
if gamestate.holding_chessman is None:
    gamestate.holding_chessman = data.pressed_figure
    return info('Now press a button where to move a chessman.')
else:
    perform_chessman_move()
    switch_turn()
    return info('You moved a chessman, now another user must turn')

...