""" Inline handlers for detailed item viewing with images """ from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.ext import ContextTypes, CommandHandler, CallbackQueryHandler from vndb_client import VndbClient from utils import ImageHandler from config import Config import logging logger = logging.getLogger(__name__) vndb_client = VndbClient(use_sandbox=Config.USE_SANDBOX) class DetailedHandlers: """Handlers for detailed item viewing""" @staticmethod async def view_vn_detail(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """View detailed VN information with image""" try: if not context.args: await update.message.reply_text( "❌ Пожалуйста, укажите ID визуальной новеллы\n" "Пример: /vn_detail v17" ) return vn_id = context.args[0] await update.message.reply_text(f"⏳ Загружаю информацию о {vn_id}...", parse_mode="Markdown") # Get detailed VN information filters = ["id", "=", vn_id] results = await vndb_client.query_vn( filters=[filters], fields=[ "title", "original", "released", "rating", "votecount", "description", "image{url,dims}", "length", "developer" ] ) if not results.get("results"): await update.message.reply_text(f"😞 ВН с ID {vn_id} не найдена") return vn = results["results"][0] # Build detailed text title = vn.get("title", "Unknown") original = vn.get("original", "") released = vn.get("released", "Unknown") rating = vn.get("rating", 0) votecount = vn.get("votecount", 0) description = vn.get("description", "") length = vn.get("length", "") developer = vn.get("developer", "") detail_text = f""" **🎮 {title}** (`{vn_id}`) """ if original: detail_text += f"Оригинал: {original}\n" detail_text += f""" Дата релиза: {released} Рейтинг: {rating/10:.1f}/10 ({votecount} голосов) """ if length: detail_text += f"Длительность: {length}\n" if developer: detail_text += f"Разработчик: {developer}\n" if description: # Truncate long descriptions desc_truncated = description[:300] + "..." if len(description) > 300 else description detail_text += f"\nОписание:\n{desc_truncated}\n" detail_text += f"\n[Открыть на VNDB](https://vndb.org/{vn_id})" # Send with image if available image_data = vn.get("image") if image_data: image_url = ImageHandler.get_image_url(image_data) if image_url: try: await update.message.reply_photo( photo=image_url, caption=detail_text, parse_mode="Markdown" ) except Exception as e: logger.warning(f"Could not send VN image: {e}") await update.message.reply_text(detail_text, parse_mode="Markdown") else: await update.message.reply_text(detail_text, parse_mode="Markdown") else: await update.message.reply_text(detail_text, parse_mode="Markdown") except Exception as e: logger.error(f"Error viewing VN detail: {e}") await update.message.reply_text(f"❌ Ошибка при загрузке информации: {str(e)}") @staticmethod async def view_character_detail(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """View detailed character information with image""" try: if not context.args: await update.message.reply_text( "❌ Пожалуйста, укажите ID персонажа\n" "Пример: /char_detail c1" ) return char_id = context.args[0] await update.message.reply_text(f"⏳ Загружаю информацию о {char_id}...", parse_mode="Markdown") # Get detailed character information filters = ["id", "=", char_id] results = await vndb_client.query_character( filters=[filters], fields=[ "name", "original", "gender", "bloodtype", "height", "weight", "bust", "waist", "hips", "description", "image{url,dims}", "vn" ] ) if not results.get("results"): await update.message.reply_text(f"😞 Персонаж с ID {char_id} не найден") return char = results["results"][0] # Build detailed text name = char.get("name", "Unknown") original = char.get("original", "") gender = char.get("gender", "") bloodtype = char.get("bloodtype", "") description = char.get("description", "") vns = char.get("vn", []) detail_text = f"**👤 {name}** (`{char_id}`)\n" if original: detail_text += f"Оригинал: {original}\n" if gender: detail_text += f"Пол: {gender}\n" if bloodtype: detail_text += f"Группа крови: {bloodtype}\n" if vns: detail_text += f"\nПоявляется в:\n" for vn in vns[:5]: # Show first 5 VNs vn_id = vn.get("id", "") if vn_id: detail_text += f"• [{vn_id}](https://vndb.org/{vn_id})\n" if description: desc_truncated = description[:300] + "..." if len(description) > 300 else description detail_text += f"\nОписание:\n{desc_truncated}\n" detail_text += f"\n[Открыть на VNDB](https://vndb.org/{char_id})" # Send with image if available image_data = char.get("image") if image_data: image_url = ImageHandler.get_image_url(image_data) if image_url: try: await update.message.reply_photo( photo=image_url, caption=detail_text, parse_mode="Markdown" ) except Exception as e: logger.warning(f"Could not send character image: {e}") await update.message.reply_text(detail_text, parse_mode="Markdown") else: await update.message.reply_text(detail_text, parse_mode="Markdown") else: await update.message.reply_text(detail_text, parse_mode="Markdown") except Exception as e: logger.error(f"Error viewing character detail: {e}") await update.message.reply_text(f"❌ Ошибка при загрузке информации: {str(e)}") @staticmethod async def view_release_detail(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """View detailed release information with image""" try: if not context.args: await update.message.reply_text( "❌ Пожалуйста, укажите ID релиза\n" "Пример: /release_detail r1" ) return release_id = context.args[0] await update.message.reply_text(f"⏳ Загружаю информацию о {release_id}...", parse_mode="Markdown") # Get detailed release information filters = ["id", "=", release_id] results = await vndb_client.query_release( filters=[filters], fields=[ "title", "original", "released", "platform", "type", "language", "edition", "description", "image{url,dims}", "vn" ] ) if not results.get("results"): await update.message.reply_text(f"😞 Релиз с ID {release_id} не найден") return release = results["results"][0] # Build detailed text title = release.get("title", "Unknown") original = release.get("original", "") released = release.get("released", "Unknown") platform = release.get("platform", "") rel_type = release.get("type", "") language = release.get("language", []) edition = release.get("edition", "") description = release.get("description", "") vns = release.get("vn", []) detail_text = f"**🎬 {title}** (`{release_id}`)\n" if original: detail_text += f"Оригинал: {original}\n" detail_text += f""" Дата выпуска: {released} Платформа: {platform} Тип: {rel_type} """ if language: lang_str = ", ".join(language) if isinstance(language, list) else str(language) detail_text += f"Языки: {lang_str}\n" if edition: detail_text += f"Издание: {edition}\n" if vns: detail_text += f"\nЧасть из:\n" for vn in vns[:3]: vn_id = vn.get("id", "") if vn_id: detail_text += f"• [{vn_id}](https://vndb.org/{vn_id})\n" if description: desc_truncated = description[:200] + "..." if len(description) > 200 else description detail_text += f"\nОписание:\n{desc_truncated}\n" detail_text += f"\n[Открыть на VNDB](https://vndb.org/{release_id})" # Send with image if available image_data = release.get("image") if image_data: image_url = ImageHandler.get_image_url(image_data) if image_url: try: await update.message.reply_photo( photo=image_url, caption=detail_text, parse_mode="Markdown" ) except Exception as e: logger.warning(f"Could not send release image: {e}") await update.message.reply_text(detail_text, parse_mode="Markdown") else: await update.message.reply_text(detail_text, parse_mode="Markdown") else: await update.message.reply_text(detail_text, parse_mode="Markdown") except Exception as e: logger.error(f"Error viewing release detail: {e}") await update.message.reply_text(f"❌ Ошибка при загрузке информации: {str(e)}") def get_detail_handlers(): """Get all detail view handlers""" return [ CommandHandler("vn_detail", DetailedHandlers.view_vn_detail), CommandHandler("char_detail", DetailedHandlers.view_character_detail), CommandHandler("release_detail", DetailedHandlers.view_release_detail), ]