[videos] Add youtube scrobbling

This commit is contained in:
2024-11-05 23:32:03 -05:00
parent b65ebbe397
commit 1b95706f70
6 changed files with 108 additions and 1 deletions

View File

@ -1186,7 +1186,7 @@ class Scrobble(TimeStampedModel):
profile = UserProfile.objects.filter( profile = UserProfile.objects.filter(
user_id=scrobble_data["user_id"] user_id=scrobble_data["user_id"]
).first() ).first()
if profile.ntfy_enabled and profile.ntfy_url: if profile and profile.ntfy_enabled and profile.ntfy_url:
# TODO allow prority and tags to be configured in the profile # TODO allow prority and tags to be configured in the profile
notify_str = f"{scrobble.media_obj}" notify_str = f"{scrobble.media_obj}"
if scrobble.log and scrobble.log.get("description"): if scrobble.log and scrobble.log.get("description"):

View File

@ -2,6 +2,7 @@ import logging
import re import re
from typing import Optional from typing import Optional
from datetime import datetime
import pendulum import pendulum
import pytz import pytz
from beers.models import Beer from beers.models import Beer
@ -133,6 +134,49 @@ def jellyfin_scrobble_media(
) )
def web_scrobbler_scrobble_media(
post_data: dict, user_id: int
) -> Optional[Scrobble]:
media_type = Scrobble.MediaType.VIDEO
event_name = post_data.get("eventName")
parsed = post_data.get("data").get("song").get("parsed")
processed = post_data.get("data").get("song").get("processed")
video, created = Video.objects.get_or_create(
video_type=Video.VideoType.YOUTUBE,
youtube_url=parsed.get("originUrl"),
)
timestamp = datetime.utcfromtimestamp(
post_data.get("time", 0)/1000
).replace(tzinfo=pytz.utc)
if created or event_name == "nowplaying":
video.run_time_seconds = 1800
processed = post_data.get("data").get("song").get("processed")
# TODO maybe artist could be the series?
video.title = " - ".join([processed.get("artist"), processed.get("track")])
video.save()
return video.scrobble_for_user(
user_id,
source="YouTube",
playback_position_seconds=0,
status=event_name,
)
scrobble = Scrobble.objects.filter(user_id=user_id, video=video, in_progress=True).first()
if not scrobble:
return video.scrobble_for_user(
user_id,
source="YouTube",
playback_position_seconds=0,
status=event_name,
)
if event_name == "paused":
scrobble.pause()
if event_name == "resumedplaying":
scrobble.resume()
return scrobble
def manual_scrobble_video(imdb_id: str, user_id: int): def manual_scrobble_video(imdb_id: str, user_id: int):
if "tt" not in imdb_id: if "tt" not in imdb_id:
imdb_id = "tt" + imdb_id imdb_id = "tt" + imdb_id

View File

@ -31,6 +31,11 @@ urlpatterns = [
views.lastfm_import, views.lastfm_import,
name="lastfm-import", name="lastfm-import",
), ),
path(
"webhook/web-scrobbler/",
views.web_scrobbler_webhook,
name="web-scrobbler-webhook",
),
path( path(
"webhook/gps/", "webhook/gps/",
views.gps_webhook, views.gps_webhook,

View File

@ -314,6 +314,29 @@ def lastfm_import(request):
return HttpResponseRedirect(request.META.get("HTTP_REFERER")) return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
@csrf_exempt
@permission_classes([IsAuthenticated])
@api_view(["POST"])
def web_scrobbler_webhook(request):
post_data = request.data
logger.info(
"[web_scrobbler_webhook] called",
extra={
"post_data": post_data,
"user_id": request.user.id,
},
)
scrobble = web_scrobbler_scrobble_media(post_data, request.user.id)
if not scrobble:
return Response({}, status=status.HTTP_400_BAD_REQUEST)
logger.info(
"[jellyfin_webhook] finished",
extra={"scrobble_id": scrobble.id},
)
return Response({"scrobble_id": scrobble.id}, status=status.HTTP_200_OK)
@csrf_exempt @csrf_exempt
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])

View File

@ -0,0 +1,33 @@
# Generated by Django 4.2.16 on 2024-11-06 03:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("videos", "0017_alter_video_video_type"),
]
operations = [
migrations.AddField(
model_name="video",
name="youtube_url",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AlterField(
model_name="video",
name="video_type",
field=models.CharField(
choices=[
("U", "Unknown"),
("E", "TV Episode"),
("M", "Movie"),
("S", "Skate Video"),
("Y", "YouTube Video"),
],
default="U",
max_length=1,
),
),
]

View File

@ -128,6 +128,7 @@ class Video(ScrobblableMixin):
TV_EPISODE = "E", _("TV Episode") TV_EPISODE = "E", _("TV Episode")
MOVIE = "M", _("Movie") MOVIE = "M", _("Movie")
SKATE_VIDEO = "S", _("Skate Video") SKATE_VIDEO = "S", _("Skate Video")
YOUTUBE = "Y", _("YouTube Video")
video_type = models.CharField( video_type = models.CharField(
max_length=1, max_length=1,
@ -161,6 +162,7 @@ class Video(ScrobblableMixin):
tvrage_id = models.CharField(max_length=20, **BNULL) tvrage_id = models.CharField(max_length=20, **BNULL)
tvdb_id = models.CharField(max_length=20, **BNULL) tvdb_id = models.CharField(max_length=20, **BNULL)
tmdb_id = models.CharField(max_length=20, **BNULL) tmdb_id = models.CharField(max_length=20, **BNULL)
youtube_url = models.CharField(max_length=255, **BNULL)
plot = models.TextField(**BNULL) plot = models.TextField(**BNULL)
year = models.IntegerField(**BNULL) year = models.IntegerField(**BNULL)