Ошибка при попытке нажать на кнопку telegram-bot'а aiogram python

Я разработал бота, имитирующего банковскую систему. Когда пользователь отправляет команду /start, бот отвечает сообщением, к которому прикреплены две кнопки: log in, register. При попытке нажать кнопку бот выводит ошибку:

TypeError: cmd_new_account() got multiple values for argument 'state'
Traceback (most recent call last):
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\dispatcher.py", line 309, in _process_update
    response = await self.feed_update(bot, update, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\dispatcher.py", line 158, in feed_update
    response = await self.update.wrap_outer_middleware(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\middlewares\error.py", line 25, in __call__
    return await handler(event, data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\middlewares\user_context.py", line 56, in __call__
    return await handler(event, data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\fsm\middleware.py", line 42, in __call__
    return await handler(event, data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\event\telegram.py", line 121, in trigger
    return await wrapped_inner(event, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\event\handler.py", line 43, in call
    return await wrapped()
           ^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\dispatcher.py", line 276, in _listen_update
    return await self.propagate_event(update_type=update_type, event=event, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 146, in propagate_event
    return await observer.wrap_outer_middleware(_wrapped, event=event, data=kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 141, in _wrapped
    return await self._propagate_event(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 174, in _propagate_event
    response = await router.propagate_event(update_type=update_type, event=event, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 174, in _propagate_event
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 174, in _propagate_event
    response = await router.propagate_event(update_type=update_type, event=event, **kwargs)
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 174, in _propagate_event
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 174, in _propagate_event
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 174, in _propagate_event
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 174, in _propagate_event
    response = await router.propagate_event(update_type=update_type, event=event, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 146, in propagate_event
    return await observer.wrap_outer_middleware(_wrapped, event=event, data=kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 141, in _wrapped
    return await self._propagate_event(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\router.py", line 166, in _propagate_event
    response = await observer.trigger(event, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\event\telegram.py", line 121, in trigger
    return await wrapped_inner(event, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\информатика\программы на Python\iogram\tg bot on aiogramm 2.0\venv\Lib\site-packages\aiogram\dispatcher\event\handler.py", line 43, in call
    return await wrapped()
                 ^^^^^^^^^
TypeError: cmd_new_account() got multiple values for argument 'state'

Вот мой код:

main

import asyncio
from aiogram import Bot, Dispatcher, F

from app.handlers import router, manager

async def main():
    bot = Bot(token='token')
    dp = Dispatcher() #dispatcher занимается обновлениями, если происходит какое-либо событие оно попадает в него
    dp.include_router(router)
    await dp.start_polling(bot) #bot каждую секунду обращается к серверу телеграм, проверяя произошло ли какое либо обновление(например сообщение)


if __name__ == '__main__': #запуск функции только в том случае, если запущенн именно данный файл. Если данный файл импортирован, то что внутри запускаться не будет
    print('bot_on')
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        manager.connection_close()
        print('bot off')

handlers

from aiogram import Router, F
from aiogram.types import Message, CallbackQuery
from aiogram.filters import CommandStart, Command
from aiogram.filters.state import State, StatesGroup
from aiogram.fsm.context import FSMContext

import app.keyboards as kb
from app.managment_database import*

from app.Bank import *

router = Router()
bank = Bank()

class Form(StatesGroup):
    unknown_user = State()
    get_new_account_password = State()
    create_new_account = State()
    get_account_number = State()
    get_account_password = State()
    account_managment = State()


@router.message(CommandStart())
async def cmd_start(message: Message, state:FSMContext):
    #await state.clear()
    await message.reply('Здравствуйте! Что вы хотите сделать?', reply_markup=kb.catalog_unknown)
    await state.set_state(Form.unknown_user)

@router.callback_query(F.data == 'register', Form.unknown_user)
async def cmd_new_account(state: FSMContext):
    await state.set_state(Form.get_new_account_password)

@router.message(F.text, Form.get_new_account_password)
async def get_new_account_password(message:Message, state:FSMContext):
    await message.answer('Придумайте пароль')
    await state.set_state(Form.create_new_account)

@router.message(F.text, Form.create_new_account)
async def new_account(message:Message, state:FSMContext):
    await state.update_data(password=message.text)
    await message.answer('Создание аккаунта...')

    id = message.from_user.id
    data = await state.get_data()
    answer = bank.new_account(id, data.get('password'))

    await message.answer(answer)
    await state.clear()

    await state.set_state(Form.account_managment)
    await message.answer('Что вы хотите сделать?', reply_markup=kb.catalog_logged)


@router.callback_query(F.data == 'log_in', Form.unknown_user)
async def cmd_log_in(message:Message, state:FSMContext):
    await message.answer('Введите номер аккаунта')
    await state.set_state(Form.get_account_number)

@router.message(F.text, Form.get_account_number)
async def get_account_number(message:Message, state:FSMContext):
    await state.update_data(account_number=message.text)
    await message.answer('Введите пароль')
    await state.set_state(Form.get_account_password)

@router.message(F.text, Form.get_account_password)
async def get_account_password(message:Message, state:FSMContext):
    await state.update_data(account_password=message.text)
    await message.answer('Вход в аккаунт...')

    id = message.from_user.id
    data = await state.get_data()

    answer = bank.log_in_account(id, data['account_number'], data['account_password'])
    await message.answer(answer)
    await state.clear()
    await state.set_state(Form.account_managment)

    await message.answer('Что вы хотите сделать?', reply_markup=kb.catalog_logged)

Bank

from app.Account import *
from app.managment_database import *

manager = Manager()

class Bank:

    def __init__(self):
        #self.accounts_dict = {}
        self.next_account_number = manager.get_account_number()

    def new_account(self, id, user_password):
        print('bank connect')
        new_account_number = self.next_account_number
        manager.add_data(id, new_account_number, user_password, 0)
        self.next_account_number += 1

        return f'You account number: {new_account_number}'
    
    def close_account(self, id, user_account_number, user_password):
        account_password, account_balance = manager.search_user(id, user_account_number)

        if account_password == user_password:
            manager.delete_data(id, user_account_number)
            if account_balance != 0:
                return f'\nYou had {account_balance} in your account, which is being returned to you.\nYour account is now closed'
            return f'Your account is now closed'
        else:
            return f'Error!'
    
    def log_in_account(self, id, user_account_number, user_password):
        account_password, account_balance = manager.search_user(id, user_account_number)

        if account_password == user_password:
            return f'Вы вошли в аккаунт {user_account_number}. На вашем балансе: {account_balance} rub'
        else:
            return f'Error!'

    def deposit(self, id, user_account_number, user_amount):
        account_password, account_balance = manager.search_user(id, user_account_number)
        manager.update_data(id, user_account_number, user_amount + account_balance)

        return f'You balance: {user_amount + account_balance}'
    
    def withdraw(self, id, user_account_number, user_amount):
        account_password, account_balance = manager.search_user(id, user_account_number)
        manager.update_data(id, user_account_number, account_balance - user_amount)

        return f'You balance: {account_balance - user_amount}'
    
    def get_balance(self, id, user_account_number):
        account_password, account_balance = manager.search_user(id, user_account_number)
        
        return f'\nYou balance: {account_balance}\n'

manager_database

import sqlite3

class Manager():
    def __init__(self):
        self.connection = sqlite3.connect('app\Database.bd')
        self.cursor = self.connection.cursor()
        self.cursor.execute('''CREATE TABLE IF NOT EXISTS Users (
                    id INTEGER,
                    account_number INTEGER,
                    password TEXT NOT NULL,
                    balance INTEGER
                    )''')
        
    def connection_close(self):
        self.connection.close()

    def search_user(self, id, account_number):
        self.cursor.execute('SELECT password, balance FROM Users WHERE (id, account_number) = (?, ?)', (id, account_number))
        data = self.cursor.fetchone()
        return data

    def add_data(self, id, account_number, password, balance):
        self.cursor.execute('INSERT INTO Users (id, account_number, password, balance) VALUES (?, ?, ?, ?)', (id, account_number, password, balance))
        self.connection.commit()

    def update_data(self, id, account_number, new_balance):
        #print('database connect')
        self.cursor.execute('UPDATE Users SET new_balance = ? WHERE (id, account_number) = (?, ?)', (new_balance, id, account_number))
        self.connection.commit()

    def delete_data(self, id, account_number):
        self.cursor.execute('DELETE FROM Users WHERE (id, account_number) = (?, ?)', (id, account_number))
        self.connection.commit()

    def get_account_number(self):
        self.cursor.execute('SELECT account_number FROM Users ORDER BY account_number DESC LIMIT 1')
        data = self.cursor.fetchall()
        #print(data)
        if data == []:
            return 0
        else: return data[0][0] + 1

keyboards

from aiogram.types import (ReplyKeyboardMarkup, KeyboardButton, 
                           InlineKeyboardMarkup, InlineKeyboardButton)

catalog_unknown = InlineKeyboardMarkup(inline_keyboard=[
    [InlineKeyboardButton(text='Log in', callback_data='log_in'), InlineKeyboardButton(text='register', callback_data='register')]
])

catalog_logged = InlineKeyboardMarkup(inline_keyboard=[
    [InlineKeyboardButton(text='Get account', callback_data='get_account'), InlineKeyboardButton(text='New account', callback_data='new_account')], 
    [InlineKeyboardButton(text='Close account', callback_data='close_account'), InlineKeyboardButton(text='Deposit', callback_data='deposit')],
    [InlineKeyboardButton(text='Withdraw', callback_data='withdraw'), InlineKeyboardButton(text='Get balance', callback_data='get_balance')],
    [InlineKeyboardButton(text='Show', callback_data='show')]
    ])

Также желаю получить мнение насчет практик, которые я использую. Буду рад, если скажете, как делать не надо, и как делать правильно. Принимаю любые советы по коду и спасибо всем, кто не полениться разобраться в той дичи, которую я понаписал


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