[videos] More dedup scripts
This commit is contained in:
@ -0,0 +1,84 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Find TV Series with duplicate imdb_id values and merge videos to the newest series"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--dry-run",
|
||||||
|
action="store_true",
|
||||||
|
help="Show what would be done without making changes",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--auto",
|
||||||
|
action="store_true",
|
||||||
|
help="Automatically fix duplicates without prompting",
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
from videos.models import Series
|
||||||
|
|
||||||
|
dry_run = options["dry_run"]
|
||||||
|
auto = options["auto"]
|
||||||
|
|
||||||
|
duplicate_imdb_ids = (
|
||||||
|
Series.objects.filter(imdb_id__isnull=False)
|
||||||
|
.exclude(imdb_id="")
|
||||||
|
.values("imdb_id")
|
||||||
|
.annotate(count=models.Count("id"))
|
||||||
|
.filter(count__gt=1)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not duplicate_imdb_ids.exists():
|
||||||
|
self.stdout.write("No duplicate imdb_id values found in Series")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.stdout.write(
|
||||||
|
f"Found {duplicate_imdb_ids.count()} imdb_ids with duplicates in Series"
|
||||||
|
)
|
||||||
|
|
||||||
|
for dup in duplicate_imdb_ids:
|
||||||
|
imdb_id = dup["imdb_id"]
|
||||||
|
series_list = list(
|
||||||
|
Series.objects.filter(imdb_id=imdb_id).order_by("created")
|
||||||
|
)
|
||||||
|
|
||||||
|
self.stdout.write(f"\nimdb_id: {imdb_id}")
|
||||||
|
self.stdout.write(f" Found {len(series_list)} series:")
|
||||||
|
|
||||||
|
for s in series_list:
|
||||||
|
video_count = s.video_set.count()
|
||||||
|
self.stdout.write(
|
||||||
|
f" id={s.id}, name='{s.name}', created={s.created}, videos={video_count}"
|
||||||
|
)
|
||||||
|
|
||||||
|
keeper = series_list[-1]
|
||||||
|
duplicates = series_list[:-1]
|
||||||
|
|
||||||
|
self.stdout.write(f" Keeping: id={keeper.id} ('{keeper.name}')")
|
||||||
|
self.stdout.write(f" Merging from: {[d.id for d in duplicates]}")
|
||||||
|
|
||||||
|
if dry_run:
|
||||||
|
self.stdout.write(self.style.WARNING(" [DRY RUN] Would move videos"))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not auto:
|
||||||
|
confirm = input(" Move videos from duplicates to keeper? [y/N] ")
|
||||||
|
if confirm.lower() != "y":
|
||||||
|
self.stdout.write(" Skipped")
|
||||||
|
continue
|
||||||
|
|
||||||
|
for dup_series in duplicates:
|
||||||
|
video_count = dup_series.video_set.count()
|
||||||
|
if video_count > 0:
|
||||||
|
dup_series.video_set.update(tv_series=keeper)
|
||||||
|
self.stdout.write(
|
||||||
|
f" Moved {video_count} videos from id={dup_series.id} to id={keeper.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
dup_series.delete()
|
||||||
|
self.stdout.write(f" Deleted series id={dup_series.id}")
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS("\nDone!"))
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Find TV Series with duplicate names, merge Videos into the one with 'tt' IMDB id"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--dry-run",
|
||||||
|
action="store_true",
|
||||||
|
help="Show what would be done without making changes",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--auto",
|
||||||
|
action="store_true",
|
||||||
|
help="Automatically fix duplicates without prompting",
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
from videos.models import Series
|
||||||
|
|
||||||
|
dry_run = options["dry_run"]
|
||||||
|
auto = options["auto"]
|
||||||
|
|
||||||
|
duplicate_names = (
|
||||||
|
Series.objects.values("name")
|
||||||
|
.annotate(count=models.Count("id"))
|
||||||
|
.filter(count__gt=1)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not duplicate_names.exists():
|
||||||
|
self.stdout.write("No duplicate Series names found")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.stdout.write(f"Found {duplicate_names.count()} names with duplicates")
|
||||||
|
|
||||||
|
for dup in duplicate_names:
|
||||||
|
name = dup["name"]
|
||||||
|
series_list = list(Series.objects.filter(name=name).order_by("created"))
|
||||||
|
|
||||||
|
self.stdout.write(f"\nSeries name: {name}")
|
||||||
|
self.stdout.write(f" Found {len(series_list)} series:")
|
||||||
|
|
||||||
|
for s in series_list:
|
||||||
|
video_count = s.video_set.count()
|
||||||
|
self.stdout.write(
|
||||||
|
f" id={s.id}, imdb_id='{s.imdb_id}', created={s.created}, videos={video_count}"
|
||||||
|
)
|
||||||
|
|
||||||
|
tt_series = None
|
||||||
|
for s in series_list:
|
||||||
|
if s.imdb_id and s.imdb_id.startswith("tt"):
|
||||||
|
tt_series = s
|
||||||
|
break
|
||||||
|
|
||||||
|
if not tt_series:
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.ERROR(
|
||||||
|
f" ERROR: No series with 'tt' IMDB id found, skipping"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
duplicates = [s for s in series_list if s.id != tt_series.id]
|
||||||
|
self.stdout.write(
|
||||||
|
f" Keeper (tt): id={tt_series.id} ('{tt_series.imdb_id}')"
|
||||||
|
)
|
||||||
|
self.stdout.write(f" Merging from: {[d.id for d in duplicates]}")
|
||||||
|
|
||||||
|
if dry_run:
|
||||||
|
self.stdout.write(self.style.WARNING(" [DRY RUN] Would move videos"))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not auto:
|
||||||
|
confirm = input(" Move videos from duplicates to keeper? [y/N] ")
|
||||||
|
if confirm.lower() != "y":
|
||||||
|
self.stdout.write(" Skipped")
|
||||||
|
continue
|
||||||
|
|
||||||
|
total_moved = 0
|
||||||
|
for dup_series in duplicates:
|
||||||
|
video_count = dup_series.video_set.count()
|
||||||
|
if video_count > 0:
|
||||||
|
dup_series.video_set.update(tv_series=tt_series)
|
||||||
|
self.stdout.write(
|
||||||
|
f" Moved {video_count} videos from id={dup_series.id} to id={tt_series.id}"
|
||||||
|
)
|
||||||
|
total_moved += video_count
|
||||||
|
|
||||||
|
dup_series.delete()
|
||||||
|
self.stdout.write(f" Deleted series id={dup_series.id}")
|
||||||
|
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS(f" Merged {total_moved} videos total")
|
||||||
|
)
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS("\nDone!"))
|
||||||
Reference in New Issue
Block a user