Files
TG_autoposter/app/handlers/message_manager.py
2025-12-18 05:55:32 +09:00

199 lines
7.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton
from telegram.ext import ContextTypes, ConversationHandler
from app.database import AsyncSessionLocal
from app.database.repository import (
GroupRepository, MessageRepository, MessageGroupRepository
)
from app.utils.keyboards import (
get_back_keyboard, get_main_keyboard, CallbackType
)
import logging
logger = logging.getLogger(__name__)
# Состояния для ConversationHandler
CREATE_MSG_TITLE = 1
CREATE_MSG_TEXT = 2
SELECT_GROUPS = 3
WAITING_GROUP_INPUT = 4
async def create_message_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Начало создания нового сообщения"""
query = update.callback_query
await query.answer()
text = "📝 Введите название сообщения (короткое описание):"
await query.edit_message_text(text)
return CREATE_MSG_TITLE
async def create_message_title(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Получаем название и просим текст"""
message = update.message
title = message.text.strip()
if len(title) > 100:
await message.reply_text("❌ Название слишком длинное (макс 100 символов)")
return CREATE_MSG_TITLE
context.user_data['message_title'] = title
text = """✏️ Теперь введите текст сообщения.
Вы можете использовать HTML форматирование:
<b>жирный</b>
<i>курсив</i>
<u>подчеркивание</u>
<code>код</code>
Введите /cancel для отмены"""
await message.reply_text(text, parse_mode='HTML')
return CREATE_MSG_TEXT
async def create_message_text(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Получаем текст и показываем выбор групп"""
message = update.message
if message.text == '/cancel':
await message.reply_text("❌ Отменено", reply_markup=get_main_keyboard())
return ConversationHandler.END
text = message.text.strip()
if len(text) > 4096:
await message.reply_text("❌ Текст слишком длинный (макс 4096 символов)")
return CREATE_MSG_TEXT
context.user_data['message_text'] = text
# Сохраняем сообщение в БД
async with AsyncSessionLocal() as session:
msg_repo = MessageRepository(session)
msg = await msg_repo.add_message(
text=text,
title=context.user_data['message_title']
)
context.user_data['message_id'] = msg.id
# Теперь показываем список групп для выбора
async with AsyncSessionLocal() as session:
group_repo = GroupRepository(session)
groups = await group_repo.get_all_active_groups()
if not groups:
await message.reply_text(
"❌ Нет активных групп. Сначала добавьте бота в группы.",
reply_markup=get_main_keyboard()
)
return ConversationHandler.END
# Создаем клавиатуру с группами
keyboard = []
for group in groups:
callback = f"select_group_{group.id}"
keyboard.append([InlineKeyboardButton(
f"{group.title} (delay: {group.slow_mode_delay}s)",
callback_data=callback
)])
keyboard.append([InlineKeyboardButton("✔️ Готово", callback_data="done_groups")])
keyboard.append([InlineKeyboardButton("❌ Отмена", callback_data=f"{CallbackType.MAIN_MENU}")])
text = f"""✅ Сообщение создано: <b>{context.user_data['message_title']}</b>
Выберите группы для отправки (нажмите на каждую):"""
await message.reply_text(
text,
parse_mode='HTML',
reply_markup=InlineKeyboardMarkup(keyboard)
)
context.user_data['selected_groups'] = []
return SELECT_GROUPS
async def select_groups(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Выбор групп для отправки"""
query = update.callback_query
callback_data = query.data
if callback_data == "done_groups":
# Подтверждаем выбор
selected = context.user_data.get('selected_groups', [])
if not selected:
await query.answer("❌ Выберите хотя бы одну группу", show_alert=True)
return SELECT_GROUPS
# Добавляем сообщение в выбранные группы
message_id = context.user_data['message_id']
async with AsyncSessionLocal() as session:
mg_repo = MessageGroupRepository(session)
for group_id in selected:
await mg_repo.add_message_to_group(message_id, group_id)
text = f"""✅ <b>Сообщение готово!</b>
Название: {context.user_data['message_title']}
Групп выбрано: {len(selected)}
Теперь вы можете отправить сообщение нажав кнопку "Отправить" в списке сообщений."""
await query.edit_message_text(text, parse_mode='HTML', reply_markup=get_main_keyboard())
return ConversationHandler.END
elif callback_data.startswith("select_group_"):
group_id = int(callback_data.split("_")[2])
selected = context.user_data.get('selected_groups', [])
if group_id in selected:
selected.remove(group_id)
else:
selected.append(group_id)
context.user_data['selected_groups'] = selected
# Обновляем клавиатуру
async with AsyncSessionLocal() as session:
group_repo = GroupRepository(session)
groups = await group_repo.get_all_active_groups()
keyboard = []
for group in groups:
callback = f"select_group_{group.id}"
is_selected = group.id in selected
prefix = "" if is_selected else ""
keyboard.append([InlineKeyboardButton(
f"{prefix} {group.title} (delay: {group.slow_mode_delay}s)",
callback_data=callback
)])
keyboard.append([InlineKeyboardButton("✔️ Готово", callback_data="done_groups")])
keyboard.append([InlineKeyboardButton("❌ Отмена", callback_data=f"{CallbackType.MAIN_MENU}")])
await query.edit_message_text(
f"Выбрано групп: {len(selected)}",
reply_markup=InlineKeyboardMarkup(keyboard)
)
await query.answer()
return SELECT_GROUPS
elif callback_data == CallbackType.MAIN_MENU:
# Отмена
await query.answer()
await query.edit_message_text(
"❌ Создание сообщения отменено",
reply_markup=get_main_keyboard()
)
return ConversationHandler.END
await query.answer()
return SELECT_GROUPS