Бот в телеграмме для игры в мафию

Всем общий, такая проблема: После регистрации игроков, бот выдает роли и тут же ломается. То бишь, даже в личку не пишет твою роль Вот код:

import logging


from aiogram import Bot, Dispatcher, types

from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup

from aiogram.dispatcher import FSMContext

from aiogram.utils import executor

import random

from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup




########   #####  ####### ######

########  ##   ## ##      #

##       ##    ## ######  ######

##       ##    ## ##      #    #

##       ##    ## ####### ######


# --- ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ --- #

game_state = False  # True - идет игра, false - пассивная

registration_state = False  # True - регистрация идет, false - пассивная

players = dict()  # Ключ: ID игрока, значение: объект класса Player

quantity = 0

used = []

roles = dict()  # Ключ: роль, значение: ID игрока

mafioso_list = []

reg_message_id = None

game_chat_id = None

last_message_id = dict()  # Ключ: id игрока, значение: последний id сообщения


# --- КОНСТАНТЫ --- #

BOT_TOKEN = "token"

REGISTRATION_TIME = 60  # В секундах

REQUIRED_PLAYERS = 1

LEADERS_INNOCENTS = ['detective']

SPECIAL_INNOCENTS = ['doctor', 'prostitute']

SPECIAL_MAFIOSI = ['godfather']

OTHERS = ['maniac']


# Инициализация бота и диспетчера

bot = Bot(token=BOT_TOKEN)

dp = Dispatcher(bot)


QUANTITY_OF_ROLES = {

    1: '0 0 0 1 0 0', 2: '1 0 0 1 0 0', 3: '1 1 0 1 0 0', 4: '1 1 0 2 0 0', 5: '1 2 0 2 0 0',

    6: '1 3 0 2 0 0', 7: '1 2 1 3 0 0', 8: '1 3 1 2 1 0', 9: '1 3 1 3 1 0', 10: '1 3 1 3 1 1',

    11: '1 5 1 2 1 1', 12: '1 5 2 2 1 1', 13: '1 6 2 2 1 1', 14: '1 6 2 3 1 1', 15: '1 7 2 3 1 1',

    16: '1 7 2 4 1 1'

}

ROLES_PRIORITY = ['prostitute', 'doctor', 'mafioso', 'detective', 'maniac', 'godfather', 'innocent']

ROLE_GREETING = {

    "Detective": '\n'.join(["Ты Детектив Дилан Бернс. Твоя цель - спасти невиновных и уничтожить мафию.",

                            "Твоя специальная способность - проверка карты или убийство кого-то ночью.",

                            "Удачи, детектив, пусть победит справедливость!"]),

    "Doctor": '\n'.join(["Ты Доктор Смолдер Брэвстоун. Твоя цель - спасти невиновных и остаться живым.",

                         "Твоя специальная способность - лечение одного человека ночью.",

                         "Удачи, доктор, пусть победит справедливость!"]),

    "Prostitute": '\n'.join(["Ты проститутка Слоан Джайлс",

                             "Твоя цель - выжить, однако ты помогаешь невиновным.",

                             "Твоя специальная способность - отключить одного игрока на один раунд ночью.",

                             "Удачи, Слоан!"]),

    "Godfather": '\n'.join(["Ты крестный отец Витторе Гуаренте.",

                            "Твоя цель - уничтожить невиновных и помочь мафии.",

                            "Твоя специальная способность - отключить одного игрока в качестве избирателя.",

                            "Удачи, крестный отец, пусть темные силы победят!"]),

    "Maniac": '\n'.join(["Ты маньяк Фрэнк МакСтайн. Твоя цель - убить всех в городе.",

                         "Ты можешь убить одного игрока ночью.",

                         "Удачи, маньяк, пусть победят силы безумия!"]),

    "Innocent": '\n'.join(["Ты Невиновный. Ты создание дня, поэтому ночью ты всегда спишь.",

                           "Твоя цель - уничтожить мафию в своем городе.",

                           "Удачи, невиновный, пусть победит закон!"]),

    "Mafioso": '\n'.join(["Ты мафиози. Твоя специальная способность - убить одного игрока ночью.",

                          "Однако помни, что сотрудничество с другими мафиози для тебя крайне важно.",

                          "Удачи, мафиози, пусть победят темные силы!"])

}


API_TOKEN = "token"

logging.basicConfig(level=logging.INFO)

