You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SoulSync/core/wishlist/resolution.py

177 lines
7.8 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""Wishlist resolution and removal helpers."""
from __future__ import annotations
from typing import Any, Dict, List
from core.imports.context import (
get_import_original_search,
get_import_search_result,
get_import_source,
get_import_source_ids,
get_import_track_info,
)
from core.wishlist.service import get_wishlist_service
from database.music_database import get_database
from utils.logging_config import get_logger
logger = get_logger("wishlist.resolution")
def _primary_track_artist_name(track_info: Dict[str, Any]) -> str:
artists = (track_info or {}).get("artists", [])
if isinstance(artists, list) and artists:
first = artists[0]
if isinstance(first, dict):
return str(first.get("name", "") or "")
return str(first or "")
if isinstance(artists, str):
return artists
return str((track_info or {}).get("artist", "") or "")
def _all_profile_wishlist_tracks(wishlist_service, database=None) -> List[Dict[str, Any]]:
database = database or get_database()
all_profiles = database.get_all_profiles()
wishlist_tracks: List[Dict[str, Any]] = []
for profile in all_profiles:
wishlist_tracks.extend(wishlist_service.get_wishlist_tracks_for_download(profile_id=profile["id"]))
return wishlist_tracks
def check_and_remove_from_wishlist(context: Dict[str, Any], wishlist_service=None, database=None) -> None:
"""Check whether a successful download should be removed from the wishlist."""
try:
wishlist_service = wishlist_service or get_wishlist_service()
source = get_import_source(context)
source_ids = get_import_source_ids(context)
source_label = {
"spotify": "Spotify",
"itunes": "iTunes",
"deezer": "Deezer",
"discogs": "Discogs",
"hydrabase": "Hydrabase",
}.get(source, "Source")
track_info = get_import_track_info(context) or get_import_search_result(context)
search_result = get_import_original_search(context) or get_import_search_result(context)
track_id = None
track_id = source_ids.get("track_id") or None
if track_id:
logger.info("[Wishlist] Found %s track ID from source_ids: %s", source_label, track_id)
elif "wishlist_id" in track_info:
wishlist_id = track_info["wishlist_id"]
logger.info("[Wishlist] Found wishlist_id in context: %s", wishlist_id)
wishlist_tracks = _all_profile_wishlist_tracks(wishlist_service, database=database)
for wishlist_track in wishlist_tracks:
if wishlist_track.get("wishlist_id") == wishlist_id:
track_id = wishlist_track.get("track_id") or wishlist_track.get("spotify_track_id") or wishlist_track.get("id")
logger.info("[Wishlist] Found track ID from wishlist entry: %s", track_id)
break
if not track_id:
track_name = track_info.get("name") or search_result.get("title", "")
artist_name = _primary_track_artist_name(track_info) or _primary_track_artist_name(search_result)
if track_name and artist_name:
logger.warning(
"[Wishlist] No track ID found, checking for fuzzy match: '%s' by '%s'",
track_name,
artist_name,
)
wishlist_tracks = _all_profile_wishlist_tracks(wishlist_service, database=database)
for wishlist_track in wishlist_tracks:
wl_name = wishlist_track.get("name", "").lower()
wl_artists = wishlist_track.get("artists", [])
wl_artist_name = ""
if wl_artists:
if isinstance(wl_artists[0], dict):
wl_artist_name = wl_artists[0].get("name", "").lower()
else:
wl_artist_name = str(wl_artists[0]).lower()
if wl_name == track_name.lower() and wl_artist_name == artist_name.lower():
track_id = wishlist_track.get("track_id") or wishlist_track.get("spotify_track_id") or wishlist_track.get("id")
logger.info("[Wishlist] Found fuzzy match - track ID: %s", track_id)
break
if track_id:
logger.info("[Wishlist] Attempting to remove track from wishlist: %s", track_id)
removed = wishlist_service.mark_track_download_result(track_id, success=True)
if removed:
logger.info("[Wishlist] Successfully removed track from wishlist: %s", track_id)
else:
logger.warning(" [Wishlist] Track not found in wishlist or already removed: %s", track_id)
else:
logger.warning(" [Wishlist] No track ID found for wishlist removal check")
except Exception as exc:
logger.error("[Wishlist] Error in wishlist removal check: %s", exc)
def check_and_remove_track_from_wishlist_by_metadata(
track_data: Dict[str, Any],
wishlist_service=None,
database=None,
) -> bool:
"""Remove a wishlist track by metadata after a database/library match."""
try:
wishlist_service = wishlist_service or get_wishlist_service()
track_name = track_data.get("name", "")
track_id = track_data.get("id", "")
artists = track_data.get("artists", [])
logger.info("[Analysis] Checking if track should be removed from wishlist: '%s' (ID: %s)", track_name, track_id)
if track_id:
removed = wishlist_service.mark_track_download_result(track_id, success=True)
if removed:
logger.info("[Analysis] Removed track from wishlist via direct ID match: %s", track_id)
return True
if track_name and artists:
primary_artist = _primary_track_artist_name(track_data)
if primary_artist:
logger.warning(
"[Analysis] No direct ID match, trying fuzzy match: '%s' by '%s'",
track_name,
primary_artist,
)
wishlist_tracks = _all_profile_wishlist_tracks(wishlist_service, database=database)
for wishlist_track in wishlist_tracks:
wl_name = wishlist_track.get("name", "").lower()
wl_artists = wishlist_track.get("artists", [])
wl_artist_name = ""
if wl_artists:
if isinstance(wl_artists[0], dict):
wl_artist_name = wl_artists[0].get("name", "").lower()
else:
wl_artist_name = str(wl_artists[0]).lower()
if wl_name == track_name.lower() and wl_artist_name == primary_artist.lower():
spotify_track_id = (
wishlist_track.get("track_id")
or wishlist_track.get("spotify_track_id")
or wishlist_track.get("id")
)
if spotify_track_id:
removed = wishlist_service.mark_track_download_result(spotify_track_id, success=True)
if removed:
logger.info("[Analysis] Removed track from wishlist via fuzzy match: %s", spotify_track_id)
return True
logger.warning(" [Analysis] Track not found in wishlist or already removed: '%s'", track_name)
return False
except Exception as e:
logger.error("[Analysis] Error checking wishlist removal by metadata: %s", e)
import traceback
traceback.print_exc()
return False
__all__ = ["check_and_remove_from_wishlist", "check_and_remove_track_from_wishlist_by_metadata"]