Commit Graph

223 Commits

Author SHA1 Message Date
firewookie 23ff40cd2c Отображение привязанных карт в разделе в боте 2026-03-12 09:31:46 +05:00
FireWookie 5c2e5dfaab Merge branch 'BEDOLAGA-DEV:main' into feature/riopay 2026-03-10 14:14:23 +05:00
Fringg bc9003c336 chore: ruff format 2026-03-10 03:36:32 +03:00
Fringg fcdeff1ee5 fix: migrate pricing to days-based proration, fix promo revenue leaks, fix admin panel bugs
- Migrate all addon pricing (devices, traffic, countries) from months-based to days-based proration
- Remove get_remaining_months() utility, use days_left / 30 consistently
- Fix promo/campaign balance bonuses counted as revenue in reports (add REAL_PAYMENT_METHODS filter)
- Fix partner stats, campaign stats, miniapp stats, referral fraud detection promo deposit leaks
- Fix admin balance history showing deductions with + sign (use -abs for expense types)
- Fix promo offer deactivation returning 400 for non-promocode offers
- Fix daily tariff renewal requesting 30-day renewal instead of 1-day purchase
2026-03-10 03:31:07 +03:00
Fringg acd2cff9ca style: format inline.py with ruff 2026-03-09 23:38:34 +03:00
Fringg 69dbd6a2df fix: enforce HTTPS for webapp mode, deduplicate keyboard builder, fix long line 2026-03-09 23:37:35 +03:00
Fringg 497a8ee5b5 feat: add open_in setting for custom buttons (external browser / webapp) 2026-03-09 23:33:18 +03:00
Fringg dd8d7f6920 feat: add cabinet menu layout editor with row arrangement, custom URL buttons, and drag-and-drop reordering
- Add menu_layout_cache.py for CABINET_MENU_LAYOUT in-process cache
- Add admin_menu_layout.py routes (GET/PUT/POST reset) with merged view
- Rewrite _build_cabinet_main_menu_keyboard to use cached row layout
- Support custom URL buttons with style, emoji, labels, enabled toggle
- Atomic dual-key DB writes for layout + button styles
- Add language button to default layout and DEFAULT_BUTTON_STYLES
- Pydantic validation with Literal types, max_length, duplicate ID checks
- Register routes and cache loading in bot startup
2026-03-09 23:07:32 +03:00
firewookie a6849242ff add riopay 2026-03-07 15:35:26 +05:00
Fringg 399ca86561 fix: hide traffic topup button when tariff doesn't support it
In tariffs mode, check tariff.can_topup_traffic() instead of just
checking tariff_id existence. Prevents showing a button that leads
to an error when the tariff has traffic limits but no topup packages.
2026-02-27 01:01:55 +03:00
Fringg cab425cfac style: format freekassa handler and keyboard files 2026-02-25 12:39:21 +03:00
Fringg 0da0c5547d feat: add separate Freekassa SBP and card payment methods
Split Freekassa into sub-methods: СБП/QR (i=44) and Карты РФ (i=36).
Each method has independent enable/display_name settings, dedicated
handlers, keyboard buttons, and correct payment_system_id routing.
Webhook notifications resolve display name from payment metadata.
2026-02-25 12:32:05 +03:00
Fringg 59fb08c3ea style: format 5 files with ruff 2026-02-24 05:59:08 +03:00
Fringg 295d2e877e refactor: remove legacy app-config.json system
Replace dual-configuration architecture (Remnawave API + local file fallback)
with Remnawave-only approach. When config is unavailable, show explicit
"not configured" message instead of silent file fallback.

- Delete app-config.json and admin_apps.py CRUD module (~1260 lines)
- Remove sync loaders, legacy step format handlers, device_mapping dicts
- Remove miniapp /app-config.json endpoint and filesystem search
- Remove backup service app-config.json snapshot/restore
- Remove APP_CONFIG_PATH setting, env var, docker volume mount
- Remove hardcoded 6-device keyboard fallback
- Remove legacy step-based keyboard rendering (installationStep etc.)
- Add "config not configured" message when Remnawave config is missing
- Update admin UI: "clear config" disables guide mode instead of reverting
2026-02-24 05:58:25 +03:00
Fringg fae6f71def fix: address code review issues in guide mode rework
- Add fallback else branch for subscriptionLink in blocks format
  (prevents silent button drop when deep link resolution fails)
- Extract render_guide_blocks() helper to eliminate duplicated
  block-rendering logic between handle_device_guide and
  handle_specific_app_guide
