feat: initial import (exclude templates and runtime temp files)
This commit is contained in:
199
app/api_get_routes.py
Normal file
199
app/api_get_routes.py
Normal file
@@ -0,0 +1,199 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import mimetypes
|
||||
from http import HTTPStatus
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from urllib.parse import parse_qs
|
||||
|
||||
|
||||
def handle_get_routes(handler: Any, parsed: Any, ctx: dict[str, Any]) -> bool:
|
||||
load_config = ctx["load_config"]
|
||||
resolve_template_path = ctx["resolve_template_path"]
|
||||
resolve_output_dir = ctx["resolve_output_dir"]
|
||||
resolve_history_path = ctx["resolve_history_path"]
|
||||
today_log_path = ctx["today_log_path"]
|
||||
list_issue_marks = ctx["list_issue_marks"]
|
||||
count_log_lines = ctx["count_log_lines"]
|
||||
load_history = ctx["load_history"]
|
||||
build_history_view_items = ctx["build_history_view_items"]
|
||||
get_generation_progress = ctx["get_generation_progress"]
|
||||
resolve_image_delivery_options = ctx["resolve_image_delivery_options"]
|
||||
ISSUE_MARKS_PATH = ctx["ISSUE_MARKS_PATH"]
|
||||
_HISTORY_LOCK = ctx["_HISTORY_LOCK"]
|
||||
_LOG_LOCK = ctx["_LOG_LOCK"]
|
||||
_DOWNLOAD_LOCK = ctx["_DOWNLOAD_LOCK"]
|
||||
DOWNLOAD_CACHE = ctx["DOWNLOAD_CACHE"]
|
||||
|
||||
if parsed.path == "/api/config":
|
||||
try:
|
||||
config = load_config()
|
||||
template = resolve_template_path(config)
|
||||
output = resolve_output_dir(config)
|
||||
except Exception as exc:
|
||||
handler._send_json({"ok": False, "error": str(exc)}, HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
return True
|
||||
|
||||
history_path = resolve_history_path(config)
|
||||
log_path = today_log_path()
|
||||
with _HISTORY_LOCK:
|
||||
history = load_history(history_path)
|
||||
_, active_issue_count = list_issue_marks(status="active", limit=1)
|
||||
|
||||
handler._send_json(
|
||||
{
|
||||
"ok": True,
|
||||
"config": {
|
||||
"template_file": str(template),
|
||||
"output_dir": str(output),
|
||||
"trigger_keyword": config.get("relay_handling", {}).get("trigger_keyword", "#接龙"),
|
||||
"allowed_branches": config.get("branches", {}).get("allowed", []),
|
||||
"type_matching": config.get("type_matching", {}),
|
||||
"status_fallback": config.get("status_extraction", {}).get("fallback", "成功营销"),
|
||||
"image_delivery": resolve_image_delivery_options(config),
|
||||
},
|
||||
"resolved_history_file": str(history_path),
|
||||
"history_count": len(history),
|
||||
"review_log_file": str(log_path),
|
||||
"review_log_count": count_log_lines(log_path),
|
||||
"issue_marks_file": str(ISSUE_MARKS_PATH),
|
||||
"active_issue_count": active_issue_count,
|
||||
"runtime_note": (
|
||||
"当前版本支持:多条解析、保险年限选择、生成PPT并按页导出PNG、逐图下载。"
|
||||
),
|
||||
}
|
||||
)
|
||||
return True
|
||||
|
||||
if parsed.path == "/api/log/today":
|
||||
path = today_log_path()
|
||||
logs: list[dict[str, Any]] = []
|
||||
if path.exists():
|
||||
with _LOG_LOCK:
|
||||
with path.open("r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
s = line.strip()
|
||||
if not s:
|
||||
continue
|
||||
try:
|
||||
obj = json.loads(s)
|
||||
except Exception:
|
||||
continue
|
||||
if isinstance(obj, dict):
|
||||
logs.append(obj)
|
||||
handler._send_json({"ok": True, "log_file": str(path), "count": len(logs), "logs": logs[-500:]})
|
||||
return True
|
||||
|
||||
if parsed.path == "/api/issues":
|
||||
try:
|
||||
params = parse_qs(parsed.query)
|
||||
status = str(params.get("status", ["active"])[0]).strip().lower()
|
||||
try:
|
||||
limit = int(params.get("limit", ["500"])[0])
|
||||
except Exception:
|
||||
limit = 500
|
||||
limit = max(1, min(2000, limit))
|
||||
items, total = list_issue_marks(status=status, limit=limit)
|
||||
except Exception as exc:
|
||||
handler._send_json({"ok": False, "error": str(exc)}, HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
return True
|
||||
|
||||
handler._send_json(
|
||||
{
|
||||
"ok": True,
|
||||
"status": status if status in {"active", "resolved", "all"} else "active",
|
||||
"count": total,
|
||||
"limit": limit,
|
||||
"items": items,
|
||||
}
|
||||
)
|
||||
return True
|
||||
|
||||
if parsed.path.startswith("/api/progress/"):
|
||||
token = parsed.path.split("/api/progress/", 1)[1].strip()
|
||||
if not token:
|
||||
handler._send_json({"ok": False, "error": "progress token missing"}, HTTPStatus.BAD_REQUEST)
|
||||
return True
|
||||
item = get_generation_progress(token)
|
||||
if item is None:
|
||||
handler._send_json({"ok": False, "error": "progress token not found"}, HTTPStatus.NOT_FOUND)
|
||||
return True
|
||||
handler._send_json({"ok": True, "progress": item})
|
||||
return True
|
||||
|
||||
if parsed.path == "/api/history":
|
||||
try:
|
||||
config = load_config()
|
||||
history_path = resolve_history_path(config)
|
||||
with _HISTORY_LOCK:
|
||||
history = load_history(history_path)
|
||||
except Exception as exc:
|
||||
handler._send_json({"ok": False, "error": str(exc)}, HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
return True
|
||||
|
||||
handler._send_json({"ok": True, "count": len(history), "history": history})
|
||||
return True
|
||||
|
||||
if parsed.path == "/api/history/view":
|
||||
try:
|
||||
config = load_config()
|
||||
history_path = resolve_history_path(config)
|
||||
params = parse_qs(parsed.query)
|
||||
try:
|
||||
limit = int(params.get("limit", ["300"])[0])
|
||||
except Exception:
|
||||
limit = 300
|
||||
limit = max(1, min(2000, limit))
|
||||
with _HISTORY_LOCK:
|
||||
history = load_history(history_path)
|
||||
items = build_history_view_items(history, config, limit=limit)
|
||||
except Exception as exc:
|
||||
handler._send_json({"ok": False, "error": str(exc)}, HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
return True
|
||||
|
||||
handler._send_json({"ok": True, "count": len(history), "limit": limit, "items": items})
|
||||
return True
|
||||
|
||||
if parsed.path.startswith("/api/download/"):
|
||||
token = parsed.path.split("/api/download/", 1)[1].strip()
|
||||
if not token:
|
||||
handler._send_json({"ok": False, "error": "download token missing"}, HTTPStatus.BAD_REQUEST)
|
||||
return True
|
||||
|
||||
with _DOWNLOAD_LOCK:
|
||||
meta = DOWNLOAD_CACHE.get(token)
|
||||
|
||||
if not meta:
|
||||
handler._send_json({"ok": False, "error": "download expired or invalid"}, HTTPStatus.NOT_FOUND)
|
||||
return True
|
||||
|
||||
file_path = Path(str(meta.get("file_path", "")))
|
||||
if not file_path.exists():
|
||||
handler._send_json({"ok": False, "error": "file missing"}, HTTPStatus.NOT_FOUND)
|
||||
return True
|
||||
|
||||
content_type = str(meta.get("content_type", "")).strip()
|
||||
if not content_type:
|
||||
content_type = mimetypes.guess_type(file_path.name)[0] or "application/octet-stream"
|
||||
filename = str(meta.get("filename", file_path.name))
|
||||
params = parse_qs(parsed.query)
|
||||
inline = str(params.get("inline", ["0"])[0]).lower() in {"1", "true", "yes"}
|
||||
rate_opts = {"max_kbps": 300, "chunk_size": 16 * 1024}
|
||||
try:
|
||||
config = load_config()
|
||||
cfg_opts = resolve_image_delivery_options(config)
|
||||
rate_opts["max_kbps"] = int(cfg_opts.get("max_kbps", 300))
|
||||
rate_opts["chunk_size"] = int(cfg_opts.get("chunk_size", 16 * 1024))
|
||||
except Exception:
|
||||
pass
|
||||
handler._send_file(
|
||||
file_path,
|
||||
content_type,
|
||||
filename=None if inline else filename,
|
||||
max_kbps=rate_opts["max_kbps"],
|
||||
chunk_size=rate_opts["chunk_size"],
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
Reference in New Issue
Block a user