Enhance direct message handling in user management to support multiple content types

- Updated the process_direct_message_handler to determine the content type of incoming messages (text, photo, video, etc.) and send them accordingly to the target user.
- Added error handling for empty messages and invalid HTML content, improving user feedback.
- Included admin signature in messages, ensuring consistent formatting across different content types.
This commit is contained in:
machka-pasla
2025-08-20 17:12:40 +03:00
parent f22e359684
commit c69f02f7c0
+121 -7
View File
@@ -1,6 +1,7 @@
import logging import logging
import re import re
from aiogram import Router, F, types, Bot from aiogram import Router, F, types, Bot
from aiogram.exceptions import TelegramBadRequest
from aiogram.fsm.context import FSMContext from aiogram.fsm.context import FSMContext
from aiogram.utils.markdown import hcode, hbold from aiogram.utils.markdown import hcode, hbold
from typing import Optional, Dict, Any from typing import Optional, Dict, Any
@@ -578,7 +579,7 @@ async def process_subscription_days_handler(message: types.Message, state: FSMCo
await state.clear() await state.clear()
@router.message(AdminStates.waiting_for_direct_message_to_user, F.text) @router.message(AdminStates.waiting_for_direct_message_to_user)
async def process_direct_message_handler(message: types.Message, state: FSMContext, async def process_direct_message_handler(message: types.Message, state: FSMContext,
settings: Settings, i18n_data: dict, settings: Settings, i18n_data: dict,
bot: Bot, session: AsyncSession): bot: Bot, session: AsyncSession):
@@ -597,8 +598,9 @@ async def process_direct_message_handler(message: types.Message, state: FSMConte
await state.clear() await state.clear()
return return
message_text = message.text.strip() # Determine content similar to broadcast
if len(message_text) > 4000: text = (message.text or message.caption or "").strip()
if len(text) > 4000:
await message.answer(_( await message.answer(_(
"admin_user_message_too_long", "admin_user_message_too_long",
default="❌ Сообщение слишком длинное (максимум 4000 символов)" default="❌ Сообщение слишком длинное (максимум 4000 символов)"
@@ -613,15 +615,127 @@ async def process_direct_message_handler(message: types.Message, state: FSMConte
await state.clear() await state.clear()
return return
# Prepare message with admin signature # Prepare admin signature and content type
admin_signature = _( admin_signature = _(
"admin_direct_message_signature", "admin_direct_message_signature",
default="\n\n---\n💬 Сообщение от администратора" default="\n\n---\n💬 Сообщение от администратора"
) )
full_message = message_text + admin_signature
# Send message to user content_type = "text"
await bot.send_message(target_user_id, full_message) file_id = None
if message.photo:
content_type = "photo"
file_id = message.photo[-1].file_id
elif message.video:
content_type = "video"
file_id = message.video.file_id
elif message.animation:
content_type = "animation"
file_id = message.animation.file_id
elif message.document:
content_type = "document"
file_id = message.document.file_id
elif message.audio:
content_type = "audio"
file_id = message.audio.file_id
elif message.voice:
content_type = "voice"
file_id = message.voice.file_id
elif message.sticker:
content_type = "sticker"
file_id = message.sticker.file_id
elif message.video_note:
content_type = "video_note"
file_id = message.video_note.file_id
if not text and not file_id:
await message.answer(_(
"admin_direct_empty_message",
default="❌ Пустое сообщение. Отправьте текст или медиа."
))
return
caption_with_signature = (text + admin_signature) if text else None
# Send to target user similar to broadcast
try:
if content_type == "text":
await bot.send_message(
target_user_id,
(caption_with_signature or admin_signature),
parse_mode="HTML",
disable_web_page_preview=True,
)
elif content_type == "photo":
await bot.send_photo(
chat_id=target_user_id,
photo=file_id,
caption=caption_with_signature,
parse_mode="HTML",
)
elif content_type == "video":
await bot.send_video(
chat_id=target_user_id,
video=file_id,
caption=caption_with_signature,
parse_mode="HTML",
)
elif content_type == "animation":
await bot.send_animation(
chat_id=target_user_id,
animation=file_id,
caption=caption_with_signature,
parse_mode="HTML",
)
elif content_type == "document":
await bot.send_document(
chat_id=target_user_id,
document=file_id,
caption=caption_with_signature,
parse_mode="HTML",
)
elif content_type == "audio":
await bot.send_audio(
chat_id=target_user_id,
audio=file_id,
caption=caption_with_signature,
parse_mode="HTML",
)
elif content_type == "voice":
await bot.send_voice(
chat_id=target_user_id,
voice=file_id,
caption=caption_with_signature,
parse_mode="HTML",
)
elif content_type == "sticker":
# Stickers do not support captions; send sticker and then optional signature/text
await bot.send_sticker(chat_id=target_user_id, sticker=file_id)
if caption_with_signature:
await bot.send_message(
target_user_id,
caption_with_signature,
parse_mode="HTML",
disable_web_page_preview=True,
)
elif content_type == "video_note":
# Video notes do not support captions; send media then optional signature/text
await bot.send_video_note(chat_id=target_user_id, video_note=file_id)
if caption_with_signature:
await bot.send_message(
target_user_id,
caption_with_signature,
parse_mode="HTML",
disable_web_page_preview=True,
)
except TelegramBadRequest as e:
await message.answer(_(
"admin_broadcast_invalid_html",
default="❌ Некорректный HTML в сообщении. Пожалуйста, отправьте корректный HTML (поддерживаются теги Telegram) или уберите теги.\nОшибка: {error}",
error=str(e),
))
return
# Confirm to admin # Confirm to admin
await message.answer(_( await message.answer(_(