Add manual scrobbling by TheSportsDB ID
This commit is contained in:
@ -148,6 +148,25 @@ class Scrobble(TimeStampedModel):
|
||||
scrobble, backoff, wait_period, scrobble_data
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def create_or_update_for_sport_event(
|
||||
cls, event: "SportEvent", user_id: int, jellyfin_data: dict
|
||||
) -> "Scrobble":
|
||||
jellyfin_data['sport_event_id'] = event.id
|
||||
scrobble = (
|
||||
cls.objects.filter(sport_event=event, user_id=user_id)
|
||||
.order_by('-modified')
|
||||
.first()
|
||||
)
|
||||
|
||||
# Backoff is how long until we consider this a new scrobble
|
||||
backoff = timezone.now() + timedelta(minutes=VIDEO_BACKOFF)
|
||||
wait_period = timezone.now() + timedelta(days=VIDEO_WAIT_PERIOD)
|
||||
|
||||
return cls.update_or_create(
|
||||
scrobble, backoff, wait_period, jellyfin_data
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def update_or_create(
|
||||
cls,
|
||||
|
||||
@ -9,6 +9,7 @@ from podcasts.models import Episode
|
||||
from scrobbles.models import Scrobble
|
||||
from scrobbles.utils import convert_to_seconds, parse_mopidy_uri
|
||||
from videos.models import Video
|
||||
from sports.models import SportEvent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -104,18 +105,23 @@ def create_jellyfin_scrobble_dict(data_dict: dict, user_id: int) -> dict:
|
||||
if data_dict.get("PlayedToCompletion"):
|
||||
jellyfin_status = "stopped"
|
||||
|
||||
playback_position_ticks = data_dict.get("PlaybackPositionTicks") // 10000
|
||||
if playback_position_ticks <= 0:
|
||||
playback_position_ticks = None
|
||||
playback_position_ticks = None
|
||||
if data_dict.get("PlaybackPositionTicks"):
|
||||
playback_position_ticks = (
|
||||
data_dict.get("PlaybackPositionTicks") // 10000
|
||||
)
|
||||
if playback_position_ticks <= 0:
|
||||
playback_position_ticks = None
|
||||
|
||||
playback_position = data_dict.get("PlaybackPosition")
|
||||
if playback_position:
|
||||
playback_position = convert_to_seconds(playback_position)
|
||||
|
||||
logger.debug(playback_position_ticks)
|
||||
return {
|
||||
"user_id": user_id,
|
||||
"timestamp": parse(data_dict.get("UtcTimestamp")),
|
||||
"playback_position_ticks": playback_position_ticks,
|
||||
"playback_position": convert_to_seconds(
|
||||
data_dict.get("PlaybackPosition")
|
||||
),
|
||||
"playback_position": playback_position,
|
||||
"source": "Jellyfin",
|
||||
"source_id": data_dict.get('MediaSourceId'),
|
||||
"jellyfin_status": jellyfin_status,
|
||||
@ -193,3 +199,18 @@ def manual_scrobble_video(data_dict: dict, user_id: Optional[int]):
|
||||
scrobble_dict = create_jellyfin_scrobble_dict(data_dict, user_id)
|
||||
|
||||
return Scrobble.create_or_update_for_video(video, user_id, scrobble_dict)
|
||||
|
||||
|
||||
def manual_scrobble_event(data_dict: dict, user_id: Optional[int]):
|
||||
if not data_dict.get("Provider_thesportsdb", None):
|
||||
logger.error(
|
||||
"No TheSportsDB ID received. This is likely because all metadata is bad, not scrobbling"
|
||||
)
|
||||
return
|
||||
event = SportEvent.find_or_create(data_dict)
|
||||
|
||||
scrobble_dict = create_jellyfin_scrobble_dict(data_dict, user_id)
|
||||
|
||||
return Scrobble.create_or_update_for_sport_event(
|
||||
event, user_id, scrobble_dict
|
||||
)
|
||||
|
||||
44
vrobbler/apps/scrobbles/thesportsdb.py
Normal file
44
vrobbler/apps/scrobbles/thesportsdb.py
Normal file
@ -0,0 +1,44 @@
|
||||
import logging
|
||||
|
||||
from dateutil.parser import parse
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from pysportsdb import TheSportsDbClient
|
||||
from sports.models import SportEvent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
API_KEY = getattr(settings, "THESPORTSDB_API_KEY", "2")
|
||||
client = TheSportsDbClient(api_key=API_KEY)
|
||||
|
||||
|
||||
def lookup_event_from_thesportsdb(event_id: str) -> dict:
|
||||
|
||||
event = client.lookup_event(event_id)['events'][0]
|
||||
league = {} # client.lookup_league(league_id=event.get('idLeague'))
|
||||
event_type = SportEvent.Type.GAME
|
||||
run_time_seconds = 11700
|
||||
run_time_ticks = run_time_seconds * 1000
|
||||
|
||||
data_dict = {
|
||||
"ItemType": event_type,
|
||||
"Name": event.get('strEventAlternate'),
|
||||
"Start": parse(event.get('strTimestamp')),
|
||||
"Provider_thesportsdb": event.get('idEvent'),
|
||||
"RunTime": run_time_seconds,
|
||||
"RunTimeTicks": run_time_ticks,
|
||||
"LeagueId": event.get('idLeague'),
|
||||
"LeagueName": event.get('strLeague'),
|
||||
"HomeTeamId": event.get('idHomeTeam'),
|
||||
"HomeTeamName": event.get('strHomeTeam'),
|
||||
"AwayTeamId": event.get('idAwayTeam'),
|
||||
"AwayTeamName": event.get('strAwayTeam'),
|
||||
"RoundId": event.get('intRound'),
|
||||
"PlaybackPositionTicks": None,
|
||||
"PlaybackPosition": None,
|
||||
"UtcTimestamp": timezone.now().strftime('%Y-%m-%d %H:%M:%S.%f%z'),
|
||||
"IsPaused": False,
|
||||
"PlayedToCompletion": False,
|
||||
}
|
||||
|
||||
return data_dict
|
||||
@ -16,16 +16,19 @@ from scrobbles.constants import (
|
||||
JELLYFIN_AUDIO_ITEM_TYPES,
|
||||
JELLYFIN_VIDEO_ITEM_TYPES,
|
||||
)
|
||||
from scrobbles.forms import ScrobbleForm
|
||||
from scrobbles.imdb import lookup_video_from_imdb
|
||||
from scrobbles.models import Scrobble
|
||||
from scrobbles.scrobblers import (
|
||||
jellyfin_scrobble_track,
|
||||
jellyfin_scrobble_video,
|
||||
manual_scrobble_event,
|
||||
manual_scrobble_video,
|
||||
mopidy_scrobble_podcast,
|
||||
mopidy_scrobble_track,
|
||||
)
|
||||
from scrobbles.serializers import ScrobbleSerializer
|
||||
from scrobbles.thesportsdb import lookup_event_from_thesportsdb
|
||||
|
||||
from vrobbler.apps.music.aggregators import (
|
||||
scrobble_counts,
|
||||
@ -33,7 +36,6 @@ from vrobbler.apps.music.aggregators import (
|
||||
top_tracks,
|
||||
week_of_scrobbles,
|
||||
)
|
||||
from scrobbles.forms import ScrobbleForm
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -95,7 +97,7 @@ class ManualScrobbleView(FormView):
|
||||
|
||||
def form_valid(self, form):
|
||||
|
||||
item_id = form.cleaned_data.get('itme_id')
|
||||
item_id = form.cleaned_data.get('item_id')
|
||||
data_dict = None
|
||||
if 'tt' in item_id:
|
||||
data_dict = lookup_video_from_imdb(
|
||||
@ -104,12 +106,13 @@ class ManualScrobbleView(FormView):
|
||||
if data_dict:
|
||||
manual_scrobble_video(data_dict, self.request.user.id)
|
||||
|
||||
# if not data_dict:
|
||||
# data_dict = lookup_event_from_thesportsdb(
|
||||
# form.cleaned_data.get('item_id')
|
||||
# )
|
||||
# if data_dict:
|
||||
# manual_scrobble_event(data_dict, self.request.user.id)
|
||||
if not data_dict:
|
||||
logger.debug(f"Looking for sport event with ID {item_id}")
|
||||
data_dict = lookup_event_from_thesportsdb(
|
||||
form.cleaned_data.get('item_id')
|
||||
)
|
||||
if data_dict:
|
||||
manual_scrobble_event(data_dict, self.request.user.id)
|
||||
|
||||
return HttpResponseRedirect(reverse("home"))
|
||||
|
||||
|
||||
@ -78,27 +78,35 @@ class SportEvent(ScrobblableMixin):
|
||||
exist.
|
||||
|
||||
"""
|
||||
league_dict = {"name": data_dict.get("LeagueName", "")}
|
||||
league_dict = {
|
||||
"abbreviation_str": data_dict.get("LeagueName", ""),
|
||||
"thesportsdb_id": data_dict.get("LeagueId", ""),
|
||||
}
|
||||
league, _created = League.objects.get_or_create(**league_dict)
|
||||
|
||||
home_team_dict = {
|
||||
"name": data_dict.get("HomeTeamName", ""),
|
||||
"thesportsdb_id": data_dict.get("HomeTeamId", ""),
|
||||
"league": league,
|
||||
}
|
||||
home_team, _created = Team.objects.get_or_create(**home_team_dict)
|
||||
|
||||
away_team_dict = {
|
||||
"name": data_dict.get("AwayTeamName", ""),
|
||||
"thesportsdb_id": data_dict.get("AwayTeamId", ""),
|
||||
"league": league,
|
||||
}
|
||||
away_team, _created = Team.objects.get_or_create(**away_team_dict)
|
||||
|
||||
event_dict = {
|
||||
"event_type": SportEvent.Type.GAME,
|
||||
"title": data_dict.get("Name"),
|
||||
"event_type": data_dict.get("ItemType"),
|
||||
"home_team": home_team,
|
||||
"away_team": away_team,
|
||||
"start_utc": data_dict['SportEventStart'],
|
||||
"start": data_dict['Start'],
|
||||
"league": league,
|
||||
"run_time_ticks": data_dict.get("RunTimeTicks"),
|
||||
"run_time": data_dict.get("RunTime", ""),
|
||||
}
|
||||
event, _created = cls.objects.get_or_create(**event_dict)
|
||||
|
||||
|
||||
@ -96,7 +96,6 @@ class Video(ScrobblableMixin):
|
||||
|
||||
video, created = cls.objects.get_or_create(**video_dict)
|
||||
|
||||
logger.debug(data_dict)
|
||||
run_time_ticks = data_dict.get("RunTimeTicks", None)
|
||||
if run_time_ticks:
|
||||
run_time_ticks = run_time_ticks // 10000
|
||||
|
||||
Reference in New Issue
Block a user