Bläddra i källkod

[videos] Update youtubes stuff

Colin Powell 8 månader sedan
förälder
incheckning
39f3a31847

+ 11 - 4
vrobbler/apps/scrobbles/tsv.py

@@ -12,8 +12,9 @@ from music.utils import (
 )
 from scrobbles.constants import AsTsvColumn
 from scrobbles.models import Scrobble
+from music.constants import MOPIDY_POST_KEYS
 
-from vrobbler.apps.scrobbles.utils import timestamp_user_tz_to_utc
+from scrobbles.utils import timestamp_user_tz_to_utc
 
 logger = logging.getLogger(__name__)
 
@@ -43,8 +44,8 @@ def process_audioscrobbler_tsv_file(file_path, user_id, user_tz=None):
             rockbox_info += row[0] + "\n"
             continue
         if len(row) > 8:
-            logger.warning(
-                "Improper row length during Audioscrobbler import",
+            logger.info(
+                "[skip] too many columns in row",
                 extra={"row": row},
             )
             continue
@@ -73,7 +74,13 @@ def process_audioscrobbler_tsv_file(file_path, user_id, user_tz=None):
 
         # TODO Set all this up as constants
         if row[AsTsvColumn["COMPLETE"].value] == "S":
-            logger.info(f"Skipping track {track} because not finished")
+            logger.info(
+                "[skip] track not finished",
+                extra={
+                    "album_name": row[AsTsvColumn["ALBUM_NAME"].value],
+                    "artist_name": row[AsTsvColumn["ARTIST_NAME"].value],
+                }
+            )
             continue
 
         timestamp = timestamp_user_tz_to_utc(

+ 88 - 0
vrobbler/apps/videos/migrations/0019_rename_youtube_url_video_youtube_id_channel_and_more.py

@@ -0,0 +1,88 @@
+# Generated by Django 4.2.16 on 2024-11-06 15:49
+
+from django.db import migrations, models
+import django.db.models.deletion
+import django_extensions.db.fields
+import taggit.managers
+import uuid
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0066_scrobble_beer_alter_scrobble_media_type"),
+        ("videos", "0018_video_youtube_url_alter_video_video_type"),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name="video",
+            old_name="youtube_url",
+            new_name="youtube_id",
+        ),
+        migrations.CreateModel(
+            name="Channel",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "created",
+                    django_extensions.db.fields.CreationDateTimeField(
+                        auto_now_add=True, verbose_name="created"
+                    ),
+                ),
+                (
+                    "modified",
+                    django_extensions.db.fields.ModificationDateTimeField(
+                        auto_now=True, verbose_name="modified"
+                    ),
+                ),
+                (
+                    "uuid",
+                    models.UUIDField(
+                        blank=True,
+                        default=uuid.uuid4,
+                        editable=False,
+                        null=True,
+                    ),
+                ),
+                ("name", models.CharField(max_length=255)),
+                (
+                    "cover_image",
+                    models.ImageField(
+                        blank=True, null=True, upload_to="videos/channels/"
+                    ),
+                ),
+                (
+                    "genre",
+                    taggit.managers.TaggableManager(
+                        help_text="A comma-separated list of tags.",
+                        through="scrobbles.ObjectWithGenres",
+                        to="scrobbles.Genre",
+                        verbose_name="Tags",
+                    ),
+                ),
+            ],
+            options={
+                "get_latest_by": "modified",
+                "abstract": False,
+            },
+        ),
+        migrations.AddField(
+            model_name="video",
+            name="channel",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.DO_NOTHING,
+                to="videos.channel",
+            ),
+        ),
+    ]

+ 59 - 2
vrobbler/apps/videos/models.py

@@ -23,6 +23,56 @@ from videos.imdb import lookup_video_from_imdb
 logger = logging.getLogger(__name__)
 BNULL = {"blank": True, "null": True}
 
+class Channel(TimeStampedModel):
+    uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
+    name = models.CharField(max_length=255)
+    cover_image = models.ImageField(upload_to="videos/channels/", **BNULL)
+    cover_small = ImageSpecField(
+        source="cover_image",
+        processors=[ResizeToFit(100, 100)],
+        format="JPEG",
+        options={"quality": 60},
+    )
+    cover_medium = ImageSpecField(
+        source="cover_image",
+        processors=[ResizeToFit(300, 300)],
+        format="JPEG",
+        options={"quality": 75},
+    )
+    genre = TaggableManager(through=ObjectWithGenres)
+
+    def __str__(self):
+        return self.name
+
+    def get_absolute_url(self):
+        return reverse("videos:channel_detail", kwargs={"slug": self.uuid})
+
+    def youtube_link(self):
+        return f"https://www.youtube.com/user/t{self.yt_username}"
+
+    @property
+    def primary_image_url(self) -> str:
+        url = ""
+        if self.cover_image:
+            url = self.cover_image_medium.url
+        return url
+
+    def scrobbles_for_user(self, user_id: int, include_playing=False):
+        from scrobbles.models import Scrobble
+
+        played_query = models.Q(played_to_completion=True)
+        if include_playing:
+            played_query = models.Q()
+        return Scrobble.objects.filter(
+            played_query,
+            video__channel=self,
+            user=user_id,
+        ).order_by("-timestamp")
+
+    def fix_metadata(self, force: bool = False):
+        # TODO Scrape channel info from Youtube
+        logger.warning("Not implemented yet")
+        return
 
 class Series(TimeStampedModel):
     uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
@@ -141,6 +191,7 @@ class Video(ScrobblableMixin):
 
     # TV show specific fields
     tv_series = models.ForeignKey(Series, on_delete=models.DO_NOTHING, **BNULL)
+    channel = models.ForeignKey(Channel, on_delete=models.DO_NOTHING, **BNULL)
     season_number = models.IntegerField(**BNULL)
     episode_number = models.IntegerField(**BNULL)
     next_imdb_id = models.CharField(max_length=20, **BNULL)
@@ -162,7 +213,7 @@ class Video(ScrobblableMixin):
     tvrage_id = models.CharField(max_length=20, **BNULL)
     tvdb_id = models.CharField(max_length=20, **BNULL)
     tmdb_id = models.CharField(max_length=20, **BNULL)
-    youtube_url = models.CharField(max_length=255, **BNULL)
+    youtube_id = models.CharField(max_length=255, **BNULL)
     plot = models.TextField(**BNULL)
     year = models.IntegerField(**BNULL)
 
@@ -171,7 +222,9 @@ class Video(ScrobblableMixin):
 
     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 f"{self.title} - {self.tv_series} - Season {self.season_number}, Episode {self.episode_number}"
+        if self.video_type == self.VideoType.YOUTUBE:
+            return f"{self.title} - {self.channel}"
         return self.title
 
     def get_absolute_url(self):
@@ -195,6 +248,10 @@ class Video(ScrobblableMixin):
     def link(self):
         return self.imdb_link
 
+    @property
+    def youtube_link(self):
+        return f"https://www.youtube.com/watch?v={self.youtube_id}"
+
     @property
     def primary_image_url(self) -> str:
         url = ""