|
@@ -20,6 +20,8 @@ from scrobbles.models import Scrobble
|
|
from scrobbles.serializers import ScrobbleSerializer
|
|
from scrobbles.serializers import ScrobbleSerializer
|
|
from videos.models import Video
|
|
from videos.models import Video
|
|
|
|
|
|
|
|
+from vrobbler.apps.music.constants import JELLYFIN_POST_KEYS as KEYS
|
|
|
|
+
|
|
logger = logging.getLogger(__name__)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
TRUTHY_VALUES = [
|
|
TRUTHY_VALUES = [
|
|
@@ -79,14 +81,35 @@ def jellyfin_websocket(request):
|
|
|
|
|
|
track = None
|
|
track = None
|
|
video = None
|
|
video = None
|
|
- existing_scrobble = False
|
|
|
|
if media_type in JELLYFIN_AUDIO_ITEM_TYPES:
|
|
if media_type in JELLYFIN_AUDIO_ITEM_TYPES:
|
|
if not data_dict.get("Provider_musicbrainztrack", None):
|
|
if not data_dict.get("Provider_musicbrainztrack", None):
|
|
logger.error(
|
|
logger.error(
|
|
"No MBrainz Track ID received. This is likely because all metadata is bad, not scrobbling"
|
|
"No MBrainz Track ID received. This is likely because all metadata is bad, not scrobbling"
|
|
)
|
|
)
|
|
return Response({}, status=status.HTTP_400_BAD_REQUEST)
|
|
return Response({}, status=status.HTTP_400_BAD_REQUEST)
|
|
- track = Track.find_or_create(data_dict)
|
|
|
|
|
|
+
|
|
|
|
+ artist_dict = {
|
|
|
|
+ 'name': data_dict.get(KEYS["ARTIST_NAME"], None),
|
|
|
|
+ 'musicbrainz_id': data_dict.get(KEYS["ARTIST_MB_ID"], None),
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ album_dict = {
|
|
|
|
+ "name": data_dict.get(KEYS["ALBUM_NAME"], None),
|
|
|
|
+ "year": data_dict.get(KEYS["YEAR"], ""),
|
|
|
|
+ "musicbrainz_id": data_dict.get(KEYS['ALBUM_MB_ID']),
|
|
|
|
+ "musicbrainz_releasegroup_id": data_dict.get(
|
|
|
|
+ KEYS["RELEASEGROUP_MB_ID"]
|
|
|
|
+ ),
|
|
|
|
+ "musicbrainz_albumartist_id": data_dict.get(KEYS["ARTIST_MB_ID"]),
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ track_dict = {
|
|
|
|
+ "title": data_dict.get("Name", ""),
|
|
|
|
+ "musicbrainz_id": data_dict.get(KEYS["TRACK_MB_ID"], None),
|
|
|
|
+ "run_time_ticks": data_dict.get(KEYS["RUN_TIME_TICKS"], None),
|
|
|
|
+ "run_time": data_dict.get(KEYS["RUN_TIME"], None),
|
|
|
|
+ }
|
|
|
|
+ track = Track.find_or_create(artist_dict, album_dict, track_dict)
|
|
|
|
|
|
if media_type in JELLYFIN_VIDEO_ITEM_TYPES:
|
|
if media_type in JELLYFIN_VIDEO_ITEM_TYPES:
|
|
if not data_dict.get("Provider_imdb", None):
|
|
if not data_dict.get("Provider_imdb", None):
|
|
@@ -102,7 +125,7 @@ def jellyfin_websocket(request):
|
|
"timestamp": parse(data_dict.get("UtcTimestamp")),
|
|
"timestamp": parse(data_dict.get("UtcTimestamp")),
|
|
"playback_position_ticks": data_dict.get("PlaybackPositionTicks"),
|
|
"playback_position_ticks": data_dict.get("PlaybackPositionTicks"),
|
|
"playback_position": data_dict.get("PlaybackPosition"),
|
|
"playback_position": data_dict.get("PlaybackPosition"),
|
|
- "source": data_dict.get('ClientName'),
|
|
|
|
|
|
+ "source": "Jellyfin",
|
|
"source_id": data_dict.get('MediaSourceId'),
|
|
"source_id": data_dict.get('MediaSourceId'),
|
|
"is_paused": data_dict.get("IsPaused") in TRUTHY_VALUES,
|
|
"is_paused": data_dict.get("IsPaused") in TRUTHY_VALUES,
|
|
}
|
|
}
|
|
@@ -123,3 +146,53 @@ def jellyfin_websocket(request):
|
|
return Response(
|
|
return Response(
|
|
{'scrobble_id': scrobble.id}, status=status.HTTP_201_CREATED
|
|
{'scrobble_id': scrobble.id}, status=status.HTTP_201_CREATED
|
|
)
|
|
)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+@csrf_exempt
|
|
|
|
+@api_view(['POST'])
|
|
|
|
+def mopidy_websocket(request):
|
|
|
|
+ data_dict = request.data
|
|
|
|
+
|
|
|
|
+ # For making things easier to build new input processors
|
|
|
|
+ if getattr(settings, "DUMP_REQUEST_DATA", False):
|
|
|
|
+ json_data = json.dumps(data_dict, indent=4)
|
|
|
|
+
|
|
|
|
+ artist_dict = {
|
|
|
|
+ "name": data_dict.get("artist", None),
|
|
|
|
+ "musicbrainz_id": data_dict.get("musicbrainz_artist_id", None),
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ album_dict = {
|
|
|
|
+ "name": data_dict.get("album"),
|
|
|
|
+ "musicbrainz_id": data_dict.get("musicbrainz_album_id"),
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ track_dict = {
|
|
|
|
+ "title": data_dict.get("name"),
|
|
|
|
+ "musicbrainz_id": data_dict.get("musicbrainz_track_id"),
|
|
|
|
+ "run_time_ticks": data_dict.get("run_time_ticks"),
|
|
|
|
+ "run_time": data_dict.get("run_time"),
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ track = Track.find_or_create(artist_dict, album_dict, track_dict)
|
|
|
|
+
|
|
|
|
+ # Now we run off a scrobble
|
|
|
|
+ mopidy_data = {
|
|
|
|
+ "user_id": request.user.id,
|
|
|
|
+ "timestamp": timezone.now(),
|
|
|
|
+ "source": "Mopidy",
|
|
|
|
+ "status": data_dict.get("status"),
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ scrobble = None
|
|
|
|
+ if track:
|
|
|
|
+ scrobble = Scrobble.create_or_update_for_track(
|
|
|
|
+ track, request.user.id, mopidy_data
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ if not scrobble:
|
|
|
|
+ return Response({}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
+
|
|
|
|
+ return Response(
|
|
|
|
+ {'scrobble_id': scrobble.id}, status=status.HTTP_201_CREATED
|
|
|
|
+ )
|