Merge branch 'master' into fix-3278

This commit is contained in:
Albert Yi
2017-12-13 14:30:08 -08:00
committed by GitHub
27 changed files with 312 additions and 79 deletions

View File

@@ -64,8 +64,8 @@ GEM
minitest (~> 5.1) minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4) thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1) tzinfo (~> 1.1)
addressable (2.5.1) addressable (2.5.2)
public_suffix (~> 2.0, >= 2.0.2) public_suffix (>= 2.0.2, < 4.0)
arel (6.0.4) arel (6.0.4)
awesome_print (1.7.0) awesome_print (1.7.0)
aws-sdk (2.7.4) aws-sdk (2.7.4)
@@ -108,7 +108,7 @@ GEM
cityhash (0.8.1) cityhash (0.8.1)
coderay (1.1.1) coderay (1.1.1)
colorize (0.7.7) colorize (0.7.7)
crack (0.4.2) crack (0.4.3)
safe_yaml (~> 1.0.0) safe_yaml (~> 1.0.0)
crass (1.0.2) crass (1.0.2)
daemons (1.2.3) daemons (1.2.3)
@@ -156,6 +156,7 @@ GEM
multi_json (~> 1.11) multi_json (~> 1.11)
os (~> 0.9) os (~> 0.9)
signet (~> 0.7) signet (~> 0.7)
hashdiff (0.3.7)
highline (1.7.8) highline (1.7.8)
hike (1.2.3) hike (1.2.3)
http (2.2.2) http (2.2.2)
@@ -246,7 +247,7 @@ GEM
pry-byebug (3.4.2) pry-byebug (3.4.2)
byebug (~> 9.0) byebug (~> 9.0)
pry (~> 0.10) pry (~> 0.10)
public_suffix (2.0.5) public_suffix (3.0.1)
rack (1.6.5) rack (1.6.5)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
@@ -385,9 +386,10 @@ GEM
unicorn-worker-killer (0.4.4) unicorn-worker-killer (0.4.4)
get_process_mem (~> 0) get_process_mem (~> 0)
unicorn (>= 4, < 6) unicorn (>= 4, < 6)
webmock (1.21.0) webmock (3.1.1)
addressable (>= 2.3.6) addressable (>= 2.3.6)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff
webrobots (0.1.2) webrobots (0.1.2)
whenever (0.9.7) whenever (0.9.7)
chronic (>= 0.6.3) chronic (>= 0.6.3)

View File

@@ -110,6 +110,10 @@ private
def respond_with_post_after_update(post) def respond_with_post_after_update(post)
respond_with(post) do |format| respond_with(post) do |format|
format.html do format.html do
if post.warnings.any?
flash[:notice] = post.warnings.full_messages.join(".\n \n")
end
if post.errors.any? if post.errors.any?
@error_message = post.errors.full_messages.join("; ") @error_message = post.errors.full_messages.join("; ")
render :template => "static/error", :status => 500 render :template => "static/error", :status => 500

View File

@@ -53,7 +53,12 @@ class UploadsController < ApplicationController
def create def create
@upload = Upload.create(params[:upload].merge(:server => Socket.gethostname)) @upload = Upload.create(params[:upload].merge(:server => Socket.gethostname))
@upload.process! if @upload.errors.empty?
if @upload.errors.empty?
post = @upload.process!
flash[:notice] = post.warnings.full_messages.join(".\n \n") if post.present? && post.warnings.any?
end
save_recent_tags save_recent_tags
respond_with(@upload) respond_with(@upload)
end end

View File

@@ -18,11 +18,12 @@ module Moderator
post.update_attributes(:tag_string => tags) post.update_attributes(:tag_string => tags)
end end
tags = Tag.scan_tags(antecedent, :strip_metatags => true)
conds = tags.map {|x| "query like ?"}.join(" AND ")
conds = [conds, *tags.map {|x| "%#{x.to_escaped_for_sql_like}%"}]
if SavedSearch.enabled? if SavedSearch.enabled?
SavedSearch.where(*conds).find_each do |ss| tags = Tag.scan_tags(antecedent, :strip_metatags => true)
# https://www.postgresql.org/docs/current/static/functions-array.html
saved_searches = SavedSearch.where("string_to_array(query, ' ') @> ARRAY[?]", tags)
saved_searches.find_each do |ss|
ss.query = (ss.query.split - tags + [consequent]).uniq.join(" ") ss.query = (ss.query.split - tags + [consequent]).uniq.join(" ")
ss.save ss.save
end end

View File

