Фаза 2: site/app.py → blueprint'ы (main, health, api), старый drhider.py удалён
Deploy drhider / validate (push) Waiting to run

This commit is contained in:
2026-07-12 08:34:06 +04:00
parent 2cf4e08100
commit 51bc1a79e7
7 changed files with 182 additions and 632 deletions
+37 -74
View File
@@ -1,87 +1,50 @@
"""
DrHider — Managed Flask приложение на платформе Штурвал.
Приложение создаётся фабрикой create_app().
Штурвал запускает Flask самостоятельно (без Dockerfile/gunicorn).
Роуты разнесены по blueprint'ам:
- main_bp: GET / — веб-интерфейс
- health_bp: GET /health — проверка живости
- api_bp: POST /api/drhider — обфускация документов
"""
import os
import io
import sys
import json
import zipfile
from flask import Flask, render_template, request, send_file, jsonify
from flask import Flask
# Добавляем корень в sys.path чтобы import drhider работал
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Добавляем корень проекта в sys.path для импорта пакета drhider
_sys_path_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if _sys_path_root not in sys.path:
sys.path.insert(0, _sys_path_root)
from drhider import obfuscate_files
app = Flask(__name__)
VERSION = "1.0.0"
MAX_BODY = 200 * 1024 * 1024 # 200 MB
# Версия приложения (меняется при изменениях)
VERSION = "2.0.0"
class LLMClient:
"""LLM-клиент для drhider (обнаружение компаний/ФИО)."""
def create_app():
"""Создать и настроить Flask-приложение.
def __init__(self):
import httpx
self._httpx = httpx
Returns:
Экземпляр Flask с зарегистрированными blueprint'ами.
"""
app = Flask(__name__)
def complete(self, prompt: str) -> str:
key = os.environ.get("LLM_KEY") or os.environ.get("LLM_API_KEY", "")
r = self._httpx.post(
os.environ.get("LLM_URL", "https://api.aillm.ru/v1/chat/completions"),
json={
"model": os.environ.get("LLM_MODEL", "gpt-oss-120b"),
"messages": [{"role": "user", "content": prompt}],
"max_tokens": 8000,
"temperature": 0.1,
},
headers={
"Authorization": f"Bearer {key}",
"Content-Type": "application/json",
},
timeout=120,
)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"]
# Конфигурация
app.config["VERSION"] = VERSION
app.config["MAX_CONTENT_LENGTH"] = 200 * 1024 * 1024 # 200 MB
# Регистрируем blueprint'ы
from routes import register_routes
register_routes(app)
return app
@app.route("/")
def index():
return render_template("index.html", version=VERSION)
@app.route("/health")
def health():
return jsonify({"ok": True, "version": VERSION})
@app.route("/api/drhider", methods=["POST"])
def api_drhider():
"""Обфускация: multipart/form-data с файлами → ZIP."""
uploaded = request.files.getlist("files")
if not uploaded:
return jsonify({"ok": False, "error": "Нет файлов"}), 400
files = []
for f in uploaded:
if f.filename:
files.append((f.filename, f.read(), f.mimetype or ""))
if not files:
return jsonify({"ok": False, "error": "Нет файлов"}), 400
try:
llm = LLMClient()
zip_data, _csv = obfuscate_files(files, llm_client=llm)
return send_file(
io.BytesIO(zip_data),
mimetype="application/zip",
as_attachment=True,
download_name="drhider_output.zip",
)
except Exception as e:
import traceback
traceback.print_exc()
return jsonify({"ok": False, "error": str(e)}), 500
# Экземпляр приложения — точка входа для Штурвала
app = create_app()