extensions-website/files/tasks.py
Anna Sirota 700c61e74a Thumbnails: flag toggling validation requirement
Introduces `REQUIRE_FILE_VALIDATION` flag (defaults to `False`), which allows
skipping checks for file validation and generate thumbnails right
after a new file is created.
2024-04-26 11:50:55 +02:00

72 lines
2.8 KiB
Python

import logging
import os.path
from background_task import background
from background_task.tasks import TaskSchedule
from django.conf import settings
import files.models
import files.utils
logger = logging.getLogger(__name__)
@background(schedule={'action': TaskSchedule.RESCHEDULE_EXISTING})
def clamdscan(file_id: int):
"""Run a scan of a given file and save its output as a FileValidation record."""
file = files.models.File.objects.get(pk=file_id)
abs_path = os.path.join(settings.MEDIA_ROOT, file.source.path)
scan_status, scan_found = files.utils.run_clamdscan(abs_path)
logger.info('File pk=%s scanned: %s', file.pk, (scan_status, scan_found))
scan_result = {'clamdscan': [scan_status, scan_found]}
is_ok = scan_status == 'OK'
file_validation, is_new = files.models.FileValidation.objects.get_or_create(
file=file, defaults={'results': scan_result, 'is_ok': is_ok}
)
if not is_new:
file_validation.results = scan_result
file_validation.is_ok = is_ok
file_validation.save(update_fields={'results', 'is_ok', 'date_modified'})
@background(schedule={'action': TaskSchedule.RESCHEDULE_EXISTING})
def make_thumbnails(file_id: int) -> None:
"""Generate thumbnails for a given file, store them in thumbnail and metadata columns."""
file = files.models.File.objects.get(pk=file_id)
args = {'pk': file_id, 'type': file.get_type_display()}
if not file.is_image and not file.is_video:
logger.error('File pk=%(pk)s of type "%(type)s" is neither an image nor a video', args)
return
if settings.REQUIRE_FILE_VALIDATION and not file.validation.is_ok:
logger.error("File pk={pk} is flagged, won't make thumbnails".format(**args))
return
# For an image, source of the thumbnails is the original image
source_path = file.source.path
thumbnail_field = file.thumbnail
unchanged_thumbnail = thumbnail_field.name
if file.is_video:
frame_path = files.utils.get_thumbnail_upload_to(file.hash)
# For a video, source of the thumbnails is a frame extracted with ffpeg
files.utils.extract_frame(source_path, frame_path)
thumbnail_field.name = frame_path
source_path = frame_path
thumbnails = files.utils.make_thumbnails(source_path, file.hash)
if not thumbnail_field.name:
thumbnail_field.name = thumbnails['1080p']['path']
update_fields = set()
if thumbnail_field.name != unchanged_thumbnail:
update_fields.add('thumbnail')
if file.metadata.get('thumbnails') != thumbnails:
file.metadata.update({'thumbnails': thumbnails})
update_fields.add('metadata')
if update_fields:
args['update_fields'] = update_fields
logger.info('Made thumbnails for file pk=%(pk)s, updating %(update_fields)s', args)
file.save(update_fields=update_fields)