@@ -87,11 +87,15 @@ module PostSets
end end
def banned_posts def banned_posts
posts.select(&:is_banned?) posts.select { |p| p.banblocked? }
end end
def censored_posts def censored_posts
hidden_posts - banned_posts posts.select { |p| p.levelblocked? && !p.banblocked? }
end
def safe_posts
posts.select { |p| p.safeblocked? && !p.levelblocked? && !p.banblocked? }
end end
def use_sequential_paginator? def use_sequential_paginator?

View File

@@ -84,5 +84,9 @@ class ApplicationRecord < ActiveRecord::Base
end end
end end
def warnings
@warnings ||= ActiveModel::Errors.new(self)
end
include ApiMethods include ApiMethods
end end

View File

@@ -182,8 +182,8 @@ class Comment < ApplicationRecord
end end
def initialize_updater def initialize_updater
self.updater_id ||= CurrentUser.user.id self.updater_id = CurrentUser.user.id
self.updater_ip_addr ||= CurrentUser.ip_addr self.updater_ip_addr = CurrentUser.ip_addr
end end
def creator_name def creator_name

View File

@@ -30,6 +30,12 @@ class Dmail < ApplicationRecord
def creator_ip_addr_str def creator_ip_addr_str
creator_ip_addr.to_s creator_ip_addr.to_s
end end
def spam?(sender = CurrentUser.user)
return false if Danbooru.config.rakismet_key.blank?
return false if sender.is_gold?
super()
end
end end
module AddressMethods module AddressMethods
@@ -52,12 +58,7 @@ class Dmail < ApplicationRecord
def initialize_attributes def initialize_attributes
self.from_id ||= CurrentUser.id self.from_id ||= CurrentUser.id
self.creator_ip_addr ||= CurrentUser.ip_addr self.creator_ip_addr ||= CurrentUser.ip_addr
if CurrentUser.is_gold? self.is_spam = spam?(CurrentUser.user)
self.is_spam = false
else
self.is_spam = spam?
end
true
end end
end end

View File

@@ -173,11 +173,13 @@ class FavoriteGroup < ApplicationRecord
end end
def add!(post_id) def add!(post_id)
post_id = post_id.id if post_id.is_a?(Post) with_lock do
return if contains?(post_id) post_id = post_id.id if post_id.is_a?(Post)
return if contains?(post_id)
clear_post_id_array clear_post_id_array
update_attributes(:post_ids => add_number_to_string(post_id, post_ids)) update_attributes(:post_ids => add_number_to_string(post_id, post_ids))
end
end end
def self.purge_post(post_id) def self.purge_post(post_id)
@@ -188,11 +190,13 @@ class FavoriteGroup < ApplicationRecord
end end
def remove!(post_id) def remove!(post_id)
post_id = post_id.id if post_id.is_a?(Post) with_lock do
return unless contains?(post_id) post_id = post_id.id if post_id.is_a?(Post)
return unless contains?(post_id)
clear_post_id_array clear_post_id_array
update_attributes(:post_ids => remove_number_from_string(post_id, post_ids)) update_attributes(:post_ids => remove_number_from_string(post_id, post_ids))
end
end end
def add_number_to_string(number, string) def add_number_to_string(number, string)

View File

