diff --git a/starpunk/media.py b/starpunk/media.py index e1fd534..fa39717 100644 --- a/starpunk/media.py +++ b/starpunk/media.py @@ -4,8 +4,10 @@ Media upload and management for StarPunk Per ADR-057 and ADR-058: - Social media attachment model (media at top of note) - Pillow-based image optimization -- 10MB max file size, 4096x4096 max dimensions -- Auto-resize to 2048px for performance +- 50MB max upload, 10MB max output (v1.4.0) +- Image variants: thumb, small, medium, large (v1.4.0) +- Tiered resize strategy based on input size (v1.4.0) +- 4096x4096 max dimensions - 4 images max per note """ @@ -594,9 +596,10 @@ def get_note_media(note_id: int) -> List[Dict]: def delete_media(media_id: int) -> None: """ - Delete media file and database record + Delete media file, variants, and database record Per Q8: Cleanup orphaned files + Per v1.4.0: Also cleanup variant files Args: media_id: Media ID to delete @@ -611,15 +614,38 @@ def delete_media(media_id: int) -> None: return media_path = row[0] + media_dir = Path(current_app.config.get('DATA_PATH', 'data')) / 'media' - # Delete database record (cascade will delete note_media entries) + # Get variant paths before deleting (v1.4.0) + variant_rows = db.execute( + "SELECT path FROM media_variants WHERE media_id = ?", + (media_id,) + ).fetchall() + + # Delete database record (cascade will delete media_variants and note_media entries) db.execute("DELETE FROM media WHERE id = ?", (media_id,)) db.commit() - # Delete file from disk - media_dir = Path(current_app.config.get('DATA_PATH', 'data')) / 'media' - full_path = media_dir / media_path + # Delete files from disk (best-effort cleanup) + deleted_count = 0 - if full_path.exists(): - full_path.unlink() - current_app.logger.info(f"Deleted media file: {media_path}") + # Delete original file + full_path = media_dir / media_path + try: + if full_path.exists(): + full_path.unlink() + deleted_count += 1 + except OSError as e: + current_app.logger.warning(f"Failed to delete media file {media_path}: {e}") + + # Delete variant files (v1.4.0) + for variant_row in variant_rows: + variant_path = media_dir / variant_row[0] + try: + if variant_path.exists(): + variant_path.unlink() + deleted_count += 1 + except OSError as e: + current_app.logger.warning(f"Failed to delete variant file {variant_row[0]}: {e}") + + current_app.logger.info(f"Deleted media {media_id}: {deleted_count} file(s) removed from disk")