diff --git a/vrobbler/apps/videos/migrations/0031_channel_custom_url_channel_description.py b/vrobbler/apps/videos/migrations/0031_channel_custom_url_channel_description.py new file mode 100644 index 0000000..3608e05 --- /dev/null +++ b/vrobbler/apps/videos/migrations/0031_channel_custom_url_channel_description.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.29 on 2026-06-16 19:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("videos", "0030_alter_channel_genre_alter_series_genre_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="channel", + name="custom_url", + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name="channel", + name="description", + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/vrobbler/apps/videos/models.py b/vrobbler/apps/videos/models.py index e6b3de6..cbaa30e 100644 --- a/vrobbler/apps/videos/models.py +++ b/vrobbler/apps/videos/models.py @@ -59,6 +59,8 @@ class Channel(ScrobblableMixin): ) youtube_id = models.CharField(max_length=255, **BNULL) twitch_id = models.CharField(max_length=255, **BNULL) + description = models.TextField(**BNULL) + custom_url = models.CharField(max_length=255, **BNULL) genre = TaggableManager(through=ObjectWithGenres, blank=True, verbose_name="Genre") class Meta: @@ -140,7 +142,7 @@ class Channel(ScrobblableMixin): def fix_metadata(self, force: bool = False): if self.youtube_id: - GOOGLE_CHANNELS_URL = "https://www.googleapis.com/youtube/v3/channels?part=snippet&id={channel_id}&key={key}" + GOOGLE_CHANNELS_URL = "https://www.googleapis.com/youtube/v3/channels?part=snippet,topicDetails&id={channel_id}&key={key}" url = GOOGLE_CHANNELS_URL.format( channel_id=self.youtube_id, key=settings.GOOGLE_API_KEY, @@ -165,6 +167,14 @@ class Channel(ScrobblableMixin): if channel_name and (not self.name or force): self.name = channel_name + channel_description = snippet.get("description", "") + if channel_description and (not self.description or force): + self.description = channel_description + + custom_url = snippet.get("customUrl", "") + if custom_url and (not self.custom_url or force): + self.custom_url = custom_url + thumbnails = snippet.get("thumbnails", {}) cover_url = ( thumbnails.get("high", {}).get("url") @@ -174,6 +184,16 @@ class Channel(ScrobblableMixin): if cover_url: self.save_image_from_url(cover_url, force_update=force) + topic_details = items[0].get("topicDetails", {}) + topic_categories = topic_details.get("topicCategories", []) + if topic_categories: + if force: + self.genre.clear() + for category_url in topic_categories: + topic_name = category_url.rstrip("/").split("/")[-1] + topic_name = topic_name.replace("_", " ").replace("-", " ") + self.genre.add(topic_name) + self.save() return diff --git a/vrobbler/apps/videos/sources/youtube.py b/vrobbler/apps/videos/sources/youtube.py index fddc992..5590fa7 100644 --- a/vrobbler/apps/videos/sources/youtube.py +++ b/vrobbler/apps/videos/sources/youtube.py @@ -4,7 +4,6 @@ import logging import pendulum import requests from django.conf import settings - from videos.metadata import VideoMetadata, VideoType logger = logging.getLogger(__name__) @@ -13,7 +12,7 @@ YOUTUBE_VIDEO_URL = "https://www.youtube.com/watch?v=" YOUTUBE_CHANNEL_URL = "https://www.youtube.com/channel/" API_KEY = settings.GOOGLE_API_KEY -GOOGLE_VIDEOS_URL = "https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id={youtube_id}&key={key}" +GOOGLE_VIDEOS_URL = "https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,topicDetails&id={youtube_id}&key={key}" def lookup_video_from_youtube(youtube_id: str) -> VideoMetadata: @@ -68,6 +67,15 @@ def lookup_video_from_youtube(youtube_id: str) -> VideoMetadata: yt_metadata.get("thumbnails", {}).get("high", {}).get("url", {}) ) video_metadata.genres = yt_metadata.get("tags", []) + topic_details = ( + json.loads(response.content).get("items", [None])[0].get("topicDetails", {}) + ) + topic_categories = topic_details.get("topicCategories", []) + for category_url in topic_categories: + topic_name = category_url.rstrip("/").split("/")[-1] + topic_name = topic_name.replace("_", " ").replace("-", " ") + if topic_name not in video_metadata.genres: + video_metadata.genres.append(topic_name) video_metadata.overview = yt_metadata.get("description", "") date_str = yt_metadata.get("publishedAt")