Просмотр исходного кода

Add rudimentary album metadata from TADB

Colin Powell 2 лет назад
Родитель
Сommit
5a8e828b81

+ 85 - 0
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),
+        ),
+    ]

+ 18 - 0
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),
+        ),
+    ]

+ 18 - 0
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),
+        ),
+    ]

+ 45 - 1
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)

+ 47 - 6
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

+ 7 - 0
vrobbler/templates/music/album_detail.html

@@ -12,6 +12,13 @@
         <img src="{{object.cover_image.url}}" width=300 height=300 />
     </p>
     {% endif %}
+    <div style="float:left; width:600px; margin-left:10px; ">
+        {% if object.theaudiodb_description %}
+        <p>{{object.theaudiodb_description|safe|linebreaks|truncatewords:160}}</p>
+        <hr/>
+        {% endif %}
+        <p><a href="{{album.mb_link}}">Musicbrainz</a> | <a href="{{album.tadb_link}}">TheAudioDB</a> {% if album.allmusic_link %}| <a href="{{album.allmusic_link}}">AllMusic</a>{% endif %}</p>
+    </div>
 </div>
 <div class="row">
     <p>{{object.scrobbles.count}} scrobbles</p>