AlexRitter66/Gazetta-control
0
1import streamlit as st2import sqlite33import fitz # PyMuPDF4from PIL import Image5from google import genai6import os7import json # Добавили для безопасной работы с ответами нейросети8 9# --- НАСТРОЙКИ СТРАНИЦЫ ---10st.set_page_config(page_title="PRO-Корректор 2.0", page_icon="🗞️", layout="wide")11 12# Получаем секретный ключ из настроек сервера13API_KEY = os.environ.get("GEMINI_API_KEY")14 15# --- БАЗА ДАННЫХ ---16def init_db():17 # Конструкция "with" гарантирует, что база закроется, даже если будет сбой18 with sqlite3.connect('database.db') as conn:19 cursor = conn.cursor()20 cursor.execute('''CREATE TABLE IF NOT EXISTS access_keys 21 (key_string TEXT PRIMARY KEY, key_type TEXT, is_active BOOLEAN DEFAULT 1, tg_id INTEGER)''')22 conn.commit()23 24def check_key(key_string):25 with sqlite3.connect('database.db') as conn:26 cursor = conn.cursor()27 cursor.execute("SELECT key_type FROM access_keys WHERE key_string = ? AND is_active = 1", (key_string,))28 result = cursor.fetchone()29 return result[0] if result else None30 31# --- ИНТЕРФЕЙС ---32st.title("🗞️ PRO-Корректор: Нейро-редактор газетных полос")33st.markdown("Добро пожаловать в систему автоматического анализа верстки и текстов.")34 35init_db()36 37if "access_granted" not in st.session_state:38 st.session_state.access_granted = False39 st.session_state.key_type = None40 41# Экран авторизации42if not st.session_state.access_granted:43 st.subheader("🔒 Вход в систему")44 user_key = st.text_input("Введите ваш ключ доступа (TRIAL или PREMIUM):", type="password")45 46 if st.button("Войти"):47 if user_key.strip() == "":48 st.warning("⚠️ Пожалуйста, введите ключ.")49 else:50 key_type = check_key(user_key.strip())51 if key_type:52 st.session_state.access_granted = True53 st.session_state.key_type = key_type54 st.success(f"✅ Доступ разрешен! Режим: {key_type.upper()}")55 st.rerun()56 else:57 st.error("❌ Неверный ключ или срок его действия истек.")58 59# Основной рабочий экран60else:61 st.sidebar.success(f"🔑 Активный режим: {st.session_state.key_type.upper()}")62 if st.sidebar.button("Выйти"):63 st.session_state.access_granted = False64 st.rerun()65 66 if not API_KEY:67 st.error("⚠️ Системная ошибка: API-ключ не найден в настройках сервера. Обратитесь к администратору.")68 else:69 st.subheader("📄 Анализ полосы")70 uploaded_file = st.file_uploader("Загрузите полосу газеты (PDF, JPG, PNG)", type=["pdf", "jpg", "jpeg", "png"])71 72 if uploaded_file:73 if st.button("🚀 Начать проверку"):74 with st.spinner("Анализирую макет..."):75 doc = None # Объявляем заранее для безопасного закрытия76 try:77 # Инициализация Gemini API скрытым ключом78 client = genai.Client(api_key=API_KEY)79 80 # Подготовка изображения81 if uploaded_file.name.lower().endswith('.pdf'):82 doc = fitz.open(stream=uploaded_file.read(), filetype="pdf")83 page = doc.load_page(0)84 pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))85 img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)86 else:87 img = Image.open(uploaded_file)88 89 st.image(img, caption="Загруженная полоса", use_container_width=True)90 91 # Обновленный промпт с жестким указанием структуры JSON92 prompt = """93 Ты - профессиональный военный журналист и выпускающий редактор.94 Проанализируй эту газетную полосу и выдай структурированный JSON.95 Отвечай ТОЛЬКО кодом, без приветствий и лишнего текста, строго в таком формате:96 {97 "Critical": "описание грубых ошибок (смысл, заголовки, фото)",98 "Layout": "описание ошибок верстки (висячие строки, выравнивание)",99 "Grammar": "описание орфографии и стилистики"100 }101 """102 103 response = client.models.generate_content(104 model='gemini-2.5-flash',105 contents=[img, prompt]106 )107 108 # Очистка ответа от Markdown-мусора (если нейросеть всё же добавит ```json)109 raw_text = response.text.strip()110 if raw_text.startswith("```"):111 raw_text = raw_text.split("\n", 1)[-1]112 if raw_text.endswith("```"):113 raw_text = raw_text.rsplit("\n", 1)[0]114 115 st.subheader("📊 Результаты проверки:")116 try:117 parsed_json = json.loads(raw_text)118 st.json(parsed_json)119 except json.JSONDecodeError:120 # Запасной вариант: если JSON не получился, выводим как обычный текст121 st.write(raw_text)122 123 except Exception as e:124 st.error(f"⚠️ Ошибка при анализе: {e}")125 finally:126 # Защита от утечки оперативной памяти сервера127 if doc is not None:128 doc.close()