bot = Bot(token=API_TOKEN)

dp = Dispatcher(bot)



class Player:

    def __init__(self, user):

        self.ID = user.id

        self.name = user.first_name + (' ' + user.last_name if user.last_name else '')

        self.nick = user.username

        self.card = None

        self.is_alive = True

        self.is_abilities_active = True

        self.can_be_killed = True

        self.able_to_vote = True

        self.able_to_discuss = True

        self.chat_id = None



def distribute_roles():

    global roles

    global players

    global QUANTITY_OF_ROLES

    global LEADERS_INNOCENTS

    global SPECIAL_MAFIOSI

    global SPECIAL_INNOCENTS

    global OTHERS

    global quantity

    global mafioso_list


    print('Раздача ролей...')


    roles_q = list(map(int, QUANTITY_OF_ROLES[quantity].split(' ')))


    leaders_innocents = random.sample(LEADERS_INNOCENTS, roles_q[0])

    special_innocents = random.sample(SPECIAL_INNOCENTS, roles_q[2])

    special_mafiosi = random.sample(SPECIAL_MAFIOSI, roles_q[4])

    others = random.sample(OTHERS, roles_q[5])


    rand_players = [i.ID for i in players.values()]

    random.shuffle(rand_players)


    ind = 0

    for i in range(len(leaders_innocents)):

        players[rand_players[ind]].card = leaders_innocents[i].capitalize()

        roles[leaders_innocents[i].capitalize()] = rand_players[ind]

        ind += 1


    for i in range(len(special_innocents)):

        players[rand_players[ind]].card = special_innocents[i].capitalize()

        roles[special_innocents[i].capitalize()] = rand_players[ind]

        ind += 1


    for i in range(len(special_mafiosi)):

        players[rand_players[ind]].card = special_mafiosi[i].capitalize()

        roles[special_mafiosi[i].capitalize()] = rand_players[ind]

        ind += 1


    for i in range(len(others)):

        players[rand_players[ind]].card = others[i].capitalize()

        roles[others[i].capitalize()] = rand_players[ind]

        ind += 1


    roles['Innocent'] = []

    for i in range(roles_q[1]):

        players[rand_players[ind]].card = 'Innocent'

        roles['Innocent'].append(rand_players[ind])

        ind += 1


    roles['Mafioso'] = []

    for i in range(roles_q[3]):

        players[rand_players[ind]].card = 'Mafioso'

        roles['Mafioso'].append(rand_players[ind])

        mafioso_list.append(

            '[' + players[rand_players[ind]].name + ']' + '(tg://user?id=' + str(rand_players[ind]) + ')')

        ind += 1


        print('Раздача ролей завершена:')

        for key, value in roles.items():

            if key == 'Mafioso':

                print('Мафиози: {}'.format(', '.join([players[i].name for i in value])))

            elif key == 'Innocent':

                print('Невиновные: {}'.format(', '.join([players[i].name for i in value])))

            else:

                print(key + ': ' + players[value].name)


    # Эти условия для отладки, так как ситуация без мафии/невиновных противоречит правилам

    if not roles['Mafioso']:

        del roles['Mafioso']


    if not roles['Innocent']:

        del roles['Innocent']



def send_roles(bot):

    global roles

    global mafioso_list

    global players

    global ROLE_GREETING

    global last_message_id


    print('Отправка ролей...')


    for role, player in roles.items():

        if role == 'Mafioso':

            for pl in player:

                bot.send_message(chat_id=pl, text=ROLE_GREETING[role])

                if len(mafioso_list) > 1:

                    bot.send_message(chat_id=pl, text='Другие мафиози: \n{}'.format(

                        '\n'.join(i for i in mafioso_list if not (str(pl) in i))),

                                     parse_mode='Markdown')

                last_message_id[pl] += 1

        elif role == 'Innocent':

            for pl in player:

                bot.send_message(chat_id=pl, text=ROLE_GREETING[role])

                last_message_id[pl] += 1

        else:

            bot.send_message(chat_id=player, text=ROLE_GREETING[role])

            last_message_id[player] += 1


    print('Роли успешно отправлены')



# Функции ролей

# ВАЖНО: названия функций такие же, как и роли, в нижнем регистре