@@ -18,6 +18,10 @@ class Post < ApplicationRecord
validates_uniqueness_of :md5, :on => :create validates_uniqueness_of :md5, :on => :create
validates_inclusion_of :rating, in: %w(s q e), message: "rating must be s, q, or e" validates_inclusion_of :rating, in: %w(s q e), message: "rating must be s, q, or e"
validate :tag_names_are_valid validate :tag_names_are_valid
validate :added_tags_are_valid
validate :removed_tags_are_valid
validate :has_artist_tag
validate :has_copyright_tag
validate :post_is_not_its_own_parent validate :post_is_not_its_own_parent
validate :updater_can_change_rating validate :updater_can_change_rating
before_save :update_tag_post_counts before_save :update_tag_post_counts
@@ -196,6 +200,14 @@ class Post < ApplicationRecord
"http://#{Danbooru.config.hostname}#{preview_file_url}" "http://#{Danbooru.config.hostname}#{preview_file_url}"
end end
def open_graph_image_url
if is_image? && has_large?
"http://#{Danbooru.config.hostname}#{large_file_url}"
else
complete_preview_file_url
end
end
def file_url_for(user) def file_url_for(user)
if CurrentUser.mobile_mode? if CurrentUser.mobile_mode?
large_file_url large_file_url
@@ -592,6 +604,18 @@ class Post < ApplicationRecord
@tag_array_was ||= Tag.scan_tags(tag_string_was) @tag_array_was ||= Tag.scan_tags(tag_string_was)
end end
def tags
Tag.where(name: tag_array)
end
def tags_was
Tag.where(name: tag_array_was)
end
def added_tags
tags - tags_was
end
def decrement_tag_post_counts def decrement_tag_post_counts
Tag.where(:name => tag_array).update_all("post_count = post_count - 1") if tag_array.any? Tag.where(:name => tag_array).update_all("post_count = post_count - 1") if tag_array.any?
end end
@@ -633,12 +657,18 @@ class Post < ApplicationRecord
end end
def merge_old_changes def merge_old_changes
@removed_tags = []
if old_tag_string if old_tag_string
# If someone else committed changes to this post before we did, # If someone else committed changes to this post before we did,
# then try to merge the tag changes together. # then try to merge the tag changes together.
current_tags = tag_array_was() current_tags = tag_array_was()
new_tags = tag_array() new_tags = tag_array()
old_tags = Tag.scan_tags(old_tag_string) old_tags = Tag.scan_tags(old_tag_string)
kept_tags = current_tags & new_tags
@removed_tags = old_tags - kept_tags
set_tag_string(((current_tags + new_tags) - old_tags + (current_tags & new_tags)).uniq.sort.join(" ")) set_tag_string(((current_tags + new_tags) - old_tags + (current_tags & new_tags)).uniq.sort.join(" "))
end end
@@ -687,10 +717,10 @@ class Post < ApplicationRecord
end end
def remove_negated_tags(tags) def remove_negated_tags(tags)
negated_tags, tags = tags.partition {|x| x =~ /\A-/i} @negated_tags, tags = tags.partition {|x| x =~ /\A-/i}
negated_tags = negated_tags.map {|x| x[1..-1]} @negated_tags = @negated_tags.map {|x| x[1..-1]}
negated_tags = TagAlias.to_aliased(negated_tags) @negated_tags = TagAlias.to_aliased(@negated_tags)
return tags - negated_tags return tags - @negated_tags
end end
def add_automatic_tags(tags) def add_automatic_tags(tags)
@@ -1136,6 +1166,7 @@ class Post < ApplicationRecord
module CountMethods module CountMethods
def fast_count(tags = "", options = {}) def fast_count(tags = "", options = {})
tags = tags.to_s
tags += " rating:s" if CurrentUser.safe_mode? tags += " rating:s" if CurrentUser.safe_mode?
tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && tags !~ /(?:^|\s)(?:-)?status:.+/ tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && tags !~ /(?:^|\s)(?:-)?status:.+/
tags = Tag.normalize_query(tags) tags = Tag.normalize_query(tags)
@@ -1368,18 +1399,15 @@ class Post < ApplicationRecord
Post.transaction do Post.transaction do
flag!(reason, is_deletion: true) flag!(reason, is_deletion: true)
self.is_deleted = true update({
self.is_pending = false is_deleted: true,
self.is_flagged = false is_pending: false,
self.is_banned = true if options[:ban] || has_tag?("banned_artist") is_flagged: false,
update_columns( is_banned: is_banned || options[:ban] || has_tag?("banned_artist")
:is_deleted => is_deleted, }, without_protection: true)
:is_pending => is_pending,
:is_flagged => is_flagged, # XXX This must happen *after* the `is_deleted` flag is set to true (issue #3419).
:is_banned => is_banned
)
give_favorites_to_parent if options[:move_favorites] give_favorites_to_parent if options[:move_favorites]
update_parent_on_save
unless options[:without_mod_action] unless options[:without_mod_action]
ModAction.log("deleted post ##{id}, reason: #{reason}") ModAction.log("deleted post ##{id}, reason: #{reason}")
@@ -1707,6 +1735,53 @@ class Post < ApplicationRecord
end end
end end
end end
def added_tags_are_valid
new_tags = added_tags.select { |t| t.post_count <= 1 }
new_general_tags = new_tags.select { |t| t.category == Tag.categories.general }
new_artist_tags = new_tags.select { |t| t.category == Tag.categories.artist }
if new_general_tags.present?
n = new_general_tags.size
tag_wiki_links = new_general_tags.map { |tag| "[[#{tag.name}]]" }
self.warnings[:base] << "Created #{n} new #{n == 1 ? "tag" : "tags"}: #{tag_wiki_links.join(", ")}"
end
new_artist_tags.each do |tag|
if tag.artist.blank?
self.warnings[:base] << "Artist [[#{tag.name}]] requires an artist entry. \"Create new artist entry\":[/artists/new?name=#{CGI::escape(tag.name)}]"
end
end
end
def removed_tags_are_valid
attempted_removed_tags = @removed_tags + @negated_tags
unremoved_tags = tag_array & attempted_removed_tags
if unremoved_tags.present?
unremoved_tags_list = unremoved_tags.map { |t| "[[#{t}]]" }.to_sentence
self.warnings[:base] << "#{unremoved_tags_list} could not be removed. Check for implications and try again"
end
end
def has_artist_tag
return if !new_record?
return if source !~ %r!\Ahttps?://!
return if has_tag?("artist_request") || has_tag?("official_art")
return if tags.any? { |t| t.category == Tag.categories.artist }
site = Sources::Site.new(source)
self.warnings[:base] << "Artist tag is required. Create a new tag with [[artist:<artist_name>]]. Ask on the forum if you need naming help"
rescue Sources::Site::NoStrategyError => e
# unrecognized source; do nothing.
end
def has_copyright_tag
return if !new_record?
return if has_tag?("copyright_request") || tags.any? { |t| t.category == Tag.categories.copyright }
self.warnings[:base] << "Copyright tag is required. Consider adding [[copyright request]] or [[original]]"
end
end end
include FileMethods include FileMethods
@@ -1737,11 +1812,22 @@ class Post < ApplicationRecord
) )
has_bit_flags BOOLEAN_ATTRIBUTES has_bit_flags BOOLEAN_ATTRIBUTES
def safeblocked?
CurrentUser.safe_mode? && (rating != "s" || has_tag?("toddlercon|toddler|diaper|tentacle|rape|bestiality|beastiality|lolita|loli|nude|shota|pussy|penis"))
end
def levelblocked?
!Danbooru.config.can_user_see_post?(CurrentUser.user, self)
end
def banblocked?
is_banned? && !CurrentUser.is_gold?
end
def visible? def visible?
return false if !Danbooru.config.can_user_see_post?(CurrentUser.user, self) return false if safeblocked?
return false if CurrentUser.safe_mode? && rating != "s" return false if levelblocked?
return false if CurrentUser.safe_mode? && has_tag?("toddlercon|toddler|diaper|tentacle|rape|bestiality|beastiality|lolita|loli|nude|shota|pussy|penis") return false if banblocked?
return false if is_banned? && !CurrentUser.is_gold?
return true return true
end end

