from __future__ import annotations from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.config import settings from app.webapi.docs import add_redoc_endpoint from .middleware import RequestLoggingMiddleware from .routes import ( broadcasts, backups, ban_notifications, campaigns, config, health, main_menu_buttons, media, menu_layout, miniapp, partners, pinned_messages, polls, promocodes, promo_groups, promo_offers, user_messages, welcome_texts, pages, remnawave, contests, servers, subscription_events, stats, subscriptions, tickets, tokens, transactions, users, logs, webhooks, websocket, ) # Cabinet (Personal Account) routes from app.cabinet.routes import router as cabinet_router 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