Colin Powell 2 vuotta sitten
vanhempi
commit
c9874b3fda

+ 25 - 0
vrobbler/apps/books/migrations/0011_book_genre.py

@@ -0,0 +1,25 @@
+# Generated by Django 4.1.5 on 2023-03-14 22:27
+
+from django.db import migrations
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0033_genre_objectwithgenres"),
+        ("books", "0010_rename_run_time_book_run_time_seconds"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="book",
+            name="genre",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="scrobbles.ObjectWithGenres",
+                to="scrobbles.Genre",
+                verbose_name="Tags",
+            ),
+        ),
+    ]

+ 25 - 0
vrobbler/apps/music/migrations/0017_track_genre.py

@@ -0,0 +1,25 @@
+# Generated by Django 4.1.5 on 2023-03-14 22:27
+
+from django.db import migrations
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0033_genre_objectwithgenres"),
+        ("music", "0016_rename_run_time_track_run_time_seconds"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="track",
+            name="genre",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="scrobbles.ObjectWithGenres",
+                to="scrobbles.Genre",
+                verbose_name="Tags",
+            ),
+        ),
+    ]

+ 25 - 0
vrobbler/apps/podcasts/migrations/0008_episode_genre.py

@@ -0,0 +1,25 @@
+# Generated by Django 4.1.5 on 2023-03-14 22:27
+
+from django.db import migrations
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0033_genre_objectwithgenres"),
+        ("podcasts", "0007_rename_run_time_episode_run_time_seconds"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="episode",
+            name="genre",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="scrobbles.ObjectWithGenres",
+                to="scrobbles.Genre",
+                verbose_name="Tags",
+            ),
+        ),
+    ]

+ 9 - 0
vrobbler/apps/scrobbles/admin.py

@@ -6,6 +6,7 @@ from scrobbles.models import (
     LastFmImport,
     Scrobble,
 )
+from scrobbles.mixins import Genre
 
 
 class ScrobbleInline(admin.TabularInline):
@@ -49,6 +50,14 @@ class KoReaderImportAdmin(ImportBaseAdmin):
     """"""
 
 
+@admin.register(Genre)
+class GenreAdmin(admin.ModelAdmin):
+    list_display = (
+        "name",
+        "source",
+    )
+
+
 @admin.register(ChartRecord)
 class ChartRecordAdmin(admin.ModelAdmin):
     date_hierarchy = "created"

+ 92 - 0
vrobbler/apps/scrobbles/migrations/0033_genre_objectwithgenres.py

@@ -0,0 +1,92 @@
+# Generated by Django 4.1.5 on 2023-03-14 22:27
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("contenttypes", "0002_remove_content_type_name"),
+        (
+            "scrobbles",
+            "0032_rename_playback_position_scrobble_playback_position_seconds",
+        ),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="Genre",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "name",
+                    models.CharField(
+                        max_length=100, unique=True, verbose_name="name"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(
+                        max_length=100, unique=True, verbose_name="slug"
+                    ),
+                ),
+                (
+                    "source",
+                    models.CharField(blank=True, max_length=255, null=True),
+                ),
+            ],
+            options={
+                "verbose_name": "Genre",
+                "verbose_name_plural": "Genres",
+            },
+        ),
+        migrations.CreateModel(
+            name="ObjectWithGenres",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "object_id",
+                    models.IntegerField(
+                        db_index=True, verbose_name="object ID"
+                    ),
+                ),
+                (
+                    "content_type",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="%(app_label)s_%(class)s_tagged_items",
+                        to="contenttypes.contenttype",
+                        verbose_name="content type",
+                    ),
+                ),
+                (
+                    "tag",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="%(app_label)s_%(class)s_items",
+                        to="scrobbles.genre",
+                    ),
+                ),
+            ],
+            options={
+                "abstract": False,
+            },
+        ),
+    ]

+ 20 - 0
vrobbler/apps/scrobbles/mixins.py

@@ -5,13 +5,31 @@ from uuid import uuid4
 from django.db import models
 from django.urls import reverse
 from django_extensions.db.models import TimeStampedModel
+from taggit.managers import TaggableManager
 from scrobbles.utils import get_scrobbles_for_media
+from taggit.models import TagBase, GenericTaggedItemBase
 
 BNULL = {"blank": True, "null": True}
 
 logger = logging.getLogger(__name__)
 
 
+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",
+    )
+
+
 class ScrobblableMixin(TimeStampedModel):
     SECONDS_TO_STALE = 1600
 
@@ -20,6 +38,8 @@ class ScrobblableMixin(TimeStampedModel):
     run_time_seconds = models.IntegerField(**BNULL)
     run_time_ticks = models.PositiveBigIntegerField(**BNULL)
 
+    genre = TaggableManager(through=ObjectWithGenres)
+
     class Meta:
         abstract = True
 

+ 0 - 1
vrobbler/apps/scrobbles/models.py

@@ -5,7 +5,6 @@ from typing import Optional
 from uuid import uuid4
 
 from books.models import Book
-from django.apps import apps
 from django.contrib.auth import get_user_model
 from django.db import models
 from django.urls import reverse

+ 25 - 0
vrobbler/apps/sports/migrations/0013_sportevent_genre.py

