diff --git a/README b/README.md similarity index 82% rename from README rename to README.md index 27e5a5a74..8e5948adb 100644 --- a/README +++ b/README.md @@ -1,23 +1,23 @@ -=== Installation +### Installation It is recommended that you install Danbooru on a Debian-based system -since most of the required packages are available on APT. Danbooru +since most of the required packages are available on APT. Danbooru has been successfully installed on Fedora, CentOS, FreeBSD, and OS X. The INSTALL.debian install script is straightforward and should be -simple to adapt for other platforms. If you want something similar to -Danbooru that is easier to install, try Shimmie -(http://code.shishnet.org/shimmie2/). Shimmie uses PHP and MySQL and -should be straightforward to install on most hosts. +simple to adapt for other platforms. For best performance, you will need at least 256MB of RAM for PostgreSQL and Rails. The memory requirement will grow as your -database gets bigger. +database gets bigger. + +On production Danbooru uses PostgreSQL 9.4, but any 9.x release should +work. Use your operating system's package management system whenever possible. This will simplify the process of installing init scripts, which will not always happen when compiling from source. -=== Troubleshooting +### Troubleshooting These instructions won't work for everyone. If your setup is not working, here are the steps I usually recommend to people: @@ -37,7 +37,7 @@ debug your Nginx configuration file. 4) Check all log files. -=== IQDB Integration +### IQDB Integration In order to enable IQDB integration, you must compile and run the IQDB server somewhere (preferably on the local server). There are two Danbooru configuration settings that you must then set: iqdb_hostname_and_port and iqdb_file. diff --git a/app/assets/javascripts/uploads.js b/app/assets/javascripts/uploads.js index 81b3a1798..d08b7bb0f 100644 --- a/app/assets/javascripts/uploads.js +++ b/app/assets/javascripts/uploads.js @@ -46,7 +46,11 @@ Danbooru.Upload.initialize_info_bookmarklet = function() { $("#source-info ul").hide(); $("#fetch-data-bookmarklet").click(function(e) { - $.get(e.target.href).success(Danbooru.Upload.fill_source_info); + var xhr = $.get(e.target.href); + xhr.success(Danbooru.Upload.fill_source_info); + xhr.fail(function(data) { + $("#source-info span#loading-data").html("Error: " + data.responseJSON["message"]) + }); e.preventDefault(); }); $("#fetch-data-bookmarklet").trigger("click"); @@ -63,7 +67,11 @@ Danbooru.error("Error: Source is not a URL"); } else { $("#source-info span#loading-data").show(); - $.get("/source.json?url=" + encodeURIComponent(source)).success(Danbooru.Upload.fill_source_info); + var xhr = $.get("/source.json?url=" + encodeURIComponent(source)); + xhr.success(Danbooru.Upload.fill_source_info); + xhr.fail(function(data) { + $("#source-info span#loading-data").html("Error: " + data.responseJSON["message"]) + }); } e.preventDefault(); }); diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb index b098ac5f7..7df7cd2e3 100644 --- a/app/controllers/sources_controller.rb +++ b/app/controllers/sources_controller.rb @@ -12,4 +12,14 @@ class SourcesController < ApplicationController end end end + +private + + def rescue_exception(exception) + respond_with do |format| + format.json do + render :json => {:message => exception.to_s}, :status => :error + end + end + end end diff --git a/app/models/post.rb b/app/models/post.rb index 855f40550..a8a2eac5c 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -20,6 +20,7 @@ class Post < ActiveRecord::Base before_save :update_tag_post_counts before_save :set_tag_counts before_save :set_pool_category_pseudo_tags + before_create :autoban before_validation :strip_source before_validation :initialize_uploader, :on => :create before_validation :parse_pixiv_id @@ -290,6 +291,12 @@ class Post < ActiveRecord::Base def disapproved_by?(user) PostDisapproval.where(:user_id => user.id, :post_id => id).exists? end + + def autoban + if has_tag?("banned_artist") + self.is_banned = true + end + end end module PresenterMethods @@ -1490,7 +1497,13 @@ class Post < ActiveRecord::Base def update_iqdb_async if Danbooru.config.iqdb_hostname_and_port && File.exists?(preview_file_path) Danbooru.config.all_server_hosts.each do |host| - delay(:queue => host).update_iqdb + if has_tag?("ugoira") + run_at = 10.seconds.from_now + else + run_at = Time.from_now + end + + delay(:queue => host, :run_at => run_at).update_iqdb end end end @@ -1558,6 +1571,7 @@ class Post < ActiveRecord::Base def reload(options = nil) super reset_tag_array_cache + @pools = nil @tag_categories = nil @typed_tags = nil self diff --git a/app/models/tag.rb b/app/models/tag.rb index 429d190ac..7ccd92ca4 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -192,6 +192,11 @@ class Tag < ActiveRecord::Base if category category_id = categories.value_for(category) + # in case a category change hasn't propagated to this server yet, + # force an update the local cache. This may get overwritten in the + # next few lines if the category is changed. + tag.update_category_cache + if category_id != tag.category && !tag.is_locked? && (CurrentUser.is_builder? || tag.post_count <= 50) tag.update_column(:category, category_id) tag.update_category_cache_for_all diff --git a/app/models/tag_alias.rb b/app/models/tag_alias.rb index bf6703c1a..3e2841ca7 100644 --- a/app/models/tag_alias.rb +++ b/app/models/tag_alias.rb @@ -198,11 +198,15 @@ class TagAlias < ActiveRecord::Base def rename_wiki_and_artist antecedent_wiki = WikiPage.titled(antecedent_name).first - if antecedent_wiki.present? && WikiPage.titled(consequent_name).blank? - CurrentUser.scoped(creator, creator_ip_addr) do - antecedent_wiki.update_attributes( - :title => consequent_name - ) + if antecedent_wiki.present? + if WikiPage.titled(consequent_name).blank? + CurrentUser.scoped(creator, creator_ip_addr) do + antecedent_wiki.update_attributes( + :title => consequent_name + ) + end + else + update_forum_topic_for_wiki_conflict end end @@ -249,6 +253,16 @@ class TagAlias < ActiveRecord::Base end end + def update_forum_topic_for_wiki_conflict + if forum_topic + CurrentUser.scoped(User.admins.first, "127.0.0.1") do + forum_topic.posts.create( + :body => "The tag alias [[#{antecedent_name}]] -> [[#{consequent_name}]] has conflicting wiki pages. [[#{consequent_name}]] should be updated to include information from [[#{antecedent_name}]] if necessary." + ) + end + end + end + def reject! update_column(:status, "deleted") clear_all_cache diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index 267dff155..73e0d4a07 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -149,7 +149,7 @@ - + <% if @post.twitter_card_supported? %> diff --git a/test/factories/tag.rb b/test/factories/tag.rb index f0b988acf..24f5dace8 100644 --- a/test/factories/tag.rb +++ b/test/factories/tag.rb @@ -1,6 +1,6 @@ FactoryGirl.define do factory(:tag) do - name {Faker::Name.first_name.downcase} + name {"#{Faker::Name.first_name.downcase}#{rand(1000)}"} post_count 0 category {Tag.categories.general} related_tags "" diff --git a/test/fixtures/vcr_cassettes/ugoira-converter.yml b/test/fixtures/vcr_cassettes/ugoira-converter.yml index 46f9c0d57..2f5589ccc 100644 --- a/test/fixtures/vcr_cassettes/ugoira-converter.yml +++ b/test/fixtures/vcr_cassettes/ugoira-converter.yml @@ -749,7 +749,7 @@ http_interactions: recorded_at: Wed, 22 Oct 2014 23:29:57 GMT - request: method: get - uri: http://i1.pixiv.net/img-zip-ugoira/img/2014/10/05/23/42/23/46378654_ugoira1920x1080.zip + uri: http://i3.pixiv.net/img-zip-ugoira/img/2014/10/05/23/42/23/46378654_ugoira1920x1080.zip body: encoding: US-ASCII string: '' diff --git a/test/functional/bulk_update_requests_controller_test.rb b/test/functional/bulk_update_requests_controller_test.rb index 74d1357dd..9c64c2d43 100644 --- a/test/functional/bulk_update_requests_controller_test.rb +++ b/test/functional/bulk_update_requests_controller_test.rb @@ -44,9 +44,9 @@ class BulkUpdateRequestsControllerTest < ActionController::TestCase context "for the creator" do should "succeed" do - assert_difference("BulkUpdateRequest.count", -1) do - delete :destroy, {:id => @bulk_update_request.id}, {:user_id => @user.id} - end + delete :destroy, {:id => @bulk_update_request.id}, {:user_id => @user.id} + @bulk_update_request.reload + assert_equal("rejected", @bulk_update_request.status) end end @@ -64,9 +64,9 @@ class BulkUpdateRequestsControllerTest < ActionController::TestCase context "for an admin" do should "succeed" do - assert_difference("BulkUpdateRequest.count", -1) do - delete :destroy, {:id => @bulk_update_request.id}, {:user_id => @admin.id} - end + delete :destroy, {:id => @bulk_update_request.id}, {:user_id => @admin.id} + @bulk_update_request.reload + assert_equal("rejected", @bulk_update_request.status) end end end diff --git a/test/functional/tag_aliases_controller_test.rb b/test/functional/tag_aliases_controller_test.rb index c488220ce..30c99ce70 100644 --- a/test/functional/tag_aliases_controller_test.rb +++ b/test/functional/tag_aliases_controller_test.rb @@ -72,14 +72,6 @@ class TagAliasesControllerTest < ActionController::TestCase end end - context "create action" do - should "create a tag alias" do - assert_difference("TagAlias.count", 1) do - post :create, {:tag_alias => {:antecedent_name => "xxx", :consequent_name => "yyy"}}, {:user_id => @user.id} - end - end - end - context "destroy action" do setup do @tag_alias = FactoryGirl.create(:tag_alias) diff --git a/test/functional/tag_implications_controller_test.rb b/test/functional/tag_implications_controller_test.rb index 15db44959..8fa68f1d7 100644 --- a/test/functional/tag_implications_controller_test.rb +++ b/test/functional/tag_implications_controller_test.rb @@ -75,14 +75,6 @@ class TagImplicationsControllerTest < ActionController::TestCase end end - context "create action" do - should "create a tag implication" do - assert_difference("TagImplication.count", 1) do - post :create, {:tag_implication => {:antecedent_name => "xxx", :consequent_name => "yyy"}}, {:user_id => @user.id} - end - end - end - context "destroy action" do setup do CurrentUser.scoped(@user, "127.0.0.1") do diff --git a/test/unit/downloads/deviant_art_test.rb b/test/unit/downloads/deviant_art_test.rb index 3d7f7f37f..bf50c7e56 100644 --- a/test/unit/downloads/deviant_art_test.rb +++ b/test/unit/downloads/deviant_art_test.rb @@ -7,13 +7,13 @@ module Downloads @source = "http://mochikko.deviantart.com/art/RESOLUTION-339610451" @tempfile = Tempfile.new("danbooru-test") @download = Downloads::File.new(@source, @tempfile.path) - VCR.use_cassette("download-deviant-art-html", :record => :new_episodes) do + VCR.use_cassette("download-deviant-art-html", :record => :none) do @download.download! end end should "set the direct image link as the source" do - assert_equal("http://www.deviantart.com/download/339610451/resolution_by_mochikko-d5m713n.jpg?token=f828643e6e86a658e80f362745a0b20e20880fc6&ts=1414021578", @download.source) + assert_equal("http://fc03.deviantart.net/fs71/f/2012/330/e/7/resolution_by_mochikko-d5m713n.jpg", @download.source) end should "work" do diff --git a/test/unit/downloads/pixiv_test.rb b/test/unit/downloads/pixiv_test.rb index 972623ce7..948055273 100644 --- a/test/unit/downloads/pixiv_test.rb +++ b/test/unit/downloads/pixiv_test.rb @@ -231,8 +231,8 @@ module Downloads should "download the full size image instead of the thumbnail" do assert_rewritten(@p0_full_size_image_3, @p0_large_thumbnail, "rewrite-pixiv-new-manga-p0-large-thumbnail") assert_rewritten(@p1_full_size_image_3, @p1_large_thumbnail, "rewrite-pixiv-new-manga-p1-large-thumbnail") - assert_downloaded(@p0_file_size, @p0_large_thumbnail, "download-pixiv-new-manga-p0-large-thumbnail", :all) - assert_downloaded(@p1_file_size, @p1_large_thumbnail, "download-pixiv-new-manga-p1-large-thumbnail", :all) + assert_downloaded(@p0_file_size, @p0_large_thumbnail, "download-pixiv-new-manga-p0-large-thumbnail") + assert_downloaded(@p1_file_size, @p1_large_thumbnail, "download-pixiv-new-manga-p1-large-thumbnail") end end diff --git a/test/unit/pool_test.rb b/test/unit/pool_test.rb index 4f79e8c6f..9e0df05df 100644 --- a/test/unit/pool_test.rb +++ b/test/unit/pool_test.rb @@ -87,7 +87,7 @@ class PoolTest < ActiveSupport::TestCase should "update any new posts that were added" do @p1.reload - assert_equal("pool:#{@pool.id}", @p1.pool_string) + assert_equal("pool:#{@pool.id} pool:series", @p1.pool_string) end end diff --git a/test/unit/post_test.rb b/test/unit/post_test.rb index 5f73a1c44..bfe80856a 100644 --- a/test/unit/post_test.rb +++ b/test/unit/post_test.rb @@ -33,18 +33,23 @@ class PostTest < ActiveSupport::TestCase end end - should "remove the post from all pools" do - pool = FactoryGirl.create(:pool) - pool.add!(@post) - @post.expunge! - pool.reload - assert_equal("", pool.post_ids) - end + context "that belongs to a pool" do + setup do + @pool = FactoryGirl.create(:pool) + @pool.add!(@post) + @post.reload + @post.expunge! + end - should "destroy the record" do - @post.expunge! - assert_equal([], @post.errors.full_messages) - assert_equal(0, Post.where("id = ?", @post.id).count) + should "remove the post from all pools" do + @pool.reload + assert_equal("", @pool.post_ids) + end + + should "destroy the record" do + assert_equal([], @post.errors.full_messages) + assert_equal(0, Post.where("id = ?", @post.id).count) + end end end @@ -425,6 +430,18 @@ class PostTest < ActiveSupport::TestCase @post = FactoryGirl.create(:post) end + context "with a banned artist" do + setup do + @artist = FactoryGirl.create(:artist) + @artist.ban! + @post = FactoryGirl.create(:post, :tag_string => @artist.name) + end + + should "ban the post" do + assert_equal(true, @post.is_banned?) + end + end + context "with an artist tag that is then changed to copyright" do setup do CurrentUser.user = FactoryGirl.create(:builder_user) diff --git a/test/unit/tag_alias_test.rb b/test/unit/tag_alias_test.rb index 9a6f43649..6d945dbd3 100644 --- a/test/unit/tag_alias_test.rb +++ b/test/unit/tag_alias_test.rb @@ -99,6 +99,19 @@ class TagAliasTest < ActiveSupport::TestCase @alias = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb", :forum_topic => @topic) end + context "and conflicting wiki pages" do + setup do + @wiki1 = FactoryGirl.create(:wiki_page, :title => "aaa") + @wiki2 = FactoryGirl.create(:wiki_page, :title => "bbb") + end + + should "update the topic when processed" do + assert_difference("ForumPost.count") do + @alias.rename_wiki_and_artist + end + end + end + should "update the topic when processed" do assert_difference("ForumPost.count") do @alias.process! diff --git a/test/unit/upload_test.rb b/test/unit/upload_test.rb index f83f13998..d6dd3dc47 100644 --- a/test/unit/upload_test.rb +++ b/test/unit/upload_test.rb @@ -255,13 +255,14 @@ class UploadTest < ActiveSupport::TestCase VCR.use_cassette("ugoira-converter", :record => :none) do assert_difference(["Post.count", "PixivUgoiraFrameData.count"]) do @upload.process! + assert_equal([], @upload.errors.full_messages) end post = Post.last assert_not_nil(post.pixiv_ugoira_frame_data) assert_equal("0d94800c4b520bf3d8adda08f95d31e2", post.md5) assert_equal(60, post.image_width) assert_equal(60, post.image_height) - assert_equal("http://i1.pixiv.net/img-zip-ugoira/img/2014/10/05/23/42/23/46378654_ugoira1920x1080.zip", post.source) + assert_equal("http://i3.pixiv.net/img-zip-ugoira/img/2014/10/05/23/42/23/46378654_ugoira1920x1080.zip", post.source) assert_operator(File.size(post.large_file_path), :>, 0) assert_operator(File.size(post.preview_file_path), :>, 0) end