Commit Graph

177 Commits

Author SHA1 Message Date
Fringg 1ab1ff90bf feat: add subscription reissue with 15-min cooldown
- Add revoke handler for classic and multi-tariff modes with 2-step
  confirmation dialog and TOCTOU-safe cooldown enforcement
- Add cabinet API endpoint POST /subscription/revoke with 429 + Retry-After
  for cooldown, IDOR protection via resolve_subscription
- Add last_revoke_at column to subscriptions (Alembic migration 0071)
- Add SUBSCRIPTION_REVOKE_ENABLED and COOLDOWN_SECONDS config settings
- Add revoke button to classic subscription settings keyboard and
  multi-tariff detail keyboard (gated by feature toggle)
- Add locale keys for revoke UI in all 5 languages (ru, en, ua, zh, fa)
2026-05-04 08:08:56 +03:00
c0mrade 2321667ecb fix: add TRAFFIC_WARNING_ALERT and LOW_BALANCE_ALERT localization keys to all locales 2026-04-10 17:58:04 +03:00
c0mrade 2f9d00343b feat: send torrent blocker notification to user (not just admin)
- torrent_blocker.report is now a dual event: admin notification + user message
- New _handle_torrent_detected user handler sends WEBHOOK_TORRENT_DETECTED
- process_event handles events registered in both admin and user handlers
- Webhook router passes DB session for dual events (needs_db_session check)
- Add WEBHOOK_NOTIFY_TORRENT_DETECTED setting (default: true)
- Add WEBHOOK_TORRENT_DETECTED locale texts (ru/en/ua/zh/fa)
2026-04-03 18:19:45 +03:00
Fringg 7dd67e36b3 feat: add tariff identification to all notifications for multi-tariff mode
When MULTI_TARIFF_ENABLED=true users can have multiple subscriptions,
so notifications must identify which tariff they relate to.

- Webhook notifications: _notify_user auto-injects tariff_label from
  subscription.tariff.name into all 16 webhook notification strings
- Monitoring service: tariff labels in expired, expiring, trial ending,
  follow-up waves, autopay success/failed notifications
- Daily subscription: tariff in insufficient balance notification
- Recurrent payments: tariff in card autopay success/failed
- Auto-purchase: tariff in all 4 auto-purchase notification paths,
  with pre-captured names to avoid MissingGreenlet after db.commit()
- Channel checker: plural form for multi-subscription deactivation
- Payment providers: tariff in YooKassa and Stars activation messages
- Admin: tariff in bulk expiry reminder
- Localization: {tariff_label} in 20 notification keys across all 5
  locales (ru, en, ua, zh, fa) + _MULTI channel keys
- Fix: selectinload(Subscription.tariff) in trial expiring query
- Fix: capture tariff_name before expire_subscription to prevent
  MissingGreenlet from db.refresh() expiring ORM relationships
2026-03-28 19:12:34 +03:00
c0mrade d071269b8c fix: comprehensive multi-subscription audit fixes across routes, handlers, and services
- Fix UUID resolution in monitoring and webhook services for multi-tariff mode
- Update cabinet routes to properly resolve per-subscription UUIDs
- Fix account merge service for multi-tariff subscription transfers
- Update admin handlers (users, promo_offers, servers) for multi-subscription
- Fix traffic, devices, servers, daily subscription modules
- Update payment handlers (stars, yookassa) and purchase services
- Fix broadcast, promocode, and subscription auto-purchase services
- Add multi-subscription support to keyboards and localization
- Fix CRUD operations for subscription queries
- Resolve code quality issues (ruff linting)
2026-03-23 18:40:23 +03:00
Fringg cbe630cab0 refactor: simplify referral invite text to single template
Replace 7 fragmented localization keys with one REFERRAL_INVITE_TEXT
template. Remove Share button (switch_inline_query). Wrap invite text
in blockquote+code for visual quote style with tap-to-copy. Update
instruction text in all 5 locales (ru, en, ua, fa, zh).
2026-03-23 08:25:19 +03:00
Fringg 67da390371 feat: show both bot and cabinet referral links everywhere
Previously the bot showed only one referral link (cabinet when CABINET_URL
is set, bot otherwise). Users who received the cabinet link were confused —
they opened a web registration form instead of being directed to the bot.

Now the bot, cabinet API, and miniapp API all return both links:
- Bot link (t.me deep link) — always shown
- Cabinet link (web registration) — shown when CABINET_URL is configured

