#!/usr/bin/env python3.12 # pylint: disable=bare-except, broad-exception-caught, wrong-import-position import sys sys.path.insert(1,'..') import traceback import logging from aiohttp import ClientTimeout, ClientSession from lyric_search_new import utils from lyric_search_new.constructors import LyricsResult from . import common logger = logging.getLogger() log_level = logging.getLevelName(logger.level) class InvalidResponseException(Exception): """ Invalid Response Exception """ class LRCLib: """LRCLib Search Module""" def __init__(self): self.label = "LRCLib" self.lrclib_url = "https://lrclib.net/api/get" self.headers = common.SCRAPE_HEADERS self.timeout = ClientTimeout(connect=2, sock_read=4) self.datautils = utils.DataUtils() self.matcher = utils.TrackMatcher() async def search(self, artist: str, song: str): """ @artist: the artist to search @song: the song to search """ try: artist = artist.strip().lower() song = song.strip().lower() returned_lyrics = '' async with ClientSession() as client: async with client.get(self.lrclib_url, params = { 'artist_name': artist, 'track_name': song, }, timeout=self.timeout, headers=self.headers) as request: request.raise_for_status() text = await request.text() if len(text) < 100: raise InvalidResponseException("Search response text was invalid (len < 100 chars.)") search_data = await request.json() if not isinstance(search_data, dict): raise InvalidResponseException("Invalid JSON.") if not isinstance(search_data['artistName'], str): raise InvalidResponseException(f"Invalid JSON: Cannot find artistName key.\n{search_data}") if not isinstance(search_data['trackName'], str): raise InvalidResponseException(f"Invalid JSON: Cannot find trackName key.\n{search_data}") returned_artist = search_data['artistName'] returned_song = search_data['trackName'] returned_lyrics = search_data['plainLyrics'] returned_lyrics = self.datautils.scrub_lyrics(returned_lyrics) input_track = f"{artist} - {song}" returned_track = f"{artist} - {song}" (_matched, confidence) = self.matcher.find_best_match(input_track=input_track, candidate_tracks=[(0, returned_track)]) if not confidence: return # No suitable match found logging.info("Result found on %s", self.label) return LyricsResult(artist=returned_artist, song=returned_song, src=self.label, lyrics=returned_lyrics, confidence=confidence) except: if log_level == "DEBUG": traceback.print_exc() return