Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c8cf80b513 | |||
| b4180afbed |
@ -590,6 +590,12 @@ We should rename `email_scrobble_board_game` to reflect the fact that it's just
|
||||
a helper method to create board game scrobbles given a json blob. It's
|
||||
independent of the email flow it was originally creatdd for
|
||||
|
||||
* Version 54.3 [1/1]
|
||||
** DONE [#B] Fix bug in series metadata cleanup script :videos:metadta:
|
||||
:PROPERTIES:
|
||||
:ID: 85448702-907c-5d63-f5af-7795661d7c46
|
||||
:END:
|
||||
|
||||
* Version 54.2 [4/4]
|
||||
** DONE [#B] Add script to clean up TV series metadata :videos:metadata:
|
||||
:PROPERTIES:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "vrobbler"
|
||||
version = "54.2"
|
||||
version = "54.3"
|
||||
description = ""
|
||||
authors = ["Colin Powell <colin@unbl.ink>"]
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import logging
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
from django.db import models, transaction
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -25,6 +25,11 @@ class Command(BaseCommand):
|
||||
type=str,
|
||||
help="Only process series with this imdb_id",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--needs-metadata",
|
||||
action="store_true",
|
||||
help="Only process series missing imdb_id or cover image",
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
from videos.models import Series
|
||||
@ -32,18 +37,30 @@ class Command(BaseCommand):
|
||||
force = options["force"]
|
||||
dry_run = options["dry_run"]
|
||||
imdb_id = options["imdb_id"]
|
||||
needs_metadata = options["needs_metadata"]
|
||||
|
||||
qs = Series.objects.all()
|
||||
if imdb_id:
|
||||
qs = qs.filter(imdb_id=imdb_id)
|
||||
if needs_metadata:
|
||||
qs = qs.filter(
|
||||
models.Q(imdb_id__isnull=True)
|
||||
| models.Q(imdb_id="")
|
||||
| models.Q(cover_image__isnull=True)
|
||||
| models.Q(cover_image="")
|
||||
)
|
||||
|
||||
total = qs.count()
|
||||
self.stdout.write(f"Processing {total} series")
|
||||
|
||||
if dry_run:
|
||||
for series in qs.iterator():
|
||||
has_imdb = bool(series.imdb_id)
|
||||
has_image = bool(series.cover_image)
|
||||
self.stdout.write(
|
||||
f" [DRY RUN] Would fix {series.name} (imdb_id={series.imdb_id})"
|
||||
f" [DRY RUN] Would fix {series.name}"
|
||||
f" (imdb_id={'✓' if has_imdb else '✗'}"
|
||||
f", image={'✓' if has_image else '✗'})"
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@ -321,13 +321,27 @@ class Series(TimeStampedModel):
|
||||
return not last_scrobble.played_to_completion
|
||||
|
||||
def fix_metadata(self, force_update=False):
|
||||
name_or_id = self.name
|
||||
if self.imdb_id:
|
||||
name_or_id = self.imdb_id
|
||||
video_metadata: VideoMetadata = lookup_video_from_tmdb(name_or_id)
|
||||
from tmdbv3api import TV
|
||||
|
||||
if not video_metadata.title:
|
||||
logger.warning(f"No imdb data for {self}")
|
||||
if not self.imdb_id:
|
||||
tv = TV()
|
||||
results = tv.search(self.name)
|
||||
if results:
|
||||
show_id = results[0].id
|
||||
external_ids = tv.external_ids(show_id)
|
||||
if external_ids and external_ids.imdb_id:
|
||||
self.imdb_id = external_ids.imdb_id
|
||||
self.save(update_fields=["imdb_id"])
|
||||
else:
|
||||
logger.warning(f"No IMDB ID found on TMDB for {self}")
|
||||
return
|
||||
else:
|
||||
logger.warning(f"No results on TMDB for {self.name}")
|
||||
return
|
||||
|
||||
video_metadata = lookup_video_from_tmdb(self.imdb_id)
|
||||
if not video_metadata or not video_metadata.title:
|
||||
logger.warning(f"No metadata for {self}")
|
||||
return
|
||||
|
||||
if video_metadata.cover_url and (not self.cover_image or force_update):
|
||||
@ -336,8 +350,8 @@ class Series(TimeStampedModel):
|
||||
fname = f"{self.name}_{self.uuid}.jpg"
|
||||
self.cover_image.save(fname, ContentFile(r.content), save=True)
|
||||
|
||||
self.plot = video_metadata.plot
|
||||
self.imdb_rating = video_metadata.imdb_rating
|
||||
self.plot = video_metadata.plot or ""
|
||||
self.imdb_rating = getattr(video_metadata, "imdb_rating", None)
|
||||
self.save()
|
||||
|
||||
if video_metadata.genres:
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
import pendulum
|
||||
from django.conf import settings
|
||||
@ -8,6 +9,8 @@ from videos.metadata import VideoMetadata, VideoType
|
||||
|
||||
TMDB_KEY = getattr(settings, "TMDB_API_KEY", "")
|
||||
|
||||
os.environ.setdefault("TMDB_API_KEY", TMDB_KEY)
|
||||
|
||||
tmdb = TMDb(key=TMDB_KEY, language="en-US", region="US")
|
||||
|
||||
TMDB_IMAGE_URL = "https://image.tmdb.org/t/p/original"
|
||||
@ -43,6 +46,28 @@ def lookup_video_from_tmdb(name_or_id: str, kind: str = "movie") -> VideoMetadat
|
||||
) # TODO: enrich this with TMDB url
|
||||
video_metadata.year = pendulum.parse(media.release_date).year
|
||||
video_metadata.genres = [g.get("name", "") for g in media.genres]
|
||||
video_metadata.tmdb_id = media.id
|
||||
video_metadata.base_run_time_seconds = media.runtime * 60
|
||||
video_metadata.plot = media.overview
|
||||
video_metadata.overview = media.overview
|
||||
video_metadata.tmdb_rating = media.vote_average
|
||||
|
||||
if len(tmdb_result.tv_results) > 0:
|
||||
media = TV().details(tmdb_result.tv_results[0].id)
|
||||
video_metadata.video_type = VideoType.TV_EPISODE.value
|
||||
video_metadata.title = media.name
|
||||
video_metadata.cover_url = (
|
||||
TMDB_IMAGE_URL + media.poster_path
|
||||
)
|
||||
video_metadata.year = pendulum.parse(media.first_air_date).year if media.first_air_date else None
|
||||
video_metadata.genres = [g.get("name", "") for g in media.genres]
|
||||
video_metadata.tmdb_id = media.id
|
||||
video_metadata.base_run_time_seconds = (
|
||||
media.episode_run_time[0] * 60 if media.episode_run_time else 1800
|
||||
)
|
||||
video_metadata.plot = media.overview
|
||||
video_metadata.overview = media.overview
|
||||
video_metadata.tmdb_rating = media.vote_average
|
||||
|
||||
if len(tmdb_result.tv_episode_results) > 0:
|
||||
video_metadata.video_type = VideoType.TV_EPISODE.value
|
||||
@ -63,15 +88,12 @@ def lookup_video_from_tmdb(name_or_id: str, kind: str = "movie") -> VideoMetadat
|
||||
series.save()
|
||||
video_metadata.tv_series_id = series.id
|
||||
|
||||
video_metadata.tmdb_id = media.id
|
||||
video_metadata.plot = media.overview
|
||||
video_metadata.overview = media.overview
|
||||
|
||||
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.base_run_time_seconds = media.runtime * 60
|
||||
video_metadata.plot = media.overview
|
||||
video_metadata.overview = media.overview
|
||||
video_metadata.tmdb_rating = media.vote_average
|
||||
# video_metadata.next_imdb_id = imdb_result.get("next episode", None)
|
||||
|
||||
return video_metadata
|
||||
|
||||
Reference in New Issue
Block a user