Skip to content
Snippets Groups Projects
fix_uploads.py 4.41 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",
    
            parser.add_argument(
                "--mimetypes",
                action="store_true",
                dest="mimetypes",
                default=True,
                help="Check and fix mimetypes",
            )
            parser.add_argument(
                "--audio-data",
                action="store_true",
                dest="data",
                default=False,
                help="Check and fix bitrate and duration, can be really slow because it needs to access files",
            )
            parser.add_argument(
                "--size",
                action="store_true",
                dest="size",
                default=False,
                help="Check and fix file size, can be really slow because it needs to access files",
            )
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            if options["dry_run"]:
                self.stdout.write("Dry-run on, will not commit anything")
    
            if options["mimetypes"]:
                self.fix_mimetypes(**options)
            if options["data"]:
                self.fix_file_data(**options)
            if options["size"]:
                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.Upload.objects.filter(
                Q(source__startswith="file://") | Q(source__startswith="upload://")
            ).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...")
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            matching = models.Upload.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, upload in enumerate(matching.only("audio_file")):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    "[bitrate/length] {}/{} fixing file #{}".format(i + 1, total, upload.pk)
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                )
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    audio_file = upload.get_audio_file()
    
                        data = utils.get_audio_file_data(audio_file)
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                        upload.bitrate = data["bitrate"]
                        upload.duration = data["length"]
                        upload.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(upload.pk, str(e))
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            self.stdout.write("Fixing missing size...")
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            matching = models.Upload.objects.filter(size__isnull=True)
    
    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, upload in enumerate(matching.only("size")):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    "[size] {}/{} fixing file #{}".format(i + 1, total, upload.pk)
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                )
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    upload.size = upload.get_file_size()
                    upload.save(update_fields=["size"])
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                        "[size] error with file #{}: {}".format(upload.pk, str(e))