This commit has no recorded session.
diff
commit fb775f2f585a81dcd51a358fffe4eace33f5e227Author: Colin Powell <colin@unbl.ink>Date: Wed Jun 17 11:05:38 2026 -0400 [videos] Add cmd to cleanup series metadata@@ -88,7 +88,7 @@ fetching and simple saving. *** Metadata sources **** Scraper -* Backlog [3/23] :vrobbler:project:personal:+* Backlog [4/24] :vrobbler:project:personal: ** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :bug:music:scrobbles: :PROPERTIES: :ID: 702462cf-d54b-48c6-8a7c-78b8de751deb@@ -590,6 +590,10 @@ 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 +** DONE [#B] Add script to clean up TV series metadata :videos:metadata:+:PROPERTIES:+:ID: a468b328-59d9-f84b-9ddb-087216783453+:END: ** DONE [#A] Update youtube video detail pages with links to channel :videos:templates: :PROPERTIES: :ID: 8b87cb42-09e5-a3f5-136f-182f967fa81f@@ -0,0 +1,68 @@+import logging++from django.core.management.base import BaseCommand+from django.db import transaction++logger = logging.getLogger(__name__)+++class Command(BaseCommand):+ help = "Enrich TV series metadata from TMDB/OMDB APIs"++ def add_arguments(self, parser):+ parser.add_argument(+ "--force",+ action="store_true",+ help="Overwrite existing cover image",+ )+ parser.add_argument(+ "--dry-run",+ action="store_true",+ help="Show what would be done without making changes",+ )+ parser.add_argument(+ "--imdb-id",+ type=str,+ help="Only process series with this imdb_id",+ )++ def handle(self, *args, **options):+ from videos.models import Series++ force = options["force"]+ dry_run = options["dry_run"]+ imdb_id = options["imdb_id"]++ qs = Series.objects.all()+ if imdb_id:+ qs = qs.filter(imdb_id=imdb_id)++ total = qs.count()+ self.stdout.write(f"Processing {total} series")++ if dry_run:+ for series in qs.iterator():+ self.stdout.write(+ f" [DRY RUN] Would fix {series.name} (imdb_id={series.imdb_id})"+ )+ return++ updated = 0+ errors = 0+ for series in qs.iterator():+ try:+ with transaction.atomic():+ series.fix_metadata(force_update=force)+ updated += 1+ self.stdout.write(f" [{updated}/{total}] {series.name}")+ except Exception as e:+ errors += 1+ self.stdout.write(+ self.style.ERROR(+ f" Error updating series {series.name} (imdb_id={series.imdb_id}): {e}"+ )+ )++ self.stdout.write(+ self.style.SUCCESS(f"\nDone! {updated} series updated, {errors} errors")+ )@@ -330,16 +330,18 @@ class Series(TimeStampedModel): logger.warning(f"No imdb data for {self}") return - cover_url = imdb_dict.get("cover_url")-- if (not self.cover_image or force_update) and cover_url:- r = requests.get(cover_url)+ if video_metadata.cover_url and (not self.cover_image or force_update):+ r = requests.get(video_metadata.cover_url) if r.status_code == 200: fname = f"{self.name}_{self.uuid}.jpg" self.cover_image.save(fname, ContentFile(r.content), save=True) - if genres := imdb_dict.get("genres"):- self.genre.add(*genres)+ self.plot = video_metadata.plot+ self.imdb_rating = video_metadata.imdb_rating+ self.save()++ if video_metadata.genres:+ self.genre.add(*video_metadata.genres) @classmethod def find_or_create(cls, imdb_id: str, overwrite: bool = True):