def detective(bot):

    global roles

    global players


    print('Детектив проснулся')


    check_or_shoot = InlineKeyboardMarkup(

        [[InlineKeyboardButton('Выстрел', callback_data='detective_shoot'),

          InlineKeyboardButton('Проверить личность', callback_data='detective_check')]])


    bot.send_message(chat_id=roles['Detective'], text='Ты чувствуешь себя миролюбивым сегодня?',

                     reply_markup=check_or_shoot)

    last_message_id[roles['Detective']] += 1



def mafioso(bot):

    global roles

    global players

    global mafioso_list


    print('Мафиози проснулись')


    shoot_voting = []

    for role, _id in roles.items():

        if role == 'Innocent':

            for inn in _id:

                shoot_voting.append([InlineKeyboardButton(players[inn].name, callback_data='maf_kill:{}'.format(inn))])

        elif role != 'Mafioso':

            shoot_voting.append([InlineKeyboardButton(players[_id].name, callback_data='maf_kill:{}'.format(_id))])


    for i in roles['Mafioso']:

        bot.send_message(chat_id=i, text='Выберите цель внимательно',

                         reply_markup=InlineKeyboardMarkup(shoot_voting))

        last_message_id[i] += 1



def innocent():

    print('Невиновные все еще спят!')



# Основной код

def game(bot, chat_id):

    global game_state

    global players

    global roles

    global ROLES_PRIORITY


    game_state = True

    print('Игра началась')

    bot.send_message(chat_id=chat_id, text='Игра началась. Пусть победит сильнейший.')


    distribute_roles()

    send_roles(bot)


    ordered_roles = sorted(roles.keys(),

                           key=lambda x: ROLES_PRIORITY.index(x.lower()))


    for i in ordered_roles:

        exec(i.lower() + '(bot)')  # Функции для каждой роли названы так же, как и сами роли



# На команду '/game'

async def registration_command(message: types.Message, state: FSMContext):

  global game_state

  global quantity

  global registration_state

  global players

  global reg_message_id

  global game_chat_id


  if not (game_state or registration_state):

      await message.answer('И пусть удача всегда будет с вами')

      registration_state = True


      keyboard = [[InlineKeyboardButton('?‍♂️Присоединиться', url="https://t.me/bss_maf_bot?start=Register")]]

      markup = InlineKeyboardMarkup(inline_keyboard=keyboard)


      reg_message_id = message.message_id + 2

      game_chat_id = message.chat.id

      await message.answer('? *Регистрация активна!* ?', parse_mode="Markdown", reply_markup=markup)


      await dp.bot.pin_chat_message(chat_id=message.chat.id, message_id=reg_message_id, disable_notification=True)

  else:

      await message.answer('Игра уже идет')



# На команду '/stop'

async def stop_command(message: types.Message, state: FSMContext):

    global game_state

    global registration_state

    global quantity

    global players

    global mafioso_list

    global roles

    global reg_message_id


    if game_state or registration_state:

        await message.answer('¡Sí, señor!')


        if registration_state:

            await dp.bot.delete_message(chat_id=message.chat.id, message_id=reg_message_id)

            await dp.bot.delete_message(chat_id=message.chat.id, message_id=reg_message_id - 1)


        game_state = False

        registration_state = False


        quantity = 0

        players.clear()

        roles.clear()

        used.clear()

        mafioso_list.clear()


        await message.answer('Игра успешно отменена.')

    else:

        await message.answer('Нет активной игры для отмены :(')



# На команду '/start'

async def reg_player_command(message: types.Message, state: FSMContext):

    global registration_state

    global quantity

    global reg_message_id

    global game_chat_id

    global last_message_id


    if registration_state:

        new_user = Player(message.from_user)


        if new_user.ID in used:

            await message.answer('Вы уже зарегистрированы. Пожалуйста, подождите других игроков :)')

            return


        players[new_user.ID] = new_user

        quantity += 1


        print(f'Игрок {quantity}: {new_user.name}, {new_user.ID}')


        last_message_id[new_user.ID] = message.message_id

        used.append(new_user.ID)


        keyboard = [[InlineKeyboardButton('?‍♂️Присоединиться', url="https://t.me/bss_maf_bot?start=Register")]]

        markup = InlineKeyboardMarkup(inline_keyboard=keyboard)


        await dp.bot.edit_message_text(chat_id=game_chat_id, message_id=reg_message_id,

                                       text=f'Регистрация активна!\n\n*Зарегистрированные игроки:* \n'

                                            f'{", ".join([f"[{i.name}](tg://user?id={i.ID})" for _, i in players.items()])}\n\n'

                                            f'Итого: *{quantity}*',

                                       parse_mode="Markdown", reply_markup=markup)

    else:

        await message.answer('Регистрация сейчас не активна. Пожалуйста, используйте "/game", чтобы начать регистрацию.')

    

