Commit Graph

36 Commits

Author SHA1 Message Date
Fringg a18f6caa9b feat: integrate PayPear payment provider
Full integration following SeverPay patterns:
- API client with Basic Auth, idempotency, HMAC webhook verification
- PayPearPaymentMixin with create, webhook, finalize (all side effects), status check
- CRUD, model, migration (0058), PaymentMethod.PAYPEAR enum
- Webhook endpoint, cabinet topup, bot handler, payment verification
- Sub-options: bank_card, sbp, sberpay, tpay
- Config: PAYPEAR_ENABLED, PAYPEAR_SHOP_ID, PAYPEAR_SECRET_KEY, etc.
2026-04-16 05:36:48 +03:00
c0mrade 522a8779d6 style: fix ruff format for all sync-related changes 2026-04-10 15:13:59 +03:00
c0mrade 3b5d5a18a1 fix: add missing WEBHOOK_TORRENT_DETECTED mapping + dedup before unique index in migration 0053 2026-04-03 20:50:13 +03:00
c0mrade 4f20e0e4cb chore: update uv.lock 2026-03-23 18:45:46 +03:00
c0mrade e99f3d9a37 fix: rename refresh('subscription') to refresh('subscriptions') in all files 2026-03-23 18:40:23 +03:00
Fringg 9eab802000 fix: handle spurious user.deleted webhooks — preserve active subscriptions and prevent orphaned panel users
- Smart end_date check: subscriptions with future end_date are preserved (not expired) and panel user is re-created automatically
- Recreation loop guard: in-memory 120s cooldown prevents unbounded recreate→delete→recreate cycles with stale entry eviction
- Race condition protection: guard timestamp stamped before any await point so concurrent coroutines are serialized
- Admin deletion: force_panel_delete=True ensures panel user is always removed, preventing orphaned subscriptions
2026-03-22 03:20:50 +03:00
Fringg 3c5bf4fa22 feat: add SOCKS proxy support for nalogo (tax service) module
Route all nalog.ru API traffic through SOCKS proxy. Uses NALOGO_PROXY_URL
env var (falls back to PROXY_URL if not set). Adds httpx[socks] dependency.

- Thread proxy_url through Client → AuthProviderImpl + AsyncHTTPClient
- Extract mask_proxy_url() and sanitize_proxy_error() utilities
- Add socks5h:// scheme support for remote DNS resolution
- Sanitize proxy credentials in error messages
- Log masked proxy URL at startup and service init
2026-03-21 04:21:11 +03:00
Fringg 82b6a8bf70 feat: add SOCKS5 proxy support for Telegram API traffic
Route bot traffic through SOCKS5 proxy when PROXY_URL env var is set.
Validates scheme to reject HTTP proxies (would expose bot token).
Credentials are masked in logs.
2026-03-21 02:32:35 +03:00
Fringg b5471b7720 perf: add covering indexes for referral network queries
Add composite indexes on advertising_campaign_registrations(user_id,
created_at) and transactions(user_id, type, is_completed, amount_kopeks)
to enable index-only scans. Uses CREATE INDEX CONCURRENTLY for zero
downtime. Also enable transaction_per_migration in Alembic env.py.
2026-03-20 02:31:03 +03:00
Fringg a6dcf26c20 chore: ruff format and cleanup 2026-03-18 18:20:50 +03:00
Fringg dcff6947dd style: ruff format 2026-03-18 01:59:12 +03:00
c0mrade 94199413c2 fix: миграция Tribute webhook с deprecated user_id на trb_user_id
- Убран fallback на deprecated поле user_id (удаляется 14 апреля 2026)
- Добавлен парсинг trb_user_id во всех ветках обработки webhook
- trb_user_id прокинут в результат и логи всех хендлеров
2026-03-17 12:43:04 +03:00
Fringg 7648707ca2 fix: campaign registration, revenue calculation, backup restore, autopay errors, referral links
- fix campaign registration not recorded when CHANNEL_IS_REQUIRED_SUB + SKIP_RULES_ACCEPT enabled (missing _apply_campaign_bonus_if_needed in required_sub_channel_check fast path)
- fix revenue calculation counting bonus-funded subscription payments as income (now deposits only via REAL_PAYMENT_METHODS)
- fix backup restore PendingRollbackError cascade on unique constraint violations (savepoint wrapping in _restore_table_records and _restore_users_without_referrals)
- fix AttributeError on message.text.strip() when users send media in referral code handlers
- suppress 'message is not modified' TelegramBadRequest in autopay toggle
- add bot_referral_link to referral API response with URL encoding
2026-03-15 01:13:50 +03:00
c0mrade 4d695be7d5 fix: resolve MissingGreenlet in switch_tariff endpoint
Use local subscription variable and db.refresh() to avoid lazy-load
of expired relationship after subtract_user_balance invalidates
the User identity map entry.
2026-03-13 18:30:32 +03:00
Fringg f59b215645 style: fix import sorting and formatting after lint
ruff auto-fix for import ordering in cabinet/subscription.py and
formatting adjustments across changed files.
2026-03-12 22:58:35 +03:00
Fringg 8b35428055 fix: reactivate subscription after traffic top-up when status is EXPIRED
When traffic is exhausted, RemnaWave may send user.expired webhook setting
local status to EXPIRED (not just DISABLED). reactivate_subscription() only
handled DISABLED→ACTIVE, silently ignoring EXPIRED subscriptions. After
purchasing additional GB, the subscription stayed expired and VPN remained
blocked despite payment.