View File

@@ -6,6 +6,7 @@ class Tag < ApplicationRecord
attr_accessible :category, :as => [:moderator, :gold, :platinum, :member, :anonymous, :default, :builder, :admin] attr_accessible :category, :as => [:moderator, :gold, :platinum, :member, :anonymous, :default, :builder, :admin]
attr_accessible :is_locked, :as => [:moderator, :admin] attr_accessible :is_locked, :as => [:moderator, :admin]
has_one :wiki_page, :foreign_key => "title", :primary_key => "name" has_one :wiki_page, :foreign_key => "title", :primary_key => "name"
has_one :artist, :foreign_key => "name", :primary_key => "name"
has_one :antecedent_alias, lambda {active}, :class_name => "TagAlias", :foreign_key => "antecedent_name", :primary_key => "name" has_one :antecedent_alias, lambda {active}, :class_name => "TagAlias", :foreign_key => "antecedent_name", :primary_key => "name"
has_many :consequent_aliases, lambda {active}, :class_name => "TagAlias", :foreign_key => "consequent_name", :primary_key => "name" has_many :consequent_aliases, lambda {active}, :class_name => "TagAlias", :foreign_key => "consequent_name", :primary_key => "name"
has_many :antecedent_implications, lambda {active}, :class_name => "TagImplication", :foreign_key => "antecedent_name", :primary_key => "name" has_many :antecedent_implications, lambda {active}, :class_name => "TagImplication", :foreign_key => "antecedent_name", :primary_key => "name"

View File

@@ -21,7 +21,7 @@ class TagImplication < TagRelationship
end end
def automatic_tags_for(names) def automatic_tags_for(names)
tags = names.grep(/\A(.+)_\(cosplay\)\Z/) { "char:#{$1}" } tags = names.grep(/\A(.+)_\(cosplay\)\Z/) { "char:#{TagAlias.to_aliased([$1]).first}" }
tags << "cosplay" if tags.present? tags << "cosplay" if tags.present?
tags.uniq tags.uniq
end end

View File

