Spaces:
Runtime error
Runtime error
File size: 4,446 Bytes
75557db | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | """
api/database.py — Endpoints quản lý database face (danh sách & xóa theo tên)
GET /api/faces — Danh sách khuôn mặt (RESTful)
GET /api/db — Legacy alias
DELETE /api/db/<filename> — Legacy: xóa theo tên file (backward compat)
GET /api/unknown-faces — Danh sách khuôn mặt chưa nhận diện
"""
import logging
import os
from flask import Blueprint, jsonify
from face_model.analyzer import face_analyzer
from storage.mongo_storage import mongo_storage
from storage.pg_storage import pg_storage
logger = logging.getLogger("api.database")
bp = Blueprint("database", __name__, url_prefix="/api")
@bp.get("/faces")
def list_faces():
"""
GET /api/faces
Trả về danh sách khuôn mặt đã đăng ký từ Supabase + MongoDB.
"""
try:
persons = pg_storage.list_persons_with_faces()
faces = [
{
"filename": f"{p['full_name']}.jpg",
"name": p["full_name"],
"person_id": p["person_id"],
"status": p.get("status", "active"),
"total_appearances": p.get("total_appearances", 0),
"last_seen_at": p.get("last_seen_at"),
"url": f"/api/face-crops/{p['face_crop_mongo_id']}" if p.get("face_crop_mongo_id") else None,
}
for p in persons
]
return jsonify({
"total": len(faces),
"faces": faces,
}), 200
except Exception as e:
logger.error(f"[list_faces] Error: {e}", exc_info=True)
return jsonify({"error": {
"code": "FETCH_FAILED",
"message": f"Lỗi khi lấy danh sách khuôn mặt: {e}",
"status": 500,
}}), 500
@bp.get("/db")
def list_faces_legacy():
"""
Legacy alias GET /api/db (backward compatibility với frontend).
Response format giữ nguyên để frontend không cần sửa.
"""
try:
persons = pg_storage.list_persons_with_faces()
faces = [
{
"filename": f"{p['full_name']}.jpg",
"name": p["full_name"],
"url": f"/api/face-crops/{p['face_crop_mongo_id']}" if p.get("face_crop_mongo_id") else "",
}
for p in persons
]
return jsonify({
"total": len(faces),
"faces": faces,
}), 200
except Exception as e:
logger.error(f"[list_faces_legacy] Error: {e}", exc_info=True)
return jsonify({"detail": f"Lỗi khi lấy danh sách khuôn mặt: {e}"}), 500
@bp.delete("/db/<filename>")
def delete_face_legacy(filename: str):
"""
Legacy DELETE /api/db/<filename> — Xóa theo tên file (backward compat với frontend).
"""
name = os.path.splitext(filename)[0]
try:
success, mongo_ids = pg_storage.delete_person_by_name(name)
if not success:
return jsonify({"detail": "Không tìm thấy người này trong database."}), 404
for mid in mongo_ids:
mongo_storage.delete_face_crop(mid)
# Xóa khỏi RAM cache (theo tên)
to_remove = [
pid for pid, n in zip(face_analyzer.known_person_ids, face_analyzer.known_names)
if n == name
]
for pid in to_remove:
face_analyzer.remove_from_cache(pid)
return jsonify({
"success": True,
"message": f"Đã xóa thành công {name} khỏi database.",
"total_faces": face_analyzer.total,
}), 200
except Exception as e:
logger.error(f"[delete_face_legacy] Error: {e}", exc_info=True)
return jsonify({"detail": f"Lỗi khi xóa khuôn mặt: {e}"}), 500
@bp.get("/unknown-faces")
def list_unknown_faces():
"""
GET /api/unknown-faces
Trả về danh sách khuôn mặt chưa nhận diện từ MongoDB.
"""
try:
unknowns = mongo_storage.list_unknown_faces(limit=50)
return jsonify({
"total": len(unknowns),
"unknown_faces": unknowns,
}), 200
except Exception as e:
logger.error(f"[list_unknown_faces] Error: {e}", exc_info=True)
return jsonify({"error": {
"code": "FETCH_FAILED",
"message": f"Lỗi khi lấy danh sách unknown faces: {e}",
"status": 500,
}}), 500
|