Fix text dialog routing and club card registration recovery
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
"""Админские обработчики для управления чатом"""
|
||||
from html import escape
|
||||
from src.utils.input_validation import numeric_id
|
||||
from src.utils.errors import public_error
|
||||
from aiogram import Router, F
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from aiogram.filters import Command
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand as Command
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
@@ -20,6 +22,23 @@ from src.core.permissions import admin_only
|
||||
router = Router(name='admin_chat_router')
|
||||
|
||||
|
||||
async def reply_target(message: Message):
|
||||
"""Resolve the human author of a bot copy only within the operator's dialog."""
|
||||
replied = message.reply_to_message
|
||||
if replied.from_user and not replied.from_user.is_bot:
|
||||
return replied.from_user.id
|
||||
from sqlalchemy import select
|
||||
from src.core.models import User, P2PMessage
|
||||
async with async_session_maker() as session:
|
||||
original = await ChatMessageService.get_message_by_telegram_id(
|
||||
session, replied.message_id, chat_id=message.chat.id)
|
||||
if original:
|
||||
return await session.scalar(select(User.telegram_id).where(User.id == original.user_id))
|
||||
operator_id = select(User.id).where(User.telegram_id == message.from_user.id).scalar_subquery()
|
||||
return await session.scalar(select(User.telegram_id).join(P2PMessage, P2PMessage.sender_id == User.id).where(
|
||||
P2PMessage.recipient_id == operator_id, P2PMessage.recipient_message_id == replied.message_id))
|
||||
|
||||
|
||||
def get_chat_mode_keyboard() -> InlineKeyboardMarkup:
|
||||
"""Клавиатура выбора режима чата"""
|
||||
return InlineKeyboardMarkup(inline_keyboard=[
|
||||
@@ -89,7 +108,11 @@ async def cmd_set_forward(message: Message):
|
||||
)
|
||||
return
|
||||
|
||||
chat_id = args[1].strip()
|
||||
try:
|
||||
chat_id = str(numeric_id(args[1], signed=True))
|
||||
except ValueError as error:
|
||||
await message.answer(str(error))
|
||||
return
|
||||
|
||||
async with async_session_maker() as session:
|
||||
settings = await ChatSettingsService.set_forward_chat(session, chat_id)
|
||||
@@ -135,7 +158,10 @@ async def cmd_ban(message: Message):
|
||||
|
||||
# Проверяем является ли это ответом на сообщение
|
||||
if message.reply_to_message:
|
||||
target_user_id = message.reply_to_message.from_user.id
|
||||
target_user_id = await reply_target(message)
|
||||
if target_user_id is None:
|
||||
await message.answer("Не удалось определить автора. Укажите его Telegram ID в команде.")
|
||||
return
|
||||
reason = message.text.split(maxsplit=1)[1] if len(message.text.split(maxsplit=1)) > 1 else None
|
||||
else:
|
||||
args = message.text.split(maxsplit=2)
|
||||
@@ -150,7 +176,7 @@ async def cmd_ban(message: Message):
|
||||
return
|
||||
|
||||
try:
|
||||
target_user_id = int(args[1])
|
||||
target_user_id = numeric_id(args[1])
|
||||
reason = args[2] if len(args) > 2 else None
|
||||
except ValueError:
|
||||
await message.answer("❌ Неверный ID пользователя")
|
||||
@@ -182,11 +208,11 @@ async def cmd_ban(message: Message):
|
||||
reason=reason
|
||||
)
|
||||
|
||||
reason_text = f"\n📝 Причина: {reason}" if reason else ""
|
||||
reason_text = f"\n📝 Причина: {escape(reason[:500])}" if reason else ""
|
||||
|
||||
await message.answer(
|
||||
f"🚫 <b>Пользователь забанен</b>\n\n"
|
||||
f"👤 Пользователь: {user.name or 'Неизвестен'}\n"
|
||||
f"👤 Пользователь: {escape(user.nickname or user.first_name or 'Неизвестен')}\n"
|
||||
f"🆔 ID: <code>{target_user_id}</code>"
|
||||
f"{reason_text}",
|
||||
parse_mode="HTML"
|
||||
@@ -200,7 +226,10 @@ async def cmd_unban(message: Message):
|
||||
|
||||
# Проверяем является ли это ответом на сообщение
|
||||
if message.reply_to_message:
|
||||
target_user_id = message.reply_to_message.from_user.id
|
||||
target_user_id = await reply_target(message)
|
||||
if target_user_id is None:
|
||||
await message.answer("Не удалось определить автора. Укажите его Telegram ID в команде.")
|
||||
return
|
||||
else:
|
||||
args = message.text.split()
|
||||
if len(args) < 2:
|
||||
@@ -214,7 +243,7 @@ async def cmd_unban(message: Message):
|
||||
return
|
||||
|
||||
try:
|
||||
target_user_id = int(args[1])
|
||||
target_user_id = numeric_id(args[1])
|
||||
except ValueError:
|
||||
await message.answer("❌ Неверный ID пользователя")
|
||||
return
|
||||
@@ -252,11 +281,11 @@ async def cmd_banlist(message: Message):
|
||||
user = ban.user
|
||||
admin = ban.admin
|
||||
|
||||
text += f"👤 {user.name or 'Неизвестен'} (<code>{ban.telegram_id}</code>)\n"
|
||||
text += f"🔨 Забанил: {admin.name if admin else 'Неизвестен'}\n"
|
||||
text += f"👤 {escape(user.nickname or user.first_name or 'Неизвестен')} (<code>{ban.telegram_id}</code>)\n"
|
||||
text += f"🔨 Забанил: {escape((admin.nickname or admin.first_name or 'Неизвестен') if admin else 'Неизвестен')}\n"
|
||||
|
||||
if ban.reason:
|
||||
text += f"📝 Причина: {ban.reason}\n"
|
||||
text += f"📝 Причина: {escape(ban.reason[:500])}\n"
|
||||
|
||||
text += f"📅 Дата: {ban.banned_at.strftime('%d.%m.%Y %H:%M')}\n"
|
||||
text += "\n"
|
||||
|
||||
Reference in New Issue
Block a user