Commit Graph

438 Commits

Author SHA1 Message Date
Fringg
fcaa9dfb27 fix: clean stale squad UUIDs from tariffs during server sync
When squads are deleted from the RemnaWave panel and servers are synced,
the bot cleaned subscription connected_squads but left stale UUIDs in
tariff.allowed_squads. This caused errors when users tried to purchase
or extend subscriptions with tariffs referencing deleted squads.

Now sync_with_remnawave also removes stale UUIDs from all tariffs.
2026-02-11 18:37:19 +03:00
Fringg
c30c2feee1 fix: handle StaleDataError in webhook user.deleted server counter decrement
When a user is deleted from the panel, the subscription may already be
cascade-deleted by the time the webhook handler tries to decrement
server counters. This caused StaleDataError followed by
PendingRollbackError when accessing subscription.id in the error handler.

- Save subscription.id before DB operations to avoid lazy load after rollback
- Catch StaleDataError explicitly and rollback the session
- Re-fetch subscription/user after potential rollback in _handle_user_deleted
- Skip subscription cleanup if it was already cascade-deleted
2026-02-11 18:35:36 +03:00
Fringg
887ea9cf5a style: format subscription.py with ruff 2026-02-11 04:45:42 +03:00
Fringg
bee4aa4284 fix: protect server counter callers and fix tariff change detection
- Wrap unprotected add/remove_user_to/from_servers calls in try/except
  in miniapp.py and cabinet subscription.py to prevent 500 errors
- Fix is_tariff_change to include classic-to-tariff transitions
  (subscription.tariff_id=None → new tariff_id) so purchased traffic
  is properly reset when switching modes
2026-02-11 04:44:15 +03:00
Fringg
b167ed3dd1 fix: preserve purchased traffic when extending same tariff
extend_subscription was unconditionally resetting purchased_traffic_gb
and deleting TrafficPurchase records whenever traffic_limit_gb was passed,
even when extending the same tariff (not changing). Now only resets
on actual tariff change (is_tariff_change=True), preserving purchased
traffic on same-tariff extensions.
2026-02-11 04:38:08 +03:00
Fringg
6cec024e46 fix: use flush instead of commit in server counter functions
add_user_to_servers and remove_user_from_servers were calling
db.commit() internally, breaking transaction atomicity for all
callers that perform additional operations afterward. Changed to
db.flush() so the caller controls the commit boundary.
2026-02-11 04:15:50 +03:00
Fringg
e94b93d0c1 fix: handle nullable traffic_limit_gb and end_date in subscription model
Add None-safety guards to Subscription model properties (is_active,
is_expired, should_be_expired, actual_status, days_left,
traffic_used_percent) and pricing handler comparisons to prevent
TypeError when nullable columns contain None values.
2026-02-10 20:35:42 +03:00
Fringg
184c52d4ea feat: webhook protection — prevent sync/monitoring from overwriting webhook data
Add last_webhook_update_at timestamp to Subscription model. When a webhook
handler modifies a subscription, it stamps this field. Auto-sync, monitoring,
and force-check services skip subscriptions updated by webhook within the
last 60 seconds, preventing stale panel data from overwriting fresh
real-time changes.

- Add last_webhook_update_at column + migration
- Stamp all 8 webhook handlers with commit in every code path
- Add is_recently_updated_by_webhook() guard in 12 sync/monitoring paths
- Add REMNAWAVE_WEBHOOK_* variables to .env.example
- Add webhook setup documentation to README with Caddy/nginx examples
- Fix pre-existing yookassa webhook test (mock AsyncSessionLocal)
2026-02-10 07:16:22 +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
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
Ali Morshedzadeh
5482e609f8 Add initial Persian locale support and language handling updates 2026-02-09 16:53:50 +03:30
Fringg
55d281b0e3 fix: handle FK violation in create_yookassa_payment when user is deleted
Catch IntegrityError on INSERT into yookassa_payments when user_id
references a deleted user. Rollback the session and return None instead
of letting the unhandled exception propagate. Protects all callers
(webhook restore, bot handlers, cabinet API, miniapp API).
2026-02-08 18:52:34 +03:00
Fringg
c46cc85144 style: format tariff.py with ruff 2026-02-08 17:54:07 +03:00
Fringg
071c23dd52 fix: resolve multiple production errors and performance issues
- tickets.py: guard against non-text messages in waiting_for_title FSM state
- payments.py: fix Wata webhook using wrong field name (order_id vs orderId),
  add full payload to error log
- tariff.py: stop overwriting admin tariff settings on every bot restart,
  sync_default_tariff_from_config now only creates if no tariff exists
- start.py: catch TelegramBadRequest specifically for "message is not modified"
  instead of bare except with useless retry
- admin/tickets.py: downgrade ticket notification log from error to warning
  for expected case of OAuth/email users without telegram_id
- pricing.py, countries.py, purchase.py: guard against expired FSM state
  causing KeyError on 'period_days'
