fix: normalize required channel checks

This commit is contained in:
3252a8
2026-06-01 22:13:35 +03:00
parent 5b19ba2c2f
commit 5218ede0f1
5 changed files with 222 additions and 2 deletions
+28 -1
View File
@@ -24,6 +24,10 @@ from bot.services.referral_service import ReferralService
from bot.services.subscription_service import SubscriptionService
from bot.services.telegram_notifications import TELEGRAM_NOTIFICATIONS_ENABLED
from bot.utils.callback_answer import safe_answer_callback
from bot.utils.channel_subscription import (
is_required_channel_access_error,
normalize_required_channel_id,
)
from bot.utils.install_links import (
append_install_share_link_text,
ensure_user_install_guide_links,
@@ -215,7 +219,7 @@ async def ensure_required_channel_subscription(
Verify that the user is a member of the required channel (if configured).
Returns True when access can proceed, False when user must subscribe first.
"""
required_channel_id = settings.REQUIRED_CHANNEL_ID
required_channel_id = normalize_required_channel_id(settings.REQUIRED_CHANNEL_ID)
if not required_channel_id:
return True
@@ -279,6 +283,29 @@ async def ensure_required_channel_subscription(
if status_value in allowed_statuses:
is_member = True
except TelegramBadRequest as bad_request:
if is_required_channel_access_error(bad_request):
logging.error(
"Required channel check failed due to channel access/configuration error "
"(configured=%s, normalized=%s): %s",
settings.REQUIRED_CHANNEL_ID,
required_channel_id,
bad_request,
)
error_text = translate("channel_subscription_check_failed")
if isinstance(event, types.CallbackQuery):
try:
await event.answer(error_text, show_alert=True)
except Exception:
pass
if message_obj:
try:
await message_obj.answer(error_text)
except Exception:
pass
else:
await event.answer(error_text)
return False
logging.info(
"Required channel check: user %s not subscribed (details: %s)",
user_id,
@@ -11,6 +11,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from bot.keyboards.inline.user_keyboards import get_channel_subscription_keyboard
from bot.middlewares.i18n import JsonI18n
from bot.utils.channel_subscription import normalize_required_channel_id
from config.settings import Settings
from db.dal import user_dal
@@ -32,7 +33,7 @@ class ChannelSubscriptionMiddleware(BaseMiddleware):
event: Update,
data: Dict[str, Any],
) -> Any:
required_channel_id = self.settings.REQUIRED_CHANNEL_ID
required_channel_id = normalize_required_channel_id(self.settings.REQUIRED_CHANNEL_ID)
if not required_channel_id:
return await handler(event, data)
+40
View File
@@ -0,0 +1,40 @@
from typing import Optional
def normalize_required_channel_id(value: object) -> Optional[int]:
if value is None:
return None
raw = str(value).strip()
if not raw:
return None
try:
channel_id = int(raw)
except (TypeError, ValueError):
return None
if channel_id == 0:
return None
if channel_id > 0:
return int(f"-100{channel_id}")
raw_abs = str(abs(channel_id))
if raw.startswith("-100"):
return channel_id
if abs(channel_id) < 1_000_000_000:
return channel_id
return -int(f"100{raw_abs}")
def is_required_channel_access_error(error: BaseException) -> bool:
message = str(error).lower()
configuration_markers = (
"chat not found",
"bot is not a member",
"not enough rights",
"have no rights",
"kicked",
)
return any(marker in message for marker in configuration_markers)
+1
View File
@@ -1018,6 +1018,7 @@ class Settings(BaseSettings):
"LOG_SUPPORT_THREAD_ID",
"BACKUP_CHAT_ID",
"BACKUP_THREAD_ID",
"REQUIRED_CHANNEL_ID",
mode="before",
)
@classmethod