Fix scrobbling tracks with featured artists
This commit is contained in:
@ -2,7 +2,7 @@ import logging
|
|||||||
|
|
||||||
from scrobbles.musicbrainz import (
|
from scrobbles.musicbrainz import (
|
||||||
lookup_album_dict_from_mb,
|
lookup_album_dict_from_mb,
|
||||||
lookup_artist_id_from_mb,
|
lookup_artist_from_mb,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -12,16 +12,18 @@ from music.models import Artist, Album, Track
|
|||||||
|
|
||||||
|
|
||||||
def get_or_create_artist(name: str, mbid: str = None) -> Artist:
|
def get_or_create_artist(name: str, mbid: str = None) -> Artist:
|
||||||
|
if 'feat.' in name:
|
||||||
|
name = name.split('feat.')[0]
|
||||||
if mbid:
|
if mbid:
|
||||||
artist, artist_created = Artist.objects.get_or_create(
|
artist, created = Artist.objects.get_or_create(musicbrainz_id=mbid)
|
||||||
name=name, musicbrainz_id=mbid
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
artist, artist_created = Artist.objects.get_or_create(name=name)
|
artist, created = Artist.objects.get_or_create(name=name)
|
||||||
|
|
||||||
if not mbid:
|
if created or not mbid:
|
||||||
artist.musicbrainz_id = lookup_artist_id_from_mb(artist.name)
|
artist_dict = lookup_artist_from_mb(name)
|
||||||
artist.save(update_fields=["musicbrainz_id"])
|
artist.musicbrainz_id = artist_dict["id"]
|
||||||
|
artist.name = artist_dict["name"]
|
||||||
|
artist.save(update_fields=["musicbrainz_id", "name"])
|
||||||
return artist
|
return artist
|
||||||
|
|
||||||
|
|
||||||
@ -80,6 +82,7 @@ def get_or_create_track(
|
|||||||
title=title, artist=artist, album=album
|
title=title, artist=artist, album=album
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
|
# TODO Can we look up mbid for tracks?
|
||||||
if not track:
|
if not track:
|
||||||
track = Track.objects.create(
|
track = Track.objects.create(
|
||||||
title=title,
|
title=title,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from django.db import models
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_extensions.db.models import TimeStampedModel
|
from django_extensions.db.models import TimeStampedModel
|
||||||
|
|
||||||
from vrobbler.apps.scrobbles.mixins import ScrobblableMixin
|
from scrobbles.mixins import ScrobblableMixin
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
BNULL = {"blank": True, "null": True}
|
BNULL = {"blank": True, "null": True}
|
||||||
|
|||||||
@ -8,11 +8,11 @@ from django.utils import timezone
|
|||||||
from django_extensions.db.models import TimeStampedModel
|
from django_extensions.db.models import TimeStampedModel
|
||||||
from music.models import Artist, Track
|
from music.models import Artist, Track
|
||||||
from podcasts.models import Episode
|
from podcasts.models import Episode
|
||||||
|
from profiles.utils import now_user_timezone
|
||||||
|
from scrobbles.lastfm import LastFM
|
||||||
from scrobbles.utils import check_scrobble_for_finish
|
from scrobbles.utils import check_scrobble_for_finish
|
||||||
from sports.models import SportEvent
|
from sports.models import SportEvent
|
||||||
from videos.models import Series, Video
|
from videos.models import Series, Video
|
||||||
from vrobbler.apps.profiles.utils import now_user_timezone
|
|
||||||
from vrobbler.apps.scrobbles.lastfm import LastFM
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|||||||
@ -73,7 +73,7 @@ def lookup_album_dict_from_mb(release_name: str, artist_name: str) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def lookup_artist_id_from_mb(artist_name: str) -> str:
|
def lookup_artist_from_mb(artist_name: str) -> str:
|
||||||
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
||||||
|
|
||||||
top_result = musicbrainzngs.search_artists(artist=artist_name)[
|
top_result = musicbrainzngs.search_artists(artist=artist_name)[
|
||||||
@ -87,4 +87,21 @@ def lookup_artist_id_from_mb(artist_name: str) -> str:
|
|||||||
)
|
)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
return top_result["id"]
|
return top_result
|
||||||
|
|
||||||
|
|
||||||
|
def lookup_track_from_mb(artist_name: str) -> str:
|
||||||
|
musicbrainzngs.set_useragent('vrobbler', '0.3.0')
|
||||||
|
|
||||||
|
top_result = musicbrainzngs.search_recordings(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
|
||||||
|
|||||||
@ -124,13 +124,6 @@ def jellyfin_scrobble_track(
|
|||||||
data_dict: dict, user_id: Optional[int]
|
data_dict: dict, user_id: Optional[int]
|
||||||
) -> Optional[Scrobble]:
|
) -> Optional[Scrobble]:
|
||||||
|
|
||||||
if not data_dict.get("Provider_musicbrainztrack", None):
|
|
||||||
# TODO we should be able to look up tracks via MB rather than error out
|
|
||||||
logger.error(
|
|
||||||
"No MBrainz Track ID received. This is likely because all metadata is bad, not scrobbling"
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
null_position_on_progress = (
|
null_position_on_progress = (
|
||||||
data_dict.get("PlaybackPosition") == "00:00:00"
|
data_dict.get("PlaybackPosition") == "00:00:00"
|
||||||
and data_dict.get("NotificationType") == "PlaybackProgress"
|
and data_dict.get("NotificationType") == "PlaybackProgress"
|
||||||
|
|||||||
@ -13,6 +13,12 @@ from django.views.decorators.csrf import csrf_exempt
|
|||||||
from django.views.generic import FormView
|
from django.views.generic import FormView
|
||||||
from django.views.generic.edit import CreateView
|
from django.views.generic.edit import CreateView
|
||||||
from django.views.generic.list import ListView
|
from django.views.generic.list import ListView
|
||||||
|
from music.aggregators import (
|
||||||
|
scrobble_counts,
|
||||||
|
top_artists,
|
||||||
|
top_tracks,
|
||||||
|
week_of_scrobbles,
|
||||||
|
)
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.decorators import (
|
from rest_framework.decorators import (
|
||||||
api_view,
|
api_view,
|
||||||
@ -26,9 +32,10 @@ from scrobbles.constants import (
|
|||||||
JELLYFIN_AUDIO_ITEM_TYPES,
|
JELLYFIN_AUDIO_ITEM_TYPES,
|
||||||
JELLYFIN_VIDEO_ITEM_TYPES,
|
JELLYFIN_VIDEO_ITEM_TYPES,
|
||||||
)
|
)
|
||||||
|
from scrobbles.export import export_scrobbles
|
||||||
from scrobbles.forms import ExportScrobbleForm, ScrobbleForm
|
from scrobbles.forms import ExportScrobbleForm, ScrobbleForm
|
||||||
from scrobbles.imdb import lookup_video_from_imdb
|
from scrobbles.imdb import lookup_video_from_imdb
|
||||||
from scrobbles.models import AudioScrobblerTSVImport, Scrobble
|
from scrobbles.models import AudioScrobblerTSVImport, LastFmImport, Scrobble
|
||||||
from scrobbles.scrobblers import (
|
from scrobbles.scrobblers import (
|
||||||
jellyfin_scrobble_track,
|
jellyfin_scrobble_track,
|
||||||
jellyfin_scrobble_video,
|
jellyfin_scrobble_video,
|
||||||
@ -41,16 +48,9 @@ from scrobbles.serializers import (
|
|||||||
AudioScrobblerTSVImportSerializer,
|
AudioScrobblerTSVImportSerializer,
|
||||||
ScrobbleSerializer,
|
ScrobbleSerializer,
|
||||||
)
|
)
|
||||||
|
from scrobbles.tasks import process_lastfm_import
|
||||||
from scrobbles.thesportsdb import lookup_event_from_thesportsdb
|
from scrobbles.thesportsdb import lookup_event_from_thesportsdb
|
||||||
|
|
||||||
from vrobbler.apps.music.aggregators import (
|
|
||||||
scrobble_counts,
|
|
||||||
top_artists,
|
|
||||||
top_tracks,
|
|
||||||
week_of_scrobbles,
|
|
||||||
)
|
|
||||||
from vrobbler.apps.scrobbles.export import export_scrobbles
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -176,6 +176,17 @@ class AudioScrobblerImportCreateView(
|
|||||||
return HttpResponseRedirect(self.get_success_url())
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
|
|
||||||
|
@permission_classes([IsAuthenticated])
|
||||||
|
@api_view(['GET'])
|
||||||
|
def lastfm_import(request):
|
||||||
|
lfm_import = LastFmImport.objects.create(user=request.user)
|
||||||
|
|
||||||
|
process_lastfm_import.delay(lfm_import.id)
|
||||||
|
|
||||||
|
success_url = reverse_lazy('vrobbler-home')
|
||||||
|
return HttpResponseRedirect(success_url)
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
def scrobble_endpoint(request):
|
def scrobble_endpoint(request):
|
||||||
|
|||||||
@ -7,12 +7,8 @@ from django.db import models
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_extensions.db.models import TimeStampedModel
|
from django_extensions.db.models import TimeStampedModel
|
||||||
from sqlalchemy import update
|
|
||||||
from scrobbles.mixins import ScrobblableMixin
|
from scrobbles.mixins import ScrobblableMixin
|
||||||
from vrobbler.apps.sports.utils import (
|
from sports.utils import get_players_from_event, get_round_name_from_event
|
||||||
get_players_from_event,
|
|
||||||
get_round_name_from_event,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
BNULL = {"blank": True, "null": True}
|
BNULL = {"blank": True, "null": True}
|
||||||
|
|||||||
Reference in New Issue
Block a user