- blacklist_service.py: add 5-min in-memory cache to is_user_blacklisted()
  to reduce DB load from per-request checks
- remnawave_service.py: fix "Session is closed" race condition — create
  new RemnaWaveAPI instance per get_api_client() call instead of reusing
  shared instance whose aiohttp session gets overwritten by parallel coroutines
2026-02-08 17:40:51 +03:00
Fringg
41633af763 refactor: fix transaction boundaries, extract _finalize_oauth_login, replace deprecated datetime.utcnow 2026-02-07 02:35:55 +03:00
Fringg
97be4afbff feat: add OAuth 2.0 authorization (Google, Yandex, Discord, VK)
- Add OAuth provider config vars and helpers to config.py
- Add google_id, yandex_id, discord_id, vk_id columns to User model
- Create OAuth provider service with state management and 4 providers
- Add CRUD functions for OAuth user lookup, linking, and creation
- Add 3 API endpoints: providers list, authorize URL, callback
- Add alembic migration and universal_migration support
- Fix trial disable logic to cover OAuth auth_types
2026-02-07 01:58:55 +03:00
Fringg
4c2e11e64b feat: add tariff reorder API endpoint
Add PUT /cabinet/admin/tariffs/order endpoint for drag-and-drop
tariff sorting in admin cabinet. Move db.commit() from CRUD to
route level for consistency.
2026-02-06 17:42:01 +03:00
Fringg
b9352a5bd5 fix(autopay): exclude daily subscriptions from global autopay
- Skip daily tariff subscriptions in monitoring autopay cycle
- Filter daily subscriptions in get_subscriptions_for_autopay CRUD
- Block autopay menu and toggle for daily tariffs in bot handler
- Reject autopay enable for daily subscriptions in Cabinet API (HTTP 400)
- Reject autopay enable for daily subscriptions in MiniApp API (HTTP 400)
2026-02-05 07:10:52 +03:00
Egor
0c0ab58236 Update promocode.py 2026-02-04 02:07:27 +03:00
Egor
5cef11f32b Update subscription.py 2026-02-03 04:14:15 +03:00
c0mrade
5e75210c8b fix: add refresh before assigning promo_groups to avoid async lazy load error 2026-02-02 04:55:27 +03:00
Egor
d7e1b8fd5d Update user.py 2026-02-01 11:28:36 +03:00
Egor
d611eecece Update user.py 2026-02-01 00:54:17 +03:00
Egor
9cc2a285dc Update user.py 2026-01-31 20:12:25 +03:00
Egor
1092301767 Update universal_migration.py 2026-01-31 18:13:42 +03:00
Egor
365f75447f Update universal_migration.py 2026-01-31 18:12:53 +03:00
Egor
701a4d51de Update universal_migration.py 2026-01-31 17:49:02 +03:00
Egor
4e9f01d439 Add files via upload 2026-01-31 17:45:19 +03:00
Egor
25aba75413 Update user.py 2026-01-30 16:06:06 +03:00
Egor
9afe370a98 Add files via upload 2026-01-30 16:05:36 +03:00
gy9vin
dd5ee45ab5 Keep local customs over main 2026-01-27 23:51:07 +03:00
gy9vin
95b7152c05 касса и прочее 2026-01-27 23:47:39 +03:00
Egor
866f89aea4 Update notification.py 2026-01-27 15:15:24 +03:00
Egor
9a4acf2016 Adjust database connection pool settings 2026-01-27 14:29:13 +03:00
Egor
d18945d0ee Update referral_contest.py 2026-01-27 01:38:42 +03:00
Egor
c5c8eb880f Update universal_migration.py 2026-01-27 01:37:18 +03:00
Egor
441bc44a24 Add files via upload 2026-01-26 22:36:48 +03:00
Egor
aaf258fbad Update universal_migration.py 2026-01-26 22:06:46 +03:00
Egor
d01492f982 Update universal_migration.py 2026-01-26 21:55:56 +03:00
Egor
f85097698a Update universal_migration.py 2026-01-26 20:01:05 +03:00
gy9vin
0d9498f169 Багфиксы и плюшки для Кассааи 2026-01-26 12:45:08 +03:00
Egor
ac892cc899 Update subscription.py 2026-01-25 13:39:47 +03:00
Egor
f8564f353f Merge pull request #2415 from BEDOLAGA-DEV/email
Email
2026-01-25 13:30:35 +03:00
Egor
4f84dc6324 Update database.py 2026-01-25 13:28:28 +03:00
Egor
658b48f154 Merge pull request #2412 from BEDOLAGA-DEV/email
Email
2026-01-25 11:55:22 +03:00
Egor
6f40cdd09c Update user.py 2026-01-25 11:52:24 +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
Egor
7e37bc4409 Update subscription.py 2026-01-24 11:23:28 +03:00
Egor
890c219d90 Update universal_migration.py 2026-01-24 11:13:30 +03:00
Egor
c27128aa30 Update models.py 2026-01-24 11:12:42 +03:00