Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e4501cad3 | |||
| 71e4ff28c8 | |||
| 9f272df99c | |||
| 8ba8ceefb8 | |||
| 9590cd0f60 | |||
| 5e7c8ff137 | |||
| fae59849f8 |
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "vrobbler"
|
name = "vrobbler"
|
||||||
version = "0.8.3"
|
version = "0.8.6"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Colin Powell <colin@unbl.ink>"]
|
authors = ["Colin Powell <colin@unbl.ink>"]
|
||||||
|
|
||||||
|
|||||||
@ -72,11 +72,19 @@ class Album(TimeStampedModel):
|
|||||||
return self.artists.first()
|
return self.artists.first()
|
||||||
|
|
||||||
def fix_metadata(self):
|
def fix_metadata(self):
|
||||||
if not self.musicbrainz_albumartist_id or not self.year:
|
if (
|
||||||
|
not self.musicbrainz_albumartist_id
|
||||||
|
or not self.year
|
||||||
|
or not self.musicbrainz_releasegroup_id
|
||||||
|
):
|
||||||
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
||||||
mb_data = musicbrainzngs.get_release_by_id(
|
mb_data = musicbrainzngs.get_release_by_id(
|
||||||
self.musicbrainz_id, includes=['artists']
|
self.musicbrainz_id, includes=['artists', 'release-groups']
|
||||||
)
|
)
|
||||||
|
if not self.musicbrainz_releasegroup_id:
|
||||||
|
self.musicbrainz_releasegroup_id = mb_data['release'][
|
||||||
|
'release-group'
|
||||||
|
]['id']
|
||||||
if not self.musicbrainz_albumartist_id:
|
if not self.musicbrainz_albumartist_id:
|
||||||
self.musicbrainz_albumartist_id = mb_data['release'][
|
self.musicbrainz_albumartist_id = mb_data['release'][
|
||||||
'artist-credit'
|
'artist-credit'
|
||||||
@ -89,7 +97,13 @@ class Album(TimeStampedModel):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.save(update_fields=['musicbrainz_albumartist_id', 'year'])
|
self.save(
|
||||||
|
update_fields=[
|
||||||
|
'musicbrainz_albumartist_id',
|
||||||
|
'musicbrainz_releasegroup_id',
|
||||||
|
'year',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
new_artist = Artist.objects.filter(
|
new_artist = Artist.objects.filter(
|
||||||
musicbrainz_id=self.musicbrainz_albumartist_id
|
musicbrainz_id=self.musicbrainz_albumartist_id
|
||||||
@ -99,6 +113,11 @@ class Album(TimeStampedModel):
|
|||||||
if not new_artist:
|
if not new_artist:
|
||||||
for t in self.track_set.all():
|
for t in self.track_set.all():
|
||||||
self.artists.add(t.artist)
|
self.artists.add(t.artist)
|
||||||
|
if (
|
||||||
|
not self.cover_image
|
||||||
|
or self.cover_image == 'default-image-replace-me'
|
||||||
|
):
|
||||||
|
self.fetch_artwork()
|
||||||
|
|
||||||
def fetch_artwork(self, force=False):
|
def fetch_artwork(self, force=False):
|
||||||
if not self.cover_image and not force:
|
if not self.cover_image and not force:
|
||||||
@ -115,7 +134,10 @@ class Album(TimeStampedModel):
|
|||||||
f'No cover art found for {self.name} by release'
|
f'No cover art found for {self.name} by release'
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self.cover_image and self.musicbrainz_releasegroup_id:
|
if (
|
||||||
|
not self.cover_image
|
||||||
|
or self.cover_image == "default-image-replace-me"
|
||||||
|
) and self.musicbrainz_releasegroup_id:
|
||||||
try:
|
try:
|
||||||
img_data = musicbrainzngs.get_release_group_image_front(
|
img_data = musicbrainzngs.get_release_group_image_front(
|
||||||
self.musicbrainz_releasegroup_id
|
self.musicbrainz_releasegroup_id
|
||||||
@ -131,8 +153,6 @@ class Album(TimeStampedModel):
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
f"No cover art found for release or release group for {self.name}, setting to default"
|
f"No cover art found for release or release group for {self.name}, setting to default"
|
||||||
)
|
)
|
||||||
# TODO Get a placeholder image in here
|
|
||||||
self.cover_image = 'default-image-replace-me'
|
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
87
vrobbler/apps/scrobbles/musicbrainz.py
Normal file
87
vrobbler/apps/scrobbles/musicbrainz.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
import musicbrainzngs
|
||||||
|
from dateutil.parser import parse
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def lookup_album_from_mb(musicbrainz_id: str) -> dict:
|
||||||
|
release_dict = {}
|
||||||
|
|
||||||
|
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
||||||
|
release_data = musicbrainzngs.get_release_by_id(
|
||||||
|
musicbrainz_id,
|
||||||
|
includes=['artists', 'release-groups', 'recordings'],
|
||||||
|
).get('release')
|
||||||
|
|
||||||
|
if not release_data:
|
||||||
|
return release_dict
|
||||||
|
|
||||||
|
primary_artist = release_data.get('artist-credit')[0]
|
||||||
|
release_dict = {
|
||||||
|
'artist': {
|
||||||
|
'name': primary_artist.get('name'),
|
||||||
|
'musicbrainz_id': primary_artist.get('id'),
|
||||||
|
},
|
||||||
|
'album': {
|
||||||
|
'name': release_data.get('title'),
|
||||||
|
'musicbrainz_id': musicbrainz_id,
|
||||||
|
'musicbrainz_releasegroup_id': release_data.get(
|
||||||
|
'release-group'
|
||||||
|
).get('id'),
|
||||||
|
'musicbrainz_albumaritist_id': primary_artist.get('id'),
|
||||||
|
'year': release_data.get('year')[0:4],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
release_dict['tracks'] = []
|
||||||
|
for track in release_data.get('medium-list')[0]['track-list']:
|
||||||
|
recording = track['recording']
|
||||||
|
release_dict['tracks'].append(
|
||||||
|
{
|
||||||
|
'title': recording['title'],
|
||||||
|
'musicbrainz_id': recording['id'],
|
||||||
|
'run_time_ticks': track['length'],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return release_dict
|
||||||
|
|
||||||
|
|
||||||
|
def lookup_album_dict_from_mb(release_name: str, artist_name: str) -> dict:
|
||||||
|
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
||||||
|
|
||||||
|
top_result = musicbrainzngs.search_releases(
|
||||||
|
release_name, artist=artist_name
|
||||||
|
)['release-list'][0]
|
||||||
|
score = int(top_result.get('ext:score'))
|
||||||
|
if score < 85:
|
||||||
|
logger.debug(
|
||||||
|
"Album lookup score below 85 threshold",
|
||||||
|
extra={"result": top_result},
|
||||||
|
)
|
||||||
|
return {}
|
||||||
|
print(top_result)
|
||||||
|
return {
|
||||||
|
"year": parse(top_result["date"]).year,
|
||||||
|
"mb_id": top_result["id"],
|
||||||
|
"mb_group_id": top_result["release-group"]["id"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def lookup_artist_id_from_mb(artist_name: str) -> str:
|
||||||
|
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
||||||
|
|
||||||
|
top_result = musicbrainzngs.search_artists(artist=artist_name)[
|
||||||
|
'artist-list'
|
||||||
|
][0]
|
||||||
|
score = int(top_result.get('ext:score'))
|
||||||
|
if score < 85:
|
||||||
|
logger.debug(
|
||||||
|
"Artist lookup score below 85 threshold",
|
||||||
|
extra={"result": top_result},
|
||||||
|
)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return top_result["id"]
|
||||||
@ -6,6 +6,11 @@ import pytz
|
|||||||
from music.models import Album, Artist, Track
|
from music.models import Album, Artist, Track
|
||||||
from scrobbles.models import Scrobble
|
from scrobbles.models import Scrobble
|
||||||
|
|
||||||
|
from vrobbler.apps.scrobbles.musicbrainz import (
|
||||||
|
lookup_album_dict_from_mb,
|
||||||
|
lookup_artist_id_from_mb,
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -32,9 +37,8 @@ def process_audioscrobbler_tsv_file(file_path, user_tz=None):
|
|||||||
continue
|
continue
|
||||||
artist, artist_created = Artist.objects.get_or_create(name=row[0])
|
artist, artist_created = Artist.objects.get_or_create(name=row[0])
|
||||||
if artist_created:
|
if artist_created:
|
||||||
logger.debug(f"Created artist {artist}")
|
artist.musicbrainz_id = lookup_artist_id_from_mb(artist.name)
|
||||||
else:
|
artist.save(update_fields=["musicbrainz_id"])
|
||||||
logger.debug(f"Found artist {artist}")
|
|
||||||
|
|
||||||
album = None
|
album = None
|
||||||
album_created = False
|
album_created = False
|
||||||
@ -52,9 +56,23 @@ def process_audioscrobbler_tsv_file(file_path, user_tz=None):
|
|||||||
album.artists.add(artist)
|
album.artists.add(artist)
|
||||||
|
|
||||||
if album_created:
|
if album_created:
|
||||||
logger.debug(f"Created album {album}")
|
album_dict = lookup_album_dict_from_mb(
|
||||||
else:
|
album.name, artist_name=artist.name
|
||||||
logger.debug(f"Found album {album}")
|
)
|
||||||
|
album.year = album_dict["year"]
|
||||||
|
album.musicbrainz_id = album_dict["mb_id"]
|
||||||
|
album.musicbrainz_releasegroup_id = album_dict["mb_group_id"]
|
||||||
|
album.musicbrainz_albumartist_id = artist.musicbrainz_id
|
||||||
|
album.save(
|
||||||
|
update_fields=[
|
||||||
|
"year",
|
||||||
|
"musicbrainz_id",
|
||||||
|
"musicbrainz_releasegroup_id",
|
||||||
|
"musicbrainz_albumartist_id",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
album.artists.add(artist)
|
||||||
|
album.fetch_artwork()
|
||||||
|
|
||||||
track, track_created = Track.objects.get_or_create(
|
track, track_created = Track.objects.get_or_create(
|
||||||
title=row[2],
|
title=row[2],
|
||||||
@ -62,13 +80,10 @@ def process_audioscrobbler_tsv_file(file_path, user_tz=None):
|
|||||||
album=album,
|
album=album,
|
||||||
)
|
)
|
||||||
|
|
||||||
if track_created:
|
|
||||||
logger.debug(f"Created track {track}")
|
|
||||||
else:
|
|
||||||
logger.debug(f"Found track {track}")
|
|
||||||
|
|
||||||
if track_created:
|
if track_created:
|
||||||
track.musicbrainz_id = row[7]
|
track.musicbrainz_id = row[7]
|
||||||
|
track.run_time = int(row[4])
|
||||||
|
track.run_time_ticks = int(row[4]) * 1000
|
||||||
track.save()
|
track.save()
|
||||||
|
|
||||||
timestamp = (
|
timestamp = (
|
||||||
|
|||||||
Reference in New Issue
Block a user