# На команду '/begin_game'

async def begin_game_command(message: types.Message, state: FSMContext):

    global quantity

    global registration_state

    global game_state

    global REQUIRED_PLAYERS

    global reg_message_id


    if game_state:

        await message.answer('Игра уже идет!')

        return


    if registration_state:

        if quantity >= REQUIRED_PLAYERS:

            await message.answer('Регистрация успешно завершена! Игра начинается...')

            registration_state = False


            await dp.bot.delete_message(chat_id=message.chat.id, message_id=reg_message_id)

            await dp.bot.delete_message(chat_id=message.chat.id, message_id=reg_message_id - 1)


            await game(dp.bot, message.chat.id)

        else:

            await message.answer('\n'.join(['Слишком мало игроков :(',

                                             f'Текущее количество игроков: {quantity}',

                                             f'Необходимое количество игроков: {REQUIRED_PLAYERS}.']))

    else:

        await message.answer('Пожалуйста, используйте "/game", чтобы начать регистрацию.')





dp.register_message_handler(registration_command, commands=['game'])



dp.register_message_handler(stop_command, commands=['stop'])



dp.register_message_handler(reg_player_command, commands=['start'])



dp.register_message_handler(begin_game_command, commands=['begin_game'])



if __name__ == '__main__':

    executor.start_polling(dp, skip_updates=True)

Код ошибок:

Игрок 1: Ник1, 123
Игрок 2: Ник2, 1234
Игрок 3: Ник3, 12345
Игра началась
Раздача ролей...
Раздача ролей завершена:
Detective: Ник1
Невиновные: Ник2
Мафиози: Ник3
Отправка ролей...
c:\Users\s1ryz\Desktop\bss_mafia_bot\maf2.py:357: RuntimeWarning: coroutine 'Bot.send_message' was never awaited
  bot.send_message(chat_id=player, text=ROLE_GREETING[role])
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
c:\Users\s1ryz\Desktop\bss_mafia_bot\maf2.py:351: RuntimeWarning: coroutine 'Bot.send_message' was never awaited
  bot.send_message(chat_id=pl, text=ROLE_GREETING[role])
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Роли успешно отправлены
Мафиози проснулись
Детектив проснулся
c:\Users\s1ryz\Desktop\bss_mafia_bot\maf2.py:387: RuntimeWarning: coroutine 'Bot.send_message' was never awaited
  bot.send_message(chat_id=roles['Detective'], text='Ты чувствуешь себя миролюбивым сегодня?',
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-99' coro=<Dispatcher._process_polling_updates() done, defined at C:\Users\s1ryz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\aiogram\dispatcher\dispatcher.py:407> exception=TypeError('innocent() takes 0 positional arguments but 1 was given')>
Traceback (most recent call last):
  File "C:\Users\s1ryz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\aiogram\dispatcher\dispatcher.py", line 415, in _process_polling_updates      
    for responses in itertools.chain.from_iterable(await self.process_updates(updates, fast)):
  File "C:\Users\s1ryz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\aiogram\dispatcher\dispatcher.py", line 235, in process_updates
    return await asyncio.gather(*tasks)
  File "C:\Users\s1ryz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\aiogram\dispatcher\handler.py", line 117, in notify
    response = await handler_obj.handler(*args, **partial_data)
  File "C:\Users\s1ryz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\aiogram\dispatcher\dispatcher.py", line 256, in process_update
    return await self.message_handlers.notify(update.message)
  File "C:\Users\s1ryz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\aiogram\dispatcher\handler.py", line 117, in notify
    response = await handler_obj.handler(*args, **partial_data)
  File "c:\Users\s1ryz\Desktop\bss_mafia_bot\maf2.py", line 670, in begin_game_command
    await game(dp.bot, message.chat.id)
  File "c:\Users\s1ryz\Desktop\bss_mafia_bot\maf2.py", line 470, in game
    exec(i.lower() + '(bot)')  # Функции для каждой роли названы так же, как и сами роли
  File "<string>", line 1, in <module>
TypeError: innocent() takes 0 positional arguments but 1 was given

Ответы (0 шт):