import logging from aiogram import Dispatcher, types, F from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton from sqlalchemy.ext.asyncio import AsyncSession from app.config import settings from app.database.models import User from app.services.version_service import version_service from app.utils.decorators import admin_required, error_handler logger = logging.getLogger(__name__) def get_updates_keyboard(language: str = "ru") -> InlineKeyboardMarkup: buttons = [ [ InlineKeyboardButton( text="🔄 Проверить обновления", callback_data="admin_updates_check" ) ], [ InlineKeyboardButton( text="📋 Информация о версии", callback_data="admin_updates_info" ) ], [ InlineKeyboardButton( text="🔗 Открыть репозиторий", url=f"https://github.com/{version_service.repo}/releases" ) ], [ InlineKeyboardButton( text="◀️ Назад", callback_data="admin_panel" ) ] ] return InlineKeyboardMarkup(inline_keyboard=buttons) def get_version_info_keyboard(language: str = "ru") -> InlineKeyboardMarkup: buttons = [ [ InlineKeyboardButton( text="🔄 Обновить", callback_data="admin_updates_info" ) ], [ InlineKeyboardButton( text="◀️ К обновлениям", callback_data="admin_updates" ) ] ] return InlineKeyboardMarkup(inline_keyboard=buttons) @admin_required @error_handler async def show_updates_menu( callback: types.CallbackQuery, db_user: User, db: AsyncSession ): try: version_info = await version_service.get_version_info() current_version = version_info['current_version'] has_updates = version_info['has_updates'] total_newer = version_info['total_newer'] last_check = version_info['last_check'] status_icon = "🆕" if has_updates else "✅" status_text = f"Доступно {total_newer} обновлений" if has_updates else "Актуальная версия" last_check_text = "" if last_check: last_check_text = f"\n🕐 Последняя проверка: {last_check.strftime('%d.%m.%Y %H:%M')}" message = f"""🔄 СИСТЕМА ОБНОВЛЕНИЙ 📦 Текущая версия: {current_version} {status_icon} Статус: {status_text} 🔗 Репозиторий: {version_service.repo}{last_check_text} ℹ️ Система автоматически проверяет обновления каждый час и отправляет уведомления о новых версиях.""" await callback.message.edit_text( message, reply_markup=get_updates_keyboard(db_user.language), parse_mode="HTML" ) await callback.answer() except Exception as e: logger.error(f"Ошибка показа меню обновлений: {e}") await callback.answer("❌ Ошибка загрузки меню обновлений", show_alert=True) @admin_required @error_handler async def check_updates( callback: types.CallbackQuery, db_user: User, db: AsyncSession ): await callback.answer("🔄 Проверяю обновления...") try: has_updates, newer_releases = await version_service.check_for_updates(force=True) if not has_updates: message = f"""✅ ОБНОВЛЕНИЯ НЕ НАЙДЕНЫ 📦 Текущая версия: {version_service.current_version} 🎯 Статус: У вас установлена последняя версия 🔗 Репозиторий: {version_service.repo}""" else: updates_list = [] for i, release in enumerate(newer_releases[:5]): icon = version_service.format_version_display(release).split()[0] updates_list.append( f"{i+1}. {icon} {release.tag_name} • {release.formatted_date}" ) updates_text = "\n".join(updates_list) more_text = f"\n\n📋 И еще {len(newer_releases) - 5} обновлений..." if len(newer_releases) > 5 else "" message = f"""🆕 НАЙДЕНЫ ОБНОВЛЕНИЯ 📦 Текущая версия: {version_service.current_version} 🎯 Доступно обновлений: {len(newer_releases)} 📋 Последние версии: {updates_text}{more_text} 🔗 Репозиторий: {version_service.repo}""" keyboard = get_updates_keyboard(db_user.language) if has_updates: keyboard.inline_keyboard.insert(-2, [ InlineKeyboardButton( text="📋 Подробнее о версиях", callback_data="admin_updates_info" ) ]) await callback.message.edit_text( message, reply_markup=keyboard, parse_mode="HTML" ) except Exception as e: logger.error(f"Ошибка проверки обновлений: {e}") await callback.message.edit_text( f"❌ ОШИБКА ПРОВЕРКИ ОБНОВЛЕНИЙ\n\n" f"Не удалось связаться с сервером GitHub.\n" f"Попробуйте позже.\n\n" f"📦 Текущая версия: {version_service.current_version}", reply_markup=get_updates_keyboard(db_user.language), parse_mode="HTML" ) @admin_required @error_handler async def show_version_info( callback: types.CallbackQuery, db_user: User, db: AsyncSession ): await callback.answer("📋 Загружаю информацию о версиях...") try: version_info = await version_service.get_version_info() current_version = version_info['current_version'] current_release = version_info['current_release'] newer_releases = version_info['newer_releases'] has_updates = version_info['has_updates'] last_check = version_info['last_check'] repo_url = version_info['repo_url'] current_info = f"📦 ТЕКУЩАЯ ВЕРСИЯ\n\n" if current_release: current_info += f"🏷️ Версия: {current_release.tag_name}\n" current_info += f"📅 Дата релиза: {current_release.formatted_date}\n" if current_release.short_description: current_info += f"📝 Описание:\n{current_release.short_description}\n" else: current_info += f"🏷️ Версия: {current_version}\n" current_info += f"ℹ️ Статус: Информация о релизе недоступна\n" message_parts = [current_info] if has_updates and newer_releases: updates_info = f"\n🆕 ДОСТУПНЫЕ ОБНОВЛЕНИЯ\n\n" for i, release in enumerate(newer_releases): icon = "🔥" if i == 0 else "📦" if release.prerelease: icon = "🧪" elif release.is_dev: icon = "🔧" updates_info += f"{icon} {release.tag_name}\n" updates_info += f" 📅 {release.formatted_date}\n" if release.short_description: updates_info += f" 📝 {release.short_description}\n" updates_info += "\n" message_parts.append(updates_info.rstrip()) system_info = f"\n🔧 СИСТЕМА ОБНОВЛЕНИЙ\n\n" system_info += f"🔗 Репозиторий: {version_service.repo}\n" system_info += f"⚡ Автопроверка: {'Включена' if version_service.enabled else 'Отключена'}\n" system_info += f"🕐 Интервал: Каждый час\n" if last_check: system_info += f"🕐 Последняя проверка: {last_check.strftime('%d.%m.%Y %H:%M')}\n" message_parts.append(system_info.rstrip()) final_message = "\n".join(message_parts) if len(final_message) > 4000: final_message = final_message[:3900] + "\n\n... (информация обрезана)" await callback.message.edit_text( final_message, reply_markup=get_version_info_keyboard(db_user.language), parse_mode="HTML", disable_web_page_preview=True ) except Exception as e: logger.error(f"Ошибка получения информации о версиях: {e}") await callback.message.edit_text( f"❌ ОШИБКА ЗАГРУЗКИ\n\n" f"Не удалось получить информацию о версиях.\n\n" f"📦 Текущая версия: {version_service.current_version}", reply_markup=get_version_info_keyboard(db_user.language), parse_mode="HTML" ) def register_handlers(dp: Dispatcher): dp.callback_query.register( show_updates_menu, F.data == "admin_updates" ) dp.callback_query.register( check_updates, F.data == "admin_updates_check" ) dp.callback_query.register( show_version_info, F.data == "admin_updates_info" )