Явное принятие согласия

This commit is contained in:
2026-02-04 13:47:01 +03:00
parent d51bbe04ba
commit bb13f60944
3 changed files with 62 additions and 27 deletions

View File

@@ -71,8 +71,6 @@ docker compose up -d --build
Везде используются inline-кнопки. При этом кнопки под старыми сообщениями автоматически удаляются. Везде используются inline-кнопки. При этом кнопки под старыми сообщениями автоматически удаляются.
История сообщений остаётся в чате с ботом. UX не строится на редактировании сообщений.
В первую очередь пользователям предлагается озвучить дорожки, которые никто ещё не начал озвучивать. Затем те дорожки, которые кто-то начал озвучивать, но ещё не закончил. И топлько потом дорожки, для которых уже озвучка. Тем не менее, одна дорожка может быть озвучена несколькими дикторами. В первую очередь пользователям предлагается озвучить дорожки, которые никто ещё не начал озвучивать. Затем те дорожки, которые кто-то начал озвучивать, но ещё не закончил. И топлько потом дорожки, для которых уже озвучка. Тем не менее, одна дорожка может быть озвучена несколькими дикторами.
## Администрирование ## Администрирование

View File

@@ -49,8 +49,12 @@ def main() -> None:
app.add_handler(CommandHandler("start", start_command)) app.add_handler(CommandHandler("start", start_command))
app.add_handler(CommandHandler("admin", admin_command)) app.add_handler(CommandHandler("admin", admin_command))
# Message handlers для текстовых ответов (должны быть перед остальными)
app.add_handler(
MessageHandler(filters.TEXT & ~filters.COMMAND, handle_accept_intro)
)
# Callback query handlers # Callback query handlers
app.add_handler(CallbackQueryHandler(handle_accept_intro, pattern="^accept_intro$"))
app.add_handler( app.add_handler(
CallbackQueryHandler(handle_select_gender, pattern="^select_gender:") CallbackQueryHandler(handle_select_gender, pattern="^select_gender:")
) )

View File

@@ -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 telegram.ext import ContextTypes
from src.config import ADMIN_LOGIN from src.config import ADMIN_LOGIN
@@ -40,7 +47,18 @@ INTRO_TEXT = """👋 Добро пожаловать!
📋 Отправляя голосовые сообщения, вы соглашаетесь с тем, что они будут 📋 Отправляя голосовые сообщения, вы соглашаетесь с тем, что они будут
использованы в исследовательских целях для обучения моделей машинного обучения. использованы в исследовательских целях для обучения моделей машинного обучения.
Нажмите кнопку ниже, чтобы начать."""
Для продолжения отправьте сообщение:
```
Принимаю условия
```
"""
ACCEPT_TEXT = "Принимаю условия"
INVALID_INTRO_RESPONSE = (
f'❌ Для продолжения нажмите кнопку или отправьте: "{ACCEPT_TEXT}"'
)
SPECIFY_GENDER_TEXT = """👤 Укажите ваш пол. SPECIFY_GENDER_TEXT = """👤 Укажите ваш пол.
@@ -76,15 +94,11 @@ REPEAT_REPLICA_TEXT = "🔄 Перезапись реплики {num}/{total}:"
# === Клавиатуры === # === Клавиатуры ===
def get_intro_keyboard() -> InlineKeyboardMarkup: def get_intro_keyboard() -> ReplyKeyboardMarkup:
return InlineKeyboardMarkup( return ReplyKeyboardMarkup(
[ [[KeyboardButton(ACCEPT_TEXT)]],
[ resize_keyboard=True,
InlineKeyboardButton( one_time_keyboard=True,
"✅ Принять и продолжить", callback_data="accept_intro"
)
]
]
) )
@@ -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 = get_user_session(user.id) or create_new_session(user.id)
session.state = UserState.INTRO session.state = UserState.INTRO
msg_id = await send_message_and_save( session.last_bot_message_id = None
update, context, session, INTRO_TEXT, get_intro_keyboard() 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) upsert_user_session(session)
logger.info(f"User {user.id} started bot") 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 === # === Callback handlers ===
@answer_callback
@with_user_and_session @with_user_and_session
@require_state(UserState.INTRO)
async def handle_accept_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: ) -> None:
"""Обработчик кнопки 'Принять и продолжить'.""" """Обработчик согласия с условиями."""
query = update.callback_query if not session or session.state != UserState.INTRO:
session.state = UserState.SPECIFY_GENDER return # Пропускаем, следующий обработчик обработает
await query.edit_message_text(
SPECIFY_GENDER_TEXT, reply_markup=get_specify_gender_keyboard() 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) upsert_user_session(session)
logger.info(f"User {user.id} accepted intro")
@answer_callback @answer_callback
@@ -597,7 +628,9 @@ async def handle_exit_admin(
# Показываем соответствующее сообщение # Показываем соответствующее сообщение
if session.state == UserState.INTRO: 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: elif session.state == UserState.SPECIFY_GENDER:
await query.edit_message_text( await query.edit_message_text(
SPECIFY_GENDER_TEXT, reply_markup=get_specify_gender_keyboard() SPECIFY_GENDER_TEXT, reply_markup=get_specify_gender_keyboard()