Fix item visibility bugs and add effects web UI
- Fix recipe filter to allow owner=None (S-expression compiled recipes) - Fix media uploads to use category (video/image/audio) not MIME type - Fix IPFS imports to detect and store correct media type - Add Effects navigation link between Recipes and Media - Create effects list and detail templates with upload functionality - Add cache/not_found.html template (was missing) - Add type annotations to service classes - Add tests for item visibility and effects web UI (30 tests) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,10 +7,14 @@ import json
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional, List, Dict, Any, Tuple
|
||||
from typing import Optional, List, Dict, Any, Tuple, TYPE_CHECKING
|
||||
|
||||
import httpx
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from database import Database
|
||||
from cache_manager import L1CacheManager
|
||||
|
||||
|
||||
def detect_media_type(cache_path: Path) -> str:
|
||||
"""Detect if file is image, video, or audio based on magic bytes."""
|
||||
@@ -86,7 +90,7 @@ class CacheService:
|
||||
Handles content retrieval, metadata, and media type detection.
|
||||
"""
|
||||
|
||||
def __init__(self, database, cache_manager):
|
||||
def __init__(self, database: "Database", cache_manager: "L1CacheManager") -> None:
|
||||
self.db = database
|
||||
self.cache = cache_manager
|
||||
self.cache_dir = Path(os.environ.get("CACHE_DIR", "/tmp/artdag-cache"))
|
||||
@@ -293,10 +297,10 @@ class CacheService:
|
||||
self,
|
||||
cid: str,
|
||||
actor_id: str,
|
||||
title: str = None,
|
||||
description: str = None,
|
||||
tags: List[str] = None,
|
||||
custom: Dict[str, Any] = None,
|
||||
title: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
tags: Optional[List[str]] = None,
|
||||
custom: Optional[Dict[str, Any]] = None,
|
||||
) -> Tuple[bool, Optional[str]]:
|
||||
"""Update content metadata. Returns (success, error)."""
|
||||
if not self.cache.has_content(cid):
|
||||
@@ -431,16 +435,19 @@ class CacheService:
|
||||
if not ipfs_client.get_file(ipfs_cid, str(tmp_path)):
|
||||
return None, f"Could not fetch CID {ipfs_cid} from IPFS"
|
||||
|
||||
# Store in cache
|
||||
cached, ipfs_cid = self.cache.put(tmp_path, node_type="import", move=True)
|
||||
cid = ipfs_cid or cached.cid # Prefer IPFS CID
|
||||
# Detect media type before storing
|
||||
media_type = detect_media_type(tmp_path)
|
||||
|
||||
# Save to database
|
||||
await self.db.create_cache_item(cid, ipfs_cid)
|
||||
# Store in cache
|
||||
cached, new_ipfs_cid = self.cache.put(tmp_path, node_type="import", move=True)
|
||||
cid = new_ipfs_cid or cached.cid # Prefer IPFS CID
|
||||
|
||||
# Save to database with detected media type
|
||||
await self.db.create_cache_item(cid, new_ipfs_cid)
|
||||
await self.db.save_item_metadata(
|
||||
cid=cid,
|
||||
actor_id=actor_id,
|
||||
item_type="media",
|
||||
item_type=media_type, # Use detected type for filtering
|
||||
filename=f"ipfs-{ipfs_cid[:16]}"
|
||||
)
|
||||
|
||||
@@ -463,19 +470,21 @@ class CacheService:
|
||||
tmp.write(content)
|
||||
tmp_path = Path(tmp.name)
|
||||
|
||||
# Detect MIME type before moving file
|
||||
mime_type = get_mime_type(tmp_path)
|
||||
# Detect media type (video/image/audio) before moving file
|
||||
media_type = detect_media_type(tmp_path)
|
||||
|
||||
# Store in cache (also stores in IPFS)
|
||||
cached, ipfs_cid = self.cache.put(tmp_path, node_type="upload", move=True)
|
||||
cid = ipfs_cid or cached.cid # Prefer IPFS CID
|
||||
|
||||
# Save to database with detected MIME type
|
||||
# Save to database with media category type
|
||||
# Using media_type ("video", "image", "audio") not mime_type ("video/mp4")
|
||||
# so list_media filtering works correctly
|
||||
await self.db.create_cache_item(cid, ipfs_cid)
|
||||
await self.db.save_item_metadata(
|
||||
cid=cid,
|
||||
actor_id=actor_id,
|
||||
item_type=mime_type, # Store actual MIME type
|
||||
item_type=media_type, # Store media category for filtering
|
||||
filename=filename
|
||||
)
|
||||
|
||||
@@ -485,11 +494,11 @@ class CacheService:
|
||||
|
||||
async def list_media(
|
||||
self,
|
||||
actor_id: str = None,
|
||||
username: str = None,
|
||||
actor_id: Optional[str] = None,
|
||||
username: Optional[str] = None,
|
||||
offset: int = 0,
|
||||
limit: int = 24,
|
||||
media_type: str = None,
|
||||
media_type: Optional[str] = None,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""List media items in cache."""
|
||||
# Get items from database (uses item_types table)
|
||||
|
||||
Reference in New Issue
Block a user