lyrics-fetcher/getlyrics.py

66 lines
2.7 KiB
Python

from sys import argv
from os import listdir as ls, chdir as cd, path
import json as j
import utils as u
tracing=True
u.tracing=tracing
with open(u.get_file('config.json')) as b: conf=j.load(b)
import importlib as il
sources=[il.import_module(f'sources.{n[:-3]}') for n in ls(u.get_file('sources')) if n.endswith('.py')]
sources=list(filter(lambda x:x.enabled,sources))
def init(args):
#Init
split=args.index('-')
band=' '.join([n.capitalize() for n in args[:split]])
song=' '.join([n.capitalize() for n in args[split+1:]])
return band,song
def local(band,song):
#Local
#All lyrics that are fetched from remote will automatically get saved in here for later reference
#Also, any time the existence of a song on a remote is proven (eg. the remote offers an album list for a band, which in turn offers a track list, and this needs to be parsed to get the correct URL), that will be indexed locally for future reference, in the indexcache config path.
#Deleting that folder will reset that, and should always be safe.
#Indices will be one file per source, so deleting individual files will be part of uninstalling a source.
#path.isabs(smth) - use as a switch for whether to join the path
try:
cd(conf['lyrics'])
prep=lambda x:x.lower().replace(' ','_')
try:
with open(f'{prep(song)}_{prep(band)}.lyric') as b:
lyrics=b.read()
except FileNotFoundError: lyrics=''
return lyrics
except FileNotFoundError:
raise u.LyricsPathUnavailable()
def remote(band,song):
#Runs through sources and tries to locate the song and fetch lyrics.
#Will search all local indices first, and offer which repository to fetch from if multiple found
#But will *not* poll all remote repositories; if not found in local indices, will begin polling sources in whatever order the underlying (他框)walk decides, and will stop as soon as an exact match is found.
#If a partial match is found, will offer to user whether it's close enough.
if not sources:
print('No sources configured! Failed to fetch lyrics from remote!')
#TODO
lyrics=''
for source in sources:
try: lyrics=source.lyrics(song,band)
except Exception: raise # This should actually catch errors later
if lyrics: break
return lyrics
if __name__=='__main__':
band,song=init(argv[1:])
try: lyrics=local(band,song)
except u.LyricsPathUnavailable:
if input("Local lyrics folder unavailable, proceed with remote lookup? (y/n)")!='y': exit()
lyrics=''
if not lyrics:
print("Lyrics not found locally, searching for remote...")
try: lyrics=remote(band,song) or ''
except u.NotFound as e:
missings={'song':'Couldn\'t find that song.','lyrics':'No lyrics for that song.'}
print(missings[str(e)])
if lyrics: print(lyrics)