diff --git a/README.md b/README.md index 817962b..52d48cd 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,6 @@ docker compose up -d --build Везде используются inline-кнопки. При этом кнопки под старыми сообщениями автоматически удаляются. -История сообщений остаётся в чате с ботом. UX не строится на редактировании сообщений. - В первую очередь пользователям предлагается озвучить дорожки, которые никто ещё не начал озвучивать. Затем те дорожки, которые кто-то начал озвучивать, но ещё не закончил. И топлько потом дорожки, для которых уже озвучка. Тем не менее, одна дорожка может быть озвучена несколькими дикторами. ## Администрирование diff --git a/main.py b/main.py index f7360aa..626f964 100644 --- a/main.py +++ b/main.py @@ -49,8 +49,12 @@ def main() -> None: app.add_handler(CommandHandler("start", start_command)) app.add_handler(CommandHandler("admin", admin_command)) + # Message handlers для текстовых ответов (должны быть перед остальными) + app.add_handler( + MessageHandler(filters.TEXT & ~filters.COMMAND, handle_accept_intro) + ) + # Callback query handlers - app.add_handler(CallbackQueryHandler(handle_accept_intro, pattern="^accept_intro$")) app.add_handler( CallbackQueryHandler(handle_select_gender, pattern="^select_gender:") ) diff --git a/src/handlers.py b/src/handlers.py index 5128acf..06ca5a0 100644 --- a/src/handlers.py +++ b/src/handlers.py @@ -1,4 +1,11 @@ -from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update +from telegram import ( + InlineKeyboardButton, + InlineKeyboardMarkup, + KeyboardButton, + ReplyKeyboardMarkup, + ReplyKeyboardRemove, + Update, +) from telegram.ext import ContextTypes from src.config import ADMIN_LOGIN @@ -40,7 +47,18 @@ INTRO_TEXT = """👋 Добро пожаловать! 📋 Отправляя голосовые сообщения, вы соглашаетесь с тем, что они будут использованы в исследовательских целях для обучения моделей машинного обучения. -Нажмите кнопку ниже, чтобы начать.""" + +Для продолжения отправьте сообщение: + +``` +Принимаю условия +``` +""" + +ACCEPT_TEXT = "Принимаю условия" +INVALID_INTRO_RESPONSE = ( + f'❌ Для продолжения нажмите кнопку или отправьте: "{ACCEPT_TEXT}"' +) SPECIFY_GENDER_TEXT = """👤 Укажите ваш пол. @@ -76,15 +94,11 @@ REPEAT_REPLICA_TEXT = "🔄 Перезапись реплики {num}/{total}:" # === Клавиатуры === -def get_intro_keyboard() -> InlineKeyboardMarkup: - return InlineKeyboardMarkup( - [ - [ - InlineKeyboardButton( - "✅ Принять и продолжить", callback_data="accept_intro" - ) - ] - ] +def get_intro_keyboard() -> ReplyKeyboardMarkup: + return ReplyKeyboardMarkup( + [[KeyboardButton(ACCEPT_TEXT)]], + resize_keyboard=True, + one_time_keyboard=True, ) @@ -315,10 +329,10 @@ async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> N session = get_user_session(user.id) or create_new_session(user.id) session.state = UserState.INTRO - msg_id = await send_message_and_save( - update, context, session, INTRO_TEXT, get_intro_keyboard() + session.last_bot_message_id = None + await update.message.reply_text( + INTRO_TEXT, reply_markup=get_intro_keyboard(), parse_mode="Markdown" ) - session.last_bot_message_id = msg_id upsert_user_session(session) logger.info(f"User {user.id} started bot") @@ -350,20 +364,37 @@ async def admin_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> N # === Callback handlers === -@answer_callback @with_user_and_session -@require_state(UserState.INTRO) async def handle_accept_intro( - update: Update, context: ContextTypes.DEFAULT_TYPE, user: User, session: UserSession + update: Update, + context: ContextTypes.DEFAULT_TYPE, + user: User, + session: UserSession | None, ) -> None: - """Обработчик кнопки 'Принять и продолжить'.""" - query = update.callback_query - session.state = UserState.SPECIFY_GENDER - await query.edit_message_text( - SPECIFY_GENDER_TEXT, reply_markup=get_specify_gender_keyboard() + """Обработчик согласия с условиями.""" + if not session or session.state != UserState.INTRO: + return # Пропускаем, следующий обработчик обработает + + text = update.message.text.strip() + + if text != ACCEPT_TEXT: + await update.message.reply_text(INVALID_INTRO_RESPONSE) + return + + # Удаляем reply-клавиатуру + await update.message.reply_text( + "✅ Отлично!", + reply_markup=ReplyKeyboardRemove(), ) - session.last_bot_message_id = query.message.message_id + + session.state = UserState.SPECIFY_GENDER + msg = await update.message.reply_text( + SPECIFY_GENDER_TEXT, + reply_markup=get_specify_gender_keyboard(), + ) + session.last_bot_message_id = msg.message_id upsert_user_session(session) + logger.info(f"User {user.id} accepted intro") @answer_callback @@ -597,7 +628,9 @@ async def handle_exit_admin( # Показываем соответствующее сообщение if session.state == UserState.INTRO: - await query.edit_message_text(INTRO_TEXT, reply_markup=get_intro_keyboard()) + await query.edit_message_text( + INTRO_TEXT, reply_markup=get_intro_keyboard(), parse_mode="Markdown" + ) elif session.state == UserState.SPECIFY_GENDER: await query.edit_message_text( SPECIFY_GENDER_TEXT, reply_markup=get_specify_gender_keyboard()