From eb2dd4c83960d8fb06ca7062fc3e8dcc2d461d16 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 10 Jun 2025 10:05:40 -0400 Subject: [PATCH 01/10] [todos] Clean up todos and add new milestone 17 --- todos.org | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/todos.org b/todos.org index 3ba4b4b..ce0cef6 100644 --- a/todos.org +++ b/todos.org @@ -1,15 +1,33 @@ #+title: TODOs -A fun way to keep track of things in the project to fix or improve. +* Version 17 +** TODO [#A] Show the description of a task in the string rep for a scrobble of a Task :personal:project:scrobbling:vrobbler:feature: +** TODO [#B] Add AllTrails as a source for Trail data :vrobbler:trails:feature:personal:project: +Pretty clear, I would love to make trails more useful. Historically I wasn't +hiking a lot, which made the source for this a bit silly. But it's clear that +AllTrails is the best source, though having TrailForks is nice to. +** TODO [#B] Add `garmin_activity_id` to the TrailMetadataLog class :vrobbler:trails:feature:personal:project: +Would be nice to have some loose connection to the actual event in my Garmin profile. +** TODO [#B] Explore a way to add metadata editing to scrobbles after saving :vrobbler:spike:scrobbling:personal:project: +Could be as simple as a JSON form on the scrobble detail page (do I have have one of those yet?). +** TODO [#B] Explore a good way to show notes and descriptions from scrobbles to users :personal:project:scrobbling:vrobbler:spike: +** TODO [#C] Fix bug where podcast scrobbling creates duplicate Podcast :project:vrobbler:scrobbling:podcasts:bug:personal: +Rather than pick up an existing Podcast using the podcast title in the mopidy +file name, Vrobbler creates a new podcast with no enriched data. Not a big deal +for my use as the volume of podcasts I listen to makes manual fixes easy. But +it's annoying. * Version 0.16.0 -** TODO [#A] Jellyfin, bandcamp tracks from Mopidy create duplicate music tracks :bug:scrobbling:music: +** DONE [#A] Jellyfin, bandcamp tracks from Mopidy create duplicate music tracks :bug:scrobbling:music: +:PROPERTIES: +:ID: 670e8634-49b5-dce9-1684-14f2ffb797f1 +:END: Effectively, any track that comes in without a MusicBrainz ID does some funky lookup where it doesn't find a track without an MB id and the track title / -artist combination and creates a new track everytime. This has to be cleaend up +artist combination and creates a new track every time. This has to be cleaned up by condensing the duplicated tracks into the original proper track. -But it opens a bigger quesiton about how much MB id should the drive the app +But it opens a bigger question about how much MB id should the drive the app lookup. If it can't be depended on to exist from all sources, it really can't be canonical. Instead, the combination of track title / artist is really the best we can do. Last.fm also has this problem, where it doesn't know about albums and @@ -481,4 +499,3 @@ has to re-populate when the server restarts. } } #+end_src -** TODO Fix bug in podcast scrobbling where a second scrobble is created after completion :scrobbling:podcasts:bug: From 73838312cd993cbbf91f5530a880672d7f8a417a Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 10 Jun 2025 11:06:47 -0400 Subject: [PATCH 02/10] [tasks] Clean up emacs webhook flow --- vrobbler/apps/tasks/webhooks.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vrobbler/apps/tasks/webhooks.py b/vrobbler/apps/tasks/webhooks.py index 68225fc..538ed4a 100644 --- a/vrobbler/apps/tasks/webhooks.py +++ b/vrobbler/apps/tasks/webhooks.py @@ -149,13 +149,6 @@ def emacs_webhook(request): post_data, user_id, started=task_in_progress, stopped=task_stopped ) - if scrobble and task_in_progress and post_data.get("notes"): - emacs_scrobble_update_task( - post_data.get("source_id"), - post_data.get("notes"), - user_id, - ) - if not scrobble: logger.info( "[emacs_webhook] finished with no note or task found", @@ -166,6 +159,13 @@ def emacs_webhook(request): status=status.HTTP_304_NOT_MODIFIED, ) + if task_in_progress and post_data.get("notes"): + emacs_scrobble_update_task( + post_data.get("source_id"), + post_data.get("notes"), + user_id, + ) + logger.info( "[emacs_webhook] finished", extra={"scrobble_id": scrobble.id}, From 41d6fe8ff64e85abefcc5564f30451bee81dd937 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 10 Jun 2025 11:27:37 -0400 Subject: [PATCH 03/10] [todos] Add new task --- todos.org | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/todos.org b/todos.org index ce0cef6..cec00d5 100644 --- a/todos.org +++ b/todos.org @@ -11,12 +11,16 @@ Would be nice to have some loose connection to the actual event in my Garmin pro ** TODO [#B] Explore a way to add metadata editing to scrobbles after saving :vrobbler:spike:scrobbling:personal:project: Could be as simple as a JSON form on the scrobble detail page (do I have have one of those yet?). ** TODO [#B] Explore a good way to show notes and descriptions from scrobbles to users :personal:project:scrobbling:vrobbler:spike: +** TODO [#C] Replace commas in the bandcamp URL for artists with nothing :vrobbler:music:bug:personal: +:PROPERTIES: +:ID: 9b30d67b-91f0-a480-dfaa-5d9dc090e76c +:END: + ** TODO [#C] Fix bug where podcast scrobbling creates duplicate Podcast :project:vrobbler:scrobbling:podcasts:bug:personal: Rather than pick up an existing Podcast using the podcast title in the mopidy file name, Vrobbler creates a new podcast with no enriched data. Not a big deal for my use as the volume of podcasts I listen to makes manual fixes easy. But it's annoying. - * Version 0.16.0 ** DONE [#A] Jellyfin, bandcamp tracks from Mopidy create duplicate music tracks :bug:scrobbling:music: :PROPERTIES: From 6fc8084f2ddde35db6fcedcfbc77ec23329549d1 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Wed, 11 Jun 2025 12:01:02 -0400 Subject: [PATCH 04/10] [scrobbles] Fix log of media type --- vrobbler/apps/scrobbles/mixins.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vrobbler/apps/scrobbles/mixins.py b/vrobbler/apps/scrobbles/mixins.py index 812e379..110b442 100644 --- a/vrobbler/apps/scrobbles/mixins.py +++ b/vrobbler/apps/scrobbles/mixins.py @@ -89,10 +89,9 @@ class ScrobblableMixin(TimeStampedModel): "[scrobble_for_user] called", extra={ "id": self.id, - "media_type": self.__class__, + "media_type": self.media_obj.__class__, "user_id": user_id, "scrobble_data": scrobble_data, - "media_type": Scrobble.MediaType.WEBPAGE, }, ) return Scrobble.create_or_update(self, user_id, scrobble_data) From d917dd8b2ca5816a8a325f8f21b1aec02e3843b3 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Thu, 12 Jun 2025 09:51:57 -0400 Subject: [PATCH 05/10] [tasks] Fix source checking for emacs/orgmode tasks when updating --- todos.org | 20 ++++++++++++++++++++ vrobbler/apps/scrobbles/scrobblers.py | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/todos.org b/todos.org index cec00d5..458a48a 100644 --- a/todos.org +++ b/todos.org @@ -1,6 +1,26 @@ #+title: TODOs * Version 17 +** DONE [#A] Emacs is not syncing notes :personal:scrobbling:emacs:bug: +:PROPERTIES: +:ID: c79cd491-b30f-0945-d84b-b8cac7562791 +:END: +<2025-06-12 Thu 9:30> + +Not sure if the problem is in my Emacs hook sending or Vrobbler itself. + +- Note taken on [2025-06-12 Thu 09:47] + + Adding a quick note to check on it + +- Note taken on [2025-06-12 Thu 09:50] + + Ah ha. All the messing about with the source field meant that I was looking + for `emacs` as a source but the hook was initially setting sources to + `orgmode` I think I prefer `orgmode` as the source, so updating it thusly. + + Fixed in `490d60cbbb1f8bf90b5fc47d8685b15bdc1d485b` + ** TODO [#A] Show the description of a task in the string rep for a scrobble of a Task :personal:project:scrobbling:vrobbler:feature: ** TODO [#B] Add AllTrails as a source for Trail data :vrobbler:trails:feature:personal:project: Pretty clear, I would love to make trails more useful. Historically I wasn't diff --git a/vrobbler/apps/scrobbles/scrobblers.py b/vrobbler/apps/scrobbles/scrobblers.py index 08ed785..ad5bfc1 100644 --- a/vrobbler/apps/scrobbles/scrobblers.py +++ b/vrobbler/apps/scrobbles/scrobblers.py @@ -508,7 +508,7 @@ def emacs_scrobble_update_task( in_progress=True, user_id=user_id, log__source_id=emacs_id, - log__source="emacs", + log__source="orgmode", ).first() if not scrobble: From c0871a3b9eb18426d62907af7dcfe1874c6ccdd6 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Thu, 12 Jun 2025 09:57:32 -0400 Subject: [PATCH 06/10] [scrobbles] Fix failing tests --- vrobbler/apps/scrobbles/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vrobbler/apps/scrobbles/mixins.py b/vrobbler/apps/scrobbles/mixins.py index 110b442..4798fe7 100644 --- a/vrobbler/apps/scrobbles/mixins.py +++ b/vrobbler/apps/scrobbles/mixins.py @@ -89,7 +89,7 @@ class ScrobblableMixin(TimeStampedModel): "[scrobble_for_user] called", extra={ "id": self.id, - "media_type": self.media_obj.__class__, + "media_type": self.__class__, "user_id": user_id, "scrobble_data": scrobble_data, }, From 53a04d064d599cf2a8b640176b3b65886ccabc39 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Fri, 13 Jun 2025 09:15:48 -0400 Subject: [PATCH 07/10] [videos] At least stop IMDB from breaking --- vrobbler/apps/videos/models.py | 4 +--- vrobbler/apps/videos/sources/imdb.py | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/vrobbler/apps/videos/models.py b/vrobbler/apps/videos/models.py index c14295b..4f06b54 100644 --- a/vrobbler/apps/videos/models.py +++ b/vrobbler/apps/videos/models.py @@ -2,7 +2,6 @@ import logging from typing import Optional from uuid import uuid4 -import pendulum import requests from django.conf import settings from django.core.files.base import ContentFile @@ -21,8 +20,7 @@ from scrobbles.mixins import ( from taggit.managers import TaggableManager from videos.metadata import VideoMetadata from videos.sources.imdb import lookup_video_from_imdb - -from vrobbler.apps.videos.sources.youtube import lookup_video_from_youtube +from videos.sources.youtube import lookup_video_from_youtube YOUTUBE_VIDEO_URL = "https://www.youtube.com/watch?v=" YOUTUBE_CHANNEL_URL = "https://www.youtube.com/channel/" diff --git a/vrobbler/apps/videos/sources/imdb.py b/vrobbler/apps/videos/sources/imdb.py index 0c7ec02..333b401 100644 --- a/vrobbler/apps/videos/sources/imdb.py +++ b/vrobbler/apps/videos/sources/imdb.py @@ -72,26 +72,30 @@ def lookup_video_from_imdb( video_metadata.video_type = VideoType.MOVIE.value series_name = None if imdb_result.get("kind") == "episode": - series_name = imdb_result.get("episode of", None).data.get( - "title", None - ) - series, _ = Series.objects.get_or_create(name=series_name) - video_metadata.video_type = VideoType.TV_EPISODE.value - video_metadata.tv_series_id = series.id + try: + series_name = imdb_result.get("episode of", None).data.get( + "title", None + ) + except IndexError: + series_name = None + if series_name: + series, _ = Series.objects.get_or_create(name=series_name) + video_metadata.video_type = VideoType.TV_EPISODE.value + video_metadata.tv_series_id = series.id if imdb_result.get("runtimes"): video_metadata.run_time_seconds = ( int(imdb_result.get("runtimes")[0]) * 60 ) + video_metadata.imdb_id = name_or_id video_metadata.title = imdb_result.get("title", "") - video_metadata.imdb_id = imdb_result.get("imdbID") video_metadata.episode_number = imdb_result.get("episode", None) video_metadata.season_number = imdb_result.get("season", None) video_metadata.next_imdb_id = imdb_result.get("next episode", None) video_metadata.year = imdb_result.get("year", None) - video_metadata.plot = imdb_result.get("plot outline") - video_metadata.imdb_rating = imdb_result.get("rating") - video_metadata.genres = imdb_result.get("genres") + video_metadata.plot = imdb_result.get("plot outline", "") + video_metadata.imdb_rating = imdb_result.get("rating", None) + video_metadata.genres = imdb_result.get("genres", []) return video_metadata From d5da8ae701bea1554be09ac738213410b186567a Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Fri, 13 Jun 2025 09:43:08 -0400 Subject: [PATCH 08/10] [todos] Update priority task --- todos.org | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/todos.org b/todos.org index 458a48a..c59662b 100644 --- a/todos.org +++ b/todos.org @@ -1,6 +1,20 @@ #+title: TODOs * Version 17 +** TODO [#A] Investigate new source of video metadata :personal:project:video:imdb: + +Cinemagoer broke and I probably should find a more reilable source of video data. + +** DONE IMDB video lookups are failing :personal:bug:video:imdb: +:PROPERTIES: +:ID: 38f1081f-37b4-f4f2-79aa-c1e87eca4b69 +:END: +<2025-06-13 Fri> + +- Note taken on [2025-06-13 Fri 08:24] + + Looks like Cinemagoer is broken: https://github.com/cinemagoer/cinemagoer/issues/537 + ** DONE [#A] Emacs is not syncing notes :personal:scrobbling:emacs:bug: :PROPERTIES: :ID: c79cd491-b30f-0945-d84b-b8cac7562791 From 24ac545f552c4feab29f23e47fdd6a367bb9ebd5 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Fri, 13 Jun 2025 11:19:15 -0400 Subject: [PATCH 09/10] [videos] Switch to TMDB for scraping videos --- poetry.lock | 49 +++++++++++- pyproject.toml | 2 + vrobbler/apps/videos/metadata.py | 6 +- .../migrations/0023_video_tmdb_rating.py | 18 +++++ vrobbler/apps/videos/models.py | 6 +- vrobbler/apps/videos/sources/tmdb.py | 77 +++++++++++++++++++ 6 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 vrobbler/apps/videos/migrations/0023_video_tmdb_rating.py create mode 100644 vrobbler/apps/videos/sources/tmdb.py diff --git a/poetry.lock b/poetry.lock index 8bf5f17..072947f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1065,6 +1065,21 @@ ssh = ["bcrypt (>=3.1.5)"] test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] +[[package]] +name = "dacite" +version = "1.9.2" +description = "Simple creation of data classes from dictionaries." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "dacite-1.9.2-py3-none-any.whl", hash = "sha256:053f7c3f5128ca2e9aceb66892b1a3c8936d02c686e707bee96e19deef4bc4a0"}, + {file = "dacite-1.9.2.tar.gz", hash = "sha256:6ccc3b299727c7aa17582f0021f6ae14d5de47c7227932c47fec4cdfefd26f09"}, +] + +[package.extras] +dev = ["black", "coveralls", "mypy", "pre-commit", "pylint", "pytest (>=5)", "pytest-benchmark", "pytest-cov"] + [[package]] name = "dataclass-wizard" version = "0.22.0" @@ -4610,6 +4625,23 @@ files = [ [package.dependencies] rapidfuzz = ">=3.0.0,<4.0.0" +[[package]] +name = "themoviedb" +version = "1.0.2" +description = "A modern and easy to use API wrapper for The Movie Database (TMDb) API v3 written in Python" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "themoviedb-1.0.2-py3-none-any.whl", hash = "sha256:badf85e91010c7085509f40270bf2a40ea30ee5ef3ed6fb3ec332c5e50adb576"}, + {file = "themoviedb-1.0.2.tar.gz", hash = "sha256:7835615142a44e7ca25e48645a3a3c5e06b382e8c518c38c3537effa9a2596ce"}, +] + +[package.dependencies] +aiohttp = ">=3.8.4" +dacite = ">=1.8.0" +requests = ">=2.31.0" + [[package]] name = "time-machine" version = "2.16.0" @@ -4710,6 +4742,21 @@ files = [ {file = "tld-0.13.tar.gz", hash = "sha256:93dde5e1c04bdf1844976eae440706379d21f4ab235b73c05d7483e074fb5629"}, ] +[[package]] +name = "tmdbv3api" +version = "1.9.0" +description = "A lightweight Python library for The Movie Database (TMDb) API." +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "tmdbv3api-1.9.0-py3-none-any.whl", hash = "sha256:2bcd8c6e8902397860715a71045f200ecc3ee06804ecf786cb4c1e09b2deeba8"}, + {file = "tmdbv3api-1.9.0.tar.gz", hash = "sha256:504c5da6b99c4516ff160a01576112d097f209c0534f943c15c4b56cbd92c33b"}, +] + +[package.dependencies] +requests = "*" + [[package]] name = "toml" version = "0.10.2" @@ -5452,4 +5499,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.12" -content-hash = "cdd7f577fe3a4c5c8cc960e0070d93b7ddbb2a7968fab63d72bb039afaa05bbe" +content-hash = "3a483aefea0a3afebf187b17b7df72a158788024ca8121b512b39567fb5ec8ca" diff --git a/pyproject.toml b/pyproject.toml index 319b93b..914141a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,8 @@ meta-yt = "^0.1.9" berserk = "^0.13.2" poetry-bumpversion = "^0.3.3" orgparse = "^0.4.20250520" +tmdbv3api = "^1.9.0" +themoviedb = "^1.0.2" [tool.poetry.group.test] optional = true diff --git a/vrobbler/apps/videos/metadata.py b/vrobbler/apps/videos/metadata.py index 80c3ca0..e836572 100644 --- a/vrobbler/apps/videos/metadata.py +++ b/vrobbler/apps/videos/metadata.py @@ -25,6 +25,7 @@ class VideoMetadata: 60 # Silly default, but things break if this is 0 or null ) imdb_id: Optional[str] + tmdb_id: Optional[str] youtube_id: Optional[str] # IMDB specific @@ -35,6 +36,7 @@ class VideoMetadata: tv_series_id: Optional[int] plot: Optional[str] imdb_rating: Optional[str] + tmdb_rating: Optional[str] cover_url: Optional[str] overview: Optional[str] @@ -59,6 +61,6 @@ class VideoMetadata: video_dict = vars(self) cover = None if "cover_url" in video_dict.keys(): - cover = video_dict.pop("cover_url") - genres = video_dict.pop("genres") + cover = video_dict.pop("cover_url", "") + genres = video_dict.pop("genres", []) return video_dict, cover, genres diff --git a/vrobbler/apps/videos/migrations/0023_video_tmdb_rating.py b/vrobbler/apps/videos/migrations/0023_video_tmdb_rating.py new file mode 100644 index 0000000..fe6bd5f --- /dev/null +++ b/vrobbler/apps/videos/migrations/0023_video_tmdb_rating.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.19 on 2025-06-13 15:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('videos', '0022_alter_video_run_time_seconds'), + ] + + operations = [ + migrations.AddField( + model_name='video', + name='tmdb_rating', + field=models.FloatField(blank=True, null=True), + ), + ] diff --git a/vrobbler/apps/videos/models.py b/vrobbler/apps/videos/models.py index 4f06b54..bd03697 100644 --- a/vrobbler/apps/videos/models.py +++ b/vrobbler/apps/videos/models.py @@ -20,6 +20,7 @@ from scrobbles.mixins import ( from taggit.managers import TaggableManager from videos.metadata import VideoMetadata from videos.sources.imdb import lookup_video_from_imdb +from videos.sources.tmdb import lookup_video_from_tmdb from videos.sources.youtube import lookup_video_from_youtube YOUTUBE_VIDEO_URL = "https://www.youtube.com/watch?v=" @@ -206,6 +207,7 @@ class Video(ScrobblableMixin): next_imdb_id = models.CharField(max_length=20, **BNULL) imdb_id = models.CharField(max_length=20, **BNULL) imdb_rating = models.FloatField(**BNULL) + tmdb_rating = models.FloatField(**BNULL) cover_image = models.ImageField(upload_to="videos/video/", **BNULL) cover_image_small = ImageSpecField( source="cover_image", @@ -307,11 +309,13 @@ class Video(ScrobblableMixin): def get_from_imdb_id( cls, imdb_id: str, overwrite: bool = False ) -> "Video": + if "tt" in imdb_id: + imdb_id = imdb_id[2:] video, created = cls.objects.get_or_create(imdb_id=imdb_id) if not created and not overwrite: return video - vdict, cover, genres = lookup_video_from_imdb( + vdict, cover, genres = lookup_video_from_tmdb( imdb_id ).as_dict_with_cover_and_genres() if created or overwrite: diff --git a/vrobbler/apps/videos/sources/tmdb.py b/vrobbler/apps/videos/sources/tmdb.py new file mode 100644 index 0000000..8bbb389 --- /dev/null +++ b/vrobbler/apps/videos/sources/tmdb.py @@ -0,0 +1,77 @@ +import logging + +from django.conf import settings +from themoviedb import TMDb +from tmdbv3api import TV, TMDb as TMDb_direct +from videos.metadata import VideoMetadata, VideoType + +key = getattr(settings, "TMDB_API_KEY", "33de8d24785931068ae356510dcfbac8") +key = "33de8d24785931068ae356510dcfbac8" + +tmdb_direct = TMDb_direct() +tmdb_direct.api_key = "33de8d24785931068ae356510dcfbac8" + +tmdb = TMDb(key=key, language="en-US", region="US") + +TMDB_STILL_URL = "https://image.tmdb.org/t/p/original" + +logger = logging.getLogger(__name__) + + +def lookup_video_from_tmdb( + name_or_id: str, kind: str = "movie" +) -> VideoMetadata: + from videos.models import Series + + imdb_id = name_or_id + if name_or_id.startswith("tt"): + imdb_id = name_or_id[2:] + + video_metadata = VideoMetadata(imdb_id=imdb_id) + imdb_result: dict = {} + + tmdb_result = tmdb.find().by_imdb("tt" + imdb_id) + + if not tmdb_result: + logger.info( + "[lookup_video_from_tmdb] no video found on tmdb", + extra={"name_or_id": name_or_id}, + ) + return None + + video_metadata = VideoMetadata(imdb_id=imdb_id) + + media = None + show = None + if len(tmdb_result.movie_results) > 0: + media = tmdb_result.movie_results[0] + video_metadata.video_type = VideoType.MOVIE.value + if len(tmdb_result.tv_episode_results) > 0: + video_metadata.video_type = VideoType.TV_EPISODE.value + media = tmdb_result.tv_episode_results[0] + series_imdb_id = TV().external_ids(media.show_id).imdb_id[2:] + + series, created = Series.objects.get_or_create(imdb_id=series_imdb_id) + if created: + show_data = TV().details(tv_id=media.show_id) + series.name = show_data.name + series.save() + video_metadata.tv_series_id = series.id + + if not media: + logger.warning("Video not found on TMDB", extra={"imdb_id":imdb_id}) + return video_metadata + + video_metadata.tmdb_id = media.id + video_metadata.cover_url = TMDB_STILL_URL + media.still_path # TODO: enrich this with TMDB url + video_metadata.run_time_seconds = media.runtime * 60 + video_metadata.title = media.name + video_metadata.episode_number = media.episode_number + video_metadata.season_number = media.season_number + #video_metadata.next_imdb_id = imdb_result.get("next episode", None) + video_metadata.year = media.air_date.year + video_metadata.plot = media.overview + video_metadata.imdb_rating = media.vote_average + #video_metadata.genres = imdb_result.get("genres", []) + + return video_metadata From 7a75b31b56823f501cbc24756e05971a90ecec81 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Fri, 13 Jun 2025 11:20:34 -0400 Subject: [PATCH 10/10] [todos] Update task for metadata fixing --- todos.org | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/todos.org b/todos.org index c59662b..7d6b412 100644 --- a/todos.org +++ b/todos.org @@ -1,10 +1,18 @@ #+title: TODOs * Version 17 -** TODO [#A] Investigate new source of video metadata :personal:project:video:imdb: +** DONE [#A] Investigate new source of video metadata :personal:project:video:imdb: +:PROPERTIES: +:ID: df2b486c-1170-5199-c312-9bc87760d962 +:END: Cinemagoer broke and I probably should find a more reilable source of video data. +- Note taken on [2025-06-13 Fri 11:19] + + TMDB is much more reliable, but does require an API key. That's all setup now, + so hopefully this breaking IMDB crap is over. + ** DONE IMDB video lookups are failing :personal:bug:video:imdb: :PROPERTIES: :ID: 38f1081f-37b4-f4f2-79aa-c1e87eca4b69