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 форматирование:
жирный
курсив
подчеркивание
код
Введите /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"""✅ Сообщение создано: {context.user_data['message_title']}
Выберите группы для отправки (нажмите на каждую):"""
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"""✅ Сообщение готово!
Название: {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