from __future__ import annotations from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware # Cabinet (Personal Account) routes from app.cabinet.routes import router as cabinet_router from app.config import settings from app.webapi.docs import add_redoc_endpoint from .middleware import RequestLoggingMiddleware from .routes import ( backups, ban_notifications, broadcasts, campaigns, config, contests, health, logs, main_menu_buttons, media, menu_layout, miniapp, pages, partners, pinned_messages, polls, promo_groups, promo_offers, promocodes, remnawave, servers, stats, subscription_events, subscriptions, tickets, tokens, transactions, user_messages, users, webhooks, websocket, welcome_texts, ) OPENAPI_TAGS = [ { 'name': 'health', 'description': 'Мониторинг состояния административного API и связанных сервисов.', }, { 'name': 'stats', 'description': 'Сводные показатели по пользователям, подпискам и платежам.', }, { 'name': 'settings', 'description': 'Получение и изменение конфигурации бота из административной панели.', }, { 'name': 'main-menu', 'description': 'Управление кнопками и сообщениями главного меню Telegram-бота.', }, { 'name': 'menu-layout', 'description': 'API конструктор меню: управление расположением и настройками кнопок.', }, { 'name': 'welcome-texts', 'description': 'Создание, редактирование и управление приветственными текстами.', }, { 'name': 'users', 'description': 'Управление пользователями, балансом и статусами подписок.', }, { 'name': 'subscriptions', 'description': 'Создание, продление и настройка подписок бота.', }, { 'name': 'support', 'description': 'Работа с тикетами поддержки, приоритетами и ограничениями на ответы.', }, { 'name': 'transactions', 'description': 'История финансовых операций и пополнений баланса.', }, { 'name': 'promo-groups', 'description': 'Создание и управление промо-группами и их участниками.', }, { 'name': 'servers', 'description': ( 'Управление серверами RemnaWave, их доступностью, промогруппами и ручная синхронизация данных.', ), }, { 'name': 'promo-offers', 'description': 'Управление промо-предложениями, шаблонами и журналом событий.', }, { 'name': 'logs', 'description': ('Журналы мониторинга бота, действий модераторов поддержки и системный лог-файл.'), }, { 'name': 'auth', 'description': 'Управление токенами доступа к административному API.', }, { 'name': 'remnawave', 'description': ( 'Интеграция с RemnaWave: статус панели, управление нодами, сквадами и синхронизацией ' 'данных между ботом и панелью.' ), }, { 'name': 'media', 'description': 'Загрузка файлов в Telegram и получение ссылок на медиа.', }, { 'name': 'miniapp', 'description': 'Endpoint для Telegram Mini App с информацией о подписке пользователя.', }, { 'name': 'partners', 'description': 'Просмотр участников реферальной программы, их доходов и рефералов.', }, { 'name': 'polls', 'description': 'Создание опросов, удаление, статистика и ответы пользователей.', }, { 'name': 'pages', 'description': 'Управление контентом публичных страниц: оферта, политика, FAQ и правила.', }, { 'name': 'notifications', 'description': ( 'Получение и просмотр уведомлений о покупках, активациях и продлениях подписок, ' 'пополнениях баланса, активациях промокодов, переходах по реферальным ссылкам и ' 'сменах промогрупп пользователей для административной панели.' ), }, { 'name': 'contests', 'description': 'Управление конкурсами: реферальными и ежедневными играми/раундами.', }, { 'name': 'webhooks', 'description': 'Управление webhooks для подписки на события системы (пользователи, платежи, тикеты).', }, { 'name': 'websocket', 'description': 'WebSocket подключения для real-time обновлений дашборда и уведомлений.', }, { 'name': 'pinned-messages', 'description': ( 'Управление закреплёнными сообщениями: создание, обновление, рассылка и настройка показа при /start.' ), }, { 'name': 'ban-notifications', 'description': ( 'Эндпоинты для приема уведомлений от системы мониторинга ban (Banhammer). ' 'Позволяет отправлять уведомления пользователям о блокировке и разблокировке.' ), }, ] def create_web_api_app() -> FastAPI: docs_config = settings.get_web_api_docs_config() # Убираем openapi_tags для предотвращения ошибок при генерации openapi.json app = FastAPI( title=settings.WEB_API_TITLE, version=settings.WEB_API_VERSION, docs_url=docs_config.get('docs_url'), redoc_url=None, openapi_url=docs_config.get('openapi_url'), swagger_ui_parameters={'persistAuthorization': True}, ) add_redoc_endpoint( app, redoc_url=docs_config.get('redoc_url'), openapi_url=docs_config.get('openapi_url'), title=settings.WEB_API_TITLE, ) allowed_origins = settings.get_web_api_allowed_origins() cabinet_origins = settings.get_cabinet_allowed_origins() all_origins = list(set(allowed_origins + cabinet_origins)) app.add_middleware( CORSMiddleware, allow_origins=['*'] if '*' in all_origins else all_origins, allow_credentials=True, allow_methods=['*'], allow_headers=['*'], ) if settings.WEB_API_REQUEST_LOGGING: app.add_middleware(RequestLoggingMiddleware) app.include_router(health.router) app.include_router(stats.router, prefix='/stats', tags=['stats']) app.include_router(config.router, prefix='/settings', tags=['settings']) app.include_router(users.router, prefix='/users', tags=['users']) app.include_router(subscriptions.router, prefix='/subscriptions', tags=['subscriptions']) app.include_router(tickets.router, prefix='/tickets', tags=['support']) app.include_router(transactions.router, prefix='/transactions', tags=['transactions']) app.include_router(promo_groups.router, prefix='/promo-groups', tags=['promo-groups']) app.include_router(promo_offers.router, prefix='/promo-offers', tags=['promo-offers']) app.include_router(servers.router, prefix='/servers', tags=['servers']) app.include_router(contests.router, prefix='/contests', tags=['contests']) app.include_router( main_menu_buttons.router, prefix='/main-menu/buttons', tags=['main-menu'], ) app.include_router( menu_layout.router, prefix='/menu-layout', tags=['menu-layout'], ) app.include_router( user_messages.router, prefix='/main-menu/messages', tags=['main-menu'], ) app.include_router( welcome_texts.router, prefix='/welcome-texts', tags=['welcome-texts'], ) app.include_router(pages.router, prefix='/pages', tags=['pages']) app.include_router(promocodes.router, prefix='/promo-codes', tags=['promo-codes']) app.include_router(broadcasts.router, prefix='/broadcasts', tags=['broadcasts']) app.include_router(backups.router, prefix='/backups', tags=['backups']) app.include_router(campaigns.router, prefix='/campaigns', tags=['campaigns']) app.include_router(tokens.router, prefix='/tokens', tags=['auth']) app.include_router(remnawave.router, prefix='/remnawave', tags=['remnawave']) app.include_router(media.router, tags=['media']) app.include_router(miniapp.router, prefix='/miniapp', tags=['miniapp']) app.include_router(partners.router, prefix='/partners', tags=['partners']) app.include_router(polls.router, prefix='/polls', tags=['polls']) app.include_router(logs.router, prefix='/logs', tags=['logs']) app.include_router( pinned_messages.router, prefix='/pinned-messages', tags=['pinned-messages'], ) app.include_router( subscription_events.router, prefix='/notifications/subscriptions', tags=['notifications'], ) app.include_router(webhooks.router, prefix='/webhooks', tags=['webhooks']) app.include_router(websocket.router, tags=['websocket']) app.include_router( ban_notifications.router, prefix='/ban-notifications', tags=['ban-notifications'], ) # Cabinet (Personal Account) routes if settings.is_cabinet_enabled(): app.include_router(cabinet_router) return app