First commit
This commit is contained in:
117
bot/handlers/commands/users/anon.py
Normal file
117
bot/handlers/commands/users/anon.py
Normal file
@@ -0,0 +1,117 @@
|
||||
from typing import Dict, Tuple
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from bot.utils import status_clear
|
||||
|
||||
# -------------------
|
||||
# Router
|
||||
# -------------------
|
||||
router: Router = Router(name="anon_router")
|
||||
|
||||
# -------------------
|
||||
# Конфигурация
|
||||
# -------------------
|
||||
# CHAT_ID в формате "-100000_29" -> chat_id + thread_id
|
||||
CHAT_ID: str = "-1003098225669_724"
|
||||
|
||||
def parse_chat_id(chat_id_str: str) -> Tuple[int, int]:
|
||||
chat_str, thread_str = chat_id_str.split("_")
|
||||
return int(chat_str), int(thread_str)
|
||||
|
||||
ADMIN_CHAT_ID, ADMIN_THREAD_ID = parse_chat_id(CHAT_ID)
|
||||
|
||||
# -------------------
|
||||
# FSM состояния
|
||||
# -------------------
|
||||
class AnonStates:
|
||||
USER_WAITING_TEXT = "user_waiting_text"
|
||||
ADMIN_WAITING_REPLY = "admin_waiting_reply"
|
||||
|
||||
# -------------------
|
||||
# Словари для отслеживания сообщений
|
||||
# -------------------
|
||||
# user_id -> message_id в админском топике
|
||||
user_to_admin_map: Dict[int, int] = {}
|
||||
# admin_message_id -> user_id
|
||||
admin_to_user_map: Dict[int, int] = {}
|
||||
|
||||
# -------------------
|
||||
# Команда /anon или callback
|
||||
# -------------------
|
||||
@router.callback_query(F.data.casefold() == "anon")
|
||||
@router.message(Command("anon"))
|
||||
async def anon_start(message: Message | CallbackQuery, state: FSMContext) -> None:
|
||||
"""Начало анонимного сообщения. Ждём текст пользователя."""
|
||||
await status_clear(message=message, state=state)
|
||||
await state.clear()
|
||||
await state.set_state(AnonStates.USER_WAITING_TEXT)
|
||||
|
||||
text = "Напишите сообщение, которое вы хотите отправить анонимно администраторам."
|
||||
if isinstance(message, Message):
|
||||
await message.reply(text)
|
||||
else:
|
||||
await message.message.answer(text)
|
||||
|
||||
# -------------------
|
||||
# Получение текста от пользователя
|
||||
# -------------------
|
||||
@router.message(F.text, F.state == AnonStates.USER_WAITING_TEXT)
|
||||
async def anon_send_text(message: Message, state: FSMContext) -> None:
|
||||
"""Пересылает текст пользователя в админский топик анонимно."""
|
||||
anon_text = message.text.strip()
|
||||
if not anon_text:
|
||||
await message.reply("Сообщение не может быть пустым. Попробуйте снова.")
|
||||
return
|
||||
|
||||
forwarded_text = f"Сообщение от [пользователя](tg://user?id={message.from_user.id}):\n{anon_text}"
|
||||
|
||||
keyboard = InlineKeyboardMarkup(
|
||||
inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Ответить", callback_data=f"anon_reply:{message.from_user.id}")]
|
||||
]
|
||||
)
|
||||
|
||||
sent_msg = await message.bot.send_message(
|
||||
chat_id=ADMIN_CHAT_ID,
|
||||
message_thread_id=ADMIN_THREAD_ID,
|
||||
text=forwarded_text,
|
||||
parse_mode="Markdown",
|
||||
reply_markup=keyboard
|
||||
)
|
||||
|
||||
user_to_admin_map[message.from_user.id] = sent_msg.message_id
|
||||
admin_to_user_map[sent_msg.message_id] = message.from_user.id
|
||||
|
||||
await message.reply("Ваше сообщение отправлено анонимно администраторам.")
|
||||
await state.clear()
|
||||
|
||||
# -------------------
|
||||
# Кнопка "Ответить" админа
|
||||
# -------------------
|
||||
@router.callback_query(F.data.startswith("anon_reply:"))
|
||||
async def anon_admin_reply(callback: CallbackQuery, state: FSMContext) -> None:
|
||||
"""Начинаем сессию ответа админа пользователю."""
|
||||
user_id = int(callback.data.split(":")[1])
|
||||
await state.set_state(AnonStates.ADMIN_WAITING_REPLY)
|
||||
await state.update_data(reply_to_user=user_id)
|
||||
await callback.message.answer(f"Введите ответ для пользователя [id={user_id}]:")
|
||||
await callback.answer()
|
||||
|
||||
# -------------------
|
||||
# Текст ответа админа
|
||||
# -------------------
|
||||
@router.message(F.text, F.state == AnonStates.ADMIN_WAITING_REPLY)
|
||||
async def anon_send_admin_text(message: Message, state: FSMContext) -> None:
|
||||
"""Пересылает текст админа пользователю."""
|
||||
data = await state.get_data()
|
||||
reply_to_user = data.get("reply_to_user")
|
||||
|
||||
if reply_to_user:
|
||||
await message.bot.send_message(
|
||||
chat_id=reply_to_user,
|
||||
text=f"Ответ администратора:\n{message.text}"
|
||||
)
|
||||
await message.reply("Сообщение отправлено пользователю.")
|
||||
await state.clear()
|
||||
Reference in New Issue
Block a user