- Add HTML escaping for admin-controlled config text in guide blocks
- Remove unused get_localized_value import from devices.py
2026-02-24 05:18:25 +03:00
Fringg 5a269b249e feat: rework guide mode with Remnawave API integration
- Add async Remnawave config loader with TTL cache and asyncio.Lock
- Normalize both legacy (steps) and Remnawave (blocks) formats to unified structure
- Build dynamic platform selection keyboard from config instead of hardcoded 6-device layout
- Add colored buttons via Bot API 9.4 (green for connect, blue for download)
- Add admin panel handler for selecting Remnawave subscription page config
- Add cache invalidation from both bot admin and cabinet API
- Fix callback data parsing for app IDs with underscores
- Add Linux platform support across all device mappings
2026-02-24 05:16:18 +03:00
Fringg 0b3b2e5dc5 feat: colored channel subscription buttons via Bot API 9.4 style
- Subscribed channels shown as green (style=success) with checkmark
- Unsubscribed channels shown as blue (style=primary)
- Clicking "I subscribed" now updates keyboard with colored status
  instead of just showing error alert
- Extracted _normalize_channels helper for DRY
2026-02-24 03:58:11 +03:00
Fringg 8375d7ecc5 feat: add multi-channel mandatory subscription system
- Multi-channel subscription enforcement via middleware, events, and cabinet API
- 3-layer cache architecture: Redis -> PostgreSQL -> rate-limited Telegram API
- ChatMemberUpdated event-driven tracking with automatic VPN access control
- Admin management via bot FSM handler and REST API with full CRUD
- Channel ID normalization: @username resolved to numeric ID at creation time
- Fail-closed error handling: API errors deny access (security-first)
- Background reconciliation with keyset pagination (100 per batch)
- Per-user rate limiting on subscription check button (5s cooldown)
- Redis connection pooling via cache singleton (no per-request connections)
- Database: channel_id index, multi-row upsert optimization
- Localization: en, ru, zh, fa, ua translations for all new strings
- Frontend blocking UI with channel list and subscription status
- Admin channel management page with toggle, delete, and create
2026-02-24 02:50:31 +03:00
Fringg 10e231e52e feat: blocked user detection during broadcasts, filter blocked from all notifications
- Broadcast tri-state return: 'sent'/'blocked'/'failed' with blocked_count tracking
- Background cleanup: mark blocked users + disable their subscriptions + Remnawave
- blocked_count in BroadcastHistory model, schemas, API responses, admin UI
- Filter User.status==ACTIVE in subscription queries: get_expiring_subscriptions,
  get_expired_subscriptions, get_subscriptions_for_autopay,
  get_daily_subscriptions_for_charge, get_disabled_daily_subscriptions_for_resume
- Guard in notification_delivery_service.send_notification for BLOCKED/DELETED users
- Fix subscription tariff switch: preserve remaining days with total_seconds()
- Fix redundant local UTC imports across 16 files
- Fix test mocks: add **kwargs, correct assertion, remove dead expression
2026-02-17 18:37:25 +03:00
Fringg eb18994b7d fix: complete datetime.utcnow() → datetime.now(UTC) migration
- Migrate 660+ datetime.utcnow() across 153 files to datetime.now(UTC)
- Migrate 30+ datetime.now() without UTC to datetime.now(UTC)
- Convert all 170 DateTime columns to DateTime(timezone=True)
- Add migrate_datetime_to_timestamptz() in universal_migration with SET LOCAL timezone='UTC' safety
- Remove 70+ .replace(tzinfo=None) workarounds
- Fix utcfromtimestamp → fromtimestamp(..., tz=UTC)
- Fix fromtimestamp() without tz= (system_logs, backup_service, referral_diagnostics)
- Fix fromisoformat/isoparse to ensure aware output (platega, yookassa, wata, miniapp, nalogo)
- Fix strptime() to add .replace(tzinfo=UTC) (backup_service, referral_diagnostics)
- Fix datetime.combine() to include tzinfo=UTC (remnawave_sync, traffic_monitoring)
- Fix datetime.max/datetime.min sentinels with .replace(tzinfo=UTC)
- Rename panel_datetime_to_naive_utc → panel_datetime_to_utc
- Remove DTZ003 from ruff ignore list
2026-02-17 04:45:40 +03:00
Fringg 1f0fef114b refactor: complete structlog migration with contextvars, kwargs, and logging hardening
- Add ContextVarsMiddleware for automatic user_id/chat_id/username binding
  via structlog contextvars (aiogram) and http_method/http_path (FastAPI)
