diff --git a/handlers/admin.py b/handlers/admin.py
index d5aec69..576d6fc 100644
--- a/handlers/admin.py
+++ b/handlers/admin.py
@@ -32,6 +32,7 @@ router = Router()
class BroadcastState(StatesGroup):
waiting_for_message = State()
+ waiting_for_photo = State() # Состояние для ожидания картинки
# =============================================================================
@@ -296,7 +297,7 @@ async def cb_admin_export(callback: CallbackQuery):
async def cb_admin_broadcast(callback: CallbackQuery):
"""Рассылка сообщений"""
await callback.answer()
-
+
# Проверяем что это личка
if callback.message.chat.type != 'private':
await callback.message.answer(
@@ -305,14 +306,15 @@ async def cb_admin_broadcast(callback: CallbackQuery):
parse_mode='HTML'
)
return
-
+
await callback.message.answer(
'📤 Рассылка\n\n'
- 'Теперь отправьте сообщение, которое нужно разослать всем жильцам.\n\n'
+ 'Вариант 1: Отправьте текст\n'
+ 'Вариант 2: Отправьте картинку с подписью\n\n'
'Или отмените командой /cancel',
parse_mode='HTML'
)
-
+
# Включаем состояние
await callback.bot.set_state(callback.from_user.id, BroadcastState.waiting_for_message)
@@ -324,54 +326,81 @@ 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)
-
- # Подтверждаем
- await message.answer(
- f'📤 Начинаю рассылку...\n\n'
- f'Сообщение: {broadcast_text[:100]}...'
- )
+ """Обработка сообщения для рассылки (текст или фото)"""
+ # Проверяем что прислал админ
+ if message.photo:
+ # Это картинка с подписью
+ photo_id = message.photo[-1].file_id # Берём наибольшее качество
+ caption = message.caption or ''
+
+ # Отключаем состояние
+ await message.bot.delete_state(message.from_user.id)
+
+ # Подтверждаем
+ await message.answer(
+ f'📤 Начинаю рассылку с картинкой...\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'📤 Начинаю рассылку...\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'📢 Объявление от администрации\n\n'
- f'{broadcast_text}',
+ f'{text}',
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 message.bot.send_message(
+ await bot.send_message(
user.user_id,
f'📢 Объявление от администрации\n\n'
- f'{broadcast_text}',
+ f'{text}',
parse_mode='HTML'
)
success_count += 1
except Exception as e:
logger.error(f'Не удалось отправить пользователю {user.user_id}: {e}')
error_count += 1
-
+
# Отчёт админу
- await message.answer(
+ await bot.send_message(
+ config.ADMIN_USER_ID,
f'✅ Рассылка завершена!\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'📢 Объявление от администрации\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'📢 Объявление от администрации\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'✅ Рассылка с фото завершена!\n\n'
+ f'Успешно: {success_count}\n'
+ f'Ошибок: {error_count}\n'
+ f'В чат: ✅',
+ parse_mode='HTML'
+ )
+
+
# =============================================================================
# СНЯТИЕ ВЕРИФИКАЦИИ (БЫСТРОЕ)
# =============================================================================