Egor 830e64afe0 Dev (#2899)
* fix: устранить MissingGreenlet в автоплатежах и починить traceback в логах

- subtract_user_balance: пишем promo_offer_log в отдельной сессии вместо rollback после commit, который экспайрил объекты основной сессии и ломал последующие обращения к subscription/user attrs
- monitoring_service._process_autopayments: перезагружаем subscription с eager-load user/tariff после списания, оборачиваем каждую итерацию в try/except + rollback, чтобы одна ошибка не валила весь батч
- logging_config: новый processor _auto_capture_exc_info автоматически подтягивает traceback из sys.exc_info() или error-kwarg → полный traceback в файле, консоли и Telegram без exc_info=True на каждом вызове
- logging_handler: дублирующая логика захвата exc_info в TelegramNotifierProcessor как резерв

* fix: устранить root cause MissingGreenlet в автоплатежах через refetch по id

Трейс показал: subscription.user падает на lazy-load → pool._checkout →
do_ping → await_ → MissingGreenlet. SQLAlchemy 2.0 async session не
поддерживает sync-lazy-load для relationships. Причина рассинхрона:
lock_user_for_pricing делает populate_existing=True + selectinload(
User.subscriptions).selectinload(Subscription.tariff), что разгружает
Subscription.user backref для сестринских подписок того же user.
Последующее обращение sub.user у другой подписки падает.

Фикс: захватываем (sub_id, user_id) пары ДО цикла, каждую итерацию
делаем fresh refetch через async select с eager load user+tariff+
promo_group. Никаких lazy access в горячем пути. В except используем
локально захваченные id вместо getattr(subscription, ...), чтобы
логирование не падало каскадом на expired объекте.

* fix: grant all available squads for unrestricted trials (#2897)

* feat: add WEBHOOK_IP to allow Telegram bypass DNS lookup for webhook (#2894)

* feat: add WEBHOOK_IP to allow Telegram bypass DNS lookup for webhook

* style: ruff format main.py

---------

Co-authored-by: Dmitry Lunin <br@slack.ru>

* fix: do not update first_name/last_name from OIDC claims (#2892)

Co-authored-by: Dmitry Lunin <br@slack.ru>

* fix: do not reset subscription_crypto_link when cryptoLink absent in webhook (#2891)

Co-authored-by: Dmitry Lunin <br@slack.ru>

* fix: FSM state loss on balance topup, PayPear confirmation_url, hidden trial tariff in renewal

- balance/platega: re-set FSM state after min/max validation errors,
  set state before pending_amount path, use balance_topup callback for back button
- balance/main: set FSM state and payment_method in handle_topup_amount_callback
  for all providers before routing, use balance_topup callback in validation errors
- payment/paypear: fix confirmation_url key (was 'url'), add fallback,
  store charged amount with commission for correct webhook amount comparison
- tariff_purchase: redirect to active tariff list when current tariff is
  inactive (hidden trial after promo code activation)
- cabinet/renewal: check tariff.is_active in both GET and POST endpoints
  to prevent hidden trial tariff periods from appearing

* fix: tariff switch pricing showing free for upgrades, admin duplicate subscription guard

- pricing_engine: use shortest period for daily rate comparison instead
  of period closest to remaining_days — fixes incorrect free/zero cost
  for upgrades when tariffs have different period sets
- pricing_engine: remove unused target_days parameter from
  get_tariff_daily_rate_fraction
- admin_users: add duplicate subscription check before create,
  change_tariff and activate actions to prevent UniqueViolationError
  on uq_subscriptions_user_tariff_active constraint
- admin_users: add IntegrityError fallback on create as TOCTOU safety net

* feat: tariff switch direction control, fix device pricing within tariff limit

Tariff switch direction:
- Add TARIFF_SWITCH_UPGRADE_ENABLED and TARIFF_SWITCH_DOWNGRADE_ENABLED
  settings to control allowed switch directions
- Guard all 10 entry points: instant switch (list, preview, confirm),
  legacy switch (list, select, confirm, daily confirm), cabinet (preview,
  execute), purchase-options API
- Filter tariff lists by allowed direction, show "unavailable" when
  both directions disabled
- Expose settings in cabinet purchase-options response for frontend

Device pricing fix:
- Devices within tariff.device_limit are now free when restoring
  (was charging for all devices regardless of tariff inclusion)
- Fix max(100, price) minimum enforcing 1 RUB even when
  chargeable_devices is 0
- Apply fix across all endpoints: bot handlers (confirm_change,
  execute_change, confirm_add), cabinet API (legacy purchase,
  modern purchase, get-price, save-cart), inline keyboard display

* fix: classic mode renewal resets device_limit to 1 via cart key mismatch

- Fix cart key mismatch: extend cart saved 'device_limit' but
  confirm_purchase read 'devices' key, falling back to DEFAULT=1.
  Now both keys are saved in both cart-save paths
- Fix confirm_purchase device resolution: use explicit is None checks
  instead of or-chain to avoid falsy-zero trap
- Fix return_to_saved_cart display: fall back to 'device_limit' and
  'traffic_limit_gb' keys when 'devices'/'traffic_gb' are absent
- Fix second cart-save path in _extend_existing_subscription with
  same dual-key pattern
- Fix RemnaWaveService import path in renewal service
- Add RESET_DEVICES_ON_RENEWAL setting: resets all connected devices
  (hwid) via RemnaWave API on each subscription renewal

* fix: menu layout schema icon limit, traffic_topup_enabled condition, shadowing imports

- Increase icon max_length from 10 to 100 in all three schemas
  (MenuButtonConfig, ButtonUpdateRequest, AddCustomButtonRequest)
  to support Telegram Custom Emoji IDs
- Add traffic_topup_enabled condition to ButtonConditions schema
- Remove shadowing local imports of MenuLayoutService in
  routes/menu_layout.py (top-level import already provides access)

* feat(tickets): multi-media message gallery (media_items JSONB)

- Add media_items JSONB column to TicketMessage model for multi-media
  gallery support (photos/videos/documents in one bubble)
- Add TicketMediaItem schema with type validation and shared
  _validate_media_bundle helper (max 10 items, legacy field compat)
- Update admin and user ticket handlers to store media_items and
  back-fill legacy media_type/media_file_id/media_caption from first
  item for backward compatibility
- Update _message_to_response in both admin and user routes to include
  media_items in API responses
- Allow empty message text when media is attached (message field now
  defaults to empty string with model validator ensuring text or media)
- Add migration 0061 with idempotent column check

Based on PR #2869 by @smediainfo — CI/CD workflow changes excluded
(hardcoded version strings would regress dynamic manifest reading)

* fix: ticket media_items review fixes

- Add if has_media else None guards in user-side ticket handlers
  (create_ticket, add_message) matching admin handler pattern
- Fix Telegram notification using resolved primary_file_id/primary_type
  instead of raw request fields for gallery messages
- Narrow except Exception to (TypeError, KeyError, ValueError) in
  _message_to_response with warning log for debugging
- Add media_items parameter to TicketCRUD.create_ticket and
  TicketCRUD.add_message for CRUD layer parity
- Add TicketMediaItemResponse and media_items field to webapi
  TicketMessageResponse to prevent data loss on read

* feat: landing page analytics goals and sticky pay button

- Add sticky_pay_button, analytics_view_enabled, analytics_view_goal,
  analytics_click_enabled, analytics_click_goal columns to LandingPage
- Add fields to CRUD updatable fields, admin create/update/detail
  schemas, create_landing() kwargs, _landing_to_detail() response
- Expose sticky_pay_button and analytics fields in public landing
  config response for frontend Yandex Metrika integration
- Add migration 0062 with idempotent column checks

Based on PR #2852 by @smediainfo — CI/CD workflow changes excluded
(hardcoded version strings would regress dynamic manifest reading)

* fix: validate analytics goal is set when analytics is enabled on landing

Prevent enabling analytics_view/click without providing the
corresponding goal identifier, which would result in empty
Yandex Metrika calls on the frontend.

* feat: Yandex Metrika offline conversions + S2S postbacks

- Add YandexClientIdMap model for user → yandex_cid mapping with
  upsert-safe CRUD (ON CONFLICT DO UPDATE)
- Add yandex_cid, subid, referrer columns to GuestPurchase
- Add yandex_offline_conv_service: Measurement Protocol integration
  with mc.yandex.ru/collect (registration, trial, purchase events),
  background task management, CID parsing from /start params
- Add s2s_postback_service: server-to-server affiliate postbacks
  with URL template placeholders and URL-safe encoding
- Add analytics offline conversion info to branding API (masked secret)
- Add POST /analytics/yandex-cid endpoint for cabinet CID capture
- Add 11 config settings (YANDEX_OFFLINE_CONV_*, S2S_POSTBACK_*)
- Add migration 0063 (yandex_client_id_map table + guest_purchases cols)
- Fix: mask measurement secret aggressively (show only last 4 chars)
- Fix: always replace {user_id} placeholder in S2S postback URLs
- Fix: use structlog kwargs instead of f-strings with LOG_PREFIX

Based on PR #2851 by @smediainfo — CI/CD workflow changes excluded

---------

Co-authored-by: c0mrade <killmy666@gmail.com>
Co-authored-by: Danila Yudin <danyayudin2012@gmail.com>
Co-authored-by: Dmitry V. Lunin <49199230+BlackRaincoat@users.noreply.github.com>
Co-authored-by: Dmitry Lunin <br@slack.ru>
2026-04-22 06:08:26 +03:00
2026-04-22 06:08:26 +03:00
2026-03-26 11:23:48 +03:00
2026-04-22 06:08:26 +03:00
2026-04-22 06:08:26 +03:00
2026-04-22 06:08:26 +03:00
2026-04-18 00:58:34 +00:00
2026-04-18 00:58:34 +00:00
2025-12-21 02:54:58 +03:00
2026-04-22 06:08:26 +03:00
2026-04-18 00:58:34 +00:00

Bedolaga Bot

Bedolaga Bot

Telegram-бот для автоматизации VPN-бизнеса на базе Remnawave

Принимает оплату, выдаёт подписки, управляет пользователями — пока вы спите.

Python 3.13+ PostgreSQL Docker License: MIT

📖 Документация · 🤖 Тестировать бота · 💬 Чат сообщества


🧩 Что такое Bedolaga?

Bedolaga — полнофункциональная платформа для продажи VPN-подписок через Telegram. Бот интегрируется с панелью Remnawave и берёт на себя весь цикл: от регистрации пользователя до автопродления подписки.

🖥 Bedolaga Cabinet — веб-кабинет на React + TypeScript, который существенно расширяет возможности бота: личный кабинет, OAuth-авторизация (Google, Yandex, Discord, VK, Telegram OIDC), лендинги, аналитика продаж, RBAC и подарочные подписки.

Bedolaga Bot — Telegram

Возможности

📦 Подписки и тарифы

  • 🎯 Гибкие тарифные планы (от X дней до X дней)
  • 📊 Трафик: безлимит, фиксированный лимит или пакеты с возможностью докупки
  • 📱 Управление устройствами (1–20 на подписку) или отключение лимитов
  • 🌍 Автовыбор сервера(Тарифы) или ручной выбор(Конфигуратор подписки - с возможностью докупки)
  • 🆓 Пробный период(Возможен платный) с конвертацией в платный
  • 🛒 Умная корзина — сохраняет выбор при недостатке баланса
  • 🔄 Автопродление за 3 дня до окончания
  • 🎁 Подарочные подписки и конфигурируемые лендинги для быстрой продажи в вебе без авторизации

💳 Платежи

  • 🏦 18 платёжных провайдеров одновременно
  • 💰 Единый баланс: пополнение любым способом → покупка с баланса
  • Автопокупка подписки после пополнения
  • 💾 Рекуррентные платежи (сохранённые карты)
  • 🧾 Фискализация через НалоGo (для самозанятых)
  • 🔍 Автопроверка статуса платежей
  • 🛍 Гостевые покупки через лендинги

📣 Маркетинг и продвижение

  • 🏷 Промокоды (деньги, дни подписки, триалы)
  • 👥 Реферальная программа с выводом средств
  • 👥 Партнерская система
  • 📨 Рассылки по сегментам пользователей
  • 🌐 Кастомные лендинги с аналитикой
  • 🎮 Конкурсы и ежедневные игры с призами
  • 🎯 Персональные предложения и скидки
  • 📈 Маркетинговые кампании с трекингом
  • 🌐 Обязательная мультиподписка на каналы с возможностью автоотключения подписки - при отписки от канала

🛠 Администрирование

  • 🤖 Панель управления прямо в Telegram
  • 👤 Управление пользователями, подписками, платежами
  • 📬 Уведомления в топики: покупки, продления, пополнения
  • 💾 Автобэкапы БД с восстановлением из бота
  • 🚧 Режим техработ (авто-детект недоступности панели)
  • 📡 Мониторинг трафика и аномалий
  • 🤝 Партнёрская программа
  • 🔐 RBAC: роли и гранулярные права доступа
  • 📈 Детальная отчетность с возможностью визуализации Реф сети
  • 🔐 Блокировка юзеров из общего черного списка И многое др...

💳 Платёжные провайдеры

Провайдер Методы оплаты Валюта
Telegram Stars Звёзды Telegram XTR
🏦 YooKassa Карты, СБП RUB
🏦 YooKassa СБП Система быстрых платежей RUB
🪙 CryptoBot USDT, TON, BTC, ETH Crypto
🪙 Heleket USDT, мульти-сеть Crypto
💳 CloudPayments Карты, 3D-Secure RUB
💳 Freekassa NSPK СБП, карты RUB
💳 Kassa AI СБП, карты, SberPay RUB
💳 PayPalych (Pal24) Карты, СБП RUB
🤝 Platega 🔸 Карты, СБП, крипто RUB
🤝 WATA 🔸 СБП, Карты RUB
💳 MulenPay Карты RUB
💳 RioPay Карты RUB
💳 SeverPay СБП, карты RUB
🤝 PayPear 🔸 Карты, СБП, SberPay, T-Pay RUB
🤝 RollyPay 🔸 СБП, карты, крипто RUB → USDT
🤝 AuraPay 🔸 Карты, СБП RUB
📲 Tribute Telegram-платежи RUB

🔸 — официальный партнёр Bedolaga (особые условия по кодовому слову bedolaga)

Все провайдеры работают параллельно через единый веб-сервер на порту 8080. Подробная настройка — в документации.

Platega

🤝 Официальный партнёр Platega

Bedolaga — официальный партнёр платёжной системы Platega.
Пользователи бота получают особые условия при подключении по кодовому слову bedolaga

📩 По вопросам: @ArstanPlatega

WATA

🤝 Официальный партнёр WATA

Bedolaga — официальный партнёр платёжной системы WATA.
Пользователи бота получают бесплатное подключение по кодовому слову bedolaga

📩 По вопросам: @wyrz_wata

🤝 Официальный партнёр PayPear

Bedolaga — официальный партнёр платёжной системы PayPear.
Банковские карты, СБП, SberPay и T-Pay — всё через единый API.
Подключение по спец. условиям через кодовое слово БЕДОЛАГА

📩 Менеджер: @Paymen1_Manager

🤝 Официальный партнёр RollyPay

Bedolaga — официальный партнёр платёжного шлюза RollyPay.
СБП (от 5%), банковские карты РФ, крипто, вывод в USDT.
Универсальная форма оплаты, высокая проходимость, стабильная работа в каскаде.
Подключение по кодовому слову БЕДОЛАГАспец. условия

📩 Менеджер: @rollypay_manager | 🌐 rollypay.io

🤝 Официальный партнёр AuraPay

Bedolaga — официальный партнёр платёжной системы AuraPay.
Банковские карты и СБП через единый API с быстрой интеграцией.
Подключение по кодовому слову БЕДОЛАГАспец. условия

📩 Менеджер: @kickdownm | 🌐 aurapay.tech


🚀 Быстрый старт

git clone https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
cd remnawave-bedolaga-telegram-bot
cp .env.example .env   # заполните переменные
docker compose up -d

📖 Подробнее: Развёртывание → · Переменные окружения →


🏗 Стек

Компонент Технология
🐍 Язык Python 3.13, полностью async
🤖 Telegram aiogram 3.x
🗄 База данных PostgreSQL + SQLAlchemy 2.x + Alembic
🔴 Кэш/очереди Redis
Web-сервер FastAPI (webhook, платежи, Cabinet API)
📝 Логирование structlog
🐳 Контейнеризация Docker + Docker Compose
🧹 Линтер ruff

🖥 Bedolaga Cabinet

Cabinet


Bedolaga Cabinet

Веб-кабинет на React + TypeScript, существенно расширяющий возможности бота:

Возможность Описание
👤 Личный кабинет Подписки, баланс, устройства, реферальная программа
🔑 OAuth-авторизация Google, Yandex, Discord, VK, Telegram OIDC
🌐 Лендинги Кастомные страницы для привлечения клиентов
📊 Админ-панель Аналитика продаж, RBAC, управление контентом
🎁 Подарки Покупка и отправка подписок другим пользователям
🔍 Поиск платежей Поиск по инвойсу, клиенту с фильтрами и статистикой

📚 Документация

Раздел Описание
🚀 Быстрый старт Развёртывание за 5 минут
💳 Настройка платежей 18 провайдеров, webhook, фискализация
📦 Подписки и тарифы Конфигурация планов и трафика
👥 Реферальная программа Партнёрка и вывод средств
🖥 Cabinet Настройка веб-кабинета
🏷 Промо-система Промокоды, предложения, скидки
🔌 API Reference REST API для внешних интеграций

📖 Полная документация: docs.bedolagam.ru


💬 Сообщество

Telegram Chat GitHub Issues


MIT License — используйте свободно для личных и коммерческих проектов.

S
Description
Система для продажи подписок в тг и вебе с вебадминкой интегрированный c Remnawave 2.7.2+ (https://docs.rw)
Readme MIT 54 MiB
Languages
Python 100%