- Use bound_contextvars() context manager instead of clear_contextvars()
  to safely restore previous state instead of wiping all context
- Register ContextVarsMiddleware as outermost middleware (before GlobalError)
  so all error logs include user context
- Replace structlog.get_logger() with structlog.get_logger(__name__) across
  270 calls in 265 files for meaningful logger names
- Switch wrapper_class from BoundLogger to make_filtering_bound_logger()
  for pre-processor level filtering (performance optimization)
- Migrate 1411 %-style positional arg logger calls to structlog kwargs
  style across 161 files via AST script
- Migrate log_rotation_service.py from stdlib logging to structlog
- Add payment module prefixes to TelegramNotifierProcessor.IGNORED_LOGGER_PREFIXES
  and ExcludePaymentFilter.PAYMENT_MODULES to prevent payment data leaking
  to Telegram notifications and general log files
- Fix LoggingMiddleware: add from_user null-safety for channel posts,
  switch time.time() to time.monotonic() for duration measurement
- Remove duplicate logger assignments in purchase.py, config.py,
  inline.py, and admin/payments.py
2026-02-16 09:18:12 +03:00
Fringg 64a684cd2f fix: filter out traffic packages with zero price from purchase options 2026-02-15 23:32:15 +03:00
Fringg 80914c1af7 fix: daily tariff subscriptions stuck in expired/disabled with no resume path
- Keyboard now shows "Возобновить" for disabled/expired daily tariffs
  instead of useless "Приостановить"
- resume_daily_subscription handles EXPIRED→ACTIVE (not only DISABLED)
- Pause handler detects inactive status and calls resume directly
- subscription_extend redirects daily tariffs to subscription info
  (daily tariffs have no period_prices, so extend page was empty)
2026-02-15 23:17:45 +03:00
Fringg 68773b7e77 feat: add per-button enable/disable toggle and custom labels per locale
- Add enabled flag to hide/show each button section in main menu
- Add per-locale custom labels (ru, en, ua, zh, fa) for button text
- Deep-copy nested labels dict in cache to prevent reference leaks
- Validate label entries from DB (type + locale key checks)
- Use selective merge in PATCH handler instead of blind .update()
2026-02-12 23:42:55 +03:00
Fringg 10538e7351 feat: add 'default' (no color) option for button styles
Allow admins to set buttons to Telegram's default style with no color
override. Refactors style resolution from or-chain to explicit if/elif/else
so that 'default' does not fall through to global config or hardcoded defaults.
2026-02-12 23:25:42 +03:00
Fringg a9687912df feat: add per-section button style and emoji customization via admin API
Add cabinet admin API for configuring button colors (primary/success/danger)
and custom emoji IDs per menu section (home, subscription, balance, referral,
support, info, admin). Styles are stored as JSON in system_settings and cached
in-process for fast resolution.

Style resolution chain: explicit param > per-section DB > global config > defaults.
2026-02-12 23:15:58 +03:00
Fringg 46c1a69456 fix: pre-validate CABINET_BUTTON_STYLE to prevent invalid values from suppressing per-section defaults 2026-02-12 22:43:30 +03:00
Fringg bf2b2f1c56 feat: add button style and emoji support for cabinet mode (Bot API 9.4)
- Upgrade aiogram to 3.25.0 for style/icon_custom_emoji_id support
- Add CABINET_BUTTON_STYLE config for global color override
- Per-section default styles: subscription (green), balance (blue),
  referral (green), admin (red), home (blue)
- Style priority: explicit > CABINET_BUTTON_STYLE > per-section default
- Add icon_custom_emoji_id pass-through for Premium bot owners
- Admin panel setting for button style with color picker
2026-02-12 22:34:38 +03:00
Fringg 9ac6da490d feat: add web admin button for admins in cabinet mode 2026-02-12 22:22:28 +03:00
Fringg ad87c5fb5e feat: rename MAIN_MENU_MODE=text to cabinet with deep-linking to frontend sections
- Rename mode from 'text' to 'cabinet' (text/text_only/minimal kept as aliases)
- Add build_cabinet_url() for joining MINIAPP_CUSTOM_URL with section paths
- Cabinet main menu now has section-specific buttons: subscription, balance,
  referral, support, info — each opens the corresponding cabinet page
- Add CALLBACK_TO_CABINET_PATH mapping for automatic deep-linking from
  callback_data to cabinet routes (/subscription, /balance, /referral, etc.)
