mirror of
https://github.com/krateng/maloja.git
synced 2023-08-10 21:12:55 +03:00
Implemented images for albums
This commit is contained in:
parent
69b456dc73
commit
fd9987ec35
@ -519,7 +519,7 @@ def post_scrobble(
|
||||
@api.post("addpicture")
|
||||
@authenticated_function(alternate=api_key_correct,api=True)
|
||||
@catch_exceptions
|
||||
def add_picture(b64,artist:Multi=[],title=None):
|
||||
def add_picture(b64,artist:Multi=[],title=None,albumtitle=None):
|
||||
"""Uploads a new image for an artist or track.
|
||||
|
||||
param string b64: Base 64 representation of the image
|
||||
@ -531,8 +531,10 @@ def add_picture(b64,artist:Multi=[],title=None):
|
||||
for a in artist:
|
||||
keys.append("artist",a)
|
||||
if title is not None: keys.append("title",title)
|
||||
elif albumtitle is not None: keys.append("albumtitle",albumtitle)
|
||||
k_filter, _, _, _, _ = uri_to_internal(keys)
|
||||
if "track" in k_filter: k_filter = k_filter["track"]
|
||||
elif "album" in k_filter: k_filter = k_filter["album"]
|
||||
url = images.set_image(b64,**k_filter)
|
||||
|
||||
return {
|
||||
|
@ -39,6 +39,13 @@ DB['tracks'] = sql.Table(
|
||||
sql.Column('expire',sql.Integer),
|
||||
sql.Column('raw',sql.String)
|
||||
)
|
||||
DB['albums'] = sql.Table(
|
||||
'albums', meta,
|
||||
sql.Column('id',sql.Integer,primary_key=True),
|
||||
sql.Column('url',sql.String),
|
||||
sql.Column('expire',sql.Integer),
|
||||
sql.Column('raw',sql.String)
|
||||
)
|
||||
|
||||
meta.create_all(engine)
|
||||
|
||||
@ -137,7 +144,7 @@ def resolve_track_image(track_id):
|
||||
|
||||
# local image
|
||||
if malojaconfig["USE_LOCAL_IMAGES"]:
|
||||
images = local_files(artists=track['artists'],title=track['title'])
|
||||
images = local_files(track=track)
|
||||
if len(images) != 0:
|
||||
result = random.choice(images)
|
||||
result = urllib.parse.quote(result)
|
||||
@ -181,31 +188,56 @@ def resolve_artist_image(artist_id):
|
||||
return result
|
||||
|
||||
|
||||
def resolve_album_image(album_id):
|
||||
|
||||
with resolve_semaphore:
|
||||
# check cache
|
||||
result = get_image_from_cache(album_id,'albums')
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
album = database.sqldb.get_album(album_id)
|
||||
|
||||
# local image
|
||||
if malojaconfig["USE_LOCAL_IMAGES"]:
|
||||
images = local_files(album=album)
|
||||
if len(images) != 0:
|
||||
result = random.choice(images)
|
||||
result = urllib.parse.quote(result)
|
||||
result = {'type':'url','value':result}
|
||||
set_image_in_cache(album_id,'tracks',result['value'])
|
||||
return result
|
||||
|
||||
# third party
|
||||
result = thirdparty.get_image_album_all((album['artists'],album['albumtitle']))
|
||||
result = {'type':'url','value':result}
|
||||
set_image_in_cache(album_id,'albums',result['value'])
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# removes emojis and weird shit from names
|
||||
def clean(name):
|
||||
return "".join(c for c in name if c.isalnum() or c in []).strip()
|
||||
|
||||
def get_all_possible_filenames(artist=None,artists=None,title=None):
|
||||
# check if we're dealing with a track or artist, then clean up names
|
||||
# (only remove non-alphanumeric, allow korean and stuff)
|
||||
|
||||
if title is not None and artists is not None:
|
||||
track = True
|
||||
title, artists = clean(title), [clean(a) for a in artists]
|
||||
elif artist is not None:
|
||||
track = False
|
||||
# new and improved
|
||||
def get_all_possible_filenames(artist=None,track=None,album=None):
|
||||
if track:
|
||||
title, artists = clean(track['title']), [clean(a) for a in track['artists']]
|
||||
superfolder = "tracks/"
|
||||
elif album:
|
||||
title, artists = clean(album['albumtitle']), [clean(a) for a in album['artists']]
|
||||
superfolder = "albums/"
|
||||
elif artist:
|
||||
artist = clean(artist)
|
||||
else: return []
|
||||
|
||||
|
||||
superfolder = "tracks/" if track else "artists/"
|
||||
superfolder = "artists/"
|
||||
else:
|
||||
return []
|
||||
|
||||
filenames = []
|
||||
|
||||
if track:
|
||||
#unsafeartists = [artist.translate(None,"-_./\\") for artist in artists]
|
||||
if track or album:
|
||||
safeartists = [re.sub("[^a-zA-Z0-9]","",artist) for artist in artists]
|
||||
#unsafetitle = title.translate(None,"-_./\\")
|
||||
safetitle = re.sub("[^a-zA-Z0-9]","",title)
|
||||
|
||||
if len(artists) < 4:
|
||||
@ -215,7 +247,6 @@ def get_all_possible_filenames(artist=None,artists=None,title=None):
|
||||
unsafeperms = [sorted(artists)]
|
||||
safeperms = [sorted(safeartists)]
|
||||
|
||||
|
||||
for unsafeartistlist in unsafeperms:
|
||||
filename = "-".join(unsafeartistlist) + "_" + title
|
||||
if filename != "":
|
||||
@ -246,10 +277,11 @@ def get_all_possible_filenames(artist=None,artists=None,title=None):
|
||||
|
||||
return [superfolder + name for name in filenames]
|
||||
|
||||
def local_files(artist=None,artists=None,title=None):
|
||||
|
||||
def local_files(artist=None,album=None,track=None):
|
||||
|
||||
|
||||
filenames = get_all_possible_filenames(artist,artists,title)
|
||||
filenames = get_all_possible_filenames(artist=artist,album=album,track=track)
|
||||
|
||||
images = []
|
||||
|
||||
@ -276,13 +308,18 @@ class MalformedB64(Exception):
|
||||
pass
|
||||
|
||||
def set_image(b64,**keys):
|
||||
track = "title" in keys
|
||||
if track:
|
||||
entity = {'artists':keys['artists'],'title':keys['title']}
|
||||
id = database.sqldb.get_track_id(entity)
|
||||
else:
|
||||
entity = keys['artist']
|
||||
id = database.sqldb.get_artist_id(entity)
|
||||
if "title" in keys:
|
||||
entity = {"track":keys}
|
||||
id = database.sqldb.get_track_id(entity['track'])
|
||||
dbtable = "tracks"
|
||||
elif "albumtitle" in keys:
|
||||
entity = {"album":keys}
|
||||
id = database.sqldb.get_album_id(entity['album'])
|
||||
dbtable = "albums"
|
||||
elif "artist" in keys:
|
||||
entity = keys
|
||||
id = database.sqldb.get_artist_id(entity['artist'])
|
||||
dbtable = "artists"
|
||||
|
||||
log("Trying to set image, b64 string: " + str(b64[:30] + "..."),module="debug")
|
||||
|
||||
@ -293,13 +330,13 @@ def set_image(b64,**keys):
|
||||
type,b64 = match.groups()
|
||||
b64 = base64.b64decode(b64)
|
||||
filename = "webupload" + str(int(datetime.datetime.now().timestamp())) + "." + type
|
||||
for folder in get_all_possible_filenames(**keys):
|
||||
for folder in get_all_possible_filenames(**entity):
|
||||
if os.path.exists(data_dir['images'](folder)):
|
||||
with open(data_dir['images'](folder,filename),"wb") as f:
|
||||
f.write(b64)
|
||||
break
|
||||
else:
|
||||
folder = get_all_possible_filenames(**keys)[0]
|
||||
folder = get_all_possible_filenames(**entity)[0]
|
||||
os.makedirs(data_dir['images'](folder))
|
||||
with open(data_dir['images'](folder,filename),"wb") as f:
|
||||
f.write(b64)
|
||||
@ -308,7 +345,6 @@ def set_image(b64,**keys):
|
||||
log("Saved image as " + data_dir['images'](folder,filename),module="debug")
|
||||
|
||||
# set as current picture in rotation
|
||||
if track: set_image_in_cache(id,'tracks',os.path.join("/images",folder,filename))
|
||||
else: set_image_in_cache(id,'artists',os.path.join("/images",folder,filename))
|
||||
set_image_in_cache(id,dbtable,os.path.join("/images",folder,filename))
|
||||
|
||||
return os.path.join("/images",folder,filename)
|
||||
|
@ -19,7 +19,7 @@ from doreah import auth
|
||||
# rest of the project
|
||||
from . import database
|
||||
from .database.jinjaview import JinjaDBConnection
|
||||
from .images import resolve_track_image, resolve_artist_image
|
||||
from .images import resolve_track_image, resolve_artist_image, resolve_album_image
|
||||
from .malojauri import uri_to_internal, remove_identical
|
||||
from .pkg_global.conf import malojaconfig, data_dir
|
||||
from .jinjaenv.context import jinja_environment
|
||||
@ -124,6 +124,8 @@ def dynamic_image():
|
||||
result = resolve_track_image(keys['id'])
|
||||
elif keys['type'] == 'artist':
|
||||
result = resolve_artist_image(keys['id'])
|
||||
elif keys['type'] == 'album':
|
||||
result = resolve_album_image(keys['id'])
|
||||
|
||||
if result is None or result['value'] in [None,'']:
|
||||
return ""
|
||||
|
33
maloja/thirdparty/__init__.py
vendored
33
maloja/thirdparty/__init__.py
vendored
@ -63,7 +63,18 @@ def get_image_artist_all(artist):
|
||||
log("Could not get artist image for " + str(artist) + " from " + service.name)
|
||||
except Exception as e:
|
||||
log("Error getting artist image from " + service.name + ": " + repr(e))
|
||||
|
||||
def get_image_album_all(album):
|
||||
with thirdpartylock:
|
||||
for service in services["metadata"]:
|
||||
try:
|
||||
res = service.get_image_album(album)
|
||||
if res is not None:
|
||||
log("Got album image for " + str(album) + " from " + service.name)
|
||||
return res
|
||||
else:
|
||||
log("Could not get album image for " + str(album) + " from " + service.name)
|
||||
except Exception as e:
|
||||
log("Error getting album image from " + service.name + ": " + repr(e))
|
||||
|
||||
|
||||
class GenericInterface:
|
||||
@ -217,6 +228,23 @@ class MetadataInterface(GenericInterface,abstract=True):
|
||||
if imgurl is not None: imgurl = self.postprocess_url(imgurl)
|
||||
return imgurl
|
||||
|
||||
def get_image_album(self,album):
|
||||
artists, title = album
|
||||
artiststring = urllib.parse.quote(", ".join(artists))
|
||||
titlestring = urllib.parse.quote(title)
|
||||
response = urllib.request.urlopen(
|
||||
self.metadata["albumurl"].format(artist=artiststring,title=titlestring,**self.settings)
|
||||
)
|
||||
|
||||
responsedata = response.read()
|
||||
if self.metadata["response_type"] == "json":
|
||||
data = json.loads(responsedata)
|
||||
imgurl = self.metadata_parse_response_album(data)
|
||||
else:
|
||||
imgurl = None
|
||||
if imgurl is not None: imgurl = self.postprocess_url(imgurl)
|
||||
return imgurl
|
||||
|
||||
# default function to parse response by descending down nodes
|
||||
# override if more complicated
|
||||
def metadata_parse_response_artist(self,data):
|
||||
@ -225,6 +253,9 @@ class MetadataInterface(GenericInterface,abstract=True):
|
||||
def metadata_parse_response_track(self,data):
|
||||
return self._parse_response("response_parse_tree_track", data)
|
||||
|
||||
def metadata_parse_response_album(self,data):
|
||||
return self._parse_response("response_parse_tree_album", data)
|
||||
|
||||
def _parse_response(self, resp, data):
|
||||
res = data
|
||||
for node in self.metadata[resp]:
|
||||
|
8
maloja/thirdparty/audiodb.py
vendored
8
maloja/thirdparty/audiodb.py
vendored
@ -9,13 +9,17 @@ class AudioDB(MetadataInterface):
|
||||
}
|
||||
|
||||
metadata = {
|
||||
#"trackurl": "https://theaudiodb.com/api/v1/json/{api_key}/searchtrack.php?s={artist}&t={title}",
|
||||
#"trackurl": "https://theaudiodb.com/api/v1/json/{api_key}/searchtrack.php?s={artist}&t={title}", #patreon
|
||||
"artisturl": "https://www.theaudiodb.com/api/v1/json/{api_key}/search.php?s={artist}",
|
||||
#"albumurl": "https://www.theaudiodb.com/api/v1/json/{api_key}/searchalbum.php?s={artist}&a={title}", #patreon
|
||||
"response_type":"json",
|
||||
#"response_parse_tree_track": ["tracks",0,"astrArtistThumb"],
|
||||
"response_parse_tree_artist": ["artists",0,"strArtistThumb"],
|
||||
"required_settings": ["api_key"],
|
||||
}
|
||||
|
||||
def get_image_track(self,artist):
|
||||
def get_image_track(self,track):
|
||||
return None
|
||||
|
||||
def get_image_album(self,album):
|
||||
return None
|
||||
|
11
maloja/thirdparty/deezer.py
vendored
11
maloja/thirdparty/deezer.py
vendored
@ -8,10 +8,17 @@ class Deezer(MetadataInterface):
|
||||
}
|
||||
|
||||
metadata = {
|
||||
"trackurl": "https://api.deezer.com/search?q={artist}%20{title}",
|
||||
#"trackurl": "https://api.deezer.com/search?q={artist}%20{title}",
|
||||
"artisturl": "https://api.deezer.com/search?q={artist}",
|
||||
"albumurl": "https://api.deezer.com/search?q={artist}%20{title}",
|
||||
"response_type":"json",
|
||||
"response_parse_tree_track": ["data",0,"album","cover_medium"],
|
||||
#"response_parse_tree_track": ["data",0,"album","cover_medium"],
|
||||
"response_parse_tree_artist": ["data",0,"artist","picture_medium"],
|
||||
"response_parse_tree_album": ["data",0,"album","cover_medium"],
|
||||
"required_settings": [],
|
||||
}
|
||||
|
||||
def get_image_track(self,track):
|
||||
return None
|
||||
# we can use the album pic from the track search,
|
||||
# but should do so via maloja logic
|
||||
|
9
maloja/thirdparty/lastfm.py
vendored
9
maloja/thirdparty/lastfm.py
vendored
@ -22,15 +22,22 @@ class LastFM(MetadataInterface, ProxyScrobbleInterface):
|
||||
"activated_setting": "SCROBBLE_LASTFM"
|
||||
}
|
||||
metadata = {
|
||||
#"artisturl": "https://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist={artist}&api_key={apikey}&format=json"
|
||||
"trackurl": "https://ws.audioscrobbler.com/2.0/?method=track.getinfo&track={title}&artist={artist}&api_key={apikey}&format=json",
|
||||
"albumurl": "https://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key={apikey}&artist={artist}&album={title}&format=json",
|
||||
"response_type":"json",
|
||||
"response_parse_tree_track": ["track","album","image",-1,"#text"],
|
||||
# technically just the album artwork, but we use it for now
|
||||
#"response_parse_tree_artist": ["artist","image",-1,"#text"],
|
||||
"response_parse_tree_album": ["album","image",-1,"#text"],
|
||||
"required_settings": ["apikey"],
|
||||
}
|
||||
|
||||
def get_image_artist(self,artist):
|
||||
return None
|
||||
# lastfm doesn't provide artist images
|
||||
# lastfm still provides that endpoint with data,
|
||||
# but doesn't provide actual images
|
||||
|
||||
|
||||
def proxyscrobble_parse_response(self,data):
|
||||
return data.attrib.get("status") == "ok" and data.find("scrobbles").attrib.get("ignored") == "0"
|
||||
|
2
maloja/thirdparty/musicbrainz.py
vendored
2
maloja/thirdparty/musicbrainz.py
vendored
@ -26,6 +26,8 @@ class MusicBrainz(MetadataInterface):
|
||||
return None
|
||||
# not supported
|
||||
|
||||
def get_image_album(self,album):
|
||||
return None
|
||||
|
||||
def get_image_track(self,track):
|
||||
self.lock.acquire()
|
||||
|
4
maloja/thirdparty/spotify.py
vendored
4
maloja/thirdparty/spotify.py
vendored
@ -15,9 +15,11 @@ class Spotify(MetadataInterface):
|
||||
|
||||
metadata = {
|
||||
"trackurl": "https://api.spotify.com/v1/search?q=artist:{artist}%20track:{title}&type=track&access_token={token}",
|
||||
"albumurl": "https://api.spotify.com/v1/search?q=artist:{artist}%album:{title}&type=album&access_token={token}",
|
||||
"artisturl": "https://api.spotify.com/v1/search?q=artist:{artist}&type=artist&access_token={token}",
|
||||
"response_type":"json",
|
||||
"response_parse_tree_track": ["tracks","items",0,"album","images",0,"url"],
|
||||
"response_parse_tree_track": ["tracks","items",0,"album","images",0,"url"], # use album art
|
||||
"response_parse_tree_album": ["albums","items",0,"images",0,"url"],
|
||||
"response_parse_tree_artist": ["artists","items",0,"images",0,"url"],
|
||||
"required_settings": ["apiid","secret"],
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user