Files
vrobbler/vrobbler/apps/videos/models.py
Colin Powell 0f562b7c58 Fix resume bug, stop trying to avoid resuming
Turns out trying to not resume in-progress Scrobbles is super painful.
Maybe I'll come up with a better idea later, but for now, I'd rather
just resurrect old paused scrobbles of past tracks, rather than
completely mess up all other aspects of scrobbling.
2023-01-16 23:44:49 -05:00

130 lines
4.3 KiB
Python

import logging
from typing import Dict
from uuid import uuid4
from django.conf import settings
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django_extensions.db.models import TimeStampedModel
from scrobbles.utils import convert_to_seconds
from scrobbles.mixins import ScrobblableMixin
logger = logging.getLogger(__name__)
BNULL = {"blank": True, "null": True}
class Series(TimeStampedModel):
uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
name = models.CharField(max_length=255)
overview = models.TextField(**BNULL)
tagline = models.TextField(**BNULL)
# tvdb_id = models.CharField(max_length=20, **BNULL)
# imdb_id = models.CharField(max_length=20, **BNULL)
def __str__(self):
return self.name
def imdb_link(self):
return f"https://www.imdb.com/title/{self.imdb_id}"
class Meta:
verbose_name_plural = "series"
class Video(ScrobblableMixin):
COMPLETION_PERCENT = getattr(settings, 'VIDEO_COMPLETION_PERCENT', 90)
class VideoType(models.TextChoices):
UNKNOWN = 'U', _('Unknown')
TV_EPISODE = 'E', _('TV Episode')
MOVIE = 'M', _('Movie')
video_type = models.CharField(
max_length=1,
choices=VideoType.choices,
default=VideoType.UNKNOWN,
)
overview = models.TextField(**BNULL)
tagline = models.TextField(**BNULL)
year = models.IntegerField(**BNULL)
# TV show specific fields
tv_series = models.ForeignKey(Series, on_delete=models.DO_NOTHING, **BNULL)
season_number = models.IntegerField(**BNULL)
episode_number = models.IntegerField(**BNULL)
tvdb_id = models.CharField(max_length=20, **BNULL)
imdb_id = models.CharField(max_length=20, **BNULL)
tvrage_id = models.CharField(max_length=20, **BNULL)
class Meta:
unique_together = [['title', 'imdb_id']]
def __str__(self):
if self.video_type == self.VideoType.TV_EPISODE:
return f"{self.tv_series} - Season {self.season_number}, Episode {self.episode_number}"
return self.title
def get_absolute_url(self):
return reverse("videos:video_detail", kwargs={'slug': self.uuid})
@property
def imdb_link(self):
return f"https://www.imdb.com/title/{self.imdb_id}"
@classmethod
def find_or_create(cls, data_dict: Dict) -> "Video":
"""Given a data dict from Jellyfin, does the heavy lifting of looking up
the video and, if need, TV Series, creating both if they don't yet
exist.
"""
video_dict = {
"title": data_dict.get("Name", ""),
"imdb_id": data_dict.get("Provider_imdb", None),
"video_type": Video.VideoType.MOVIE,
}
series = None
if data_dict.get("ItemType", "") == "Episode":
series_name = data_dict.get("SeriesName", "")
series, series_created = Series.objects.get_or_create(
name=series_name
)
if series_created:
logger.debug(f"Created new series {series}")
else:
logger.debug(f"Found series {series}")
video_dict['video_type'] = Video.VideoType.TV_EPISODE
video, created = cls.objects.get_or_create(**video_dict)
run_time_ticks = data_dict.get("RunTimeTicks", None)
if run_time_ticks:
run_time_ticks = run_time_ticks // 10000
video_extra_dict = {
"year": data_dict.get("Year", ""),
"overview": data_dict.get("Overview", None),
"tagline": data_dict.get("Tagline", None),
"run_time_ticks": run_time_ticks,
"run_time": convert_to_seconds(data_dict.get("RunTime", "")),
"tvdb_id": data_dict.get("Provider_tvdb", None),
"tvrage_id": data_dict.get("Provider_tvrage", None),
"episode_number": data_dict.get("EpisodeNumber", None),
"season_number": data_dict.get("SeasonNumber", None),
}
if series:
video_extra_dict["tv_series_id"] = series.id
if not video.run_time_ticks:
logger.debug(f"Created new video: {video}")
for key, value in video_extra_dict.items():
setattr(video, key, value)
video.save()
else:
logger.debug(f"Found video {video}")
return video