📸 РАССЫЛКА С КАРТИНКАМИ
✅ Реализовано: - Рассылка текста (работает) - Рассылка картинки с подписью (НОВОЕ!) - Отправка в общий чат + в личку каждому - Отчёт админу об успешной рассылке 🎯 Как использовать: 1. /admin → 📤 Рассылка 2. Отправить текст ИЛИ картинку с подписью 3. Бот разошлёт всем верифицированным: - В общий чат - В личку каждому 📝 Для срочного объявления: 1. Напиши боту в личку 2. /admin 3. 📤 Рассылка 4. Отправь картинку + текст 5. Готово! 💡 Важно: - Рассылка только верифицированным - Картинка сжимается Telegram - Подпись до 1024 символов Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
d81ee6d238
commit
b4c06d09a3
1 changed files with 100 additions and 24 deletions
|
|
@ -32,6 +32,7 @@ router = Router()
|
|||
|
||||
class BroadcastState(StatesGroup):
|
||||
waiting_for_message = State()
|
||||
waiting_for_photo = State() # Состояние для ожидания картинки
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -308,7 +309,8 @@ async def cb_admin_broadcast(callback: CallbackQuery):
|
|||
|
||||
await callback.message.answer(
|
||||
'📤 <b>Рассылка</b>\n\n'
|
||||
'Теперь отправьте сообщение, которое нужно разослать всем жильцам.\n\n'
|
||||
'<b>Вариант 1:</b> Отправьте текст\n'
|
||||
'<b>Вариант 2:</b> Отправьте картинку с подписью\n\n'
|
||||
'Или отмените командой /cancel',
|
||||
parse_mode='HTML'
|
||||
)
|
||||
|
|
@ -324,24 +326,50 @@ async def cb_admin_broadcast(callback: CallbackQuery):
|
|||
@router.message(StateFilter(BroadcastState.waiting_for_message))
|
||||
@admin_only
|
||||
async def process_broadcast_message(message: Message):
|
||||
"""Обработка сообщения для рассылки"""
|
||||
broadcast_text = message.text
|
||||
"""Обработка сообщения для рассылки (текст или фото)"""
|
||||
|
||||
# Отключаем состояние
|
||||
await message.bot.delete_state(message.from_user.id)
|
||||
# Проверяем что прислал админ
|
||||
if message.photo:
|
||||
# Это картинка с подписью
|
||||
photo_id = message.photo[-1].file_id # Берём наибольшее качество
|
||||
caption = message.caption or ''
|
||||
|
||||
# Подтверждаем
|
||||
await message.answer(
|
||||
f'📤 <b>Начинаю рассылку...</b>\n\n'
|
||||
f'Сообщение: {broadcast_text[:100]}...'
|
||||
)
|
||||
# Отключаем состояние
|
||||
await message.bot.delete_state(message.from_user.id)
|
||||
|
||||
# Подтверждаем
|
||||
await message.answer(
|
||||
f'📤 <b>Начинаю рассылку с картинкой...</b>\n\n'
|
||||
f'Текст: {caption[:100]}...' if caption else 'Без текста'
|
||||
)
|
||||
|
||||
# Рассылаем
|
||||
await send_broadcast_with_photo(message.bot, photo_id, caption)
|
||||
else:
|
||||
# Это текст
|
||||
broadcast_text = message.text or ''
|
||||
|
||||
# Отключаем состояние
|
||||
await message.bot.delete_state(message.from_user.id)
|
||||
|
||||
# Подтверждаем
|
||||
await message.answer(
|
||||
f'📤 <b>Начинаю рассылку...</b>\n\n'
|
||||
f'Сообщение: {broadcast_text[:100]}...'
|
||||
)
|
||||
|
||||
# Рассылаем текст
|
||||
await send_broadcast_text(message.bot, broadcast_text)
|
||||
|
||||
|
||||
async def send_broadcast_text(bot, text: str):
|
||||
"""Рассылка текста"""
|
||||
# Отправляем в чат дома
|
||||
try:
|
||||
await message.bot.send_message(
|
||||
await bot.send_message(
|
||||
config.ADMIN_CHAT_ID,
|
||||
f'📢 <b>Объявление от администрации</b>\n\n'
|
||||
f'{broadcast_text}',
|
||||
f'{text}',
|
||||
parse_mode='HTML'
|
||||
)
|
||||
logger.info(f'Рассылка отправлена в чат {config.ADMIN_CHAT_ID}')
|
||||
|
|
@ -359,10 +387,10 @@ async def process_broadcast_message(message: Message):
|
|||
|
||||
for user in users:
|
||||
try:
|
||||
await message.bot.send_message(
|
||||
await bot.send_message(
|
||||
user.user_id,
|
||||
f'📢 <b>Объявление от администрации</b>\n\n'
|
||||
f'{broadcast_text}',
|
||||
f'{text}',
|
||||
parse_mode='HTML'
|
||||
)
|
||||
success_count += 1
|
||||
|
|
@ -371,7 +399,8 @@ async def process_broadcast_message(message: Message):
|
|||
error_count += 1
|
||||
|
||||
# Отчёт админу
|
||||
await message.answer(
|
||||
await bot.send_message(
|
||||
config.ADMIN_USER_ID,
|
||||
f'✅ <b>Рассылка завершена!</b>\n\n'
|
||||
f'Успешно: {success_count}\n'
|
||||
f'Ошибок: {error_count}\n'
|
||||
|
|
@ -380,6 +409,53 @@ async def process_broadcast_message(message: Message):
|
|||
)
|
||||
|
||||
|
||||
async def send_broadcast_with_photo(bot, photo_id: str, caption: str):
|
||||
"""Рассылка картинки с подписью"""
|
||||
# Отправляем в чат дома
|
||||
try:
|
||||
await bot.send_photo(
|
||||
config.ADMIN_CHAT_ID,
|
||||
photo_id,
|
||||
caption=f'📢 <b>Объявление от администрации</b>\n\n{caption}',
|
||||
parse_mode='HTML'
|
||||
)
|
||||
logger.info(f'Рассылка с фото отправлена в чат {config.ADMIN_CHAT_ID}')
|
||||
except Exception as e:
|
||||
logger.error(f'Ошибка отправки фото в чат: {e}')
|
||||
|
||||
# Рассылаем всем верифицированным в личку
|
||||
async with AsyncSessionLocal() as session:
|
||||
stmt = select(User).where(User.verified == True)
|
||||
result = await session.execute(stmt)
|
||||
users = list(result.scalars().all())
|
||||
|
||||
success_count = 0
|
||||
error_count = 0
|
||||
|
||||
for user in users:
|
||||
try:
|
||||
await bot.send_photo(
|
||||
user.user_id,
|
||||
photo_id,
|
||||
caption=f'📢 <b>Объявление от администрации</b>\n\n{caption}',
|
||||
parse_mode='HTML'
|
||||
)
|
||||
success_count += 1
|
||||
except Exception as e:
|
||||
logger.error(f'Не удалось отправить фото пользователю {user.user_id}: {e}')
|
||||
error_count += 1
|
||||
|
||||
# Отчёт админу
|
||||
await bot.send_message(
|
||||
config.ADMIN_USER_ID,
|
||||
f'✅ <b>Рассылка с фото завершена!</b>\n\n'
|
||||
f'Успешно: {success_count}\n'
|
||||
f'Ошибок: {error_count}\n'
|
||||
f'В чат: ✅',
|
||||
parse_mode='HTML'
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# СНЯТИЕ ВЕРИФИКАЦИИ (БЫСТРОЕ)
|
||||
# =============================================================================
|
||||
|
|
|
|||
Loading…
Reference in a new issue