- Unmapped callback_data gracefully falls back to regular Telegram callbacks
- Add startup validation warning when cabinet mode is active without MINIAPP_CUSTOM_URL
- Update admin broadcast buttons with section-specific routing
- Backward compatible: is_text_main_menu_mode() kept as alias for is_cabinet_mode()
2026-02-12 22:21:08 +03:00
Fringg 3dac332a9f chore: ruff format 7 files 2026-02-11 21:50:49 +03:00
Fringg ee2e79db31 refactor: remove modem functionality from classic subscriptions
Remove all modem purchase/management code:
- Delete modem handler, service, and tests
- Remove modem button from keyboards and admin panel
- Remove modem pricing from calculations
- Remove modem REST API endpoint and schemas
- Remove modem decorator, config settings, and notification formatting
- Keep DB column and migration for backwards compatibility
2026-02-11 21:14:08 +03:00
Fringg 90d9df8f0e fix: preserve payment initiation time in transaction created_at
Transaction created_at and completed_at showed identical timestamps
because webhook handlers created transactions with is_completed=True
in a single step. Now all 10 payment providers pass payment.created_at
to the transaction so created_at reflects when the user initiated
the payment, not when the webhook processed it.

Also: remove duplicate datetime import in inline.py, upgrade button
stats DB error logging from debug to warning, add index on
button_click_logs.button_type for analytics queries.
2026-02-10 04:26:23 +03:00
Ali Morshedzadeh 5482e609f8 Add initial Persian locale support and language handling updates 2026-02-09 16:53:50 +03:30
Egor 3ebbb42096 Update inline.py 2026-02-04 02:57:12 +03:00
Egor 3dbaf99733 Update inline.py 2026-02-02 05:26:09 +03:00
Egor 7d9d1b0a6f Update inline.py 2026-02-01 17:16:28 +03:00
Egor 1bb5ef85aa Update inline.py 2026-01-31 17:04:59 +03:00
c0mrade 9a2aea038a chore: add uv package manager and ruff linter configuration
- Add pyproject.toml with uv and ruff configuration
- Pin Python version to 3.13 via .python-version
- Add Makefile commands: lint, format, fix
- Apply ruff formatting to entire codebase
- Remove unused imports (base64 in yookassa/simple_subscription)
- Update .gitignore for new config files
2026-01-24 17:45:27 +03:00
gy9vin 7aa64521d2 feat(payments): добавить KassaAI как отдельную платёжную систему
Новая платёжка KassaAI (api.fk.life) работает параллельно с Freekassa.

  Добавлено:
  - app/services/kassa_ai_service.py — API-сервис
  - app/database/crud/kassa_ai.py — CRUD-операции
  - app/services/payment/kassa_ai.py — KassaAiPaymentMixin
  - app/handlers/balance/kassa_ai.py — хендлеры пополнения

  Изменено:
  - config.py — настройки KASSA_AI_*
  - models.py — PaymentMethod.KASSA_AI, модель KassaAiPayment
  - payment_service.py — подключён KassaAiPaymentMixin
  - webserver/payments.py — webhook /kassa-ai-webhook
  - keyboards/inline.py — кнопка KassaAI
  - handlers/balance/main.py — регистрация хендлеров
  - universal_migration.py — миграция таблицы kassa_ai_payments
  - system_settings_service.py — настройки в админке
  - .env.example — примеры переменных

  Способы оплаты: 44=СБП, 36=Карты РФ, 43=SberPay
2026-01-20 19:09:27 +03:00
Egor 2090da3603 Update inline.py 2026-01-12 16:30:24 +03:00
Egor 7c4471a510 Update inline.py 2026-01-12 15:48:51 +03:00
Egor 42978e2a37 Update inline.py 2026-01-12 15:27:37 +03:00
Egor b2577d5973 Update inline.py 2026-01-11 04:09:19 +03:00
Egor 2c4b77ff8c Update inline.py 2026-01-10 21:05:58 +03:00
Egor e6676720f2 Update inline.py 2026-01-10 20:57:49 +03:00
Egor e66944e2bf Update inline.py 2026-01-10 20:29:53 +03:00
gy9vin 3299d47b11 merge: resolve conflict in universal_migration.py 2026-01-07 15:05:14 +03:00
gy9vin 4afefcafa4 Добавлена система вывода реферального баланса
Новая функциональность вывода средств:
  - config.py: добавлены настройки вывода (минимальная сумма, кулдаун, анализ подозрительности, тестовый режим)
  - models.py: добавлена модель WithdrawalRequest с полями для заявок, анализа рисков и обработки админ
2026-01-07 14:54:50 +03:00
Egor 61fe7f0be4 Update inline.py 2026-01-07 03:49:31 +03:00