Files
ai-char-bot/routers/char_router.py
2026-02-04 15:10:55 +03:00

156 lines
6.3 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import io
import logging
import traceback
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import *
from aiogram import Router, F, Bot
from models.Asset import Asset, AssetType
from models.Character import Character
from repos.dao import DAO
router = Router()
class States(StatesGroup):
char_wait_name = State()
char_wait_bio = State()
@router.message(F.document, Command("add_char"))
async def add_char(message: Message, state: FSMContext, dao: DAO):
if not message.document.mime_type.startswith("image/"):
await message.answer("❌ Пожалуйста, отправьте файл изображения (png/jpg).")
return
await state.set_data({"photo": message.document.file_id})
await state.set_state(States.char_wait_name)
await message.answer("Кайф, теперь напиши ее имя")
@router.message(States.char_wait_name)
async def new_char_name(message: Message, state: FSMContext, dao: DAO):
data = await state.get_data()
data["name"] = message.text
await state.set_data(data)
await state.set_state(States.char_wait_bio)
await message.answer("А теперь напиши био. Хоть чуть чуть.")
# 3. Хендлер био (Финал)
@router.message(States.char_wait_bio, F.text)
async def new_char_bio(message: Message, state: FSMContext, dao: DAO, bot: Bot):
# Получаем все накопленные данные
data = await state.get_data()
file_id = data["photo"]
name = data["name"]
bio = message.text
wait_msg = await message.answer("💾 Сохраняю персонажа...")
try:
# ВОТ ТУТ скачиваем файл (прямо перед сохранением)
file_io = await bot.download(file_id)
# photo_bytes = file_io.getvalue() # Получаем байты
# Создаем модель
char = Character(
id=None,
name=name,
character_image_data=file_io.read(),
character_image_tg_id=None,
character_image_doc_tg_id=file_id,
character_bio=bio
)
file_io.close()
# Сохраняем через DAO
await dao.chars.add_character(char)
file_info = await bot.get_file(char.character_image_doc_tg_id)
file_bytes = await bot.download_file(file_info.file_path)
file_io = file_bytes.read()
avatar_asset = await dao.assets.create_asset(
Asset(name="avatar.png", type=AssetType.IMAGE, linked_char_id=str(char.id), data=file_io,
tg_doc_file_id=file_id))
char.avatar_image = avatar_asset.link
# Отправляем подтверждение
# Используем байты для отправки обратно
photo_msg = await message.answer_photo(
photo=BufferedInputFile(file_io,
filename="char.jpg") if not char.character_image_tg_id else char.character_image_tg_id,
caption=(
"🎉 <b>Персонаж создан!</b>\n\n"
f"👤 <b>Имя:</b> {char.name}\n"
f"📝 <b>Био:</b> {char.character_bio}"
)
)
file_bytes.close()
char.character_image_tg_id = photo_msg.photo[0].file_id
await dao.chars.update_char(char.id, char)
await wait_msg.delete()
# Сбрасываем состояние
await state.clear()
except Exception as e:
logging.error(e)
await wait_msg.edit_text(f"❌ Ошибка при сохранении: {e}")
# Не сбрасываем стейт, даем возможность попробовать ввести био снова или начать заново
@router.message(Command("chars"))
async def get_chars(message: Message, state: FSMContext, dao: DAO):
wait_msg = await message.answer("Ищем персонажей")
chars = await dao.chars.get_all_characters()
keyboards = []
if len(chars) > 0:
for char in chars:
keyboards.append(InlineKeyboardButton(text=char.name, callback_data=f'char_info_{char.id}'))
keyboard = InlineKeyboardMarkup(inline_keyboard=[keyboards])
else:
keyboard = InlineKeyboardMarkup(
inline_keyboard=[[InlineKeyboardButton(text="Персонажей нет", callback_data=f'no_chars')]])
await message.answer("Сейчас есть такие персонажи:", reply_markup=keyboard)
await wait_msg.delete()
@router.callback_query(F.data.startswith("char_info_"))
async def get_char_info(callback_query: CallbackQuery, state: FSMContext, dao: DAO, bot: Bot):
await callback_query.message.delete()
wait_msg = await callback_query.message.answer("Ищем инфу о персонаже")
char = await dao.chars.get_character(callback_query.data.split("_")[-1])
if char is None:
await callback_query.message.answer("Информация о персонаже не найдена")
await get_chars(callback_query.message, state, dao)
await wait_msg.delete()
return
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Запросить фото в документе", callback_data=f'char_photo_file_{char.id}')]])
photo_msg = await callback_query.message.answer_photo(
photo=char.character_image_tg_id,
caption=f"👤 <b>Имя:</b> {char.name}\n"
f"📝 <b>Био:</b> {char.character_bio}",
reply_markup=keyboard)
await wait_msg.delete()
@router.callback_query(F.data.startswith("char_photo_file"))
async def get_char_info_photo_file(callback_query: CallbackQuery, state: FSMContext, dao: DAO):
char = await dao.chars.get_character(callback_query.data.split("_")[-1])
await callback_query.message.answer_document(char.character_image_doc_tg_id)
# 4. Хендлер-помощник (если отправили команду без файла)
@router.message(Command("add_char"))
async def add_char_help(message: Message):
await message.answer(
" **Как добавить персонажа:**\n"
"Прикрепите фото (файлом/документом) и добавьте в подпись команду `/add_char`."
)