Skip to content
Snippets Groups Projects

Add clean_library command

Closed Toke Høiland-Jørgensen requested to merge tohojo/funkwhale:clean-library into develop
2 files
+ 101
0
Compare changes
  • Side-by-side
  • Inline
Files
2
import os
from django.core.management.base import BaseCommand
from django.db.models import Count
from funkwhale_api.music import models
class Command(BaseCommand):
help = "Clean library of missing files and empty albums/artists"
def add_arguments(self, parser):
parser.add_argument(
"--no-confirm",
action="store_false",
dest="confirm",
default=True,
help="Don't ask for confirmation before deleting data",
)
def confirm(self, message):
if self.confirm_enabled:
message = message + "\n\nType 'yes' to continue, or 'no' to cancel: "
return input(message) == "yes"
return True
def handle(self, *args, **options):
self.stdout.write("Cleaning library...")
self.confirm_enabled = options["confirm"]
files = self.find_missing_files()
self.stdout.write("- Found {} files that no longer exist.".format(len(files)))
if files and self.confirm("Remove files from database?"):
i = 0
for tf in files:
tf.delete()
i += 1
self.stdout.write(" Removed {} files from database".format(i))
tracks = self.find_empty_tracks()
self.stdout.write(
"- Found {} tracks with no associated files.".format(len(tracks))
)
if tracks and self.confirm("Remove tracks?"):
i = 0
for t in tracks:
t.delete()
i += 1
self.stdout.write(" Removed {} tracks from database".format(i))
albums = self.find_empty_albums()
self.stdout.write("- Found {} empty albums.".format(len(albums)))
if albums and self.confirm("Remove albums?"):
i = 0
for a in albums:
a.delete()
i += 1
self.stdout.write(" Removed {} albums from database".format(i))
artists = self.find_empty_artists()
self.stdout.write("- Found {} empty artists.".format(len(artists)))
if artists and self.confirm("Remove artists?"):
i = 0
for a in artists:
a.delete()
i += 1
self.stdout.write(" Removed {} artists from database".format(i))
def find_missing_files(self):
missing_files = []
for tf in models.TrackFile.objects.filter(source__startswith="file://"):
fname = tf.source.replace("file://", "")
if not os.path.exists(fname):
missing_files.append(tf)
return missing_files
def find_empty(self, model, field):
return model.objects.annotate(num_obj=Count(field)).filter(num_obj=0)
def find_empty_tracks(self):
return self.find_empty(models.Track, "files")
def find_empty_albums(self):
return self.find_empty(models.Album, "tracks")
def find_empty_artists(self):
return models.Artist.objects.annotate(
num_tracks=Count("tracks"), num_albums=Count("albums")
).filter(num_tracks=0, num_albums=0)
Loading