""" History Router - Upload history management Note: This is a simplified version. The original Next.js version stores history in memory/file. For FastAPI, we'll use a simple JSON file approach similar to prompts. """ from fastapi import APIRouter, HTTPException, UploadFile, File, Form from models.responses import HistoryResponse, HistoryItem, ErrorResponse from services.whisk_client import WhiskClient from pathlib import Path import json import uuid import base64 from typing import Optional from datetime import datetime router = APIRouter(prefix="/history", tags=["History"]) # History storage HISTORY_FILE = Path(__file__).parent.parent.parent / "data" / "history.json" def load_history() -> list: """Load history from JSON file""" try: if HISTORY_FILE.exists(): return json.loads(HISTORY_FILE.read_text()) except: pass return [] def save_history(history: list) -> None: """Save history to JSON file""" HISTORY_FILE.parent.mkdir(parents=True, exist_ok=True) HISTORY_FILE.write_text(json.dumps(history, indent=2)) @router.get( "", response_model=HistoryResponse, responses={500: {"model": ErrorResponse}} ) async def get_history(category: Optional[str] = None): """ Get upload history. - **category**: Optional filter by category (subject, scene, style) """ try: history = load_history() if category: history = [h for h in history if h.get("category") == category] return HistoryResponse(history=[HistoryItem(**h) for h in history]) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post( "", response_model=HistoryItem, responses={ 400: {"model": ErrorResponse}, 500: {"model": ErrorResponse} } ) async def upload_to_history( file: UploadFile = File(...), category: str = Form(default="subject"), cookies: Optional[str] = Form(default=None) ): """ Upload an image to history. - **file**: Image file to upload - **category**: Category (subject, scene, style) - **cookies**: Optional Whisk cookies to also upload to Whisk """ try: # Read file content = await file.read() base64_data = base64.b64encode(content).decode('utf-8') mime_type = file.content_type or 'image/png' # Upload to Whisk if cookies provided media_id = None if cookies: try: client = WhiskClient(cookies) media_id = await client.upload_reference_image(base64_data, mime_type, category) except Exception as e: print(f"[History] Whisk upload failed: {e}") # Create history item new_item = { "id": str(uuid.uuid4()), "url": f"data:{mime_type};base64,{base64_data}", "originalName": file.filename or "upload.png", "category": category, "mediaId": media_id, "createdAt": int(datetime.now().timestamp() * 1000) } # Save to history history = load_history() history.insert(0, new_item) # Add to beginning save_history(history) return HistoryItem(**new_item) except Exception as e: print(f"Upload error: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.delete( "/{item_id}", responses={ 404: {"model": ErrorResponse}, 500: {"model": ErrorResponse} } ) async def delete_history_item(item_id: str): """ Delete an item from history. - **item_id**: ID of the history item to delete """ try: history = load_history() original_len = len(history) history = [h for h in history if h.get("id") != item_id] if len(history) == original_len: raise HTTPException(status_code=404, detail="Item not found") save_history(history) return {"success": True, "deleted": item_id} except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.delete( "", responses={500: {"model": ErrorResponse}} ) async def clear_history(): """ Clear all history items. """ try: save_history([]) return {"success": True, "message": "History cleared"} except Exception as e: raise HTTPException(status_code=500, detail=str(e))