Changes:
- reactivate_subscription() now handles both DISABLED and EXPIRED→ACTIVE
  when end_date is still in the future
- Inverted null end_date guard to block reactivation (defense-in-depth)
- Added enable_remnawave_user() call after update in all traffic/device
  top-up paths to ensure panel exits LIMITED state
- Gated enable call on subscription.status == 'active' to prevent
  enabling when reactivation was a no-op
- Fixed all 12 call sites across bot handlers, cabinet routes,
  miniapp, webapi, and auto-purchase service
2026-03-12 03:57:35 +03:00
Fringg 2e59330e95 chore: resolve uv.lock merge conflict 2026-03-10 21:19:28 +03:00
firewookie fd3466b75c fix PR problems 2026-03-10 14:29:29 +05:00
Fringg 6349b2f442 fix: align tariff pricing with calculate_renewal_price reference
- balance/main.py: single period discount on combined total (base + devices),
  add promo-offer discount, fix device_limit fallback to tariff_device_limit
- pricing.py: same combined discount + promo-offer, proper device_limit
  fallback matching reference (is not None check)
- admin/users.py: delegate to calculate_renewal_price() which handles both
  tariff and classic modes correctly, removing classic-only calculate_subscription_price
- menu.py: use renewal_service.calculate_pricing() for both price check and
  charge to ensure consistency, add try/except with user-facing error,
  show actual charged amount in success message
2026-03-09 00:39:16 +03:00
Fringg a7fea86c99 chore: update uv.lock 2026-03-07 17:15:49 +03:00
Fringg 26b486cdd9 chore: sync uv.lock with pyproject.toml version bump 2026-03-07 07:18:43 +03:00
Fringg bc52fd2711 fix: sync uv.lock version with pyproject.toml 3.23.1
release-please обновляет version в pyproject.toml, но не
перегенерирует uv.lock — Docker build падает на uv sync --locked.
2026-03-06 05:27:05 +03:00
Fringg 1e930af7d4 chore: regenerate uv.lock for v3.23.0 2026-03-06 04:46:15 +03:00
Fringg b31a893b13 fix: синхронизация версии pyproject.toml с main и обновление uv в Dockerfile
- pyproject.toml: 3.18.0 → 3.22.0 (соответствие main)
- Dockerfile: uv 0.10.7 → 0.10.8
- uv.lock: перегенерирован с новой версией
2026-03-05 11:29:35 +03:00
Fringg e2c9aab7ba chore: sync uv.lock with pyproject.toml version 2026-03-03 01:57:13 +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 bf646112df feat: colored console logs via structlog + rich + FORCE_COLOR
- Add rich dependency for colored tracebacks and console rendering
- Set FORCE_COLOR=1 in docker-compose for color output in containers
- Remove format_exc_info from processor chain — ConsoleRenderer now
  handles exc_info directly (Rich tracebacks on console, plain in files)
- Let ConsoleRenderer auto-detect colors via FORCE_COLOR env var
2026-02-16 09:43:41 +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 d4dfa235e5 chore: update all dependencies to latest stable versions
Security: cryptography 41.0→44.0+ (4 CVEs patched)
Major: redis 5.0→7.1, fastapi 0.115→0.129, bcrypt 4.2→5.0
Minor: sqlalchemy 2.0.46, alembic 1.18.4, asyncpg 0.31,
  aiosqlite 0.22, qrcode 8.0, packaging 26.0, pyjwt 2.11,
  yookassa 3.10, pyyaml 6.0.3
2026-02-16 06:59:48 +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 119f463c36 refactor: remove Flask, use FastAPI exclusively for all webhooks
Delete dead Flask-based PAL24 webhook server (app/external/pal24_webhook.py).
PAL24 webhooks already handled by unified FastAPI server on port 8080.

- Remove flask dependency from pyproject.toml and requirements.txt
- Remove PAL24_WEBHOOK_PORT config (unused, FastAPI uses shared port)
- Remove pal24_webhook module reference from log filter
- Update docs: webhook example rewritten from Flask to FastAPI
- Uninstall flask, werkzeug, blinker, itsdangerous
2026-02-09 21:54:15 +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
Fringg 8b924df64f chore: bump version to 3.6.0 in Dockerfile and workflows 2026-02-07 07:15:15 +03:00
Fringg e3f932afe4 chore: bump version to 3.5.0 in Dockerfile and workflows 2026-02-06 23:55:36 +03:00
Fringg b6fc63e33c chore: bump version to 3.4.0
Update version references across all files:
- pyproject.toml
- Dockerfile
- docker-hub.yml
- docker-registry.yml
- .release-please-manifest.json
2026-02-05 07:49:02 +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