lrc-dl/lrc_dl/__init__.py
Arthur K. bad4a355e8
feat: add lrclib and genius providers (#5)
* feat: lrclib and genius providers

* revert `prepend_header` to true

* change providers order

---------

Co-authored-by: mrsobakin <68982655+mrsobakin@users.noreply.github.com>
2025-04-02 01:37:19 +03:00

101 lines
3.1 KiB
Python

import time
import traceback
from pathlib import Path
from typing import Optional
# Initialize classes from lrc_dl/providers
import lrc_dl.providers as _
from lrc_dl.core import Song
from lrc_dl.registry import Registry
from lrc_dl.config import LyricsDlConfig
from lrc_dl.logger import DefaultLogger, AbstractLogger
class LyricsDl:
logger: AbstractLogger
def __init__(self, config: LyricsDlConfig = LyricsDlConfig(), logger: AbstractLogger = DefaultLogger()):
self.config = config
self.logger = logger
providers_classes = Registry.get_synced_providers()
self.providers = []
for name in config.order:
Provider = providers_classes.get(name)
if not Provider:
continue
provider_config = config.providers_configs.get(name, {})
try:
provider = Provider(**provider_config)
except TypeError as e:
self.logger.error(f"[lrc-dl] {e}")
continue
self.providers.append(provider)
def fetch_lyrics(self, song: Song) -> Optional[str]:
self.logger.info(f"[lrc-dl] Fetching lyrics for \"{song.artist} - {song.title}\"")
for provider in self.providers:
self.logger.info(f"[{provider.name}] Fetching lyrics...")
try:
lyrics = provider.fetch_lyrics(song)
except Exception as e:
lyrics = None
self.logger.error(f"[{provider.name}] Got exception while fetching lyrics! ({type(e).__name__}: {e})")
self.logger.debug(f"[{provider.name}] {traceback.format_exc()}")
if lyrics:
self.logger.info(f"[{provider.name}] Found lyrics!")
if self.config.prepend_header:
lyrics = f"[re:lrc-dl:{provider.name}]\n\n{lyrics}"
return lyrics
self.logger.info(f"[{provider.name}] No lyrics were found!")
return None
def process_file(self, path: Path, force: bool = False) -> bool:
lyrics_path = path.with_suffix(".lrc")
if lyrics_path.exists() and not force:
self.logger.error("[lrc-dl] Lyrics file already exists!")
return False
# TODO handle errors
try:
song = Song.from_file(path)
except Exception as e:
self.logger.error(f"[lrc-dl] {path}: {e}")
return False
lyrics = self.fetch_lyrics(song)
if not lyrics:
self.logger.error("[lrc-dl] No lyrics were found!")
return True
with open(lyrics_path, "w") as f:
f.write(lyrics)
return True
def process_directory(self, path: Path, extensions: list[str], force: bool = False) -> None:
delay_next = False
for file_path in path.rglob("*"):
if delay_next and self.config.delay is not None:
self.logger.info(f"[lrc-dl] Sleeping for {self.config.delay:.2f}s...")
time.sleep(self.config.delay)
if file_path.suffix[1:] not in extensions:
continue
delay_next = self.process_file(file_path, force)