Пишу бота на Python на aiogram 3. Появилась ошибка. С чем она может быть связана?

Рейтинг: -1Ответов: 1Опубликовано: 16.04.2023

Пытаюсь прописать в модуле user.py регистрацию с подтверждением от руководителя. Появляется ошибка

TypeError: Bot.send_message() missing 1 required positional argument: 'self'

С чем она может быть связана?

from aiogram import Router, F
from aiogram.filters import Command, CommandStart, Text, StateFilter
from aiogram.types import (CallbackQuery, InlineKeyboardButton,
                           InlineKeyboardMarkup, Message, PhotoSize)
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import default_state
from keyboards.keyboards import game_kb, yes_no_kb
from lexicon.lexicon_ru import LEXICON_RU
from services.services import get_bot_choice, get_winner
from database.database import cur, conn
from FSM import FSMFillForm
from main import Bot as bt

router: Router = Router()
user = []
HEADID = '6159544161'


# Этот хэндлер срабатывает на команду /start
@router.message(CommandStart())
async def process_start_command(message: Message):
    await message.answer(text=LEXICON_RU['/start'], reply_markup=yes_no_kb)


# Этот хэндлер срабатывает на команду /help
@router.message(Command(commands=['help']))
async def process_help_command(message: Message):
    await message.answer(text=LEXICON_RU['/help'], reply_markup=yes_no_kb)


# Этот хэндлер срабатывает на согласие пользователя играть в игру
@router.message(Text(text=LEXICON_RU['user_button']))
async def process_yes_answer(message: Message):
    await message.answer(text=LEXICON_RU['yes'])
    base = cur.fetchall()
    base = [i[0] for i in base]
    if message.from_user.id not in base:
        await message.answer(text=LEXICON_RU['reg1'])


@router.message(Command(commands='registration'), StateFilter(default_state))
async def process_fillform_command(message: Message, state: FSMContext):
    await message.answer(text='Пожалуйста, введите ваше ФИО:')
    # Устанавливаем состояние ожидания ввода ФИО
    await state.set_state(FSMFillForm.fill_name)


# Этот хэндлер будет срабатывать, если введено корректное имя
# и переводить в состояние ожидания ввода возраста
@router.message(StateFilter(FSMFillForm.fill_name), F.text)
async def process_name_sent(message: Message, state: FSMContext):
    # Cохраняем введенное имя в хранилище по ключу "name"
    user.append(message.from_user.id)
    user.append(message.text)
    await message.answer(text='Спасибо!\n\nА теперь введите номер вашей группы:')
    # Устанавливаем состояние ожидания ввода номера группы
    await state.set_state(FSMFillForm.fill_group)


# Этот хэндлер будет срабатывать, если во время ввода имени
# будет введено что-то некорректное
@router.message(StateFilter(FSMFillForm.fill_name))
async def warning_not_name(message: Message):
    await message.answer(text='То, что вы отправили не похоже на ФИО\n\n'
                              'Пожалуйста, введите ваше ФИО:')


# Этот хэндлер будет срабатывать, если введена корректная группа
# и переводить в состояние проверки статуса
@router.message(StateFilter(FSMFillForm.fill_group),
            lambda x: x.text.split('/')[0].isdigit() and x.text.split('/')[1].isdigit())
async def process_age_sent(message: Message, state: FSMContext):
    # Cохраняем группу в хранилище
    user.append(message.text)
    # Отправляем пользователю сообщение с клавиатурой
    await message.answer(text='Спасибо!\n\nТеперь мы отправим сообщение руководителю, чтобы подтвердить, что вы Адаптер!')
    print(user)
    await bt.send_message(chat_id=HEADID, text=f"Пользователь {user[1]} из группы {user[2]} запрашивает регистрацию." \
                             f"Подтвердить регистрацию: /approve_{message.from_user.id}" \
                             f"Отказать в регистрации: /approve_000")
    # Устанавливаем состояние ожидания подтверждения регистрации
    await state.set_state(FSMFillForm.wait_for_status)

# Этот хэндлер будет срабатывать, если во время ввода номера группы
# будет введено что-то некорректное
@router.message(StateFilter(FSMFillForm.fill_group))
async def warning_not_age(message: Message):
    await message.answer(
        text='Вы неправильно ввели группу!\n\n'
             'Попробуйте еще раз')


@router.message(Command(commands=['approve']), StateFilter(FSMFillForm.wait_for_status))
async def approve_registration(message: Message, state: FSMContext):
    # Получаем ID пользователя из команды /approve_{user_id}
    user_id = int(message.text.split('_')[1])
    if user_id != message.from_user.id and user_id != '000':
        await message.answer("Ошибка: неверный ID пользователя.")
        return
    if user_id == '000':
        await message.answer("Отказ подтвержден.")
        user.append(False)
    user.append(True)
    # Отправляем сообщение пользователю о подтверждении регистрации
    await bt.send_message(chat_id=message.from_user.id, text="Ваша регистрация была подтверждена!", reply_markup=game_kb)
    cur.execute("INSERT INTO users VALUES(?, ?, ?, ?);", tuple(user))
    conn.commit()
    await state.clear()


# Этот хэндлер срабатывает на любую из кнопок меню
@router.message(Text(text=[LEXICON_RU['Abstract'],
                           LEXICON_RU['Manual'],
                           LEXICON_RU['HW']]))
async def process_game_button(message: Message):
    bot_choice = get_bot_choice()
    await message.answer(text=f'{LEXICON_RU["bot_choice"]} '
                              f'- {LEXICON_RU[bot_choice]}')
    winner = get_winner(message.text, bot_choice)
    await message.answer(text=LEXICON_RU[winner], reply_markup=yes_no_kb)

Помимо этого в проекте используется библиотека sqlite3 для базы данных, есть отдельные модули для клавиатуры, запуска бота, конфига, режима руководителя и текста

Уже пыталась по разному вызывать бота и прочитала всю документацию для aiogram 3

Ответы

▲ 2

Сама ошибка missing 1 required positional argument: 'self' появляется в тех случаях когда к методу класса обращаются извне (не из метода класса), так как в классах при выборе сестринских методов вызов идет через self.метод() и таким образом Python организует передачу self, нам не приходится его передавать вручную типа такого self.метод(self). Но из внешней функции передать self просто не возможно он не известен снаружи, если об этом не побеспокоится, и не передать его туда каким-то методом.

Пример:

class MissingSelfError:
  def run(self):
    print('без self будет ошибка')

m = MissingSelfError
m.run()

Traceback (most recent call last): File "/home/daniil/Desktop/err.py", line 8, in m.run() TypeError: MissingSelfError.run() missing 1 required positional argument: 'self'

Теперь что касается aiogram на сайте документации говориться что в 3-ей версии произошли breaking changes т.е. изменения влекущие невозможность полной обратной совместимости.

Danger Breaking News: aiogram 3.0 has breaking changes. It breaks backward compatibility by introducing new breaking changes!

Поэтому раз Вы пишете появилась, то возможно именно с этим она и связана.

Кода в вопросе Вы разместили много, возможно больше чем нужно, а вот главного там нет. Вы импортируете бота из main.py однако не ясно как он там создается, на той же странице с предупреждением есть небольшой пример с созданием бота.

Убедитесь что у Вас в файле main создание происходит таким же или подобным способом:

async def main() -> None:
    # Dispatcher is a root router
    dp = Dispatcher()
    # ... and all other routers should be attached to Dispatcher
    dp.include_router(router)

    # Initialize Bot instance with a default parse mode which will be passed to all API calls
    bot = Bot(TOKEN, parse_mode="HTML")
    # And the run events dispatching
    await dp.start_polling(bot)


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(main())

Надеюсь, это поможет решить Вашу проблему.