Changes:
- Add get_bot_referral_link() and get_cabinet_referral_link() to config
- Refactor config methods to eliminate code duplication
- Update bot referral handler to display both links
- Fix switch_inline_query 256-char limit with auto-truncation
- Add html_escape() to all user-controlled strings in HTML messages
- Add translations for 5 new keys in all 5 locale files (ru/en/ua/zh/fa)
- Simplify cabinet route to use new methods instead of inline URL construction
- Add bot_referral_link to MiniApp API schema and response
2026-03-20 23:12:22 +03:00
firewookie 23ff40cd2c Отображение привязанных карт в разделе в боте 2026-03-12 09:31:46 +05:00
FireWookie 9ad684c8c9 Merge pull request #7 from FireWookie/dev
Dev
2026-03-10 14:42:53 +05:00
FireWookie d147be0316 Merge pull request #6 from FireWookie/dev
Dev
2026-03-10 14:42:05 +05:00
FireWookie 5c2e5dfaab Merge branch 'BEDOLAGA-DEV:main' into feature/riopay 2026-03-10 14:14:23 +05:00
firewookie be2ec091a6 Правки по замечаниям 2026-03-09 14:06:00 +05:00
Fringg 770b31d3d0 feat: auto-resume disabled daily subscriptions on balance topup
- Add try_resume_disabled_daily_after_topup() for instant resume when balance is topped up
- Fix all 5 resume paths to charge daily fee BEFORE activating subscription
- Remove unsafe inline auto-resume from add_user_balance() that bypassed fee charging
- Add NULL-safe is_daily_paused filter in subscription queries
- Use create_remnawave_user() instead of enable_remnawave_user() for full VPN panel sync
- Add DAILY_SUBSCRIPTION_RESUMED_AFTER_TOPUP localization key (ru, en, fa, zh, ua)
2026-03-08 21:36:17 +03:00
firewookie a6849242ff add riopay 2026-03-07 15:35:26 +05:00
firewookie 319f49435a - Карточки "Бонус новому пользователю" и "Бонус пригласившему"
скрыты когда значение = 0
- Динамический grid-cols в зависимости от количества видимых карточек
- Добавлено поле max_commission_payments в тип ReferralTerms
- Уведомления бота: строки с бонусом нового пользователя и бонусом
    пригласившего скрываются если соответствующие настройки = 0
- Раздел "Как работают награды": карточки бонусов скрыты при значении 0
- Invite message: строка про бонус за первое пополнение скрыта при 0
- Текст комиссии: "с каждого пополнения" при без лимита,
    "с пополнений" при наличии REFERRAL_MAX_COMMISSION_PAYMENTS- API /terms: добавлено поле max_commission_payments
- Добавлен ключ локали REFERRAL_REWARD_COMMISSION_LIMITED (ru/en/ua/zh/fa)
2026-03-06 11:08:52 +05:00
firewookie aaffc26a90 - Интеграция рекурентов от Юкассы
- Багфикс личного кабинета
2026-03-06 09:47:58 +05:00
Fringg 1256ddcd1a fix: restore panel user discovery on admin tariff change, localize cart reminder
Bug 1: Admin tariff change used update_remnawave_user() which returns
early when user has no remnawave_uuid. Restored _sync_subscription_to_panel()
which discovers/creates panel users via telegram_id/email fallback, then
applies traffic reset if RESET_TRAFFIC_ON_TARIFF_SWITCH is enabled.

Bug 2: Post-topup cart reminder in payment/common.py had hardcoded Russian
text sent to all users regardless of language. Replaced with localized
BALANCE_TOPPED_UP_CART_SUFFICIENT/INSUFFICIENT keys and used existing
MY_BALANCE_BUTTON/MAIN_MENU_BUTTON for inline keyboard buttons.
Added new i18n keys to all 5 locales (ru, en, ua, zh, fa).
2026-03-02 20:48:02 +03:00
Fringg ccb61d6473 chore: remove dead BALANCE_TOPUP_CART_REMINDER_DETAILED keys and unused cryptobot cart payload 2026-03-01 23:28:26 +03:00
Fringg 2fab50c340 fix: correct cart notification after balance top-up
- Remove misleading "Важно" and "При наличии корзины" warnings from all
  payment success notifications
- Fix cart total bug: show actual cart price from Redis instead of top-up
  amount, and suppress "insufficient funds" when balance is enough
- Extract shared send_cart_notification_after_topup() in common.py to
  replace duplicated code across all 10 payment providers
