[music] Add listenbrainz support
This commit is contained in:
@ -0,0 +1,123 @@
|
||||
import logging
|
||||
import time
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from music.listenbrainz import get_similar_artists
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Fetch similar artists from ListenBrainz for artists with a musicbrainz_id"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"--commit",
|
||||
action="store_true",
|
||||
help="Commit changes to the database",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--batch-size",
|
||||
type=int,
|
||||
default=100,
|
||||
help="Number of artists to process per batch (default: 100)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--artist-id",
|
||||
type=str,
|
||||
default="",
|
||||
help="Only process the artist with this musicbrainz_id",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--overwrite",
|
||||
action="store_true",
|
||||
help="Re-fetch similar artists even if already populated",
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
from music.models import Artist
|
||||
|
||||
commit = options["commit"]
|
||||
batch_size = options["batch_size"]
|
||||
artist_id = options["artist_id"]
|
||||
overwrite = options["overwrite"]
|
||||
|
||||
if not commit:
|
||||
self.stdout.write(
|
||||
"Dry run — no changes will be saved. Use --commit to apply."
|
||||
)
|
||||
|
||||
qs = Artist.objects.exclude(musicbrainz_id__isnull=True).exclude(
|
||||
musicbrainz_id=""
|
||||
)
|
||||
|
||||
if artist_id:
|
||||
qs = qs.filter(musicbrainz_id=artist_id)
|
||||
self.stdout.write(f"Filtering to artist with musicbrainz_id: {artist_id}")
|
||||
elif not overwrite:
|
||||
qs = qs.filter(similar_artists__isnull=True)
|
||||
else:
|
||||
qs = qs.all()
|
||||
|
||||
total = qs.count()
|
||||
if total == 0:
|
||||
self.stdout.write("No artists to process.")
|
||||
return
|
||||
|
||||
self.stdout.write(
|
||||
f"Found {total} artists with musicbrainz_id"
|
||||
+ (" (overwrite mode)" if overwrite else "")
|
||||
+ (" (--artist-id filter)" if artist_id else "")
|
||||
)
|
||||
|
||||
if not commit:
|
||||
self.stdout.write(
|
||||
"\nSkipping API lookups in dry-run mode. Use --commit to run against ListenBrainz."
|
||||
)
|
||||
return
|
||||
|
||||
found_count = 0
|
||||
empty_count = 0
|
||||
error_count = 0
|
||||
artist_ids = list(qs.values_list("pk", flat=True))
|
||||
i = 0
|
||||
|
||||
for batch_num, offset in enumerate(
|
||||
range(0, len(artist_ids), batch_size)
|
||||
):
|
||||
batch_pks = artist_ids[offset : offset + batch_size]
|
||||
for artist in Artist.objects.filter(pk__in=batch_pks).iterator():
|
||||
i += 1
|
||||
self.stdout.write(
|
||||
f" [{i}/{total}] Fetching similar artists for {artist}...",
|
||||
ending="",
|
||||
)
|
||||
try:
|
||||
similar = get_similar_artists(artist.musicbrainz_id)
|
||||
if similar:
|
||||
artist.similar_artists = similar
|
||||
artist.save(update_fields=["similar_artists"])
|
||||
self.stdout.write(f" {len(similar)} similar artists found")
|
||||
found_count += 1
|
||||
else:
|
||||
artist.similar_artists = []
|
||||
artist.save(update_fields=["similar_artists"])
|
||||
self.stdout.write(" none found")
|
||||
empty_count += 1
|
||||
except Exception as e:
|
||||
self.stdout.write(f" error: {e}")
|
||||
error_count += 1
|
||||
|
||||
self.stdout.write(
|
||||
f" Batch {batch_num + 1}: {offset + len(batch_pks)}/{total} processed, "
|
||||
f"found: {found_count}, empty: {empty_count}, errors: {error_count}"
|
||||
)
|
||||
time.sleep(1)
|
||||
|
||||
self.stdout.write(
|
||||
f"\nResults (commit={commit}):\n"
|
||||
f" Similar artists found: {found_count}\n"
|
||||
f" No similar artists: {empty_count}\n"
|
||||
f" Errors: {error_count}"
|
||||
)
|
||||
Reference in New Issue
Block a user