Introduce an admin portal (React + Nginx), WebSocket routing, and API versioning middleware with `/api/v1/` prefix deprecation. Add master API key authentication, new Prometheus metrics for AI token consumption and active WebSockets, and extend S3 config with a public endpoint URL. Update test paths and fixtures to align with the new routing structure.
85 lines
2.4 KiB
Python
85 lines
2.4 KiB
Python
"""
|
|
Data models for the Imago Client SDK.
|
|
"""
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Dict, List, Optional
|
|
from datetime import datetime
|
|
|
|
@dataclass
|
|
class ExifCamera:
|
|
make: Optional[str] = None
|
|
model: Optional[str] = None
|
|
lens: Optional[str] = None
|
|
iso: Optional[int] = None
|
|
aperture: Optional[str] = None
|
|
shutter_speed: Optional[str] = None
|
|
focal_length: Optional[str] = None
|
|
flash: Optional[int] = None
|
|
orientation: Optional[int] = None
|
|
software: Optional[str] = None
|
|
taken_at: Optional[datetime] = None
|
|
|
|
@dataclass
|
|
class ExifGPS:
|
|
latitude: Optional[float] = None
|
|
longitude: Optional[float] = None
|
|
altitude: Optional[float] = None
|
|
has_gps: bool = False
|
|
maps_url: Optional[str] = None
|
|
|
|
@dataclass
|
|
class ExifData:
|
|
camera: Optional[ExifCamera] = None
|
|
gps: Optional[ExifGPS] = None
|
|
raw: Optional[Dict[str, Any]] = None
|
|
|
|
@dataclass
|
|
class OcrData:
|
|
has_text: bool = False
|
|
text: Optional[str] = None
|
|
language: Optional[str] = None
|
|
confidence: Optional[float] = None
|
|
|
|
@dataclass
|
|
class AiData:
|
|
description: Optional[str] = None
|
|
tags: List[str] = field(default_factory=list)
|
|
confidence: Optional[float] = None
|
|
model_used: Optional[str] = None
|
|
processed_at: Optional[datetime] = None
|
|
prompt_tokens: Optional[int] = None
|
|
output_tokens: Optional[int] = None
|
|
|
|
@dataclass
|
|
class ProcessingInfo:
|
|
status: str
|
|
error: Optional[str] = None
|
|
started_at: Optional[datetime] = None
|
|
done_at: Optional[datetime] = None
|
|
|
|
@dataclass
|
|
class HubImage:
|
|
id: int
|
|
uuid: str
|
|
original_name: str
|
|
mime_type: Optional[str] = None
|
|
file_size: Optional[int] = None
|
|
width: Optional[int] = None
|
|
height: Optional[int] = None
|
|
uploaded_at: Optional[datetime] = None
|
|
processing_status: str = "pending"
|
|
client_id: Optional[str] = None
|
|
client_name: Optional[str] = None
|
|
thumbnail_path: Optional[str] = None
|
|
|
|
# Extended data
|
|
exif: Optional[ExifData] = None
|
|
ocr: Optional[OcrData] = None
|
|
ai: Optional[AiData] = None
|
|
processing: Optional[ProcessingInfo] = None
|
|
|
|
@classmethod
|
|
def from_dict(cls, data: Dict[str, Any]) -> "HubImage":
|
|
# Simplified factory method from a JSON API response
|
|
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__ and k not in ("exif", "ocr", "ai", "processing")})
|