@@ -148,6 +148,8 @@ class Upload < ApplicationRecord
else else
update_attribute(:status, "error: " + post.errors.full_messages.join(", ")) update_attribute(:status, "error: " + post.errors.full_messages.join(", "))
end end
post
end end
def process!(force = false) def process!(force = false)
@@ -155,7 +157,7 @@ class Upload < ApplicationRecord
return if !force && status =~ /processing|completed|error/ return if !force && status =~ /processing|completed|error/
process_upload process_upload
create_post_from_upload post = create_post_from_upload
rescue Timeout::Error, Net::HTTP::Persistent::Error => x rescue Timeout::Error, Net::HTTP::Persistent::Error => x
if @tries > 3 if @tries > 3
@@ -164,9 +166,11 @@ class Upload < ApplicationRecord
@tries += 1 @tries += 1
retry retry
end end
nil
rescue Exception => x rescue Exception => x
update_attributes(:status => "error: #{x.class} - #{x.message}", :backtrace => x.backtrace.join("\n")) update_attributes(:status => "error: #{x.class} - #{x.message}", :backtrace => x.backtrace.join("\n"))
nil
ensure ensure
delete_temp_file delete_temp_file

View File

@@ -155,10 +155,19 @@ class PostPresenter < Presenter
categorized_tag_groups.flatten.slice(0, 25).join(", ").tr("_", " ") categorized_tag_groups.flatten.slice(0, 25).join(", ").tr("_", " ")
end end
def safe_mode_message(template)
html = ["This image is unavailable on safe mode (#{Danbooru.config.app_name}). Go to "]
html << template.link_to("Danbooru", "http://danbooru.donmai.us")
html << " or disable safe mode to view ("
html << template.link_to("learn more", template.wiki_pages_path(title: "help:user_settings"))
html << ")."
html.join.html_safe
end
def image_html(template) def image_html(template)
return template.content_tag("p", "The artist requested removal of this image") if @post.is_banned? && !CurrentUser.user.is_gold? return template.content_tag("p", "The artist requested removal of this image") if @post.banblocked?
return template.content_tag("p", template.link_to("You need a gold account to see this image.", template.new_user_upgrade_path)) if !Danbooru.config.can_user_see_post?(CurrentUser.user, @post) return template.content_tag("p", template.link_to("You need a gold account to see this image.", template.new_user_upgrade_path)) if @post.levelblocked?
return template.content_tag("p", "This image is unavailable") if !@post.visible? return template.content_tag("p", safe_mode_message(template)) if @post.safeblocked?
if @post.is_flash? if @post.is_flash?
template.render("posts/partials/show/flash", :post => @post) template.render("posts/partials/show/flash", :post => @post)

View File

@@ -112,7 +112,7 @@
<% end %> <% end %>
<div class="ui-corner-all ui-state-highlight" id="notice" style="<%= "display: none;" unless flash[:notice] %>"> <div class="ui-corner-all ui-state-highlight" id="notice" style="<%= "display: none;" unless flash[:notice] %>">
<span><%= flash[:notice] %></span> <span><%= format_text(flash[:notice], inline: true) %>.</span>
<a href="#" id="close-notice-link">close</a> <a href="#" id="close-notice-link">close</a>
</div> </div>

View File

@@ -6,11 +6,15 @@
<% if post_set.hidden_posts.present? %> <% if post_set.hidden_posts.present? %>
<div class="tn hidden-posts-notice"> <div class="tn hidden-posts-notice">
<% if post_set.banned_posts.present? %> <% if post_set.banned_posts.present? %>
<%= post_set.banned_posts.size %> post(s) were removed from this page at the artist's request (<%= link_to "learn more", wiki_pages_path(title: "banned_artist") %>). <%= post_set.banned_posts.size %> post(s) were removed from this page at the artist's request (<%= link_to "learn more", wiki_pages_path(title: "banned_artist") %>).<br>
<% end %> <% end %>
<% if post_set.censored_posts.present? %> <% if post_set.censored_posts.present? %>
<%= post_set.censored_posts.size %> post(s) on this page require a <%= link_to "Gold account", new_user_upgrade_path %> to view (<%= link_to "learn more", wiki_pages_path(title: "help:censored_tags") %>). <%= post_set.censored_posts.size %> post(s) on this page require a <%= link_to "Gold account", new_user_upgrade_path %> to view (<%= link_to "learn more", wiki_pages_path(title: "help:censored_tags") %>).<br>
<% end %>
<% if post_set.safe_posts.present? %>
<%= post_set.safe_posts.size %> post(s) on this page were hidden by safe mode (<%= Danbooru.config.app_name %>). Go to <%= link_to "Danbooru", "http://danbooru.donmai.us" %> or disable safe mode to view (<%= link_to "learn more", wiki_pages_path(title: "help:user_settings") %>).<br>
<% end %> <% end %>
</div> </div>
<% end %> <% end %>

View File

