From 69d88568a6dd00eb57e77a778054722742653e0f Mon Sep 17 00:00:00 2001 From: evazion Date: Tue, 1 Nov 2022 17:26:03 -0500 Subject: [PATCH] media assets: allow assets to be regenerated. Add a `MediaAsset#regenerate!` method that regenerates everything about the asset, including the metadata, thumbnails, IQDB, cached Cloudflare URLs, and AI tags. Fixes it so that a) it's possible to regenerate media assets that aren't attached to posts and b) regenerating a post regenerates everything. Before it didn't regenerate the metadata, AI tags, or all of the cached URLs. --- app/models/media_asset.rb | 46 ++++++++++++++++++++++++++++++++++++--- app/models/post.rb | 29 +----------------------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/app/models/media_asset.rb b/app/models/media_asset.rb index 138d0d3df..d99b5fb4e 100644 --- a/app/models/media_asset.rb +++ b/app/models/media_asset.rb @@ -320,13 +320,53 @@ class MediaAsset < ApplicationRecord self.duration = media_file.duration end - def regenerate_ai_tags! + def regenerate!(metadata: true, files: true, ai_tags: true) with_lock do - ai_tags.each(&:destroy!) - update!(ai_tags: generate_ai_tags) + variant("original").open_file! do |original_file| + regenerate_metadata!(original_file) if metadata + regenerate_files!(original_file) if files + end + + regenerate_ai_tags! if ai_tags end end + # Regenerate all metadata for the asset, including the md5, width, height, file size, file ext, + # duration, and EXIF metadata, both on the media asset and on the post. This may change the tags + # as well if the new metadata causes automatic tags to be recalculated. + def regenerate_metadata!(original_file) + update!(file: original_file) + media_metadata.update!(file: original_file) + + if saved_changes? && post.present? + CurrentUser.scoped(User.system) do + post.update!(md5: md5, file_ext: file_ext, file_size: file_size, image_width: image_width, image_height: image_height) + end + end + end + + # Regenerate all thumbnail and sample image files for the asset. + def regenerate_files!(original_file) + distribute_files!(original_file) + purge_cached_urls! + post.update_iqdb if post.present? + end + + # Purge all image URLs from Cloudflare. + def purge_cached_urls! + urls = variants.map(&:file_url) + urls += [post.tagged_file_url(tagged_filenames: true), post.tagged_large_file_url(tagged_filenames: true)] if post.present? + + CloudflareService.new.purge_cache(urls.uniq) + end + + # Regenerate the AI tags for the asset. This is based on the 360x360 thumbnail, so the files + # should be regenerated first in case the thumbnail changed. + def regenerate_ai_tags! + ai_tags.each(&:destroy!) + update!(ai_tags: generate_ai_tags) + end + def generate_ai_tags return [] if !has_variant?("360x360") diff --git a/app/models/post.rb b/app/models/post.rb index 3efd66bef..76b25a9a0 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1454,38 +1454,11 @@ class Post < ApplicationRecord ModAction.log("regenerated IQDB for post ##{id}", :post_regenerate_iqdb, subject: self, user: user) else - media_file = media_asset.variant(:original).open_file - media_asset.distribute_files!(media_file) - - update!( - image_width: media_file.width, - image_height: media_file.height, - file_size: media_file.file_size, - file_ext: media_file.file_ext - ) - - media_asset.update!( - image_width: media_file.width, - image_height: media_file.height, - file_size: media_file.file_size, - file_ext: media_file.file_ext - ) - - purge_cached_urls! - update_iqdb + media_asset.regenerate! ModAction.log("regenerated image samples for post ##{id}", :post_regenerate, subject: self, user: user) end end - - def purge_cached_urls! - urls = [ - preview_file_url, large_file_url, file_url, - tagged_file_url(tagged_filenames: true), tagged_large_file_url(tagged_filenames: true), - ] - - CloudflareService.new.purge_cache(urls) - end end concerning :IqdbMethods do