mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-03-03 00:31:24 +00:00
@@ -1,4 +1,5 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from aiogram import Dispatcher, F, types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
@@ -11,6 +12,14 @@ from app.utils.decorators import admin_required, error_handler
|
||||
from app.utils.validators import get_html_help_text, validate_html_tags
|
||||
|
||||
|
||||
def _safe_preview(html_text: str, limit: int = 500) -> str:
|
||||
"""Создаёт превью текста, безопасно обрезая HTML-теги."""
|
||||
plain = re.sub(r'<[^>]+>', '', html_text)
|
||||
if len(plain) <= limit:
|
||||
return plain
|
||||
return plain[:limit] + '...'
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -79,7 +88,7 @@ async def start_edit_rules(callback: types.CallbackQuery, db_user: User, state:
|
||||
try:
|
||||
current_rules = await get_current_rules_content(db, db_user.language)
|
||||
|
||||
preview = current_rules[:500] + ('...' if len(current_rules) > 500 else '')
|
||||
preview = _safe_preview(current_rules, 500)
|
||||
|
||||
text = (
|
||||
'✏️ <b>Редактирование правил</b>\n\n'
|
||||
@@ -139,7 +148,7 @@ async def process_rules_edit(message: types.Message, db_user: User, state: FSMCo
|
||||
if len(preview_text) > 4000:
|
||||
preview_text = (
|
||||
'📋 <b>Предварительный просмотр новых правил:</b>\n\n'
|
||||
f'{new_rules[:500]}...\n\n'
|
||||
f'{_safe_preview(new_rules, 500)}\n\n'
|
||||
f'⚠️ <b>Внимание!</b> Новые правила будут показываться всем пользователям.\n\n'
|
||||
f'Текст правил: {len(new_rules)} символов\n'
|
||||
f'Сохранить изменения?'
|
||||
|
||||
@@ -7,16 +7,19 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from types import SimpleNamespace
|
||||
from typing import Any
|
||||
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import MissingGreenlet
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.config import settings
|
||||
from app.database.crud.user import get_user_by_telegram_id
|
||||
from app.database.database import get_db
|
||||
from app.database.database import AsyncSessionLocal, get_db
|
||||
from app.database.models import Subscription
|
||||
from app.localization.texts import get_texts
|
||||
from app.services.subscription_checkout_service import (
|
||||
has_subscription_checkout_draft,
|
||||
@@ -46,12 +49,26 @@ class PaymentCommonMixin:
|
||||
and not getattr(subscription, 'is_trial', False)
|
||||
and getattr(subscription, 'is_active', False)
|
||||
)
|
||||
except MissingGreenlet as error:
|
||||
logger.warning(
|
||||
'Не удалось лениво загрузить подписку пользователя %s при построении клавиатуры после пополнения: %s',
|
||||
getattr(user, 'id', None),
|
||||
error,
|
||||
)
|
||||
except MissingGreenlet:
|
||||
# user вне сессии — загружаем подписку отдельным запросом
|
||||
try:
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(
|
||||
select(Subscription.status, Subscription.is_trial, Subscription.end_date)
|
||||
.where(Subscription.user_id == user.id)
|
||||
.order_by(Subscription.created_at.desc())
|
||||
.limit(1)
|
||||
)
|
||||
row = result.one_or_none()
|
||||
if row:
|
||||
is_active = row.status == 'active' and row.end_date > datetime.utcnow()
|
||||
has_active_subscription = bool(is_active and not row.is_trial)
|
||||
except Exception as db_error:
|
||||
logger.warning(
|
||||
'Не удалось загрузить подписку пользователя %s из БД: %s',
|
||||
getattr(user, 'id', None),
|
||||
db_error,
|
||||
)
|
||||
except Exception as error: # pragma: no cover - защитный код
|
||||
logger.error(
|
||||
'Ошибка загрузки подписки пользователя %s при построении клавиатуры после пополнения: %s',
|
||||
|
||||
@@ -260,7 +260,10 @@ class HeleketPaymentMixin:
|
||||
invoice_message = metadata.get('invoice_message') or {}
|
||||
invoice_message_removed = False
|
||||
|
||||
if getattr(self, 'bot', None) and invoice_message:
|
||||
status_normalized = (status or '').lower()
|
||||
is_final = status_normalized in {'paid', 'paid_over', 'cancel', 'fail', 'system_fail', 'refund_paid'}
|
||||
|
||||
if getattr(self, 'bot', None) and invoice_message and is_final:
|
||||
chat_id = invoice_message.get('chat_id')
|
||||
message_id = invoice_message.get('message_id')
|
||||
if chat_id and message_id:
|
||||
@@ -300,7 +303,6 @@ class HeleketPaymentMixin:
|
||||
)
|
||||
return updated_payment
|
||||
|
||||
status_normalized = (status or '').lower()
|
||||
if status_normalized not in {'paid', 'paid_over'}:
|
||||
logger.info('Heleket платеж %s в статусе %s, зачисление не требуется', updated_payment.uuid, status)
|
||||
return updated_payment
|
||||
|
||||
Reference in New Issue
Block a user