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.
118 lines
3.8 KiB
Ruby
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
|