good
This commit is contained in:
parent
6358de554f
commit
8e0e77f4d2
1 changed files with 35 additions and 21 deletions
|
|
@ -250,9 +250,8 @@ class PlexClient:
|
|||
|
||||
def search_tracks(self, title: str, artist: str, limit: int = 15) -> List[PlexTrackInfo]:
|
||||
"""
|
||||
Searches for tracks in the Plex music library. If an artist is provided, it
|
||||
searches within that artist's scope. If the artist is empty or not found,
|
||||
it falls back to a library-wide search for the title.
|
||||
Searches for tracks using a robust, multi-stage fallback strategy to find
|
||||
the best possible candidates for matching.
|
||||
"""
|
||||
if not self.music_library:
|
||||
logger.warning("Plex music library not found. Cannot perform search.")
|
||||
|
|
@ -260,41 +259,56 @@ class PlexClient:
|
|||
|
||||
try:
|
||||
candidate_tracks = []
|
||||
|
||||
# If an artist is provided, perform a targeted search.
|
||||
# Use a set to keep track of found track keys to avoid duplicates
|
||||
found_track_keys = set()
|
||||
|
||||
def add_candidates(tracks):
|
||||
"""Helper function to add unique tracks to the main candidate list."""
|
||||
for track in tracks:
|
||||
if track.ratingKey not in found_track_keys:
|
||||
candidate_tracks.append(track)
|
||||
found_track_keys.add(track.ratingKey)
|
||||
|
||||
# --- Stage 1: High-Precision Search (Artist -> then filter by Title) ---
|
||||
if artist:
|
||||
logger.debug(f"Stage 1: Searching for artist '{artist}'")
|
||||
artist_results = self.music_library.searchArtists(title=artist, limit=1)
|
||||
if artist_results:
|
||||
plex_artist = artist_results[0]
|
||||
all_artist_tracks = plex_artist.tracks()
|
||||
lower_title = title.lower()
|
||||
for track in all_artist_tracks:
|
||||
if lower_title in track.title.lower():
|
||||
candidate_tracks.append(track)
|
||||
else:
|
||||
# If artist not found, still fall back to a general title search
|
||||
logger.debug(f"Artist '{artist}' not found. Falling back to title search for '{title}'.")
|
||||
candidate_tracks = self.music_library.searchTracks(title=title, limit=limit)
|
||||
|
||||
# If no artist is provided, perform a library-wide title search directly.
|
||||
else:
|
||||
logger.debug(f"Performing title-only search for '{title}'.")
|
||||
candidate_tracks = self.music_library.searchTracks(title=title, limit=limit)
|
||||
# Find all tracks by this artist that contain the title text
|
||||
stage1_results = [track for track in all_artist_tracks if lower_title in track.title.lower()]
|
||||
add_candidates(stage1_results)
|
||||
logger.debug(f"Stage 1 found {len(stage1_results)} candidates.")
|
||||
|
||||
# --- Stage 2: Flexible Keyword Search (Artist + Title combined) ---
|
||||
# This is good for artist variations like "The Dare" vs "Dare"
|
||||
search_query = f"{artist} {title}".strip()
|
||||
logger.debug(f"Stage 2: Performing keyword search for '{search_query}'")
|
||||
stage2_results = self.music_library.search(title=search_query, libtype='track', limit=limit)
|
||||
add_candidates(stage2_results)
|
||||
|
||||
# --- Stage 3: Title-Only Fallback Search ---
|
||||
# This is the broadest search for cases where artist metadata is wrong or missing.
|
||||
logger.debug(f"Stage 3: Performing title-only search for '{title}'")
|
||||
stage3_results = self.music_library.searchTracks(title=title, limit=limit)
|
||||
add_candidates(stage3_results)
|
||||
|
||||
# Convert the raw Plex track objects to our simplified PlexTrackInfo dataclass
|
||||
tracks = [PlexTrackInfo.from_plex_track(track) for track in candidate_tracks[:limit]]
|
||||
|
||||
|
||||
if tracks:
|
||||
logger.debug(f"Plex search for title='{title}', artist='{artist or 'N/A'}' found {len(tracks)} potential matches.")
|
||||
logger.info(f"Found {len(tracks)} total potential matches for '{title}' by '{artist}' after all stages.")
|
||||
|
||||
return tracks
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error searching Plex tracks for title='{title}', artist='{artist}': {e}")
|
||||
logger.error(f"Error during multi-stage search for title='{title}', artist='{artist}': {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return []
|
||||
|
||||
|
||||
def get_library_stats(self) -> Dict[str, int]:
|
||||
if not self.music_library:
|
||||
return {}
|
||||
|
|
|
|||
Loading…
Reference in a new issue