@@ -174,7 +174,7 @@
<meta property="og:title" content="<%= @post.presenter.humanized_essential_tag_string %> - <%= Danbooru.config.app_name %>"> <meta property="og:title" content="<%= @post.presenter.humanized_essential_tag_string %> - <%= Danbooru.config.app_name %>">
<% if @post.visible? %> <% if @post.visible? %>
<meta property="og:image" content="http://<%= Danbooru.config.hostname %><%= @post.large_file_url %>"> <meta property="og:image" content="<%= @post.open_graph_image_url %>">
<% end %> <% end %>
<% if Danbooru.config.enable_post_search_counts %> <% if Danbooru.config.enable_post_search_counts %>
@@ -189,7 +189,7 @@
<meta name="twitter:description" content="<%= @post.presenter.humanized_tag_string %> - <%= Danbooru.config.app_name %>"> <meta name="twitter:description" content="<%= @post.presenter.humanized_tag_string %> - <%= Danbooru.config.app_name %>">
<% if @post.visible? %> <% if @post.visible? %>
<meta name="twitter:image" content="http://<%= Danbooru.config.hostname %><%= @post.large_file_url %>"> <meta name="twitter:image" content="<%= @post.open_graph_image_url %>">
<% end %> <% end %>
<% end %> <% end %>

View File

@@ -10,20 +10,17 @@
<li><%= link_to "Help", wiki_pages_path(:search => {:title => "help:wiki"}) %></li> <li><%= link_to "Help", wiki_pages_path(:search => {:title => "help:wiki"}) %></li>
<% if @wiki_page %> <% if @wiki_page && !@wiki_page.new_record? %>
<li>|</li> <li>|</li>
<li><%= link_to "Posts (#{Post.fast_count(@wiki_page.title)})", posts_path(:tags => @wiki_page.title) %></li> <li><%= link_to "Posts (#{@wiki_page.tag.try(:post_count) || 0})", posts_path(:tags => @wiki_page.title) %></li>
<% unless @wiki_page.new_record? %> <li><%= link_to "History", wiki_page_versions_path(:search => {:wiki_page_id => @wiki_page.id}) %></li>
<li><%= link_to "History", wiki_page_versions_path(:search => {:wiki_page_id => @wiki_page.id}) %></li> <% if CurrentUser.is_member? %>
<% if CurrentUser.is_member? %> <li id="wiki-page-edit"><%= link_to "Edit", edit_wiki_page_path(@wiki_page) %></li>
<li id="wiki-page-edit"><%= link_to "Edit", edit_wiki_page_path(@wiki_page) %></li>
<% end %>
<% if CurrentUser.is_builder? && !@wiki_page.is_deleted? %>
<li id="wiki-page-delete"><%= link_to "Delete", wiki_page_path(@wiki_page), :remote => true, :method => :delete, :data => {:confirm => "Are you sure you want to delete this wiki page?"} %></li>
<% end %>
<% end %> <% end %>
<% end %> <% if CurrentUser.is_builder? && !@wiki_page.is_deleted? %>
<% if @wiki_page_version %> <li id="wiki-page-delete"><%= link_to "Delete", wiki_page_path(@wiki_page), :remote => true, :method => :delete, :data => {:confirm => "Are you sure you want to delete this wiki page?"} %></li>
<% end %>
<% elsif @wiki_page_version %>
<li>|</li> <li>|</li>
<li><%= link_to "Newest", wiki_page_path(@wiki_page_version.wiki_page_id) %></li> <li><%= link_to "Newest", wiki_page_path(@wiki_page_version.wiki_page_id) %></li>
<% if CurrentUser.is_member? %> <% if CurrentUser.is_member? %>

View File

