Files
danbooru/app/logical/upload_service/replacer.rb
evazion 8d5e0a5b58 replacements: don't delete replaced files.
Don't delete replaced files after 30 days. There are only about 30k
replacements in total, so the cost of keeping replaced files is
negligible. It was also wrong because the media asset wasn't destroyed
too, so there were active media assets with missing files.
2021-10-24 04:35:13 -05:00

118 lines
3.8 KiB
Ruby

class UploadService
class Replacer
extend Memoist
class Error < StandardError; end
attr_reader :post, :replacement
def initialize(post:, replacement:)
@post = post
@replacement = replacement
end
def comment_replacement_message(post, replacement)
%{"#{replacement.creator.name}":[#{Routes.user_path(replacement.creator)}] replaced this post with a new file:\n\n#{replacement_message(post, replacement)}}
end
def replacement_message(post, replacement)
linked_source = linked_source(replacement.replacement_url)
linked_source_was = linked_source(post.source_was)
<<-EOS.strip_heredoc
[table]
[tbody]
[tr]
[th]Old[/th]
[td]#{linked_source_was}[/td]
[td]#{post.md5_was}[/td]
[td]#{post.file_ext_was}[/td]
[td]#{post.image_width_was} x #{post.image_height_was}[/td]
[td]#{post.file_size_was.to_s(:human_size, precision: 4)}[/td]
[/tr]
[tr]
[th]New[/th]
[td]#{linked_source}[/td]
[td]#{post.md5}[/td]
[td]#{post.file_ext}[/td]
[td]#{post.image_width} x #{post.image_height}[/td]
[td]#{post.file_size.to_s(:human_size, precision: 4)}[/td]
[/tr]
[/tbody]
[/table]
EOS
end
def linked_source(source)
return nil if source.nil?
# truncate long sources in the middle: "www.pixiv.net...lust_id=23264933"
truncated_source = source.gsub(%r{\Ahttps?://}, "").truncate(64, omission: "...#{source.last(32)}")
if source =~ %r{\Ahttps?://}i
%{"#{truncated_source}":[#{source}]}
else
truncated_source
end
end
def undo!
undo_replacement = post.replacements.create(replacement_url: replacement.original_url)
undoer = Replacer.new(post: post, replacement: undo_replacement)
undoer.process!
end
def replacement_url
if replacement.replacement_file.present?
"file://#{replacement.replacement_file.original_filename}"
else
Sources::Strategies.find(replacement.replacement_url).canonical_url
end
end
def process!
media_file = Utils::get_file_for_upload(replacement.replacement_url, nil, replacement.replacement_file&.tempfile)
if media_file.md5 == post.md5
raise Error, "Can't replace a post with itself; regenerate the post instead"
elsif Post.exists?(md5: media_file.md5)
raise Error, "Duplicate: post with md5 #{media_file.md5} already exists"
end
media_asset = MediaAsset.upload!(media_file)
replacement.replacement_url = replacement_url
replacement.file_ext = media_asset.file_ext
replacement.file_size = media_asset.file_size
replacement.image_height = media_asset.image_height
replacement.image_width = media_asset.image_width
replacement.md5 = media_asset.md5
post.md5 = media_asset.md5
post.file_ext = media_asset.file_ext
post.image_width = media_asset.image_width
post.image_height = media_asset.image_height
post.file_size = media_asset.file_size
post.source = replacement.final_source.presence || replacement.replacement_url
post.tag_string = replacement.tags
rescale_notes(post)
CurrentUser.scoped(User.system) { Comment.create!(post: post, creator: User.system, updater: User.system, body: comment_replacement_message(post, replacement), do_not_bump_post: true, creator_ip_addr: "127.0.0.1") }
replacement.save!
post.save!
post.update_iqdb
end
def rescale_notes(post)
x_scale = post.image_width.to_f / post.image_width_was.to_f
y_scale = post.image_height.to_f / post.image_height_was.to_f
post.notes.each do |note|
note.rescale!(x_scale, y_scale)
end
end
end
end