chore: Update everything

This commit is contained in:
2026-07-24 15:58:31 +02:00
parent 5100ad8365
commit 6bd4d58373
34 changed files with 8829 additions and 1 deletions
+105
View File
@@ -0,0 +1,105 @@
import httpx
import os
from datetime import datetime
from collections import defaultdict
from typing import List, Dict, Any
# Get environment variables
IMMICH_API_KEY = os.environ.get("IMMICH_API_KEY")
IMMICH_SERVER_URL = os.environ.get("IMMICH_SERVER_URL")
if not IMMICH_API_KEY or not IMMICH_SERVER_URL:
raise ValueError("IMMICH_API_KEY and IMMICH_SERVER_URL environment variables must be set")
# Setup HTTP client with auth headers
headers = {"Content-Type": "application/json", "Accept": "application/json", "x-api-key": IMMICH_API_KEY}
# Global HTTP client
client = httpx.Client(headers=headers)
def get_albums() -> List[Dict[str, Any]]:
"""Fetch all albums from Immich API"""
response = client.get(f"{IMMICH_SERVER_URL}/api/albums")
response.raise_for_status()
return response.json()
def get_album_assets(album_id: str) -> List[str]:
"""Fetch all asset IDs from a specific album"""
response = client.get(f"{IMMICH_SERVER_URL}/api/albums/{album_id}?withoutAssets=false")
response.raise_for_status()
album_data = response.json()
return [asset["id"] for asset in album_data.get("assets", [])]
def add_assets_to_album(album_id: str, asset_ids: List[str]) -> None:
"""Add assets to an album"""
if not asset_ids:
return
response = client.put(f"{IMMICH_SERVER_URL}/api/albums/{album_id}/assets", json={"ids": asset_ids})
response.raise_for_status()
def delete_album(album_id: str) -> None:
"""Delete an album"""
response = client.delete(f"{IMMICH_SERVER_URL}/api/albums/{album_id}")
response.raise_for_status()
def deduplicate_albums():
"""Main function to deduplicate albums"""
print("Fetching albums...")
albums = get_albums()
# Group albums by name (case-insensitive)
album_groups = defaultdict(list)
for album in albums:
album_name = album["albumName"].lower().strip()
album_groups[album_name].append(album)
# Process groups with duplicates
for album_name, album_list in album_groups.items():
if len(album_list) <= 1:
continue # Skip groups with only one album
print(f"\nProcessing duplicate albums for: '{album_name}' ({len(album_list)} albums)")
# Sort by creation date to find the oldest
album_list.sort(key=lambda x: datetime.fromisoformat(x["createdAt"].replace("Z", "+00:00")))
oldest_album = album_list[0]
duplicate_albums = album_list[1:]
print(f" Oldest album: {oldest_album['id']} (created: {oldest_album['createdAt']})")
# Collect assets from duplicate albums
all_asset_ids = []
for dup_album in duplicate_albums:
print(f" Processing duplicate: {dup_album['id']} (created: {dup_album['createdAt']})")
asset_ids = get_album_assets(dup_album["id"])
all_asset_ids.extend(asset_ids)
print(f" Found {len(asset_ids)} assets")
# Add assets to oldest album
if all_asset_ids:
print(f" Adding {len(all_asset_ids)} assets to oldest album...")
add_assets_to_album(oldest_album["id"], all_asset_ids)
# Delete duplicate albums
for dup_album in duplicate_albums:
print(f" Deleting duplicate album: {dup_album['id']}")
delete_album(dup_album["id"])
print(f" ✓ Merged {len(duplicate_albums)} duplicate albums into {oldest_album['id']}")
if __name__ == "__main__":
try:
deduplicate_albums()
print("\n✓ Album deduplication completed successfully!")
except Exception as e:
print(f"\n✗ Error: {e}")
raise
finally:
client.close()