@@ -30,11 +30,6 @@ module Danbooru
config.x.git_hash = nil config.x.git_hash = nil
end end
if ENV["DANBOORU_RAKISMET_KEY"]
config.rakismet.key = ENV["DANBOORU_RAKISMET_KEY"]
config.rakismet.url = ENV["DANBOORU_RAKISMET_URL"]
end
config.after_initialize do config.after_initialize do
Rails.application.routes.default_url_options = { Rails.application.routes.default_url_options = {
host: Danbooru.config.hostname, host: Danbooru.config.hostname,

View File

@@ -619,6 +619,13 @@ module Danbooru
def aws_sqs_cropper_url def aws_sqs_cropper_url
end end
# Akismet API key. Used for Dmail spam detection. http://akismet.com/signup/
def rakismet_key
end
def rakismet_url
end
end end
class EnvironmentConfiguration class EnvironmentConfiguration

View File

@@ -0,0 +1,2 @@
Rails.application.config.rakismet.key = Danbooru.config.rakismet_key
Rails.application.config.rakismet.url = Danbooru.config.rakismet_url

View File

@@ -244,6 +244,11 @@ class CommentTest < ActiveSupport::TestCase
@comment.update_attributes({:body => "nope"}, :as => :moderator) @comment.update_attributes({:body => "nope"}, :as => :moderator)
end end
end end
should "credit the moderator as the updater" do
@comment.update({ body: "test" }, as: :moderator)
assert_equal(@mod.id, @comment.updater_id)
end
end end
context "that is below the score threshold" do context "that is below the score threshold" do

View File

@@ -34,8 +34,21 @@ module Moderator
ss = FactoryGirl.create(:saved_search, :user => @user, :query => "123 ... 456") ss = FactoryGirl.create(:saved_search, :user => @user, :query => "123 ... 456")
tag_batch_change = TagBatchChange.new("...", "bbb", @user.id, "127.0.0.1") tag_batch_change = TagBatchChange.new("...", "bbb", @user.id, "127.0.0.1")
tag_batch_change.perform tag_batch_change.perform
ss.reload
assert_equal(%w(123 456 bbb), ss.query.scan(/\S+/).sort) assert_equal("123 456 bbb", ss.reload.normalized_query)
end
should "move only saved searches that match the mass update exactly" do
ss = FactoryGirl.create(:saved_search, :user => @user, :query => "123 ... 456")
tag_batch_change = TagBatchChange.new("1", "bbb", @user.id, "127.0.0.1")
tag_batch_change.perform
assert_equal("... 123 456", ss.reload.normalized_query, "expected '123' to remain unchanged")
tag_batch_change = TagBatchChange.new("123 456", "789", @user.id, "127.0.0.1")
tag_batch_change.perform
assert_equal("... 789", ss.reload.normalized_query, "expected '123 456' to be changed to '789'")
end end
should "raise an error if there is no predicate" do should "raise an error if there is no predicate" do

View File

@@ -149,6 +149,9 @@ class PoolTest < ActiveSupport::TestCase
context "to a deleted pool" do context "to a deleted pool" do
setup do setup do
# must be a builder to update deleted pools.
CurrentUser.user = FactoryGirl.create(:builder_user)
@pool.update_attribute(:is_deleted, true) @pool.update_attribute(:is_deleted, true)
@pool.post_ids = "#{@pool.post_ids} #{@p2.id}" @pool.post_ids = "#{@pool.post_ids} #{@p2.id}"
@pool.synchronize! @pool.synchronize!

View File

@@ -111,6 +111,9 @@ class PostTest < ActiveSupport::TestCase
context "that belongs to a pool" do context "that belongs to a pool" do
setup do setup do
# must be a builder to update deleted pools. must be >1 week old to remove posts from pools.
CurrentUser.user = FactoryGirl.create(:builder_user, created_at: 1.month.ago)
SqsService.any_instance.stubs(:send_message) SqsService.any_instance.stubs(:send_message)
@pool = FactoryGirl.create(:pool) @pool = FactoryGirl.create(:pool)
@pool.add!(@post) @pool.add!(@post)
@@ -350,6 +353,17 @@ class PostTest < ActiveSupport::TestCase
p1.reload p1.reload
assert(p1.has_children?, "Parent should have children") assert(p1.has_children?, "Parent should have children")
end end
should "clear the has_active_children flag when the 'move favorites' option is set" do
user = FactoryGirl.create(:gold_user)
p1 = FactoryGirl.create(:post)
c1 = FactoryGirl.create(:post, :parent_id => p1.id)
c1.add_favorite!(user)
assert_equal(true, p1.reload.has_active_children?)
c1.delete!("test", :move_favorites => true)
assert_equal(false, p1.reload.has_active_children?)
end
end end
context "one child" do context "one child" do
@@ -776,6 +790,14 @@ class PostTest < ActiveSupport::TestCase
assert(Tag.where(name: "someone_(cosplay)", category: 4).exists?, "expected 'someone_(cosplay)' tag to be created as character") assert(Tag.where(name: "someone_(cosplay)", category: 4).exists?, "expected 'someone_(cosplay)' tag to be created as character")
assert(Tag.where(name: "someone", category: 4).exists?, "expected 'someone' tag to be created") assert(Tag.where(name: "someone", category: 4).exists?, "expected 'someone' tag to be created")
end end
should "apply aliases when the character tag is added" do
FactoryGirl.create(:tag_alias, antecedent_name: "jim", consequent_name: "james")
@post.add_tag("jim_(cosplay)")
@post.save
assert(@post.has_tag?("james"), "expected 'jim' to be aliased to 'james'")
end
end end
context "for a parent" do context "for a parent" do
@@ -813,6 +835,25 @@ class PostTest < ActiveSupport::TestCase
end end
end end
context "for a favgroup" do
setup do
@favgroup = FactoryGirl.create(:favorite_group, creator: @user)
@post = FactoryGirl.create(:post, :tag_string => "aaa favgroup:#{@favgroup.id}")
end
should "add the post to the favgroup" do
assert_equal(1, @favgroup.reload.post_count)
assert_equal(true, !!@favgroup.contains?(@post.id))
end
should "remove the post from the favgroup" do
@post.update(:tag_string => "-favgroup:#{@favgroup.id}")
assert_equal(0, @favgroup.reload.post_count)
assert_equal(false, !!@favgroup.contains?(@post.id))
end
end
context "for a pool" do context "for a pool" do
setup do setup do
mock_pool_archive_service! mock_pool_archive_service!
@@ -1546,6 +1587,42 @@ class PostTest < ActiveSupport::TestCase
assert_equal("http://www.hentai-foundry.com/pictures/user/AnimeFlux/219123", @post.normalized_source) assert_equal("http://www.hentai-foundry.com/pictures/user/AnimeFlux/219123", @post.normalized_source)
end end
end end
context "when validating tags" do
should "warn when creating a new general tag" do
@post.add_tag("tag")
@post.save
assert_match(/Created 1 new tag: \[\[tag\]\]/, @post.warnings.full_messages.join)
end
should "warn when adding an artist tag without an artist entry" do
@post.add_tag("artist:bkub")
@post.save
assert_match(/Artist \[\[bkub\]\] requires an artist entry./, @post.warnings.full_messages.join)
end
should "warn when a tag removal failed due to implications or automatic tags" do
ti = FactoryGirl.create(:tag_implication, antecedent_name: "cat", consequent_name: "animal")
@post.reload
@post.update(old_tag_string: @post.tag_string, tag_string: "chen_(cosplay) chen cosplay cat animal")
@post.reload
@post.update(old_tag_string: @post.tag_string, tag_string: "chen_(cosplay) chen cosplay cat -cosplay")
assert_match(/\[\[animal\]\] and \[\[cosplay\]\] could not be removed./, @post.warnings.full_messages.join)
end
should "warn when a post from a known source is missing an artist tag" do
post = FactoryGirl.build(:post, source: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=65985331")
post.save
assert_match(/Artist tag is required/, post.warnings.full_messages.join)
end
should "warn when missing a copyright tag" do
assert_match(/Copyright tag is required/, @post.warnings.full_messages.join)
end
end
end end
end end
@@ -2458,13 +2535,17 @@ class PostTest < ActiveSupport::TestCase
context "in safe mode" do context "in safe mode" do
setup do setup do
CurrentUser.stubs(:safe_mode?).returns(true) CurrentUser.stubs(:safe_mode?).returns(true)
FactoryGirl.create(:post, "rating" => "s")
end end
should "execute a search" do should "work for a blank search" do
Post.expects(:fast_count_search).once.with("rating:s", kind_of(Hash)).returns(1)
assert_equal(1, Post.fast_count("")) assert_equal(1, Post.fast_count(""))
end end
should "work for a nil search" do
assert_equal(1, Post.fast_count(nil))
end
should "not fail for a two tag search by a member" do should "not fail for a two tag search by a member" do
post1 = FactoryGirl.create(:post, tag_string: "aaa bbb rating:s") post1 = FactoryGirl.create(:post, tag_string: "aaa bbb rating:s")
post2 = FactoryGirl.create(:post, tag_string: "aaa bbb rating:e") post2 = FactoryGirl.create(:post, tag_string: "aaa bbb rating:e")

View File

@@ -49,6 +49,7 @@ class PostViewCountServiceTest < ActiveSupport::TestCase
context "failure" do context "failure" do
setup do setup do
@date = "2000-01-01"
stub_request(:get, "localhost:1234/post_views/rank").with(query: {"date" => @date}).to_return(body: "", status: 400) stub_request(:get, "localhost:1234/post_views/rank").with(query: {"date" => @date}).to_return(body: "", status: 400)
end end

View File

@@ -152,7 +152,7 @@ module Sources
should "get the image urls" do should "get the image urls" do
urls = %w[ urls = %w[
https://vt.media.tumblr.com/tumblr_os31dkexhK1wsfqep.mp4 https://vtt.tumblr.com/tumblr_os31dkexhK1wsfqep.mp4
http://data.tumblr.com/afed9f5b3c33c39dc8c967e262955de2/tumblr_inline_os31dclyCR1v11u29_raw.png http://data.tumblr.com/afed9f5b3c33c39dc8c967e262955de2/tumblr_inline_os31dclyCR1v11u29_raw.png
] ]