2026-03-01 23:09:49 +03:00
Fringg 1bc9074c1b fix: translate required channels handler to Russian, add localization keys
- All bot handler strings translated from English to Russian
- Back button now correctly navigates to admin_submenu_settings
- Added ADMIN_SETTINGS_REQUIRED_CHANNELS key to all 5 locales
2026-02-24 03:22:39 +03:00
Fringg a47ef67090 fix: add missing CHANNEL_CHECK_NOT_SUBSCRIBED localization key
Added to all 5 locales (en, ru, fa, ua, zh) to fix runtime warning
when user clicks subscription check button in middleware.
2026-02-24 03:00:08 +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 d9de15a5a0 feat: add close button to all webhook notifications
Add dismissible close button (✖️) to every webhook notification message.
Users can now close any webhook notification by tapping the button,
which deletes the message via webhook:close callback handler.
2026-02-10 06:22:17 +03:00
Fringg 1e37fd9dd2 feat: add all remaining RemnaWave webhook events (node, service, crm, device)
Handle all 44 webhook events: admin alerts for node health (connection
lost/restored), service security (login attempts), CRM billing reminders,
plus user-facing device added/deleted and not_connected notifications
with localized messages across all 5 languages.
2026-02-10 05:47:35 +03:00
Fringg 6d67cad3e7 feat: add RemnaWave incoming webhooks for real-time subscription events
- Add FastAPI webhook endpoint with HMAC-SHA256 signature verification
- Handle 16 user events: expired, disabled, enabled, limited, traffic_reset,
  modified, deleted, revoked, created, expires_in_72h/48h/24h,
  expired_24h_ago, first_connected, bandwidth_threshold
- URL validation for subscription_url/subscription_crypto_link (XSS prevention)
- 64KB body size limit, 32-char minimum secret enforcement
- Sanitized percent value in bandwidth threshold notifications
- DB rollback on handler errors to prevent dirty session commits
- Localization for all 5 languages (ru, en, ua, zh, fa)
2026-02-10 05:13:39 +03:00
Fringg a3903a252e refactor: remove smart auto-activation & activation prompt, fix production bugs
Remove AUTO_ACTIVATE_AFTER_TOPUP and SHOW_ACTIVATION_PROMPT_AFTER_TOPUP
features from all payment providers, config, system settings, and tests.
Cart auto-purchase (AUTO_PURCHASE_AFTER_TOPUP) is preserved.

Bug fixes:
- fix KeyError 'months' in devices.py for custom locale overrides
- fix IntegrityError on trial subscription retry (update existing PENDING instead of INSERT)
- fix PendingRollbackError cascade by adding db.rollback() before recovery
- fix TelegramForbiddenError not caught in photo_message.py
- fix "query is too old" spam in required_sub_channel_check
- add missing trial locale keys (TRIAL_PAYMENT_DESCRIPTION, TRIAL_REFUND_DESCRIPTION, TRIAL_ACTIVATION_ERROR)
2026-02-09 21:39:53 +03:00
Egor 9483517258 Add files via upload 2026-02-04 02:08:18 +03:00
Egor 1bd301f21a Add files via upload 2026-02-02 05:26:41 +03:00
Egor 6a2fd5a7de Add files via upload 2026-02-02 02:58:22 +03:00
Mikhail e9dc9630b2 Merge branch 'BEDOLAGA-DEV:main' into main 2026-02-01 14:38:39 +03:00
Egor 9f66e176f7 Add files via upload 2026-02-01 12:34:24 +03:00
gy9vin bea6c02d89 kassa ai 2026-02-01 11:18:54 +03:00
Egor 2a82b037d8 Add files via upload 2026-01-22 22:39:01 +03:00
Egor b994a5ffd6 Add files via upload 2026-01-20 06:23:00 +03:00
libkit 8b6683302d feat(localization): добавить тексты для DISCOUNT промокодов
Добавлены переводы на все 4 языка (ru, en, ua, zh):
- ADMIN_PROMOCODE_TYPE_DISCOUNT - название типа в админке
- PROMOCODE_ACTIVE_DISCOUNT_EXISTS - ошибка при конфликте скидок

