Files
Random-image-api/backend/app/api/admin/summary.py
T
2026-02-22 18:58:55 +08:00

157 lines
6.2 KiB
Python

from __future__ import annotations
import json
from typing import Any
from fastapi import APIRouter, Depends, Request
from app.api.admin.deps import get_admin_claims
from app.core.request_id import get_or_create_request_id
from app.db.session import with_sqlite_busy_retry
router = APIRouter()
def _worker_last_seen_from_value_json(value_json: str | None) -> str | None:
if value_json is None:
return None
raw = str(value_json or "").strip()
if not raw:
return None
try:
data = json.loads(raw)
except Exception:
return None
if isinstance(data, dict):
at = data.get("at")
return str(at) if isinstance(at, str) and at.strip() else None
if isinstance(data, str):
return data.strip() or None
return None
@router.get("/summary")
async def get_summary(
request: Request,
_claims: dict[str, Any] = Depends(get_admin_claims),
) -> dict[str, Any]:
_ = _claims
rid = get_or_create_request_id(request)
engine = request.app.state.engine
async def _op() -> dict[str, Any]:
async with engine.connect() as conn:
images_total = int((await conn.exec_driver_sql("SELECT COUNT(*) FROM images;")).scalar_one())
images_enabled = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM images WHERE status=1;")).scalar_one()
)
missing_tags = int(
(
await conn.exec_driver_sql(
"""
SELECT COUNT(*)
FROM images
WHERE status=1
AND id NOT IN (SELECT DISTINCT image_id FROM image_tags);
""".strip()
)
).scalar_one()
)
missing_geometry = int(
(
await conn.exec_driver_sql(
"SELECT COUNT(*) FROM images WHERE status=1 AND (width IS NULL OR height IS NULL);"
)
).scalar_one()
)
missing_r18 = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM images WHERE status=1 AND x_restrict IS NULL;")).scalar_one()
)
missing_ai = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM images WHERE status=1 AND ai_type IS NULL;")).scalar_one()
)
missing_illust_type = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM images WHERE status=1 AND illust_type IS NULL;")).scalar_one()
)
missing_user = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM images WHERE status=1 AND user_id IS NULL;")).scalar_one()
)
missing_title = int(
(
await conn.exec_driver_sql(
"SELECT COUNT(*) FROM images WHERE status=1 AND (title IS NULL OR TRIM(title)='');"
)
).scalar_one()
)
missing_created_at = int(
(
await conn.exec_driver_sql(
"SELECT COUNT(*) FROM images WHERE status=1 AND (created_at_pixiv IS NULL OR TRIM(created_at_pixiv)='');"
)
).scalar_one()
)
missing_popularity = int(
(
await conn.exec_driver_sql(
"SELECT COUNT(*) FROM images "
"WHERE status=1 AND (bookmark_count IS NULL OR view_count IS NULL OR comment_count IS NULL);"
)
).scalar_one()
)
tokens_total = int((await conn.exec_driver_sql("SELECT COUNT(*) FROM pixiv_tokens;")).scalar_one())
tokens_enabled = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM pixiv_tokens WHERE enabled=1;")).scalar_one()
)
proxies_total = int((await conn.exec_driver_sql("SELECT COUNT(*) FROM proxy_endpoints;")).scalar_one())
proxies_enabled = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM proxy_endpoints WHERE enabled=1;")).scalar_one()
)
pools_total = int((await conn.exec_driver_sql("SELECT COUNT(*) FROM proxy_pools;")).scalar_one())
pools_enabled = int(
(await conn.exec_driver_sql("SELECT COUNT(*) FROM proxy_pools WHERE enabled=1;")).scalar_one()
)
bindings_total = int((await conn.exec_driver_sql("SELECT COUNT(*) FROM token_proxy_bindings;")).scalar_one())
jobs_counts: dict[str, int] = {}
rows = (await conn.exec_driver_sql("SELECT status, COUNT(*) AS c FROM jobs GROUP BY status;")).fetchall()
for status, count in rows:
jobs_counts[str(status)] = int(count)
worker_last_seen_json = (
await conn.exec_driver_sql("SELECT value_json FROM runtime_settings WHERE key = ?;", ("worker.last_seen_at",))
).scalar_one_or_none()
worker_last_seen_at = _worker_last_seen_from_value_json(str(worker_last_seen_json) if worker_last_seen_json is not None else None)
return {
"images": {"total": images_total, "enabled": images_enabled},
"hydration": {
"enabled_images_total": images_enabled,
"missing": {
"tags": missing_tags,
"geometry": missing_geometry,
"r18": missing_r18,
"ai": missing_ai,
"illust_type": missing_illust_type,
"user": missing_user,
"title": missing_title,
"created_at": missing_created_at,
"popularity": missing_popularity,
},
},
"tokens": {"total": tokens_total, "enabled": tokens_enabled},
"proxies": {"endpoints_total": proxies_total, "endpoints_enabled": proxies_enabled},
"proxy_pools": {"total": pools_total, "enabled": pools_enabled},
"bindings": {"total": bindings_total},
"jobs": {"counts": jobs_counts},
"worker": {"last_seen_at": worker_last_seen_at},
}
counts = await with_sqlite_busy_retry(_op)
return {"ok": True, "counts": counts, "request_id": rid}