123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- from dataclasses import dataclass
- import logging
- from typing import Optional
- from uuid import uuid4
- from django.apps import apps
- from django.db import models
- from django.urls import reverse
- from django.utils import timezone
- from django_extensions.db.models import TimeStampedModel
- from scrobbles.utils import get_scrobbles_for_media
- from taggit.managers import TaggableManager
- from taggit.models import GenericTaggedItemBase, TagBase
- BNULL = {"blank": True, "null": True}
- logger = logging.getLogger(__name__)
- @dataclass
- class ScrobblableConstants:
- verb: str
- tags: str
- priority: str
- def __init__(
- self,
- verb: str = "Scrobbling",
- tags: str = "green_square",
- priority: str = "default",
- ):
- self.verb = verb
- self.tags = tags
- self.priority = priority
- class Genre(TagBase):
- source = models.CharField(max_length=255, **BNULL)
- class Meta:
- verbose_name = "Genre"
- verbose_name_plural = "Genres"
- class ObjectWithGenres(GenericTaggedItemBase):
- tag = models.ForeignKey(
- Genre,
- on_delete=models.CASCADE,
- related_name="%(app_label)s_%(class)s_items",
- **BNULL,
- )
- class ScrobblableMixin(TimeStampedModel):
- SECONDS_TO_STALE = 1600
- COMPLETION_PERCENT = 100
- uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
- title = models.CharField(max_length=255, **BNULL)
- run_time_seconds = models.IntegerField(default=900)
- run_time_ticks = models.PositiveBigIntegerField(**BNULL)
- genre = TaggableManager(through=ObjectWithGenres, blank=True)
- class Meta:
- abstract = True
- def scrobble_for_user(
- self,
- user_id,
- source: str = "Vrobbler",
- playback_position_seconds: int = 0,
- status: str = "started",
- log: Optional[dict] = None,
- ):
- Scrobble = apps.get_model("scrobbles", "Scrobble")
- scrobble_data = {
- "user_id": user_id,
- "timestamp": timezone.now(),
- "source": source,
- "status": status,
- "playback_position_seconds": playback_position_seconds,
- }
- if log:
- scrobble_data["log"] = log
- logger.info(
- "[scrobble_for_user] called",
- extra={
- "id": self.id,
- "media_type": self.__class__,
- "user_id": user_id,
- "scrobble_data": scrobble_data,
- "media_type": Scrobble.MediaType.WEBPAGE,
- },
- )
- return Scrobble.create_or_update(self, user_id, scrobble_data)
- @property
- def start_url(self):
- return reverse("scrobbles:start", kwargs={"uuid": self.uuid})
- @property
- def strings(self) -> ScrobblableConstants:
- return ScrobblableConstants()
- @property
- def primary_image_url(self) -> str:
- logger.warning(f"Not implemented yet")
- return ""
- @property
- def logdata_cls(self) -> None:
- from scrobbles.dataclasses import ScrobbleLogData
- return ScrobbleLogData
- @property
- def subtitle(self) -> str:
- return ""
- def fix_metadata(self) -> None:
- logger.warning("fix_metadata() not implemented yet")
- @classmethod
- def find_or_create(cls):
- logger.warning("find_or_create() not implemented yet")
- def __str__(self) -> str:
- if self.title:
- return str(self.title)
- return str(self.uuid)
- class LongPlayScrobblableMixin(ScrobblableMixin):
- class Meta:
- abstract = True
- def get_longplay_finish_url(self):
- return reverse("scrobbles:longplay-finish", kwargs={"uuid": self.uuid})
- def first_long_play_scrobble_for_user(self, user) -> Optional["Scrobble"]:
- return (
- get_scrobbles_for_media(self, user)
- .filter(
- log__long_play_complete=False,
- log__serial_scrobble_id__isnull=True,
- )
- .order_by("timestamp")
- .first()
- )
- def last_long_play_scrobble_for_user(self, user) -> Optional["Scrobble"]:
- return (
- get_scrobbles_for_media(self, user)
- .filter(
- log__long_play_complete=False,
- log__serial_scrobble_id__isnull=False,
- )
- .order_by("timestamp")
- .last()
- )
|