Тексты описывают функционал одноразовой процентной скидки.
2026-01-17 11:25:51 +05:00
Egor e987b25e6b Add files via upload 2026-01-12 18:26:54 +03:00
Egor d9514ac00e Add files via upload 2026-01-12 17:33:52 +03:00
Egor 09bb52f8e5 Add files via upload 2026-01-12 17:25:47 +03:00
Egor 0903f42da9 Add files via upload 2026-01-12 17:20:55 +03:00
Egor 891b388799 Add files via upload 2026-01-12 16:41:36 +03:00
Egor 39c3ec9ed4 Add files via upload 2026-01-10 21:43:29 +03:00
Egor d9ce09b3bf Update ru.json 2026-01-08 23:14:40 +03:00
Egor f19e2b2a34 Update ru.json 2026-01-07 02:36:43 +03:00
gy9vin 23f8bdfbec feat(restrictions): добавить систему ограничений пользователей
Добавлена возможность ограничивать пользователям:
  - Пополнение баланса (restriction_topup)
  - Покупку/продление подписки (restriction_subscription)

  Изменения:
  - models.py: добавлены поля restriction_topup, restriction_subscription,
    restriction_reason и property has_restrictions
  - universal_migration.py: миграция для новых полей
  - admin/users.py: меню управления ограничениями в карточке пользователя
  - keyboards/admin.py: клавиатура ограничений с toggle-кнопками
  - states.py: состояние editing_user_restriction_reason

  Проверки ограничений добавлены на двух уровнях:
  - start_*_payment: при выборе метода оплаты
  - process_*_payment_amount: при создании платежа

  Затронутые провайдеры: stars, yookassa, mulenpay, wata, pal24,
  cryptobot, heleket, platega, tribute, cloudpayments

  При ограничении пользователь видит причину и кнопку "Обжаловать",
  ведущую на контакт поддержки из настроек.
2025-12-28 13:32:04 +03:00
gy9vin 0538d0e337 feat(traffic): улучшение системы докупки и сброса трафика
- Добавлен ENV переключатель TRAFFIC_TOPUP_ENABLED для вкл/выкл докупки
- Добавлена отдельная конфигурация пакетов TRAFFIC_TOPUP_PACKAGES_CONFIG
- Добавлено поле purchased_traffic_gb для отслеживания докупленного трафика
- Добавлены режимы расчета цены сброса (period/traffic/traffic_with_purchased)
- Исправлен абьюз: цена сброса теперь учитывает докупленный трафик
- Сброс purchased_traffic_gb при продлении/покупке подписки
- UX: меню сброса теперь показывает цену и баланс вместо alert
- UX: кнопка пополнения если не хватает средств на сброс
- Добавлена миграция для нового поля purchased_traffic_gb
- Добавлена локализация TRAFFIC_TOPUP_DISABLED (ru/en/ua/zh)
2025-12-25 14:48:24 +03:00
gy9vin 90c3df6331 Добавлен функционал подключения модема к подписке
Изменения:
- Добавлены настройки модема в .env.example и config.py (MODEM_ENABLED, MODEM_PRICE_PER_MONTH, MODEM_PERIOD_DISCOUNTS)
- Добавлено поле modem_enabled в модель Subscription
- Реализован модуль handlers/subscription/modem.py с обработчиками подключения/отключения модема
- Добавлено управ
2025-12-25 14:26:15 +03:00
gy9vin b3cdd3c03a Расширение функционала конкурсов: разнообразие наград, напоминания, многоязычность
Изменения:
- ContestTemplate: prize_days заменен на prize_type и prize_value для поддержки разных типов наград (days, balance, custom)
- _award_prize: обновлена логика выдачи призов для всех типов наград
- DEFAULT_TEMPLATES: обновлены для использования prize_type/prize_value
- upsert_template: обновлена сигнатура для новых полей
- _announce_round_start: добавлена локализация и напоминания о конкурсах
- handle_text_answer: исправлена гонка условий с атомарным инкрементом победителей
- Локализация: добавлены ключи CONTEST_START_ANNOUNCEMENT, CONTEST_PRIZE, DAYS, CONTEST_WINNERS, CONTEST_ATTEMPTS, CONTEST_ELIGIBILITY, REMINDER, CONTEST_REMINDER_TEXT в ru.json и en.json
- API схемы: обновлены ContestTemplateResponse и ContestTemplateUpdateRequest

Требуется миграция БД для новых колонок prize_type и prize_value.
2025-12-23 19:15:40 +03:00
Egor f8ba587e5c Add files via upload 2025-12-22 22:43:51 +03:00
Egor 866fa56f5b Add files via upload 2025-12-22 14:43:58 +03:00
Egor 85d4c9c208 Add files via upload 2025-12-22 13:57:37 +03:00