Files
remnawave-bedolaga-telegram…/app/services/menu_layout/context.py
T
c0mrade 335be66980 feat: multi-subscription support (1 user = N subscriptions)
- Add MULTI_TARIFF_ENABLED feature flag for gradual rollout
- Migration 0041: remove unique constraint on subscriptions.user_id
- Migration 0042: add remnawave_short_id (NOT NULL, UNIQUE) to subscriptions
- Each subscription gets its own Remnawave user (user_{tg_id}_{short_id})
- Add _resolve_subscription() to all 30+ bot handlers for per-subscription routing
- Add my_subscriptions.py with list/detail views and delegation handlers
- Refactor cabinet subscription.py (4687 lines -> 10 focused modules)
- Add subscription_id parameter to all cabinet API endpoints
- Adapt all services: autopay, wheel, contests, campaign, guest purchase,
  monitoring, blocked users, account merge, promo codes, payments
- Replace all user.subscription (singular) with user.subscriptions iteration
- IDOR protection via get_subscription_by_id_for_user on all endpoints
- Full backward compatibility: MULTI_TARIFF_ENABLED=False = legacy behavior
2026-03-23 18:37:17 +03:00

37 lines
1.2 KiB
Python

"""Контекст меню для построения кнопок."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
from aiogram.types import InlineKeyboardButton
@dataclass
class MenuContext:
"""Контекст пользователя для построения меню."""
language: str = 'ru'
is_admin: bool = False
is_moderator: bool = False
has_active_subscription: bool = False
subscription_is_active: bool = False
has_had_paid_subscription: bool = False
balance_kopeks: int = 0
subscription: Any | None = None
subscriptions: list[Any] = field(default_factory=list)
show_resume_checkout: bool = False
has_saved_cart: bool = False
custom_buttons: list[InlineKeyboardButton] = field(default_factory=list)
# Расширенные поля для плейсхолдеров и условий
username: str = ''
subscription_days: int = 0
traffic_used_gb: float = 0.0
traffic_left_gb: float = 0.0
referral_count: int = 0
referral_earnings_kopeks: int = 0
registration_days: int = 0
promo_group_id: str | None = None
has_autopay: bool = False