refactor: add is_available method to fetchers

This commit is contained in:
2026-03-31 16:56:49 +02:00
parent 03acda4478
commit d3090ceb1c
9 changed files with 29 additions and 12 deletions
+3 -12
View File
@@ -51,18 +51,9 @@ class LrcManager:
return [self.fetchers[force_method]]
sequence: list[BaseFetcher] = []
if track.is_local:
sequence.append(self.fetchers["local"])
if track.title:
sequence.append(self.fetchers["cache-search"])
if track.trackid:
sequence.append(self.fetchers["spotify"])
if track.is_complete:
sequence.append(self.fetchers["lrclib"])
if track.title:
sequence.append(self.fetchers["lrclib-search"])
sequence.append(self.fetchers["netease"])
sequence.append(self.fetchers["qqmusic"])
for method in self.fetchers.keys():
if self.fetchers[method].is_available(track):
sequence.append(self.fetchers[method])
logger.debug(f"Fallback sequence: {[f.source_name for f in sequence]}")
return sequence
+5
View File
@@ -22,6 +22,11 @@ class BaseFetcher(ABC):
"""True if this fetcher manages its own cache (skip per-source cache check)."""
return False
@abstractmethod
def is_available(self, track: TrackMeta) -> bool:
"""Check if the fetcher is available for the given track (e.g. has required metadata)."""
pass
@abstractmethod
def fetch(
self, track: TrackMeta, bypass_cache: bool = False
+3
View File
@@ -30,6 +30,9 @@ class CacheSearchFetcher(BaseFetcher):
def self_cached(self) -> bool:
return True
def is_available(self, track: TrackMeta) -> bool:
return bool(track.title)
def fetch(
self, track: TrackMeta, bypass_cache: bool = False
) -> Optional[LyricResult]:
+3
View File
@@ -25,6 +25,9 @@ class LocalFetcher(BaseFetcher):
def source_name(self) -> str:
return "local"
def is_available(self, track: TrackMeta) -> bool:
return track.is_local
def fetch(
self, track: TrackMeta, bypass_cache: bool = False
) -> Optional[LyricResult]:
+3
View File
@@ -31,6 +31,9 @@ class LrclibFetcher(BaseFetcher):
def source_name(self) -> str:
return "lrclib"
def is_available(self, track: TrackMeta) -> bool:
return track.is_complete
def fetch(
self, track: TrackMeta, bypass_cache: bool = False
) -> Optional[LyricResult]:
+3
View File
@@ -33,6 +33,9 @@ class LrclibSearchFetcher(BaseFetcher):
def source_name(self) -> str:
return "lrclib-search"
def is_available(self, track: TrackMeta) -> bool:
return bool(track.title)
def fetch(
self, track: TrackMeta, bypass_cache: bool = False
) -> Optional[LyricResult]:
+3
View File
@@ -40,6 +40,9 @@ class NeteaseFetcher(BaseFetcher):
def source_name(self) -> str:
return "netease"
def is_available(self, track: TrackMeta) -> bool:
return bool(track.title)
def _search(self, track: TrackMeta, limit: int = 10) -> Optional[int]:
"""Search Netease and return the best-matching song ID.
+3
View File
@@ -32,6 +32,9 @@ class QQMusicFetcher(BaseFetcher):
def source_name(self) -> str:
return "qqmusic"
def is_available(self, track: TrackMeta) -> bool:
return bool(track.title) and bool(QQ_MUSIC_API_URL)
def _search(self, track: TrackMeta, limit: int = 10) -> Optional[str]:
"""Search QQ Music and return the best-matching song MID."""
query = f"{track.artist or ''} {track.title or ''}".strip()
+3
View File
@@ -55,6 +55,9 @@ class SpotifyFetcher(BaseFetcher):
def source_name(self) -> str:
return "spotify"
def is_available(self, track: TrackMeta) -> bool:
return bool(track.trackid) and bool(SPOTIFY_SP_DC)
# ─── Auth helpers ────────────────────────────────────────────────
def _get_server_time(self, client: httpx.Client) -> Optional[int]: