photo_bot: remove AI validator, restore prepare_ad_photo workflow

This commit is contained in:
2026-08-14 00:54:27 +07:00
parent 95803b2c3c
commit 9a9b90b3a1
+29 -39
View File
@@ -15,11 +15,19 @@ from trueconf.types import FSInputFile
import config.config as config import config.config as config
from utils import states from utils import states
from utils.menu import MENU_TEXT from utils.menu import MENU_TEXT
from utils.texts import * # 👈 Импортируем все тексты и константы проекта
# 🔌 Бизнес-логика обработки и ИИ-валидации
from photo_bot.photo_processor import prepare_ad_photo from photo_bot.photo_processor import prepare_ad_photo
from photo_bot.ai_validator import validate_photo_ai from utils.texts import (
EMOJI_DIGITS,
PHOTO_MAIN_MENU_TEXT,
system_error_text,
photo_error_handling,
PHOTO_UPLOADING_TEXT,
photo_success_sent,
photo_cancel_text,
PHOTO_PROCESSING_TEXT,
photo_preview_ready,
photo_error_processing,
)
# 🔌 Импортируем централизованную функцию сбора статистики из main # 🔌 Импортируем централизованную функцию сбора статистики из main
from utils.stats_logger import log_menu_stats from utils.stats_logger import log_menu_stats
@@ -94,6 +102,7 @@ def log_and_notify_photo_error(user_id: str, action: str, error_details: str):
async def handle_photo_error(msg: Message, user_id: str, action: str, error_details: str): async def handle_photo_error(msg: Message, user_id: str, action: str, error_details: str):
"""Вызывает системное логирование и выдает заглушку пользователю""" """Вызывает системное логирование и выдает заглушку пользователю"""
await asyncio.to_thread(log_and_notify_photo_error, user_id, action, error_details) await asyncio.to_thread(log_and_notify_photo_error, user_id, action, error_details)
await msg.answer(photo_error_handling(), parse_mode="html") await msg.answer(photo_error_handling(), parse_mode="html")
@@ -149,6 +158,7 @@ async def photo_module_handler(msg: Message):
response = await client.post(config.TRASH_API_URL, files=files) response = await client.post(config.TRASH_API_URL, files=files)
if response.status_code == 200: if response.status_code == 200:
# ФИКСАЦИЯ СТАТИСТИКИ: Успешная выгрузка фото на утверждение
log_menu_stats(user_id, "Photo Bot", "Отправка фото на утверждение") log_menu_stats(user_id, "Photo Bot", "Отправка фото на утверждение")
await msg.answer(photo_success_sent(), parse_mode="html") await msg.answer(photo_success_sent(), parse_mode="html")
@@ -176,6 +186,7 @@ async def photo_module_handler(msg: Message):
await msg.answer(photo_cancel_text(), parse_mode="html") await msg.answer(photo_cancel_text(), parse_mode="html")
return return
# --- ИСПРАВЛЕНО: Защита от мусорного ввода при висящем превью ---
else: else:
await msg.answer(system_error_text(EMOJI_DIGITS), parse_mode="html") await msg.answer(system_error_text(EMOJI_DIGITS), parse_mode="html")
return return
@@ -184,37 +195,20 @@ async def photo_module_handler(msg: Message):
if is_attachment: if is_attachment:
file_id = getattr(msg.content, "file_id", None) file_id = getattr(msg.content, "file_id", None)
ready_path = f"/tmp/{user_login}.bmp" ready_path = f"/tmp/{user_login}.bmp"
raw_path = f"/tmp/raw_{user_login}.webp" raw_path = None
await msg.answer(PHOTO_PROCESSING_TEXT, parse_mode="html") await msg.answer(PHOTO_PROCESSING_TEXT, parse_mode="html")
try: try:
# 1. Скачиваем байты файла из TrueConf downloaded_file = await states.tc_bot.download_file_by_id(file_id)
file_bytes = await states.tc_bot.download_file_by_id(file_id) raw_path = downloaded_file
result = await asyncio.to_thread(prepare_ad_photo, raw_path, ready_path, 96)
# 2. Сохраняем байты во временный файл на диск if result["success"]:
def save_raw_bytes(b_data, target_path): # ФИКСАЦИЯ СТАТИСТИКИ: Факт успешной загрузки и обработки нового фото
with open(target_path, "wb") as f: log_menu_stats(user_id, "Photo Bot", "Загрузка и конвертация нового фото")
f.write(b_data)
await asyncio.to_thread(save_raw_bytes, file_bytes, raw_path)
# 3. Техническая конвертация в BMP без геометрических проверок
def convert_to_bmp_only(src_path, dst_path):
with Image.open(src_path) as img:
img.convert("RGB").save(dst_path, format="BMP")
await asyncio.to_thread(convert_to_bmp_only, raw_path, ready_path)
# 4. ИИ-ПРОВЕРКА ЧЕРЕЗ GEMMA 4 VISION (srvkem-ii-03)
ai_res = await validate_photo_ai(raw_path)
if ai_res["success"] and ai_res["approved"]:
# --- УСПЕШНАЯ ПРОВЕРКА ИИ ---
log_menu_stats(user_id, "Photo Bot", "Загрузка фото: Одобрено ИИ")
pending_photos[user_id] = ready_path pending_photos[user_id] = ready_path
preview_path = f"/tmp/prev_{user_login}.jpg" preview_path = f"/tmp/prev_{user_login}.jpg"
try: try:
Image.open(ready_path).save(preview_path, format="JPEG") Image.open(ready_path).save(preview_path, format="JPEG")
p_main = FSInputFile(preview_path, filename="preview.jpg") p_main = FSInputFile(preview_path, filename="preview.jpg")
@@ -227,19 +221,16 @@ async def photo_module_handler(msg: Message):
os.remove(preview_path) os.remove(preview_path)
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
await msg.answer(photo_preview_ready(), parse_mode="html")
else:
# --- ИИ ОТКЛОНИЛ ФОТО ИЛИ ПРОИЗОШЛА ОШИБКА ---
log_menu_stats(user_id, "Photo Bot", "Загрузка фото: Отклонено ИИ")
reason_text = ai_res["text"] if ai_res["success"] else ai_res.get("error", "Не удалось проверить фото через ИИ.")
await msg.answer( await msg.answer(
f"<b>❌ Фотография не прошла проверку</b>\n\n{reason_text}", photo_preview_ready(),
parse_mode="html"
)
else:
error_text = result.get('error', 'Не удалось обработать фото.')
await msg.answer(
photo_error_processing(error_text),
parse_mode="html" parse_mode="html"
) )
except Exception as e: except Exception as e:
await handle_photo_error(msg, user_id, "Скачивание и обработка файла", str(e)) await handle_photo_error(msg, user_id, "Скачивание и обработка файла", str(e))
finally: finally:
@@ -249,4 +240,3 @@ async def photo_module_handler(msg: Message):
except Exception as cleanup_err: except Exception as cleanup_err:
await asyncio.to_thread(log_and_notify_photo_error, user_id, "Очистка временных файлов", str(cleanup_err)) await asyncio.to_thread(log_and_notify_photo_error, user_id, "Очистка временных файлов", str(cleanup_err))
return return