Compare commits

...

8 Commits
0.8.1 ... 0.8.4

Author SHA1 Message Date
5e7c8ff137 Bump version to 0.8.4 2023-02-07 00:52:11 -05:00
fae59849f8 Add mb lookups to TSV imports 2023-02-07 00:51:43 -05:00
837e1280bd Bump version to 0.8.3 2023-02-06 23:30:14 -05:00
8f9c825903 Fix user timezones in scrobbler files 2023-02-06 23:28:57 -05:00
541073aae3 Bump version to 0.8.2 2023-02-06 19:32:15 -05:00
b63ec6b15f Fix bug in export when artist does not exist 2023-02-06 19:31:25 -05:00
117157e3ae Fix audioscrobbler import bug
Issue was not having a user so we couldn't set a timezone. All fixed now
2023-02-06 19:30:58 -05:00
0c10e78d5e Fix bug in unified scrobbler for podcasts 2023-02-06 17:54:48 -05:00
7 changed files with 85 additions and 19 deletions

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "vrobbler"
version = "0.8.1"
version = "0.8.4"
description = ""
authors = ["Colin Powell <colin@unbl.ink>"]

View File

@ -1,3 +1,5 @@
import pytz
from django.contrib.auth import get_user_model
from django.db import models
from django_extensions.db.models import TimeStampedModel
@ -16,3 +18,7 @@ class UserProfile(TimeStampedModel):
def __str__(self):
return f"User profile for {self.user}"
@property
def tzinfo(self):
return pytz.timezone(self.timezone)

View File

@ -52,8 +52,9 @@ def export_scrobbles(start_date=None, end_date=None, format="AS"):
track = scrobble.track
track_number = 0 # TODO Add track number
track_rating = "S" # TODO implement ratings?
track_artist = track.artist or track.album.primary_artist
row = [
track.album.primary_artist.name,
track_artist,
track.album.name,
track.title,
track_number,

View File

@ -0,0 +1,26 @@
# Generated by Django 4.1.5 on 2023-02-07 00:07
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('scrobbles', '0016_audioscrobblertsvimport_process_count'),
]
operations = [
migrations.AddField(
model_name='audioscrobblertsvimport',
name='user',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
to=settings.AUTH_USER_MODEL,
),
),
]

View File

@ -24,6 +24,7 @@ class AudioScrobblerTSVImport(TimeStampedModel):
uuid = instance.uuid
return f'audioscrobbler-uploads/{uuid}.{extension}'
user = models.ForeignKey(User, on_delete=models.DO_NOTHING, **BNULL)
uuid = models.UUIDField(editable=False, default=uuid4)
tsv_file = models.FileField(upload_to=get_path, **BNULL)
processed_on = models.DateTimeField(**BNULL)
@ -48,7 +49,12 @@ class AudioScrobblerTSVImport(TimeStampedModel):
logger.info(f"{self} already processed on {self.processed_on}")
return
scrobbles = process_audioscrobbler_tsv_file(self.tsv_file.path)
tz = None
if self.user:
tz = self.user.profile.tzinfo
scrobbles = process_audioscrobbler_tsv_file(
self.tsv_file.path, user_tz=tz
)
if scrobbles:
self.process_log = f"Created {len(scrobbles)} scrobbles"
for scrobble in scrobbles:
@ -255,7 +261,7 @@ class Scrobble(TimeStampedModel):
scrobble_data['video_id'] = media.id
if media.__class__.__name__ == 'Episode':
media_query = models.Q(podcast_episode=media)
scrobble_data['podcast_id'] = media.id
scrobble_data['podcast_episode_id'] = media.id
if media.__class__.__name__ == 'SportEvent':
media_query = models.Q(sport_event=media)
scrobble_data['sport_event_id'] = media.id

View File

@ -6,12 +6,19 @@ import pytz
from music.models import Album, Artist, Track
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__)
def process_audioscrobbler_tsv_file(file_path):
def process_audioscrobbler_tsv_file(file_path, user_tz=None):
"""Takes a path to a file of TSV data and imports it as past scrobbles"""
new_scrobbles = []
if not user_tz:
user_tz = pytz.utc
with open(file_path) as infile:
source = 'Audioscrobbler File'
@ -30,9 +37,8 @@ def process_audioscrobbler_tsv_file(file_path):
continue
artist, artist_created = Artist.objects.get_or_create(name=row[0])
if artist_created:
logger.debug(f"Created artist {artist}")
else:
logger.debug(f"Found artist {artist}")
artist.musicbrainz_id = lookup_artist_id_from_mb(artist.name)
artist.save(update_fields=["musicbrainz_id"])
album = None
album_created = False
@ -50,9 +56,22 @@ def process_audioscrobbler_tsv_file(file_path):
album.artists.add(artist)
if album_created:
logger.debug(f"Created album {album}")
else:
logger.debug(f"Found album {album}")
album_dict = lookup_album_dict_from_mb(
album.name, artist_name=artist.name
)
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)
track, track_created = Track.objects.get_or_create(
title=row[2],
@ -60,17 +79,16 @@ def process_audioscrobbler_tsv_file(file_path):
album=album,
)
if track_created:
logger.debug(f"Created track {track}")
else:
logger.debug(f"Found track {track}")
if track_created:
track.musicbrainz_id = row[7]
track.run_time = int(row[4])
track.run_time_ticks = int(row[4]) * 1000
track.save()
timestamp = datetime.utcfromtimestamp(int(row[6])).replace(
tzinfo=pytz.utc
timestamp = (
datetime.utcfromtimestamp(int(row[6]))
.replace(tzinfo=user_tz)
.astimezone(pytz.utc)
)
source = 'Audioscrobbler File'

View File

@ -4,6 +4,7 @@ from datetime import datetime
import pytz
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models.fields import timezone
from django.http import FileResponse, HttpResponseRedirect, JsonResponse
from django.urls import reverse, reverse_lazy
@ -160,12 +161,20 @@ class JsonableResponseMixin:
return JsonResponse(data)
class AudioScrobblerImportCreateView(JsonableResponseMixin, CreateView):
class AudioScrobblerImportCreateView(
LoginRequiredMixin, JsonableResponseMixin, CreateView
):
model = AudioScrobblerTSVImport
fields = ['tsv_file']
template_name = 'scrobbles/upload_form.html'
success_url = reverse_lazy('vrobbler-home')
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return HttpResponseRedirect(self.get_success_url())
@csrf_exempt
@api_view(['GET'])