diff --git a/photo_bot/__pycache__/handlers.cpython-313.pyc b/photo_bot/__pycache__/handlers.cpython-313.pyc
index 3e6d474..681a76c 100644
Binary files a/photo_bot/__pycache__/handlers.cpython-313.pyc and b/photo_bot/__pycache__/handlers.cpython-313.pyc differ
diff --git a/photo_bot/handlers.py b/photo_bot/handlers.py
index 16d74c5..3240af9 100644
--- a/photo_bot/handlers.py
+++ b/photo_bot/handlers.py
@@ -30,7 +30,7 @@ from utils.texts import (
photo_cancel_text,
photo_preview_ready,
photo_moderation_pending,
- photo_rejected_notice,
+ photo_welcome_with_status,
PHOTO_TEST_ENTRY_TEXT,
PHOTO_TEST_WELCOME_TEXT,
PHOTO_TEST_PREVIEW_TEXT,
@@ -158,14 +158,16 @@ async def check_moderation_status(user_id: str) -> dict:
async def send_dynamic_photo_main_menu(msg: Message, user_id: str):
"""Вход в раздел фото (паттерн ЛК): модуль сам запрашивает данные и показывает их.
- - pending — показать инфо «фото на модерации» и НЕ вводить в модуль
+ - pending — отдельное сообщение «фото на модерации», модуль НЕ открывается
(кнопок загрузки фото нет);
- - rejected — показать причину отказа, кнопки остаются (новое фото);
- - иначе/ошибка API — штатный вход в модуль.
+ - rejected — ОДНО сообщение: меню + причина отказа (кнопки на месте);
+ - иначе/ошибка API — штатное меню входа.
"""
+ status = None
if not config.PHOTO_TEST_MODE:
status = await check_moderation_status(user_id)
if status.get("status") == "ok" and status.get("moderation_status") == "pending":
+ # Фото на модерации — не вводим в модуль (кнопок загрузки нет)
photo_id = status.get("photo_id", "???")
log_menu_stats(user_id, "Photo Bot", "Вход заблокирован — фото на модерации")
await msg.answer(
@@ -173,22 +175,22 @@ async def send_dynamic_photo_main_menu(msg: Message, user_id: str):
parse_mode="html"
)
return
- elif status.get("status") == "ok" and status.get("moderation_status") == "rejected":
- reason = (status.get("rejection_reason") or "Причина не указана.").strip()
+ if status.get("status") == "ok" and status.get("moderation_status") == "rejected":
log_menu_stats(user_id, "Photo Bot", "Вход — фото отклонено, показана причина")
- await msg.answer(photo_rejected_notice(reason), parse_mode="html")
- # Меню показывается ниже: кнопки остаются, пользователь шлёт новое фото
elif status.get("status") != "ok":
logger.warning(
f"Не удалось проверить статус модерации для {user_id}: {status.get('reason')}"
)
+ status = None
states.set_state(user_id, "PHOTO_MODE")
log_menu_stats(user_id, "Photo Bot (TEST)" if config.PHOTO_TEST_MODE else "Photo Bot", "Вход")
- await msg.answer(
- PHOTO_TEST_ENTRY_TEXT if config.PHOTO_TEST_MODE else PHOTO_MAIN_MENU_TEXT,
- parse_mode="html"
- )
+ # Одно универсальное сообщение: меню + (если нужно) причина отказа
+ if config.PHOTO_TEST_MODE:
+ entry_text = PHOTO_TEST_ENTRY_TEXT
+ else:
+ entry_text = photo_welcome_with_status(status)
+ await msg.answer(entry_text, parse_mode="html")
# =========================================================
diff --git a/utils/__pycache__/texts.cpython-313.pyc b/utils/__pycache__/texts.cpython-313.pyc
new file mode 100644
index 0000000..b2b7bdf
Binary files /dev/null and b/utils/__pycache__/texts.cpython-313.pyc differ
diff --git a/utils/texts.py b/utils/texts.py
index e7385bd..2c90526 100644
--- a/utils/texts.py
+++ b/utils/texts.py
@@ -202,13 +202,17 @@ def sd_file_upload_error() -> str:
# --- Private functions (Internal logic) ---
-def _photo_welcome(emojis: dict, show_test: bool = False) -> str:
+def _photo_welcome(emojis: dict, show_test: bool = False, info: str = None) -> str:
+ """Входное сообщение фото-режима. info — необязательный блок о статусе
+ модерации (отказ/ожидание) — вставляется перед списком кнопок."""
text = (
f"🖼 Режим обновления фото профиля\n\n"
f"📸 Пришлите мне вашу фотографию.\n\n"
f"Бот автоматически найдёт лицо, покажет превью\n"
f"и отправит фото на публикацию в ваши корпоративные сервисы.\n\n"
)
+ if info:
+ text += info + "\n\n"
if show_test:
text += f"{emojis['1']} — тест проверка фото\n"
return text + f"{emojis['0']} — В главное меню"
@@ -245,12 +249,25 @@ def _photo_moderation_pending(photo_id: str, emojis: dict) -> str:
f"{emojis['0']} — В главное меню"
)
-def _photo_rejected_notice(reason: str, emojis: dict) -> str:
- return (
- f"⚠️ Ваше предыдущее фото было отклонено.\n\n"
- f"📝 Причина: {reason}\n\n"
- f"Пожалуйста, отправьте новое фото."
- )
+def _photo_status_info(status: dict = None, emojis: dict = None) -> str | None:
+ """Блок о статусе модерации для входного сообщения. Универсальный для всех
+ случаев: rejected → причина отказа, pending → ожидание, прочее → пусто."""
+ if not status or status.get("status") != "ok":
+ return None
+ ms = status.get("moderation_status")
+ if ms == "rejected":
+ reason = (status.get("rejection_reason") or "Причина не указана.").strip()
+ return (
+ f"⚠️ Ваше предыдущее фото было отклонено.\n"
+ f"📝 Причина: {reason}\n\n"
+ f"Пожалуйста, отправьте новое фото."
+ )
+ if ms == "pending":
+ return (
+ f"⏳ У вас уже есть фото на модерации.\n"
+ f"Ожидайте решения модератора."
+ )
+ return None
def _photo_test_welcome(emojis: dict) -> str:
return (
@@ -378,8 +395,11 @@ def photo_cancel_text() -> str:
def photo_moderation_pending(photo_id: str) -> str:
return _photo_moderation_pending(photo_id, EMOJI_DIGITS)
-def photo_rejected_notice(reason: str) -> str:
- return _photo_rejected_notice(reason, EMOJI_DIGITS)
+def photo_welcome_with_status(status: dict = None) -> str:
+ """Универсальное входное сообщение фото-режима: меню + статус модерации,
+ если он требует внимания (отказ с причиной)."""
+ info = _photo_status_info(status, EMOJI_DIGITS)
+ return _photo_welcome(EMOJI_DIGITS, info=info)
PHOTO_TEST_WELCOME_TEXT = _photo_test_welcome(EMOJI_DIGITS)
PHOTO_TEST_PREVIEW_TEXT = _photo_test_preview(EMOJI_DIGITS)