mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-03-03 00:31:24 +00:00
Merge pull request #408 from Fr1ngg/bedolaga/update-subscription-service-for-trial-users-9k5u2q
Check trial channel subscription status
This commit is contained in:
@@ -5,6 +5,7 @@ from pathlib import Path
|
||||
from typing import Dict, List, Any, Optional, Set
|
||||
|
||||
from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
from aiogram.types import FSInputFile
|
||||
from sqlalchemy import select, and_, or_
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -181,6 +182,7 @@ class MonitoringService:
|
||||
await self._check_expiring_subscriptions(db)
|
||||
await self._check_trial_expiring_soon(db)
|
||||
await self._check_trial_inactivity_notifications(db)
|
||||
await self._check_trial_channel_subscriptions(db)
|
||||
await self._check_expired_subscription_followups(db)
|
||||
await self._process_autopayments(db)
|
||||
await self._cleanup_inactive_users(db)
|
||||
@@ -456,6 +458,145 @@ class MonitoringService:
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка проверки неактивных тестовых подписок: {e}")
|
||||
|
||||
async def _check_trial_channel_subscriptions(self, db: AsyncSession):
|
||||
if not settings.CHANNEL_IS_REQUIRED_SUB:
|
||||
return
|
||||
|
||||
channel_id = settings.CHANNEL_SUB_ID
|
||||
if not channel_id:
|
||||
return
|
||||
|
||||
if not self.bot:
|
||||
logger.debug("⚠️ Пропускаем проверку подписки на канал — бот недоступен")
|
||||
return
|
||||
|
||||
try:
|
||||
now = datetime.utcnow()
|
||||
result = await db.execute(
|
||||
select(Subscription)
|
||||
.options(selectinload(Subscription.user))
|
||||
.where(
|
||||
and_(
|
||||
Subscription.is_trial.is_(True),
|
||||
Subscription.end_date > now,
|
||||
Subscription.status.in_(
|
||||
[
|
||||
SubscriptionStatus.ACTIVE.value,
|
||||
SubscriptionStatus.DISABLED.value,
|
||||
]
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
subscriptions = result.scalars().all()
|
||||
if not subscriptions:
|
||||
return
|
||||
|
||||
disabled_count = 0
|
||||
restored_count = 0
|
||||
|
||||
for subscription in subscriptions:
|
||||
user = subscription.user
|
||||
if not user or not user.telegram_id:
|
||||
continue
|
||||
|
||||
try:
|
||||
member = await self.bot.get_chat_member(channel_id, user.telegram_id)
|
||||
member_status = member.status
|
||||
is_member = member_status in (
|
||||
ChatMemberStatus.MEMBER,
|
||||
ChatMemberStatus.ADMINISTRATOR,
|
||||
ChatMemberStatus.CREATOR,
|
||||
)
|
||||
except TelegramForbiddenError as error:
|
||||
logger.error(
|
||||
"❌ Не удалось проверить подписку пользователя %s на канал %s: бот заблокирован (%s)",
|
||||
user.telegram_id,
|
||||
channel_id,
|
||||
error,
|
||||
)
|
||||
continue
|
||||
except TelegramBadRequest as error:
|
||||
logger.error(
|
||||
"❌ Ошибка Telegram при проверке подписки пользователя %s: %s",
|
||||
user.telegram_id,
|
||||
error,
|
||||
)
|
||||
continue
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
"❌ Неожиданная ошибка при проверке подписки пользователя %s: %s",
|
||||
user.telegram_id,
|
||||
error,
|
||||
)
|
||||
continue
|
||||
|
||||
if subscription.status == SubscriptionStatus.ACTIVE.value and not is_member:
|
||||
subscription = await deactivate_subscription(db, subscription)
|
||||
disabled_count += 1
|
||||
logger.info(
|
||||
"🚫 Триальная подписка пользователя %s (ID %s) отключена из-за отписки от канала",
|
||||
user.telegram_id,
|
||||
subscription.id,
|
||||
)
|
||||
|
||||
if user.remnawave_uuid:
|
||||
try:
|
||||
await self.subscription_service.disable_remnawave_user(user.remnawave_uuid)
|
||||
except Exception as api_error:
|
||||
logger.error(
|
||||
"❌ Не удалось отключить пользователя RemnaWave %s: %s",
|
||||
user.remnawave_uuid,
|
||||
api_error,
|
||||
)
|
||||
elif subscription.status == SubscriptionStatus.DISABLED.value and is_member:
|
||||
subscription.status = SubscriptionStatus.ACTIVE.value
|
||||
subscription.updated_at = datetime.utcnow()
|
||||
await db.commit()
|
||||
await db.refresh(subscription)
|
||||
restored_count += 1
|
||||
|
||||
logger.info(
|
||||
"✅ Триальная подписка пользователя %s (ID %s) восстановлена после повторной подписки на канал",
|
||||
user.telegram_id,
|
||||
subscription.id,
|
||||
)
|
||||
|
||||
try:
|
||||
if user.remnawave_uuid:
|
||||
await self.subscription_service.update_remnawave_user(db, subscription)
|
||||
else:
|
||||
await self.subscription_service.create_remnawave_user(db, subscription)
|
||||
except Exception as api_error:
|
||||
logger.error(
|
||||
"❌ Не удалось обновить RemnaWave пользователя %s: %s",
|
||||
user.telegram_id,
|
||||
api_error,
|
||||
)
|
||||
|
||||
if disabled_count or restored_count:
|
||||
await self._log_monitoring_event(
|
||||
db,
|
||||
"trial_channel_subscription_check",
|
||||
(
|
||||
"Проверено {total} триальных подписок: отключено {disabled}, "
|
||||
"восстановлено {restored}"
|
||||
).format(
|
||||
total=len(subscriptions),
|
||||
disabled=disabled_count,
|
||||
restored=restored_count,
|
||||
),
|
||||
{
|
||||
"checked": len(subscriptions),
|
||||
"disabled": disabled_count,
|
||||
"restored": restored_count,
|
||||
},
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(f"Ошибка проверки подписки на канал для триальных пользователей: {error}")
|
||||
|
||||
async def _check_expired_subscription_followups(self, db: AsyncSession):
|
||||
if not NotificationSettingsService.are_notifications_globally_enabled():
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user