Fails more cleanly now, even distinguishes between wrong name and no lyrics
This commit is contained in:
parent
4c2d1043fc
commit
0ea7db4dc7
|
@ -1 +1,3 @@
|
|||
A lyrics fetching tool, written in python. Similarly designed to a package manager. Manages indexing itself, sources don't need to do that.
|
||||
Offers a similarity checker for matching strings, if sources do not wish to implement their own.
|
||||
Most paths in config.json, if relative, will be relative to the base "lyrics" path. If that path is relative, it's relative to the current working directory. Please do not make that path relative.
|
28
getlyrics.py
28
getlyrics.py
|
@ -1,15 +1,15 @@
|
|||
import requests as r
|
||||
import sys
|
||||
from os import listdir as ls
|
||||
from sys import argv
|
||||
from os import listdir as ls, chdir as cd, path
|
||||
import json as j
|
||||
import .utils as u
|
||||
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))
|
||||
class FlashyNotMountedError(Exception):
|
||||
pass
|
||||
|
||||
def init(args):
|
||||
#Init
|
||||
|
@ -24,8 +24,9 @@ def local(band,song):
|
|||
#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:
|
||||
os.chdir(conf['lyrics'])
|
||||
cd(conf['lyrics'])
|
||||
prep=lambda x:x.lower().replace(' ','_')
|
||||
try:
|
||||
with open(f'{prep(song)}_{prep(band)}.lyric') as b:
|
||||
|
@ -51,12 +52,15 @@ def remote(band,song):
|
|||
return lyrics
|
||||
|
||||
if __name__=='__main__':
|
||||
band,song=init(sys.argv[1:])
|
||||
band,song=init(argv[1:])
|
||||
try: lyrics=local(band,song)
|
||||
except FlashyNotMountedError:
|
||||
if input("Flashy not mounted, proceed? (y/n)")!='y': exit()
|
||||
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...")
|
||||
lyrics=remote(band,song) or ''
|
||||
if lyrics: print(lyrics)
|
||||
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)
|
|
@ -12,4 +12,4 @@ Documentation for files in this folder.
|
|||
- massfetch(band,album=''), which should fetch lyrics to all tracks of the band (on that album) and return them in a list
|
||||
- This will, at some point, become a definitive list of optional functions that the fetcher supports; it will always accept recommendations for change.
|
||||
6) Input formats: All names will be passed in exactly as the user presents the information, it is the source's job to wrangle it correctly into URLs. For example, "wither." is an album name that may be given to the source. It should generally assume that words will be separated with spaces, but there's no guarantee. Also it may occasionally get bands and songs passed in as each other. It isn't expected to figure that out.
|
||||
7) Output: If a function returns more, or different, data than was expected (eg. lyrics are available on an album's track list), it is welcome to raise a utils.AdditionalDataException, containing a nested dictionary with the actual received data. The only valid keys are "name", "contents", "metadata" and "type". "type" must be one of "band", "album", "track". "metadata" will later allow other keys (such as "url", "duration", "number", "year", "artist" - for guest tracks, etc.). "contents" may be a dictionary which obeys the same rules.
|
||||
7) Output: If a function returns more, or different, data than was expected (eg. lyrics are available on an album's track list), it is welcome to raise a utils.AdditionalData, containing a nested dictionary with the actual received data. The only valid keys are "name", "contents", "metadata" and "type". "type" must be one of "band", "album", "track". "metadata" will later allow other keys (such as "url", "duration", "number", "year", "artist" - for guest tracks, etc.). "contents" may be a dictionary which obeys the same rules. It is also welcome to raise a utils.NotFound with a message of "song", "lyrics", "band" or "album", to indicate a failure. The distinction between "song" and "lyrics" is that the song appears to exist, but no lyrics are present (not provided yet, or instrumental).
|
|
@ -1,7 +1,7 @@
|
|||
enabled=True
|
||||
|
||||
import requests as r
|
||||
import ..utils as u
|
||||
import utils as u
|
||||
|
||||
def bandget(band):
|
||||
peg=r.get(f'https://{band}.bandcamp.com/').content.decode('utf-8') # Just assume success,
|
||||
|
@ -38,8 +38,11 @@ def lyrics(song,band='',album=''):
|
|||
if not (band):
|
||||
return "Bandcamp does not currently support song search (due to being a webscraper). You must specify the band that performed the song."
|
||||
band=band.replace(' ',''); song=song.replace(' ','-')
|
||||
peg=r.get(f'https://{band}.bandcamp.com/track/{song}').content.decode('utf-8')
|
||||
peg=r.get(f'https://{band}.bandcamp.com/track/{song}')
|
||||
if peg.status_code!=200: raise u.NotFound('song')
|
||||
peg=peg.content.decode('utf-8')
|
||||
needle=('<div class="tralbumData lyricsText">','</div>','lyrics')
|
||||
lyrics=next(u.stringiter(peg,needle=needle))
|
||||
try: lyrics=next(u.stringiter(peg,needle=needle))
|
||||
except StopIteration: raise u.NotFound('lyrics')
|
||||
lyrics=lyrics.replace('\r','').replace('\n','').replace('<br>','\n')
|
||||
return lyrics
|
||||
|
|
Loading…
Reference in New Issue
Block a user