@@ -0,0 +1,25 @@
+# Generated by Django 4.1.5 on 2023-03-14 22:27
+
+from django.db import migrations
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0033_genre_objectwithgenres"),
+        ("sports", "0012_sport_default_event_run_time_seconds"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="sportevent",
+            name="genre",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="scrobbles.ObjectWithGenres",
+                to="scrobbles.Genre",
+                verbose_name="Tags",
+            ),
+        ),
+    ]

+ 25 - 0
vrobbler/apps/videogames/migrations/0009_videogame_genre.py

@@ -0,0 +1,25 @@
+# Generated by Django 4.1.5 on 2023-03-14 22:27
+
+from django.db import migrations
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0033_genre_objectwithgenres"),
+        ("videogames", "0008_rename_run_time_videogame_run_time_seconds"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="videogame",
+            name="genre",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="scrobbles.ObjectWithGenres",
+                to="scrobbles.Genre",
+                verbose_name="Tags",
+            ),
+        ),
+    ]

+ 28 - 0
vrobbler/apps/videos/migrations/0010_rename_genres_series_tags_alter_video_cover_image.py

@@ -0,0 +1,28 @@
+# Generated by Django 4.1.5 on 2023-03-14 19:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        (
+            "videos",
+            "0009_rename_overview_series_plot_remove_series_tagline_and_more",
+        ),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name="series",
+            old_name="genres",
+            new_name="tags",
+        ),
+        migrations.AlterField(
+            model_name="video",
+            name="cover_image",
+            field=models.ImageField(
+                blank=True, null=True, upload_to="videos/video/"
+            ),
+        ),
+    ]

+ 25 - 0
vrobbler/apps/videos/migrations/0011_video_tags.py

@@ -0,0 +1,25 @@
+# Generated by Django 4.1.5 on 2023-03-14 19:42
+
+from django.db import migrations
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"),
+        ("videos", "0010_rename_genres_series_tags_alter_video_cover_image"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="video",
+            name="tags",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="taggit.TaggedItem",
+                to="taggit.Tag",
+                verbose_name="Tags",
+            ),
+        ),
+    ]

+ 43 - 0
vrobbler/apps/videos/migrations/0012_remove_series_tags_remove_video_tags_series_genre_and_more.py

@@ -0,0 +1,43 @@
+# Generated by Django 4.1.5 on 2023-03-14 22:27
+
+from django.db import migrations
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0033_genre_objectwithgenres"),
+        ("videos", "0011_video_tags"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="series",
+            name="tags",
+        ),
+        migrations.RemoveField(
+            model_name="video",
+            name="tags",
+        ),
+        migrations.AddField(
+            model_name="series",
+            name="genre",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="scrobbles.ObjectWithGenres",
+                to="scrobbles.Genre",
+                verbose_name="Tags",
+            ),
+        ),
+        migrations.AddField(
+            model_name="video",
+            name="genre",
+            field=taggit.managers.TaggableManager(
+                help_text="A comma-separated list of tags.",
+                through="scrobbles.ObjectWithGenres",
+                to="scrobbles.Genre",
+                verbose_name="Tags",
+            ),
+        ),
+    ]

+ 12 - 4
vrobbler/apps/videos/models.py

@@ -9,8 +9,7 @@ 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.mixins import ScrobblableMixin
-from scrobbles.utils import convert_to_seconds
+from scrobbles.mixins import ObjectWithGenres, ScrobblableMixin
 from taggit.managers import TaggableManager
 
 from videos.imdb import lookup_video_from_imdb
@@ -27,7 +26,7 @@ class Series(TimeStampedModel):
     imdb_rating = models.FloatField(**BNULL)
     cover_image = models.ImageField(upload_to="videos/series/", **BNULL)
 
-    genres = TaggableManager()
+    genre = TaggableManager(through=ObjectWithGenres)
 
     class Meta:
         verbose_name_plural = "series"
@@ -49,7 +48,10 @@ class Series(TimeStampedModel):
         ).order_by("-timestamp")
 
     def fix_metadata(self, force_update=False):
-        imdb_dict = lookup_video_from_imdb(self.name, kind="tv series")
+        name_or_id = self.name
+        if self.imdb_id:
+            name_or_id = self.imdb_id
+        imdb_dict = lookup_video_from_imdb(name_or_id)
         if not imdb_dict:
             logger.warn(f"No imdb data for {self}")
             return
@@ -67,6 +69,9 @@ class Series(TimeStampedModel):
                 fname = f"{self.name}_{self.uuid}.jpg"
                 self.cover_image.save(fname, ContentFile(r.content), save=True)
 
+        if genres := imdb_dict.data.get("genres"):
+            self.genre.add(*genres)
+
 
 class Video(ScrobblableMixin):
     COMPLETION_PERCENT = getattr(settings, "VIDEO_COMPLETION_PERCENT", 90)
@@ -149,6 +154,9 @@ class Video(ScrobblableMixin):
                 fname = f"{self.title}_{self.uuid}.jpg"
                 self.cover_image.save(fname, ContentFile(r.content), save=True)
 
+        if genres := imdb_dict.data.get("genres"):
+            self.genre.add(*genres)
+
     @classmethod
     def find_or_create(cls, data_dict: Dict) -> "Video":
         """Given a data dict from Jellyfin, does the heavy lifting of looking up