Merge pull request #2168 from Gy9vin/main

Фиксы
This commit is contained in:
Egor
2025-12-19 07:22:42 +03:00
committed by GitHub
5 changed files with 98 additions and 1 deletions

View File

@@ -509,6 +509,10 @@ BOT_RUN_MODE=polling # polling, webhook или both
CONTESTS_ENABLED=false
CONTESTS_BUTTON_VISIBLE=false
# ===== КНОПКА АКТИВАЦИИ =====
ACTIVATE_BUTTON_VISIBLE=false
# ACTIVATE_BUTTON_TEXT=активировать
# ===== ЕДИНЫЙ ВЕБ-СЕРВЕР =====
WEB_API_ENABLED=false
WEB_API_HOST=0.0.0.0

View File

@@ -239,6 +239,8 @@ class Settings(BaseSettings):
# Отключение превью ссылок в сообщениях бота
DISABLE_WEB_PAGE_PREVIEW: bool = False
ACTIVATE_BUTTON_VISIBLE: bool = False
ACTIVATE_BUTTON_TEXT: str = "активировать"
PAYMENT_BALANCE_DESCRIPTION: str = "Пополнение баланса"
PAYMENT_SUBSCRIPTION_DESCRIPTION: str = "Оплата подписки"
PAYMENT_SERVICE_NAME: str = "Интернет-сервис"

View File

@@ -1223,6 +1223,85 @@ async def get_main_menu_text(user, texts, db: AsyncSession):
return base_text
async def handle_activate_button(
callback: types.CallbackQuery,
db_user: User,
db: AsyncSession
):
texts = get_texts(db_user.language)
# Получить подписку пользователя
from app.database.crud.subscription import get_subscription_by_user_id
subscription = await get_subscription_by_user_id(db, db_user.id)
if subscription and subscription.status == "ACTIVE" and subscription.end_date > datetime.utcnow():
await callback.answer(
texts.t("SUBSCRIPTION_ALREADY_ACTIVE", "✅ Подписка уже активна!"),
show_alert=True,
)
return
# Параметры из подписки или дефолтные
device_limit = subscription.device_limit if subscription else settings.DEFAULT_DEVICE_LIMIT
traffic_limit_gb = subscription.traffic_limit_gb if subscription else 0
connected_squads = subscription.connected_squads if subscription else []
# Получить IDs серверов из UUIDs
from app.database.crud.server_squad import get_server_ids_by_uuids
server_ids = await get_server_ids_by_uuids(db, connected_squads) if connected_squads else []
balance = db_user.balance_kopeks
available_periods = [int(p) for p in settings.AVAILABLE_SUBSCRIPTION_PERIODS]
best_period = None
best_price = 0
from app.services.subscription_service import SubscriptionService
subscription_service = SubscriptionService()
# Найти максимальный период, цена которого <= баланса
for period in sorted(available_periods, reverse=True):
price, _ = await subscription_service.calculate_subscription_price_with_months(
period,
traffic_limit_gb,
server_ids,
device_limit,
db,
user=db_user
)
if price <= balance:
best_period = period
best_price = price
break
if best_period:
# Создать новую подписку
from app.database.crud.subscription import create_paid_subscription
new_subscription = await create_paid_subscription(
db,
db_user.id,
best_period,
traffic_limit_gb=traffic_limit_gb,
device_limit=device_limit,
connected_squads=connected_squads,
update_server_counters=True
)
# Списать деньги
db_user.balance_kopeks -= best_price
await db.commit()
await callback.answer(
texts.t("ACTIVATION_SUCCESS", f"✅ Подписка активирована на {best_period} дней за {best_price//100} руб!"),
show_alert=True,
)
else:
await callback.answer(
texts.t("INSUFFICIENT_FUNDS", "❌ Недостаточно средств для активации подписки"),
show_alert=True,
)
def register_handlers(dp: Dispatcher):
dp.callback_query.register(
@@ -1295,3 +1374,8 @@ def register_handlers(dp: Dispatcher):
handle_add_traffic,
F.data == "buy_traffic"
)
dp.callback_query.register(
handle_activate_button,
F.data == "activate_button"
)

View File

@@ -445,7 +445,7 @@ def get_main_menu_keyboard(
)
# Добавляем кнопку конкурсов
if settings.CONTESTS_BUTTON_VISIBLE:
if settings.CONTESTS_ENABLED and settings.CONTESTS_BUTTON_VISIBLE:
paired_buttons.append(
InlineKeyboardButton(text=texts.t("CONTESTS_BUTTON", "🎲 Конкурсы"), callback_data="contests_menu")
)
@@ -461,6 +461,12 @@ def get_main_menu_keyboard(
InlineKeyboardButton(text=texts.MENU_SUPPORT, callback_data="menu_support")
)
# Добавляем кнопку активации
if settings.ACTIVATE_BUTTON_VISIBLE:
paired_buttons.append(
InlineKeyboardButton(text=settings.ACTIVATE_BUTTON_TEXT, callback_data="activate_button")
)
paired_buttons.append(
InlineKeyboardButton(
text=texts.t("MENU_INFO", " Инфо"),

View File

@@ -104,6 +104,7 @@
"ADMIN_INVALID_NUMBER": "Некорректное число",
"ADMIN_INVALID_JSON": "Некорректный JSON",
"CONTEST_MENU_TITLE": "🎲 <b>Игры/Конкурсы</b>\nВыберите игру:",
"CONTESTS_BUTTON": "🎲 Конкурсы",
"CONTEST_EMPTY": "Сейчас игр нет",
"CONTEST_NOT_ELIGIBLE": "Игры доступны только с активной или триальной подпиской.",
"CONTEST_ROUND_FINISHED": "Раунд завершён или недоступен.",