diff --git a/vrobbler/apps/music/migrations/0012_album_allmusic_id_album_discogs_id_and_more.py b/vrobbler/apps/music/migrations/0012_album_allmusic_id_album_discogs_id_and_more.py new file mode 100644 index 0000000..3ef6732 --- /dev/null +++ b/vrobbler/apps/music/migrations/0012_album_allmusic_id_album_discogs_id_and_more.py @@ -0,0 +1,85 @@ +# Generated by Django 4.1.5 on 2023-03-02 19:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0011_artist_thumbnail'), + ] + + operations = [ + migrations.AddField( + model_name='album', + name='allmusic_id', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='discogs_id', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='rateyourmusic_id', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_description', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_genre', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_id', + field=models.CharField( + blank=True, max_length=255, null=True, unique=True + ), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_mood', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_score', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_score_votes', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_speed', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_style', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='theaudiodb_theme', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='wikidata_id', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='album', + name='wikipedia_slug', + field=models.CharField(blank=True, max_length=255, null=True), + ), + ] diff --git a/vrobbler/apps/music/migrations/0013_alter_album_theaudiodb_score.py b/vrobbler/apps/music/migrations/0013_alter_album_theaudiodb_score.py new file mode 100644 index 0000000..0734c6d --- /dev/null +++ b/vrobbler/apps/music/migrations/0013_alter_album_theaudiodb_score.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.5 on 2023-03-02 19:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0012_album_allmusic_id_album_discogs_id_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='album', + name='theaudiodb_score', + field=models.FloatField(blank=True, null=True), + ), + ] diff --git a/vrobbler/apps/music/migrations/0014_album_theaudiodb_year_released.py b/vrobbler/apps/music/migrations/0014_album_theaudiodb_year_released.py new file mode 100644 index 0000000..6de5e5e --- /dev/null +++ b/vrobbler/apps/music/migrations/0014_album_theaudiodb_year_released.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.5 on 2023-03-02 19:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('music', '0013_alter_album_theaudiodb_score'), + ] + + operations = [ + migrations.AddField( + model_name='album', + name='theaudiodb_year_released', + field=models.IntegerField(blank=True, null=True), + ), + ] diff --git a/vrobbler/apps/music/models.py b/vrobbler/apps/music/models.py index aa10266..56f37a9 100644 --- a/vrobbler/apps/music/models.py +++ b/vrobbler/apps/music/models.py @@ -13,6 +13,7 @@ from django.utils.translation import gettext_lazy as _ from django_extensions.db.models import TimeStampedModel from scrobbles.mixins import ScrobblableMixin from scrobbles.theaudiodb import lookup_artist_from_tadb +from vrobbler.apps.scrobbles.theaudiodb import lookup_album_from_tadb logger = logging.getLogger(__name__) BNULL = {"blank": True, "null": True} @@ -86,6 +87,21 @@ class Album(TimeStampedModel): musicbrainz_releasegroup_id = models.CharField(max_length=255, **BNULL) musicbrainz_albumartist_id = models.CharField(max_length=255, **BNULL) cover_image = models.ImageField(upload_to="albums/", **BNULL) + theaudiodb_id = models.CharField(max_length=255, unique=True, **BNULL) + theaudiodb_description = models.TextField(**BNULL) + theaudiodb_year_released = models.IntegerField(**BNULL) + theaudiodb_score = models.FloatField(**BNULL) + theaudiodb_score_votes = models.IntegerField(**BNULL) + theaudiodb_genre = models.CharField(max_length=255, **BNULL) + theaudiodb_style = models.CharField(max_length=255, **BNULL) + theaudiodb_mood = models.CharField(max_length=255, **BNULL) + theaudiodb_speed = models.CharField(max_length=255, **BNULL) + theaudiodb_theme = models.CharField(max_length=255, **BNULL) + allmusic_id = models.CharField(max_length=255, **BNULL) + rateyourmusic_id = models.CharField(max_length=255, **BNULL) + wikipedia_slug = models.CharField(max_length=255, **BNULL) + discogs_id = models.CharField(max_length=255, **BNULL) + wikidata_id = models.CharField(max_length=255, **BNULL) def __str__(self): return self.name @@ -112,6 +128,15 @@ class Album(TimeStampedModel): def primary_artist(self): return self.artists.first() + def scrape_theaudiodb(self) -> None: + artist = self.primary_artist.name + album_data = lookup_album_from_tadb(self.name, artist) + if not album_data.get('theaudiodb_id'): + logger.info(f"No data for {self} found in TheAudioDB") + return + + Album.objects.filter(pk=self.pk).update(**album_data) + def fix_metadata(self): if ( not self.musicbrainz_albumartist_id @@ -159,6 +184,7 @@ class Album(TimeStampedModel): or self.cover_image == 'default-image-replace-me' ): self.fetch_artwork() + self.scrape_theaudiodb() def fetch_artwork(self, force=False): if not self.cover_image and not force: @@ -197,9 +223,27 @@ class Album(TimeStampedModel): self.save() @property - def mb_link(self): + def mb_link(self) -> str: return f"https://musicbrainz.org/release/{self.musicbrainz_id}" + @property + def allmusic_link(self) -> str: + if self.allmusic_id: + return f"https://www.allmusic.com/artist/{self.allmusic_id}" + return "" + + @property + def wikipedia_link(self): + if self.wikipedia_slug: + return f"https://www.wikipedia.org/en/{self.wikipedia_slug}" + return "" + + @property + def tadb_link(self): + if self.theaudiodb_id: + return f"https://www.theaudiodb.com/album/{self.theaudiodb_id}" + return "" + class Track(ScrobblableMixin): COMPLETION_PERCENT = getattr(settings, 'MUSIC_COMPLETION_PERCENT', 90) diff --git a/vrobbler/apps/scrobbles/theaudiodb.py b/vrobbler/apps/scrobbles/theaudiodb.py index b315be9..0abbf95 100644 --- a/vrobbler/apps/scrobbles/theaudiodb.py +++ b/vrobbler/apps/scrobbles/theaudiodb.py @@ -5,14 +5,15 @@ import requests from django.conf import settings THEAUDIODB_API_KEY = getattr(settings, "THEAUDIODB_API_KEY") -SEARCH_URL = f"https://www.theaudiodb.com/api/v1/json/{THEAUDIODB_API_KEY}/search.php?s=" +ARIST_SEARCH_URL = f"https://www.theaudiodb.com/api/v1/json/{THEAUDIODB_API_KEY}/search.php?s=" +ALBUM_SEARCH_URL = f"https://www.theaudiodb.com/api/v1/json/{THEAUDIODB_API_KEY}/searchalbum.php?s=" logger = logging.getLogger(__name__) def lookup_artist_from_tadb(name: str) -> dict: artist_info = {} - response = requests.get(SEARCH_URL + name) + response = requests.get(ARTIST_SEARCH_URL + name) if response.status_code != 200: logger.warn(f"Bad response from TADB: {response.status_code}") @@ -26,9 +27,49 @@ def lookup_artist_from_tadb(name: str) -> dict: if results['artists']: artist = results['artists'][0] - artist_info['biography'] = artist['strBiographyEN'] - artist_info['genre'] = artist['strGenre'] - artist_info['mood'] = artist['strMood'] - artist_info['thumb_url'] = artist['strArtistThumb'] + artist_info['biography'] = artist.get('strBiographyEN') + artist_info['genre'] = artist.get('strGenre') + artist_info['mood'] = artist.get('strMood') + artist_info['thumb_url'] = artist.get('strArtistThumb') return artist_info + + +def lookup_album_from_tadb(name: str, artist: str) -> dict: + album_info = {} + response = requests.get(''.join([ALBUM_SEARCH_URL, artist, "&a=", name])) + + if response.status_code != 200: + logger.warn(f"Bad response from TADB: {response.status_code}") + return {} + + if not response.content: + logger.warn(f"Bad content from TADB: {response.content}") + return {} + + results = json.loads(response.content) + if results['album']: + album = results['album'][0] + + album_info['theaudiodb_id'] = album.get('idAlbum') + album_info['theaudiodb_description'] = album.get('strDescriptionEN') + album_info['theaudiodb_genre'] = album.get('strGenre') + album_info['theaudiodb_style'] = album.get('strStyle') + album_info['theaudiodb_mood'] = album.get('strMood') + album_info['theaudiodb_speed'] = album.get('strSpeed') + album_info['theaudiodb_theme'] = album.get('strTheme') + album_info['theaudiodb_year_released'] = album.get('intYearReleased') + album_info['allmusic_id'] = album.get('strAllMusicID') + album_info['wikipedia_slug'] = album.get('strWikipediaID') + album_info['discogs_id'] = album.get('strDiscogsID') + album_info['wikidata_id'] = album.get('strWikidataID') + album_info['rateyourmusic_id'] = album.get('strRateYourMusicID') + + if album.get('intScore'): + album_info['theaudiodb_score'] = float(album.get('intScore')) + if album.get('intScoreVotes'): + album_info['theaudiodb_score_votes'] = int( + album.get('intScoreVotes') + ) + + return album_info diff --git a/vrobbler/templates/music/album_detail.html b/vrobbler/templates/music/album_detail.html index 63fd692..396657e 100644 --- a/vrobbler/templates/music/album_detail.html +++ b/vrobbler/templates/music/album_detail.html @@ -12,6 +12,13 @@

{% endif %} +
+ {% if object.theaudiodb_description %} +

{{object.theaudiodb_description|safe|linebreaks|truncatewords:160}}

+
+ {% endif %} +

Musicbrainz | TheAudioDB {% if album.allmusic_link %}| AllMusic{% endif %}

+

{{object.scrobbles.count}} scrobbles