diff --git a/app/assets/javascripts/related_tag.js.erb b/app/assets/javascripts/related_tag.js.erb index 88ea5ed71..af359d4e7 100644 --- a/app/assets/javascripts/related_tag.js.erb +++ b/app/assets/javascripts/related_tag.js.erb @@ -34,7 +34,6 @@ $dest.empty(); Danbooru.RelatedTag.build_recent_and_frequent($dest); $dest.append("Loading..."); - $("#related-tags-container").show(); $.get("/related_tag.json", { "query": Danbooru.RelatedTag.current_tag(), "category": category @@ -93,6 +92,9 @@ } Danbooru.RelatedTag.process_response = function(data) { + if (data.tags.length || data.wiki_page_tags.length || data.other_wikis.length) { + $("#related-tags-container").show(); + } Danbooru.RelatedTag.recent_search = data; Danbooru.RelatedTag.build_all(); } diff --git a/app/assets/stylesheets/specific/posts.scss b/app/assets/stylesheets/specific/posts.scss index d0b6ab846..af8cfe0a3 100644 --- a/app/assets/stylesheets/specific/posts.scss +++ b/app/assets/stylesheets/specific/posts.scss @@ -471,9 +471,10 @@ div#c-post-versions, div#c-artist-versions { div#c-posts, div#c-uploads { /* Fetch source data box */ div#source-info { + border-radius: 4px; margin: 1em 0; padding: 1em; - border: 1px solid gray; + border: 1px solid #666; p { margin: 0; diff --git a/app/assets/stylesheets/specific/related_tags.scss b/app/assets/stylesheets/specific/related_tags.scss index ff5fe72ee..6511d9ecd 100644 --- a/app/assets/stylesheets/specific/related_tags.scss +++ b/app/assets/stylesheets/specific/related_tags.scss @@ -1,6 +1,7 @@ @import "../common/000_vars.scss"; div#related-tags-container { + display: none; padding-right: 2em; h1 { @@ -14,6 +15,7 @@ div.related-tags { padding: 1em; background: #EEE; overflow: auto; + border-radius: 4px; div.tag-column { max-width: 15em; diff --git a/app/assets/stylesheets/specific/uploads.scss b/app/assets/stylesheets/specific/uploads.scss index f32d49fd6..21f024005 100644 --- a/app/assets/stylesheets/specific/uploads.scss +++ b/app/assets/stylesheets/specific/uploads.scss @@ -41,11 +41,18 @@ div#c-uploads { max-width: 700px; min-height: 50px; + .placeholder { + font-style: italic; + color: #333; + } + &.error { + border-color: darken(#f2dede, 30%); background-color: #f2dede; } &.success { + border-color: darken(#dff0d8, 30%); background-color: #dff0d8; } } diff --git a/app/logical/upload_service.rb b/app/logical/upload_service.rb index 3b27d9f03..7b000291e 100644 --- a/app/logical/upload_service.rb +++ b/app/logical/upload_service.rb @@ -302,8 +302,8 @@ class UploadService end end - def finish! - pred = self.predecessor() + def finish!(upload = nil) + pred = upload || self.predecessor() pred.attributes = self.params pred.status = "completed" pred.save @@ -356,7 +356,7 @@ class UploadService [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.human_size(precision: 4)}[/td] + [td]#{post.file_size_was.to_s(:human_size, precision: 4)}[/td] [/tr] [tr] [th]New[/th] @@ -364,7 +364,7 @@ class UploadService [td]#{post.md5}[/td] [td]#{post.file_ext}[/td] [td]#{post.image_width} x #{post.image_height}[/td] - [td]#{post.file_size.human_size(precision: 4)}[/td] + [td]#{post.file_size.to_s(:human_size, precision: 4)}[/td] [/tr] [/tbody] [/table] @@ -384,10 +384,10 @@ class UploadService end end - def suggested_tags_for_removal - tags = post.tag_array.select { |tag| Danbooru.config.remove_tag_after_replacement?(tag) } - tags = tags.map { |tag| "-#{tag}" } - tags.join(" ") + def undo! + undo_replacement = post.replacements.create(replacement_url: replacement.original_url) + undoer = Replacer.new(post: post, replacement: undo_replacement) + undoer.process! end def process! @@ -398,9 +398,9 @@ class UploadService file: replacement.replacement_file ) upload = preprocessor.start!(CurrentUser.id) - upload = preprocessor.finish! + upload = preprocessor.finish!(upload) md5_changed = upload.md5 != post.md5 - + if replacement.replacement_file.present? replacement.replacement_url = "file://#{replacement.replacement_file.original_filename}" elsif upload.downloaded_source.present? @@ -422,10 +422,9 @@ class UploadService post.image_width = upload.image_width post.image_height = upload.image_height post.file_size = upload.file_size - post.source = upload.source + post.source = upload.downloaded_source || upload.source post.tag_string = upload.tag_string - rescale_notes(post) update_ugoira_frame_data(post, upload) if md5_changed @@ -434,22 +433,38 @@ class UploadService end end + if replacement.final_source.present? + post.update(source: replacement.final_source) + end + replacement.save! post.save! + + rescale_notes(post) 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 + x_scale = post.image_width.to_f / post.image_width_before_last_save.to_f + y_scale = post.image_height.to_f / post.image_height_before_last_save.to_f post.notes.each do |note| + note.reload note.rescale!(x_scale, y_scale) end end def update_ugoira_frame_data(post, upload) post.pixiv_ugoira_frame_data.destroy if post.pixiv_ugoira_frame_data.present? - upload.ugoira_service.save_frame_data(post) if post.is_ugoira? + + unless post.is_ugoira? + return + end + + PixivUgoiraFrameData.create( + post_id: post.id, + data: upload.context["ugoira"]["frame_data"], + content_type: upload.context["ugoira"]["content_type"] + ) end end diff --git a/app/models/post.rb b/app/models/post.rb index 70ab22905..a4b56dc88 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1396,7 +1396,8 @@ class Post < ApplicationRecord def replace!(params) transaction do replacement = replacements.create(params) - replacement.process! + processor = UploadService::Replacer.new(post: self, replacement: replacement) + processor.process! replacement end end diff --git a/app/models/post_replacement.rb b/app/models/post_replacement.rb index 2174d0972..840a90f8b 100644 --- a/app/models/post_replacement.rb +++ b/app/models/post_replacement.rb @@ -18,43 +18,40 @@ class PostReplacement < ApplicationRecord self.md5_was = post.md5 end - def undo! - undo_replacement = post.replacements.create(replacement_url: original_url) - undo_replacement.process! - end - - def update_ugoira_frame_data(upload) - post.pixiv_ugoira_frame_data.destroy if post.pixiv_ugoira_frame_data.present? - upload.ugoira_service.save_frame_data(post) if post.is_ugoira? - end - - module SearchMethods - def post_tags_match(query) - PostQueryBuilder.new(query).build(self.joins(:post)) - end - - def search(params = {}) - q = super - - if params[:creator_id].present? - q = q.where(creator_id: params[:creator_id].split(",").map(&:to_i)) + concerning :Search do + class_methods do + def post_tags_match(query) + PostQueryBuilder.new(query).build(self.joins(:post)) end - if params[:creator_name].present? - q = q.where(creator_id: User.name_to_id(params[:creator_name])) - end + def search(params = {}) + q = super - if params[:post_id].present? - q = q.where(post_id: params[:post_id].split(",").map(&:to_i)) - end + if params[:creator_id].present? + q = q.where(creator_id: params[:creator_id].split(",").map(&:to_i)) + end - if params[:post_tags_match].present? - q = q.post_tags_match(params[:post_tags_match]) - end + if params[:creator_name].present? + q = q.where(creator_id: User.name_to_id(params[:creator_name])) + end - q.apply_default_order(params) + if params[:post_id].present? + q = q.where(post_id: params[:post_id].split(",").map(&:to_i)) + end + + if params[:post_tags_match].present? + q = q.post_tags_match(params[:post_tags_match]) + end + + q.apply_default_order(params) + end end end - extend SearchMethods + def suggested_tags_for_removal + tags = post.tag_array.select { |tag| Danbooru.config.remove_tag_after_replacement?(tag) } + tags = tags.map { |tag| "-#{tag}" } + tags.join(" ") + end + end diff --git a/app/views/uploads/new.html.erb b/app/views/uploads/new.html.erb index 7fa2d59ec..9dd3995c6 100644 --- a/app/views/uploads/new.html.erb +++ b/app/views/uploads/new.html.erb @@ -111,7 +111,7 @@
<%= f.label :tag_string, "Tags" %> - <%= f.text_area :tag_string, :size => "60x5", :data => { :autocomplete => "tag-edit" } %> + <%= f.text_area :tag_string, :size => "60x5", :spellcheck => false, :data => { :autocomplete => "tag-edit" } %>
diff --git a/test/models/upload_service_test.rb b/test/models/upload_service_test.rb index aa37fa3d0..7849a44d1 100644 --- a/test/models/upload_service_test.rb +++ b/test/models/upload_service_test.rb @@ -380,11 +380,13 @@ class UploadServiceTest < ActiveSupport::TestCase context "for a file replacement" do setup do @new_file = upload_file("test/files/test.jpg") + @old_file = upload_file("test/files/test.png") travel_to(1.month.ago) do @user = FactoryBot.create(:user) end as_user do - @post = FactoryBot.create(:post) + @post = FactoryBot.create(:post, md5: Digest::MD5.hexdigest(@old_file.read)) + @old_md5 = @post.md5 @post.stubs(:queue_delete_files) @replacement = FactoryBot.create(:post_replacement, post: @post, replacement_url: "", replacement_file: @new_file) end @@ -418,6 +420,53 @@ class UploadServiceTest < ActiveSupport::TestCase @post.reload end end + + should "preserve the old values" do + as_user { subject.process! } + assert_equal(1500, @replacement.image_width_was) + assert_equal(1000, @replacement.image_height_was) + assert_equal(2000, @replacement.file_size_was) + assert_equal("jpg", @replacement.file_ext_was) + assert_equal(@old_md5, @replacement.md5_was) + end + + should "record the new values" do + as_user { subject.process! } + assert_equal(500, @replacement.image_width) + assert_equal(335, @replacement.image_height) + assert_equal(28086, @replacement.file_size) + assert_equal("jpg", @replacement.file_ext) + assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @replacement.md5) + end + + should "correctly update the attributes" do + as_user { subject.process! } + assert_equal(500, @post.image_width) + assert_equal(335, @post.image_height) + assert_equal(28086, @post.file_size) + assert_equal("jpg", @post.file_ext) + assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @post.md5) + assert(File.exists?(@post.file.path)) + end + end + + context "a post with the same file" do + should "not raise a duplicate error" do + upload_file("test/files/test.png") do |file| + assert_nothing_raised do + as_user { @post.replace!(replacement_file: file, replacement_url: "") } + end + end + end + + should "not queue a deletion or log a comment" do + upload_file("test/files/test.png") do |file| + assert_no_difference(-> { @post.comments.count }) do + as_user { @post.replace!(replacement_file: file, replacement_url: "") } + @post.reload + end + end + end end end @@ -428,7 +477,7 @@ class UploadServiceTest < ActiveSupport::TestCase @user = FactoryBot.create(:user) end as_user do - @post = FactoryBot.create(:post) + @post = FactoryBot.create(:post, uploader_ip_addr: "127.0.0.2") @post.stubs(:queue_delete_files) @replacement = FactoryBot.create(:post_replacement, post: @post, replacement_url: @new_url) end @@ -436,6 +485,56 @@ class UploadServiceTest < ActiveSupport::TestCase subject { UploadService::Replacer.new(post: @post, replacement: @replacement) } + context "a post when given a final_source" do + should "change the source to the final_source" do + replacement_url = "http://data.tumblr.com/afed9f5b3c33c39dc8c967e262955de2/tumblr_orwwptNBCE1wsfqepo1_raw.png" + final_source = "https://noizave.tumblr.com/post/162094447052" + + as_user { @post.replace!(replacement_url: replacement_url, final_source: final_source) } + + assert_equal(final_source, @post.source) + end + end + + context "a post when replaced with a HTML source" do + should "record the image URL as the replacement URL, not the HTML source" do + skip "Twitter key not set" unless Danbooru.config.twitter_api_key + replacement_url = "https://twitter.com/nounproject/status/540944400767922176" + image_url = "https://pbs.twimg.com/media/B4HSEP5CUAA4xyu.png:orig" + as_user { @post.replace!(replacement_url: replacement_url) } + + assert_equal(image_url, @post.replacements.last.replacement_url) + end + end + + context "#undo!" do + setup do + @user = travel_to(1.month.ago) { FactoryBot.create(:user) } + as_user do + @post = FactoryBot.create(:post, source: "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png") + @post.stubs(:queue_delete_files) + @post.replace!(replacement_url: "https://danbooru.donmai.us/data/preview/download.png", tags: "-tag1 tag2") + end + + @replacement = @post.replacements.last + end + + should "update the attributes" do + as_user do + subject.undo! + end + + assert_equal("lowres tag2", @post.tag_string) + assert_equal(272, @post.image_width) + assert_equal(92, @post.image_height) + assert_equal(5969, @post.file_size) + assert_equal("png", @post.file_ext) + assert_equal("8f9327db2597fa57d2f42b4a6c5a9855", @post.md5) + assert_equal("8f9327db2597fa57d2f42b4a6c5a9855", Digest::MD5.file(@post.file).hexdigest) + assert_equal("https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", @post.source) + end + end + context "#process!" do should "create a new upload" do assert_difference(-> { Upload.count }) do @@ -469,6 +568,192 @@ class UploadServiceTest < ActiveSupport::TestCase @post.reload end end + + should "not change the post status or uploader" do + assert_no_changes(-> { {ip_addr: @post.uploader_ip_addr.to_s, uploader: @post.uploader_id, pending: @post.is_pending?} }) do + as_user { subject.process! } + @post.reload + end + end + + should "leave a system comment" do + as_user { subject.process! } + comment = @post.comments.last + assert_not_nil(comment) + assert_equal(User.system.id, comment.creator_id) + assert_match(/replaced this post/, comment.body) + end + end + + context "a post with a pixiv html source" do + setup do + Delayed::Worker.delay_jobs = true + end + + teardown do + Delayed::Worker.delay_jobs = false + end + + should "replace with the full size image" do + begin + as_user do + @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") + end + + assert_equal(80, @post.image_width) + assert_equal(82, @post.image_height) + assert_equal(16275, @post.file_size) + assert_equal("png", @post.file_ext) + assert_equal("4ceadc314938bc27f3574053a3e1459a", @post.md5) + assert_equal("4ceadc314938bc27f3574053a3e1459a", Digest::MD5.file(@post.file).hexdigest) + assert_equal("https://i.pximg.net/img-original/img/2017/04/04/08/54/15/62247350_p0.png", @post.replacements.last.replacement_url) + assert_equal("https://i.pximg.net/img-original/img/2017/04/04/08/54/15/62247350_p0.png", @post.source) + rescue Net::OpenTimeout + skip "Remote connection to Pixiv failed" + end + end + + should "delete the old files after thirty days" do + begin + @post.unstub(:queue_delete_files) + FileUtils.expects(:rm_f).times(3) + + as_user { @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") } + + travel_to((PostReplacement::DELETION_GRACE_PERIOD + 1).days.from_now) do + Delayed::Worker.new.work_off + end + rescue Net::OpenTimeout + skip "Remote connection to Pixiv failed" + end + end + end + + context "a post that is replaced by a ugoira" do + should "save the frame data" do + skip "ffmpeg not installed" unless check_ffmpeg + begin + as_user { @post.replace!(replacement_url: "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") } + @post.reload + + assert_equal(80, @post.image_width) + assert_equal(82, @post.image_height) + assert_equal(2804, @post.file_size) + assert_equal("zip", @post.file_ext) + assert_equal("cad1da177ef309bf40a117c17b8eecf5", @post.md5) + assert_equal("cad1da177ef309bf40a117c17b8eecf5", Digest::MD5.file(@post.file).hexdigest) + + assert_equal("https://i.pximg.net/img-zip-ugoira/img/2017/04/04/08/57/38/62247364_ugoira1920x1080.zip", @post.source) + assert_equal([{"delay"=>125, "file"=>"000001.jpg"}, {"delay"=>125,"file"=>"000002.jpg"}], @post.pixiv_ugoira_frame_data.data) + rescue Net::OpenTimeout + skip "Remote connection to Pixiv failed" + end + end + end + + context "a post that is replaced to another file then replaced back to the original file" do + setup do + Delayed::Worker.delay_jobs = true + end + + teardown do + Delayed::Worker.delay_jobs = false + end + + should "not delete the original files" do + begin + FileUtils.expects(:rm_f).never + + as_user do + @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") + @post.reload + @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") + @post.reload + Upload.destroy_all + @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") + end + + assert_nothing_raised { @post.file(:original) } + assert_nothing_raised { @post.file(:preview) } + + travel_to((PostReplacement::DELETION_GRACE_PERIOD + 1).days.from_now) do + Delayed::Worker.new.work_off + end + + assert_nothing_raised { @post.file(:original) } + assert_nothing_raised { @post.file(:preview) } + rescue Net::OpenTimeout + skip "Remote connection to Pixiv failed" + end + end + end + + context "two posts that have had their files swapped" do + setup do + Delayed::Worker.delay_jobs = true + + as_user do + @post1 = FactoryBot.create(:post) + @post2 = FactoryBot.create(:post) + end + end + + teardown do + Delayed::Worker.delay_jobs = false + end + + should "not delete the still active files" do + # swap the images between @post1 and @post2. + begin + as_user do + @post1.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") + @post2.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") + @post2.replace!(replacement_url: "https://www.google.com/intl/en_ALL/images/logo.gif") + Upload.destroy_all + @post1.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") + @post2.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") + end + + Timecop.travel(Time.now + PostReplacement::DELETION_GRACE_PERIOD + 1.day) do + Delayed::Worker.new.work_off + end + + assert_nothing_raised { @post1.file(:original) } + assert_nothing_raised { @post2.file(:original) } + rescue Net::OpenTimeout + skip "Remote connection to Pixiv failed" + end + end + end + + context "a post with notes" do + setup do + Note.any_instance.stubs(:merge_version?).returns(false) + + as_user do + @post.update(image_width: 160, image_height: 164) + @note = @post.notes.create(x: 80, y: 82, width: 80, height: 82, body: "test") + @note.reload + end + end + + should "rescale the notes" do + assert_equal([80, 82, 80, 82], [@note.x, @note.y, @note.width, @note.height]) + + begin + assert_difference(-> { @note.versions.count }) do + # replacement image is 80x82, so we're downscaling by 50% (160x164 -> 80x82). + as_user do + @post.replace!(replacement_url: "https://upload.wikimedia.org/wikipedia/commons/c/c5/Moraine_Lake_17092005.jpg") + end + @note.reload + end + + assert_equal([1024, 768, 1024, 768], [@note.x, @note.y, @note.width, @note.height]) + rescue Net::OpenTimeout + skip "Remote connection to Pixiv failed" + end + end end end end diff --git a/test/unit/post_replacement_test.rb b/test/unit/post_replacement_test.rb index 128407dba..5a20bbbf3 100644 --- a/test/unit/post_replacement_test.rb +++ b/test/unit/post_replacement_test.rb @@ -33,274 +33,5 @@ class PostReplacementTest < ActiveSupport::TestCase @post = upload.post end end - - context "a post from a generic source" do - setup do - @post.update(source: "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png") - @post.replace!(replacement_url: "https://www.google.com/intl/en_ALL/images/logo.gif", tags: "-tag1 tag2") - @replacement = @post.replacements.last - @upload = Upload.last - end - - context "that is then undone" do - setup do - Timecop.travel(Time.now + PostReplacement::DELETION_GRACE_PERIOD + 1.day) do - Delayed::Worker.new.work_off - end - - @replacement = @post.replacements.first - @replacement.undo! - @post.reload - end - - should "update the attributes" do - assert_equal("lowres tag2", @post.tag_string) - assert_equal(272, @post.image_width) - assert_equal(92, @post.image_height) - assert_equal(5969, @post.file_size) - assert_equal("png", @post.file_ext) - assert_equal("8f9327db2597fa57d2f42b4a6c5a9855", @post.md5) - assert_equal("8f9327db2597fa57d2f42b4a6c5a9855", Digest::MD5.file(@post.file).hexdigest) - assert_equal("https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", @post.source) - end - end - - should "create a post replacement record" do - binding.pry - assert_equal(@post.id, PostReplacement.last.post_id) - end - - should "record the old file metadata" do - assert_equal(500, @replacement.image_width_was) - assert_equal(335, @replacement.image_height_was) - assert_equal(28086, @replacement.file_size_was) - assert_equal("jpg", @replacement.file_ext_was) - assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @replacement.md5_was) - end - - should "record the new file metadata" do - assert_equal(276, @replacement.image_width) - assert_equal(110, @replacement.image_height) - assert_equal(8558, @replacement.file_size) - assert_equal("gif", @replacement.file_ext) - assert_equal("e80d1c59a673f560785784fb1ac10959", @replacement.md5) - end - - should "correctly update the attributes" do - assert_equal(@post.id, @upload.post.id) - assert_equal("completed", @upload.status) - - assert_equal(276, @post.image_width) - assert_equal(110, @post.image_height) - assert_equal(8558, @post.file_size) - assert_equal("gif", @post.file_ext) - assert_equal("e80d1c59a673f560785784fb1ac10959", @post.md5) - assert_equal("e80d1c59a673f560785784fb1ac10959", Digest::MD5.file(@post.file).hexdigest) - assert_equal("https://www.google.com/intl/en_ALL/images/logo.gif", @post.source) - end - - should "not change the post status or uploader" do - assert_equal("127.0.0.2", @post.uploader_ip_addr.to_s) - assert_equal(@uploader.id, @post.uploader_id) - assert_equal(false, @post.is_pending) - end - - should "leave a system comment" do - comment = @post.comments.last - - assert_not_nil(comment) - assert_equal(User.system.id, comment.creator_id) - assert_match(/replaced this post/, comment.body) - end - - should "not send an @mention to the replacer" do - assert_equal(0, @replacer.dmails.size) - end - end - - context "a post with notes" do - setup do - @post.update(image_width: 160, image_height: 164) - CurrentUser.scoped(@uploader, "127.0.0.1") do - @note = @post.notes.create(x: 80, y: 82, width: 80, height: 82, body: "test") - end - end - - should "rescale the notes" do - assert_equal([80, 82, 80, 82], [@note.x, @note.y, @note.width, @note.height]) - - begin - assert_difference("@replacer.note_versions.count") do - # replacement image is 80x82, so we're downscaling by 50% (160x164 -> 80x82). - @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") - @note.reload - end - - assert_equal([40, 41, 40, 41], [@note.x, @note.y, @note.width, @note.height]) - rescue Net::OpenTimeout - skip "Remote connection to Pixiv failed" - end - end - end - - context "a post with a pixiv html source" do - should "replace with the full size image" do - begin - @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") - - assert_equal(80, @post.image_width) - assert_equal(82, @post.image_height) - assert_equal(16275, @post.file_size) - assert_equal("png", @post.file_ext) - assert_equal("4ceadc314938bc27f3574053a3e1459a", @post.md5) - assert_equal("4ceadc314938bc27f3574053a3e1459a", Digest::MD5.file(@post.file).hexdigest) - assert_equal("https://i.pximg.net/img-original/img/2017/04/04/08/54/15/62247350_p0.png", @post.source) - assert_equal("https://i.pximg.net/img-original/img/2017/04/04/08/54/15/62247350_p0.png", @post.replacements.last.replacement_url) - rescue Net::OpenTimeout - skip "Remote connection to Pixiv failed" - end - end - - should "delete the old files after thirty days" do - begin - old_file_path, old_preview_file_path = @post.file(:original).path, @post.file(:preview).path - @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") - - assert(File.exists?(old_file_path)) - assert(File.exists?(old_preview_file_path)) - - Timecop.travel(Time.now + PostReplacement::DELETION_GRACE_PERIOD + 1.day) do - Delayed::Worker.new.work_off - end - - assert_not(File.exists?(old_file_path)) - assert_not(File.exists?(old_preview_file_path)) - rescue Net::OpenTimeout - skip "Remote connection to Pixiv failed" - end - end - end - - context "a post that is replaced by a ugoira" do - should "save the frame data" do - skip "ffmpeg not installed" unless check_ffmpeg - begin - @post.replace!(replacement_url: "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") - @post.reload - - assert_equal(80, @post.image_width) - assert_equal(82, @post.image_height) - assert_equal(2804, @post.file_size) - assert_equal("zip", @post.file_ext) - assert_equal("cad1da177ef309bf40a117c17b8eecf5", @post.md5) - assert_equal("cad1da177ef309bf40a117c17b8eecf5", Digest::MD5.file(@post.file).hexdigest) - - assert_equal("https://i.pximg.net/img-zip-ugoira/img/2017/04/04/08/57/38/62247364_ugoira1920x1080.zip", @post.source) - assert_equal([{"delay"=>125, "file"=>"000001.jpg"}, {"delay"=>125,"file"=>"000002.jpg"}], @post.pixiv_ugoira_frame_data.data) - rescue Net::OpenTimeout - skip "Remote connection to Pixiv failed" - end - end - end - - context "a post that is replaced to another file then replaced back to the original file" do - should "not delete the original files" do - skip "ffmpeg is not installed" unless check_ffmpeg - - begin - @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") - @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") - @post.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") - - assert_nothing_raised { @post.file(:original) } - assert_nothing_raised { @post.file(:preview) } - - Timecop.travel(Time.now + PostReplacement::DELETION_GRACE_PERIOD + 1.day) do - Delayed::Worker.new.work_off - end - - assert_nothing_raised { @post.file(:original) } - assert_nothing_raised { @post.file(:preview) } - rescue Net::OpenTimeout - skip "Remote connection to Pixiv failed" - end - end - end - - context "two posts that have had their files swapped" do - should "not delete the still active files" do - skip "ffmpeg is not installed" unless check_ffmpeg - - @post1 = FactoryBot.create(:post) - @post2 = FactoryBot.create(:post) - - # swap the images between @post1 and @post2. - begin - @post1.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") - @post2.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") - @post2.replace!(replacement_url: "https://www.google.com/intl/en_ALL/images/logo.gif") - @post1.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") - @post2.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350") - - Timecop.travel(Time.now + PostReplacement::DELETION_GRACE_PERIOD + 1.day) do - Delayed::Worker.new.work_off - end - - assert_nothing_raised { @post1.file(:original) } - assert_nothing_raised { @post2.file(:original) } - rescue Net::OpenTimeout - skip "Remote connection to Pixiv failed" - end - end - end - - context "a post with an uploaded file" do - should "work" do - upload_file("test/files/test.png") do |file| - @post.replace!(replacement_file: file, replacement_url: "") - assert_equal(@post.md5, Digest::MD5.file(file.tempfile).hexdigest) - assert_equal("file://test.png", @post.replacements.last.replacement_url) - end - end - end - - context "a post when given a final_source" do - should "change the source to the final_source" do - replacement_url = "http://data.tumblr.com/afed9f5b3c33c39dc8c967e262955de2/tumblr_orwwptNBCE1wsfqepo1_raw.png" - final_source = "https://noizave.tumblr.com/post/162094447052" - @post.replace!(replacement_url: replacement_url, final_source: final_source) - - assert_equal(final_source, @post.source) - end - end - - context "a post when replaced with a HTML source" do - should "record the image URL as the replacement URL, not the HTML source" do - skip "Twitter key not set" unless Danbooru.config.twitter_api_key - replacement_url = "https://twitter.com/nounproject/status/540944400767922176" - image_url = "https://pbs.twimg.com/media/B4HSEP5CUAA4xyu.png:orig" - @post.replace!(replacement_url: replacement_url) - - assert_equal(image_url, @post.replacements.last.replacement_url) - end - end - - context "a post with the same file" do - should "not raise a duplicate error" do - upload_file("test/files/test.jpg") do |file| - assert_nothing_raised do - @post.replace!(replacement_file: file, replacement_url: "") - end - end - end - - should "not queue a deletion or log a comment" do - upload_file("test/files/test.jpg") do |file| - assert_no_difference(["@post.comments.count"]) do - @post.replace!(replacement_file: file, replacement_url: "") - end - end - end - end end end diff --git a/test/unit/post_test.rb b/test/unit/post_test.rb index 30dcb0110..f894f254e 100644 --- a/test/unit/post_test.rb +++ b/test/unit/post_test.rb @@ -28,8 +28,7 @@ class PostTest < ActiveSupport::TestCase context "Deletion:" do context "Expunging a post" do setup do - @upload = FactoryBot.create(:jpg_upload) - @upload.process! + @upload = UploadService.new(FactoryBot.attributes_for(:jpg_upload)).start! @post = @upload.post Favorite.add(post: @post, user: @user) end @@ -2677,4 +2676,19 @@ class PostTest < ActiveSupport::TestCase end end end + + context "#replace!" do + subject { @post.replace!(tags: "something", replacement_url: "https://danbooru.donmai.us/data/preview/download.png") } + + setup do + @post = FactoryBot.create(:post) + @post.stubs(:queue_delete_files) + end + + should "update the post" do + assert_changes(-> { @post.md5 }) do + subject + end + end + end end