Skip to content
Snippets Groups Projects
fix_track_files.py 3.55 KiB
Newer Older
  • Learn to ignore specific revisions
  • Eliot Berriot's avatar
    Eliot Berriot committed
    from django.core.management.base import BaseCommand
    
    
    from funkwhale_api.music import models, utils
    
    
    class Command(BaseCommand):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        help = "Run common checks and fix against imported tracks"
    
    
        def add_arguments(self, parser):
            parser.add_argument(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "--dry-run",
                action="store_true",
                dest="dry_run",
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                help="Do not execute anything",
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            if options["dry_run"]:
                self.stdout.write("Dry-run on, will not commit anything")
    
            self.fix_file_data(**options)
            self.fix_file_size(**options)
    
    
        @transaction.atomic
        def fix_mimetypes(self, dry_run, **kwargs):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            self.stdout.write("Fixing missing mimetypes...")
    
            matching = models.TrackFile.objects.filter(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                source__startswith="file://"
            ).exclude(mimetype__startswith="audio/")
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "[mimetypes] {} entries found with bad or no mimetype".format(
                    matching.count()
                )
            )
    
            for extension, mimetype in utils.EXTENSION_TO_MIMETYPE.items():
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                qs = matching.filter(source__endswith=".{}".format(extension))
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    "[mimetypes] setting {} {} files to {}".format(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    )
                )
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    self.stdout.write("[mimetypes] commiting...")
    
    
        def fix_file_data(self, dry_run, **kwargs):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            self.stdout.write("Fixing missing bitrate or length...")
    
            matching = models.TrackFile.objects.filter(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                Q(bitrate__isnull=True) | Q(duration__isnull=True)
            )
    
            total = matching.count()
            self.stdout.write(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "[bitrate/length] {} entries found with missing values".format(total)
            )
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            for i, tf in enumerate(matching.only("audio_file")):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    "[bitrate/length] {}/{} fixing file #{}".format(i + 1, total, tf.pk)
                )
    
    
                try:
                    audio_file = tf.get_audio_file()
                    if audio_file:
    
                        data = utils.get_audio_file_data(audio_file)
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                        tf.bitrate = data["bitrate"]
                        tf.duration = data["length"]
                        tf.save(update_fields=["duration", "bitrate"])
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                        self.stderr.write("[bitrate/length] no file found")
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                        "[bitrate/length] error with file #{}: {}".format(tf.pk, str(e))
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            self.stdout.write("Fixing missing size...")
    
            matching = models.TrackFile.objects.filter(size__isnull=True)
            total = matching.count()
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            self.stdout.write("[size] {} entries found with missing values".format(total))
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            for i, tf in enumerate(matching.only("size")):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    "[size] {}/{} fixing file #{}".format(i + 1, total, tf.pk)
                )
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    tf.save(update_fields=["size"])
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                        "[size] error with file #{}: {}".format(tf.pk, str(e))