Удаление сценариев

This commit is contained in:
2026-02-02 22:57:27 +03:00
parent 73c6986645
commit d0445d4480
6 changed files with 305 additions and 10 deletions

View File

@@ -6,14 +6,18 @@ from src.database import (
User,
UserSession,
UserState,
delete_scenario_data,
delete_user_recordings_for_scenario,
get_all_scenarios,
get_connection,
get_or_create_user,
get_replicas_for_track,
get_scenario,
get_scenario_stats,
get_stats,
get_user_session,
get_users_in_state,
get_users_with_scenario,
upsert_user_session,
)
from src.decorators import answer_callback, require_state, with_user_and_session
@@ -135,11 +139,16 @@ def get_ask_replica_number_keyboard() -> InlineKeyboardMarkup:
def get_admin_keyboard() -> InlineKeyboardMarkup:
return InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
"🗑 Удалить сценарий", callback_data="delete_scenario_list"
)
],
[
InlineKeyboardButton(
"👤 Вернуться в пользовательский режим", callback_data="exit_admin"
)
]
],
]
)
@@ -153,6 +162,28 @@ def get_admin_upload_confirm_keyboard() -> InlineKeyboardMarkup:
)
def get_admin_delete_list_keyboard() -> InlineKeyboardMarkup:
"""Клавиатура со списком сценариев для удаления."""
scenarios = get_all_scenarios()
buttons = [
[InlineKeyboardButton(f"📄 {s.id}", callback_data=f"delete_scenario:{s.id}")]
for s in scenarios
]
buttons.append(
[InlineKeyboardButton("❌ Отмена", callback_data="cancel_delete_list")]
)
return InlineKeyboardMarkup(buttons)
def get_admin_delete_confirm_keyboard() -> InlineKeyboardMarkup:
return InlineKeyboardMarkup(
[
[InlineKeyboardButton("🗑 Да, удалить", callback_data="confirm_delete")],
[InlineKeyboardButton("❌ Отмена", callback_data="cancel_delete")],
]
)
# === Вспомогательные функции ===
@@ -580,6 +611,171 @@ async def handle_cancel_upload(
upsert_user_session(session)
# === Delete scenario handlers ===
@answer_callback
@with_user_and_session
@require_state(UserState.ADMIN)
async def handle_delete_scenario_list(
update: Update, context: ContextTypes.DEFAULT_TYPE, user: User, session: UserSession
) -> None:
"""Показывает список сценариев для удаления."""
query = update.callback_query
scenarios = get_all_scenarios()
if not scenarios:
await query.edit_message_text(
"📭 Нет сценариев для удаления.\n\n" + format_admin_stats(),
reply_markup=get_admin_keyboard(),
)
return
try:
await query.edit_message_text(
"🗑 Выберите сценарий для удаления:",
reply_markup=get_admin_delete_list_keyboard(),
)
except Exception:
pass # Сообщение уже такое же
session.last_bot_message_id = query.message.message_id
upsert_user_session(session)
@answer_callback
@with_user_and_session
@require_state(UserState.ADMIN)
async def handle_select_scenario_delete(
update: Update, context: ContextTypes.DEFAULT_TYPE, user: User, session: UserSession
) -> None:
"""Обработчик выбора сценария для удаления."""
query = update.callback_query
scenario_id = query.data.replace("delete_scenario:", "")
stats = get_scenario_stats(scenario_id)
context.user_data["pending_delete_scenario"] = scenario_id
text = f"""🗑 Удаление сценария: {scenario_id}
📊 Статистика:
- Дорожек: {stats["total_tracks"]}
- Реплик: {stats["total_replicas"]}
- Записей: {stats["total_recordings"]}
⚠️ Это действие необратимо!
Будут удалены все записи из БД и файлы из data/ и data_partial/.
Пользователи, озвучивающие этот сценарий, будут перенаправлены."""
session.state = UserState.ADMIN_DELETE_CONFIRM
await query.edit_message_text(
text, reply_markup=get_admin_delete_confirm_keyboard()
)
session.last_bot_message_id = query.message.message_id
upsert_user_session(session)
@answer_callback
@with_user_and_session
@require_state(UserState.ADMIN_DELETE_CONFIRM)
async def handle_confirm_delete(
update: Update, context: ContextTypes.DEFAULT_TYPE, user: User, session: UserSession
) -> None:
"""Подтверждение удаления сценария."""
query = update.callback_query
scenario_id = context.user_data.get("pending_delete_scenario")
if not scenario_id:
await query.edit_message_text("❌ Данные потеряны. Попробуйте снова.")
session.state = UserState.ADMIN
upsert_user_session(session)
return
from src.scenarios import delete_scenario_files
# Получаем пользователей, которые озвучивают этот сценарий
affected_users = get_users_with_scenario(scenario_id)
# Удаляем файлы и данные
deleted_files = delete_scenario_files(scenario_id)
delete_scenario_data(scenario_id)
del context.user_data["pending_delete_scenario"]
# Уведомляем и перенаправляем пользователей
for affected_user_id, telegram_id in affected_users:
if affected_user_id == user.id:
continue # Админа обработаем отдельно
try:
affected_session = get_user_session(affected_user_id)
if affected_session:
track = find_available_track(affected_user_id)
if track:
new_scenario_id, speaker_id = track
affected_session.state = UserState.FIRST_REPLICA
affected_session.scenario_id = new_scenario_id
affected_session.speaker_id = speaker_id
affected_session.replica_index = 0
msg = (
" Сценарий, который вы озвучивали, был удалён. Начинаем новый!"
)
else:
affected_session.state = UserState.NO_MORE_SCENARIOS
affected_session.scenario_id = None
affected_session.speaker_id = None
affected_session.replica_index = None
msg = (
" Сценарий, который вы озвучивали, был удалён.\n\n"
+ NO_MORE_SCENARIOS_TEXT
)
upsert_user_session(affected_session)
await context.bot.send_message(telegram_id, msg)
except Exception:
pass
session.state = UserState.ADMIN
await query.edit_message_text(
f"✅ Сценарий {scenario_id} удалён! (файлов: {deleted_files})\n\n"
+ format_admin_stats(),
reply_markup=get_admin_keyboard(),
)
session.last_bot_message_id = query.message.message_id
upsert_user_session(session)
logger.info(f"Scenario {scenario_id} deleted, affected: {len(affected_users)}")
@answer_callback
@with_user_and_session
@require_state(UserState.ADMIN_DELETE_CONFIRM)
async def handle_cancel_delete(
update: Update, context: ContextTypes.DEFAULT_TYPE, user: User, session: UserSession
) -> None:
"""Отмена удаления сценария."""
query = update.callback_query
context.user_data.pop("pending_delete_scenario", None)
session.state = UserState.ADMIN
await query.edit_message_text(
format_admin_stats(), reply_markup=get_admin_keyboard()
)
session.last_bot_message_id = query.message.message_id
upsert_user_session(session)
@answer_callback
@with_user_and_session
@require_state(UserState.ADMIN)
async def handle_cancel_delete_list(
update: Update, context: ContextTypes.DEFAULT_TYPE, user: User, session: UserSession
) -> None:
"""Отмена выбора сценария для удаления."""
query = update.callback_query
await query.edit_message_text(
format_admin_stats(), reply_markup=get_admin_keyboard()
)
session.last_bot_message_id = query.message.message_id
upsert_user_session(session)
# === Message handlers ===