From 602952ff8d61bcffc504553da19e895f17176baf Mon Sep 17 00:00:00 2001 From: King-of-the-all-Cookies Date: Fri, 1 May 2026 18:24:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4:=20=D1=80=D0=B5?= =?UTF-8?q?=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D1=84?= =?UTF-8?q?=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B9=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0,=20=D1=83=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BE=D0=BE=D0=B1?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BE=D0=B1=20=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=B1=D0=BA=D0=B0=D1=85=20=D0=B8=20=D1=83=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B0=D1=80=D0=B3=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 141 ++++++++++++++++++++++++--------------------------------- 1 file changed, 58 insertions(+), 83 deletions(-) diff --git a/bot.py b/bot.py index 79580da..8a21c1b 100644 --- a/bot.py +++ b/bot.py @@ -6,17 +6,13 @@ from aiogram.filters import Command, CommandObject from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode -# Настройки TOKEN = os.getenv("TELEGRAM_TOKEN") API_URL = os.getenv("VNDB_API_URL", "https://api.vndb.org/kana") logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -bot = Bot( - token=TOKEN, - default=DefaultBotProperties(parse_mode=ParseMode.HTML) -) +bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) dp = Dispatcher() async def fetch_vndb(endpoint: str, filters: list, fields: str): @@ -26,7 +22,7 @@ async def fetch_vndb(endpoint: str, filters: list, fields: str): response = await client.post(f"{API_URL}/{endpoint}", json=payload) if response.status_code == 200: return response.json().get("results", []) - logger.error(f"VNDB API Error {response.status_code}: {response.text}") + logger.error(f"VNDB Error {response.status_code} on {endpoint}: {response.text}") return None except Exception as e: logger.error(f"Request failed: {e}") @@ -34,103 +30,82 @@ async def fetch_vndb(endpoint: str, filters: list, fields: str): @dp.message(Command("start", "help")) async def cmd_help(message: types.Message): - help_text = ( + await message.answer( "🤖 VNDB Bot\n\n" - "Поиск:\n" - "/search <name>\n" - "/char <name>\n" - "/release <name>\n\n" - "Инфо по ID:\n" - "/vn <id> (v17)\n" - "/char_id <id> (c1)\n" - "/rel_id <id> (r1)" + "• /vn <id или название>\n" + "• /char <id или название>\n" + "• /release <id или название>" ) - await message.answer(help_text) - -# --- SEARCH HANDLERS --- - -@dp.message(Command("search")) -async def search_vn(message: types.Message, command: CommandObject): - if not command.args: - return await message.answer("Пример: /search Steins;Gate") - - res = await fetch_vndb("vn", ["search", "=", command.args], "title") - if not res: return await message.answer("❌ Ничего не найдено.") - - out = ["🔍 VN Results:"] - for i in res[:10]: - out.append(f"• {i['title']} ({i['id']})") - await message.answer("\n".join(out)) - -@dp.message(Command("char")) -async def search_char(message: types.Message, command: CommandObject): - if not command.args: - return await message.answer("Пример: /char Kurisu") - - res = await fetch_vndb("character", ["search", "=", command.args], "name") - if not res: return await message.answer("❌ Персонаж не найден.") - - out = ["👤 Characters:"] - for i in res[:10]: - out.append(f"• {i['name']} ({i['id']})") - await message.answer("\n".join(out)) - -@dp.message(Command("release")) -async def search_release(message: types.Message, command: CommandObject): - if not command.args: - return await message.answer("Пример: /release Chaos;Head") - - res = await fetch_vndb("release", ["search", "=", command.args], "title") - if not res: return await message.answer("❌ Релиз не найден.") - - out = ["💿 Releases:"] - for i in res[:10]: - out.append(f"• {i['title']} ({i['id']})") - await message.answer("\n".join(out)) - -# --- DETAIL HANDLERS --- @dp.message(Command("vn")) -async def detail_vn(message: types.Message, command: CommandObject): - if not command.args: return await message.answer("Введите ID (v17)") +async def handle_vn(message: types.Message, command: CommandObject): + if not command.args: return await message.answer("Введите название или ID (v17)") - res = await fetch_vndb("vn", ["id", "=", command.args], "id, title, original, released, rating, votecount") - if not res: return await message.answer("❌ VN не найдена.") + # Если это ID (начинается с 'v' + цифры) + if command.args.startswith('v') and command.args[1:].isdigit(): + filt = ["id", "=", command.args] + else: + filt = ["search", "=", command.args] + + # Важно: для VN используем alttitle вместо original + res = await fetch_vndb("vn", filt, "id, title, alttitle, released, rating, votecount") + if not res: return await message.answer("❌ Ничего не найдено.") + + if len(res) > 1 and not command.args.startswith('v'): + out = ["🔍 Результаты поиска:"] + for i in res[:10]: + out.append(f"• {i['title']} ({i['id']})") + return await message.answer("\n".join(out)) + v = res[0] rating = f"{v['rating']/10} ⭐" if v.get('rating') else "N/A" text = (f"📖 {v['title']}\n" - f"Original: {v.get('original', 'N/A')}\n" + f"Original: {v.get('alttitle', 'N/A')}\n" f"Released: {v.get('released', 'N/A')}\n" f"Rating: {rating} ({v.get('votecount', 0)} votes)\n" f"https://vndb.org/{v['id']}") await message.answer(text) -@dp.message(Command("char_id")) -async def detail_char(message: types.Message, command: CommandObject): - if not command.args: return await message.answer("Введите ID (c1)") +@dp.message(Command("char")) +async def handle_char(message: types.Message, command: CommandObject): + if not command.args: return await message.answer("Введите имя или ID (c1)") - res = await fetch_vndb("character", ["id", "=", command.args], "id, name, original") - if not res: return await message.answer("❌ Персонаж не найден.") + filt = ["id", "=", command.args] if command.args.startswith('c') and command.args[1:].isdigit() else ["search", "=", command.args] - c = res[0] - text = (f"👤 {c['name']}\n" - f"Original: {c.get('original', 'N/A')}\n" - f"https://vndb.org/{c['id']}") - await message.answer(text) + # Для персонажей original работает + res = await fetch_vndb("character", filt, "id, name, original") + if not res: return await message.answer("❌ Не найдено.") + + if len(res) > 1 and not command.args.startswith('c'): + out = ["👤 Персонажи:"] + for i in res[:10]: out.append(f"• {i['name']} ({i['id']})") + return await message.answer("\n".join(out)) -@dp.message(Command("rel_id")) -async def detail_rel(message: types.Message, command: CommandObject): - if not command.args: return await message.answer("Введите ID (r1)") + c = res[0] + await message.answer(f"👤 {c['name']}\nOriginal: {c.get('original', 'N/A')}\nhttps://vndb.org/{c['id']}") + +@dp.message(Command("release")) +async def handle_rel(message: types.Message, command: CommandObject): + if not command.args: return await message.answer("Введите название или ID (r1)") - res = await fetch_vndb("release", ["id", "=", command.args], "id, title, released") - if not res: return await message.answer("❌ Релиз не найден.") + filt = ["id", "=", command.args] if command.args.startswith('r') and command.args[1:].isdigit() else ["search", "=", command.args] + res = await fetch_vndb("release", filt, "id, title, alttitle, released") + if not res: return await message.answer("❌ Не найдено.") + + if len(res) > 1 and not command.args.startswith('r'): + out = ["💿 Релизы:"] + for i in res[:10]: out.append(f"• {i['title']} ({i['id']})") + return await message.answer("\n".join(out)) + r = res[0] - text = (f"💿 {r['title']}\n" - f"Released: {r.get('released', 'N/A')}\n" - f"https://vndb.org/{r['id']}") - await message.answer(text) + await message.answer(f"💿 {r['title']}\nReleased: {r.get('released', 'N/A')}\nhttps://vndb.org/{r['id']}") + +# Прямые команды поиска (алиасы для удобства) +@dp.message(Command("search")) +async def search_alias(message: types.Message, command: CommandObject): + await handle_vn(message, command) if __name__ == "__main__": dp.run_polling(bot) \ No newline at end of file