Kill trailing whitespace in ruby files
This commit is contained in:
@@ -7,7 +7,7 @@ class Advertisement < ActiveRecord::Base
|
||||
def copy_to_servers
|
||||
RemoteFileManager.new(image_path).distribute
|
||||
end
|
||||
|
||||
|
||||
def delete_from_servers
|
||||
RemoteFileManager.new(image_path).delete
|
||||
end
|
||||
@@ -19,15 +19,15 @@ class Advertisement < ActiveRecord::Base
|
||||
def hit_sum(start_date, end_date)
|
||||
hits.where(["created_at BETWEEN ? AND ?", start_date, end_date]).count
|
||||
end
|
||||
|
||||
|
||||
def unique_identifier
|
||||
@unique_identifier ||= ("%.0f" % (Time.now.to_f * 1_000))
|
||||
end
|
||||
|
||||
|
||||
def image_url
|
||||
"/images/advertisements/ads-#{date_prefix}/#{file_name}"
|
||||
end
|
||||
|
||||
|
||||
def date_prefix
|
||||
created_at.try(:strftime, "%Y%m%d")
|
||||
end
|
||||
@@ -35,11 +35,11 @@ class Advertisement < ActiveRecord::Base
|
||||
def image_path
|
||||
"#{Danbooru.config.advertisement_path}/ads-#{date_prefix}/#{file_name}"
|
||||
end
|
||||
|
||||
|
||||
def file
|
||||
nil
|
||||
end
|
||||
|
||||
|
||||
def file=(f)
|
||||
if f.size > 0
|
||||
self.file_name = unique_identifier + File.extname(f.original_filename)
|
||||
@@ -55,7 +55,7 @@ class Advertisement < ActiveRecord::Base
|
||||
image_size = ImageSize.new(File.open(image_path, "rb"))
|
||||
self.width = image_size.get_width
|
||||
self.height = image_size.get_height
|
||||
|
||||
|
||||
if width > height
|
||||
self.ad_type = "horizontal"
|
||||
else
|
||||
@@ -63,7 +63,7 @@ class Advertisement < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def preview_width
|
||||
if width > 100 || height > 100
|
||||
if width < height
|
||||
@@ -72,9 +72,9 @@ class Advertisement < ActiveRecord::Base
|
||||
else
|
||||
return 100
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def preview_height
|
||||
if width > 100 || height > 100
|
||||
if height < width
|
||||
@@ -83,6 +83,6 @@ class Advertisement < ActiveRecord::Base
|
||||
else
|
||||
return 100
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class AdvertisementHit < ActiveRecord::Base
|
||||
belongs_to :advertisement
|
||||
|
||||
|
||||
scope :between, lambda {|start_date, end_date| where("created_at BETWEEN ? AND ?", start_date, end_date)}
|
||||
end
|
||||
|
||||
@@ -5,17 +5,17 @@ class AmazonBackup < ActiveRecord::Base
|
||||
def self.last_id
|
||||
first.last_id
|
||||
end
|
||||
|
||||
|
||||
def self.update_id(new_id)
|
||||
first.update_column(:last_id, new_id)
|
||||
end
|
||||
|
||||
|
||||
def self.execute
|
||||
last_id = AmazonBackup.last_id
|
||||
|
||||
|
||||
Post.where("id > ?", last_id).limit(200).order("id").each do |post|
|
||||
AWS::S3::Base.establish_connection!(
|
||||
:access_key_id => Danbooru.config.amazon_s3_access_key_id,
|
||||
:access_key_id => Danbooru.config.amazon_s3_access_key_id,
|
||||
:secret_access_key => Danbooru.config.amazon_s3_secret_access_key
|
||||
)
|
||||
|
||||
@@ -31,7 +31,7 @@ class AmazonBackup < ActiveRecord::Base
|
||||
if File.exists?(post.large_file_path)
|
||||
AWS::S3::S3Object.store("large/#{post.md5}.jpg", open(post.large_file_path, "rb"), Danbooru.config.amazon_s3_bucket_name)
|
||||
end
|
||||
|
||||
|
||||
AmazonBackup.update_id(last_id)
|
||||
end
|
||||
rescue Exception => x
|
||||
|
||||
@@ -13,10 +13,10 @@ class Artist < ActiveRecord::Base
|
||||
accepts_nested_attributes_for :wiki_page
|
||||
attr_accessible :body, :name, :url_string, :other_names, :other_names_comma, :group_name, :wiki_page_attributes, :notes, :is_active, :as => [:member, :privileged, :builder, :platinum, :contributor, :janitor, :moderator, :default, :admin]
|
||||
attr_accessible :is_banned, :as => :admin
|
||||
|
||||
|
||||
module UrlMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def find_all_by_url(url)
|
||||
url = ArtistUrl.normalize(url)
|
||||
@@ -43,11 +43,11 @@ class Artist < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def url_string=(string)
|
||||
@url_string = string
|
||||
end
|
||||
|
||||
|
||||
def url_string
|
||||
@url_string || urls.map {|x| x.url}.join("\n")
|
||||
end
|
||||
@@ -55,7 +55,7 @@ class Artist < ActiveRecord::Base
|
||||
|
||||
module NameMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def normalize_name(name)
|
||||
name.to_s.downcase.strip.gsub(/ /, '_')
|
||||
@@ -65,26 +65,26 @@ class Artist < ActiveRecord::Base
|
||||
def normalize_name
|
||||
self.name = Artist.normalize_name(name)
|
||||
end
|
||||
|
||||
|
||||
def other_names_array
|
||||
other_names.try(:split, / /)
|
||||
end
|
||||
|
||||
|
||||
def other_names_comma
|
||||
other_names_array.try(:join, ", ")
|
||||
end
|
||||
|
||||
|
||||
def other_names_comma=(string)
|
||||
self.other_names = string.split(/,/).map {|x| Artist.normalize_name(x)}.join(" ")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module GroupMethods
|
||||
def member_names
|
||||
members.map(&:name).join(", ")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module VersionMethods
|
||||
def create_version
|
||||
ArtistVersion.create(
|
||||
@@ -98,14 +98,14 @@ class Artist < ActiveRecord::Base
|
||||
:group_name => group_name
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
def revert_to!(version)
|
||||
self.name = version.name
|
||||
self.url_string = version.url_string
|
||||
self.is_active = version.is_active
|
||||
self.other_names = version.other_names
|
||||
self.group_name = version.group_name
|
||||
save
|
||||
save
|
||||
end
|
||||
end
|
||||
|
||||
@@ -119,11 +119,11 @@ class Artist < ActiveRecord::Base
|
||||
artist.url_string = post.source
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if params[:other_names]
|
||||
artist.other_names = params[:other_names]
|
||||
end
|
||||
|
||||
|
||||
if params[:urls]
|
||||
artist.url_string = params[:urls]
|
||||
end
|
||||
@@ -139,7 +139,7 @@ class Artist < ActiveRecord::Base
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def notes=(msg)
|
||||
if wiki_page
|
||||
wiki_page.title = name
|
||||
@@ -152,7 +152,7 @@ class Artist < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module TagMethods
|
||||
def has_tag_alias?
|
||||
TagAlias.exists?(["antecedent_name = ?", name])
|
||||
@@ -162,7 +162,7 @@ class Artist < ActiveRecord::Base
|
||||
TagAlias.find_by_antecedent_name(name).consequent_name
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module BanMethods
|
||||
def ban!
|
||||
Post.transaction do
|
||||
@@ -178,24 +178,24 @@ class Artist < ActiveRecord::Base
|
||||
rescue Post::SearchError
|
||||
# swallow
|
||||
end
|
||||
|
||||
|
||||
# potential race condition but unlikely
|
||||
unless TagImplication.where(:antecedent_name => name, :consequent_name => "banned_artist").exists?
|
||||
tag_implication = TagImplication.create(:antecedent_name => name, :consequent_name => "banned_artist")
|
||||
tag_implication.delay(:queue => "default").process!
|
||||
end
|
||||
|
||||
|
||||
update_column(:is_active, false)
|
||||
update_column(:is_banned, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def active
|
||||
where("is_active = true")
|
||||
end
|
||||
|
||||
|
||||
def banned
|
||||
where("is_banned = true")
|
||||
end
|
||||
@@ -209,27 +209,27 @@ class Artist < ActiveRecord::Base
|
||||
where("false")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def other_names_match(string)
|
||||
where("other_names_index @@ to_tsquery('danbooru', E?)", Artist.normalize_name(string).to_escaped_for_tsquery)
|
||||
end
|
||||
|
||||
|
||||
def group_name_matches(name)
|
||||
stripped_name = normalize_name(name).to_escaped_for_sql_like
|
||||
where("group_name LIKE ? ESCAPE E'\\\\'", stripped_name)
|
||||
end
|
||||
|
||||
|
||||
def name_matches(name)
|
||||
stripped_name = normalize_name(name).to_escaped_for_sql_like
|
||||
where("name LIKE ? ESCAPE E'\\\\'", stripped_name)
|
||||
end
|
||||
|
||||
|
||||
def any_name_matches(name)
|
||||
stripped_name = normalize_name(name).to_escaped_for_sql_like
|
||||
name_for_tsquery = normalize_name(name).to_escaped_for_tsquery
|
||||
where("(name LIKE ? ESCAPE E'\\\\' OR other_names_index @@ to_tsquery('danbooru', E?))", stripped_name, name_for_tsquery)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = active
|
||||
params = {} if params.blank?
|
||||
@@ -240,7 +240,7 @@ class Artist < ActiveRecord::Base
|
||||
|
||||
when /name:(.+)/
|
||||
q = q.name_matches($1)
|
||||
|
||||
|
||||
when /other:(.+)/
|
||||
q = q.other_names_match($1)
|
||||
|
||||
@@ -253,7 +253,7 @@ class Artist < ActiveRecord::Base
|
||||
when /./
|
||||
q = q.any_name_matches(params[:name])
|
||||
end
|
||||
|
||||
|
||||
if params[:sort] == "Name"
|
||||
q = q.reorder("name")
|
||||
else
|
||||
@@ -263,11 +263,11 @@ class Artist < ActiveRecord::Base
|
||||
if params[:id].present?
|
||||
q = q.where("id = ?", params[:id])
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include UrlMethods
|
||||
include NameMethods
|
||||
include GroupMethods
|
||||
@@ -277,7 +277,7 @@ class Artist < ActiveRecord::Base
|
||||
include TagMethods
|
||||
include BanMethods
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def status
|
||||
if is_banned?
|
||||
"Banned"
|
||||
@@ -287,11 +287,11 @@ class Artist < ActiveRecord::Base
|
||||
"Deleted"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def legacy_api_hash
|
||||
return {
|
||||
:id => id,
|
||||
:name => name,
|
||||
:id => id,
|
||||
:name => name,
|
||||
:other_names => other_names,
|
||||
:group_name => group_name,
|
||||
:urls => artist_urls.map {|x| x.url},
|
||||
@@ -299,7 +299,7 @@ class Artist < ActiveRecord::Base
|
||||
:updater_id => 0
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.user.id
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ class ArtistUrl < ActiveRecord::Base
|
||||
before_save :normalize
|
||||
validates_presence_of :url
|
||||
belongs_to :artist
|
||||
|
||||
|
||||
def self.normalize(url)
|
||||
if url.nil?
|
||||
nil
|
||||
@@ -17,24 +17,24 @@ class ArtistUrl < ActiveRecord::Base
|
||||
url + "/"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.normalize_for_search(url)
|
||||
if url =~ /\.\w+\Z/ && url =~ /\w\/\w/
|
||||
url = File.dirname(url)
|
||||
end
|
||||
|
||||
|
||||
url = url.gsub(/^https:\/\//, "http://")
|
||||
url = url.gsub(/^http:\/\/blog\d+\.fc2/, "http://blog*.fc2")
|
||||
url = url.gsub(/^http:\/\/blog-imgs-\d+\.fc2/, "http://blog*.fc2")
|
||||
url = url.gsub(/^http:\/\/blog-imgs-\d+-\w+\.fc2/, "http://blog*.fc2")
|
||||
url = url.gsub(/^http:\/\/img\d+\.pixiv\.net/, "http://img*.pixiv.net")
|
||||
url = url.gsub(/^http:\/\/img\d+\.pixiv\.net/, "http://img*.pixiv.net")
|
||||
url = url.gsub(/^http:\/\/i\d+\.pixiv\.net\/img\d+/, "http://*.pixiv.net/img*")
|
||||
end
|
||||
|
||||
def normalize
|
||||
self.normalized_url = self.class.normalize(url)
|
||||
end
|
||||
|
||||
|
||||
def to_s
|
||||
url
|
||||
end
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
class ArtistVersion < ActiveRecord::Base
|
||||
belongs_to :updater
|
||||
belongs_to :artist
|
||||
|
||||
|
||||
def self.search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:name]
|
||||
q = q.where("name like ? escape E'\\\\'", params[:name].to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
|
||||
if params[:artist_id]
|
||||
q = q.where("artist_id = ?", params[:artist_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:sort] == "Name"
|
||||
q = q.reorder("name")
|
||||
else
|
||||
q = q.reorder("id desc")
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
def url_array
|
||||
url_string.scan(/\S+/)
|
||||
end
|
||||
|
||||
|
||||
def updater_name
|
||||
User.id_to_name(updater_id).tr("_", " ")
|
||||
end
|
||||
|
||||
@@ -6,42 +6,42 @@ class Ban < ActiveRecord::Base
|
||||
validate :user_is_inferior
|
||||
validates_presence_of :user_id, :reason, :duration
|
||||
before_validation :initialize_banner_id, :on => :create
|
||||
|
||||
|
||||
def self.is_banned?(user)
|
||||
exists?(["user_id = ? AND expires_at > ?", user.id, Time.now])
|
||||
end
|
||||
|
||||
|
||||
def self.search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:banner_name]
|
||||
q = q.where("banner_id = (select _.id from users _ where lower(_.name) = ?)", params[:banner_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:banner_id]
|
||||
q = q.where("banner_id = ?", params[:banner_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:user_name]
|
||||
q = q.where("user_id = (select _.id from users _ where lower(_.name) = ?)", params[:user_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:user_id]
|
||||
q = q.where("user_id = ?", params[:user_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
def initialize_banner_id
|
||||
self.banner_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def user_is_inferior
|
||||
if user
|
||||
if user.is_admin?
|
||||
errors[:base] << "You can never ban an admin."
|
||||
errors[:base] << "You can never ban an admin."
|
||||
false
|
||||
elsif user.is_moderator? && banner.is_admin?
|
||||
true
|
||||
@@ -56,7 +56,7 @@ class Ban < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update_feedback
|
||||
if user
|
||||
feedback = user.feedback.build
|
||||
@@ -66,24 +66,24 @@ class Ban < ActiveRecord::Base
|
||||
feedback.save
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def user_name
|
||||
user ? user.name : nil
|
||||
end
|
||||
|
||||
|
||||
def user_name=(username)
|
||||
self.user_id = User.name_to_id(username)
|
||||
end
|
||||
|
||||
|
||||
def duration=(dur)
|
||||
self.expires_at = dur.to_i.days.from_now
|
||||
@duration = dur
|
||||
end
|
||||
|
||||
|
||||
def duration
|
||||
@duration
|
||||
end
|
||||
|
||||
|
||||
def expired?
|
||||
expires_at < Time.now
|
||||
end
|
||||
|
||||
@@ -10,62 +10,62 @@ class Comment < ActiveRecord::Base
|
||||
after_destroy :update_last_commented_at
|
||||
attr_accessible :body, :post_id, :do_not_bump_post
|
||||
attr_accessor :do_not_bump_post
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def recent
|
||||
reorder("comments.id desc").limit(6)
|
||||
end
|
||||
|
||||
|
||||
def body_matches(query)
|
||||
where("body_index @@ plainto_tsquery(?)", query.to_escaped_for_tsquery_split).order("comments.id DESC")
|
||||
end
|
||||
|
||||
|
||||
def hidden(user)
|
||||
where("score < ?", user.comment_threshold)
|
||||
end
|
||||
|
||||
|
||||
def visible(user)
|
||||
where("score >= ?", user.comment_threshold)
|
||||
end
|
||||
|
||||
|
||||
def post_tags_match(query)
|
||||
joins(:post).where("posts.tag_index @@ to_tsquery('danbooru', ?)", query.to_escaped_for_tsquery_split)
|
||||
end
|
||||
|
||||
|
||||
def for_creator(user_id)
|
||||
where("creator_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def for_creator_name(user_name)
|
||||
where("creator_id = (select _.id from users _ where lower(_.name) = lower(?))", user_name.downcase)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:body_matches].present?
|
||||
q = q.body_matches(params[:body_matches])
|
||||
end
|
||||
|
||||
|
||||
if params[:post_tags_match].present?
|
||||
q = q.post_tags_match(params[:post_tags_match])
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.for_creator_name(params[:creator_name])
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.for_creator(params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.user.id
|
||||
self.ip_addr = CurrentUser.ip_addr
|
||||
@@ -79,7 +79,7 @@ class Comment < ActiveRecord::Base
|
||||
def creator_name
|
||||
User.id_to_name(creator_id)
|
||||
end
|
||||
|
||||
|
||||
def updater_name
|
||||
User.id_to_name(updater_id)
|
||||
end
|
||||
@@ -100,15 +100,15 @@ class Comment < ActiveRecord::Base
|
||||
Post.update_all(["last_commented_at = ?", created_at], ["id = ?", post_id])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def do_not_bump_post?
|
||||
do_not_bump_post == "1"
|
||||
end
|
||||
|
||||
|
||||
def vote!(val)
|
||||
numerical_score = val == "up" ? 1 : -1
|
||||
vote = votes.create(:score => numerical_score)
|
||||
|
||||
|
||||
if vote.errors.empty?
|
||||
if vote.is_positive?
|
||||
update_column(:score, score + 1)
|
||||
@@ -119,7 +119,7 @@ class Comment < ActiveRecord::Base
|
||||
|
||||
return vote
|
||||
end
|
||||
|
||||
|
||||
def editable_by?(user)
|
||||
creator_id == user.id || user.is_janitor?
|
||||
end
|
||||
|
||||
@@ -9,22 +9,22 @@ class CommentVote < ActiveRecord::Base
|
||||
validate :validate_user_can_vote
|
||||
validate :validate_comment_can_be_down_voted
|
||||
validates_inclusion_of :score, :in => [-1, 1], :message => "must be 1 or -1"
|
||||
|
||||
|
||||
def self.prune!
|
||||
destroy_all("created_at < ?", 14.days.ago)
|
||||
end
|
||||
|
||||
|
||||
def self.search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:comment_id]
|
||||
q = q.where("comment_id = ?", params[:comment_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
def validate_user_can_vote
|
||||
if !user.can_comment_vote?
|
||||
errors.add :base, "You cannot vote on comments"
|
||||
@@ -33,24 +33,24 @@ class CommentVote < ActiveRecord::Base
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def validate_comment_can_be_down_voted
|
||||
if is_negative? && comment.creator.is_janitor?
|
||||
if is_negative? && comment.creator.is_janitor?
|
||||
errors.add :base, "You cannot downvote a janitor comment"
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def is_positive?
|
||||
score == 1
|
||||
end
|
||||
|
||||
|
||||
def is_negative?
|
||||
score == -1
|
||||
end
|
||||
|
||||
|
||||
def initialize_user
|
||||
self.user_id = CurrentUser.user.id
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ class Dmail < ActiveRecord::Base
|
||||
after_create :update_recipient
|
||||
after_create :send_dmail
|
||||
attr_accessible :title, :body, :is_deleted, :to_id, :to, :to_name
|
||||
|
||||
|
||||
module AddressMethods
|
||||
def to_name
|
||||
User.id_to_pretty_name(to_id)
|
||||
@@ -26,19 +26,19 @@ class Dmail < ActiveRecord::Base
|
||||
return if user.nil?
|
||||
self.to_id = user.id
|
||||
end
|
||||
|
||||
|
||||
def initialize_from_id
|
||||
self.from_id = CurrentUser.id
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module FactoryMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def create_split(params)
|
||||
copy = nil
|
||||
|
||||
|
||||
Dmail.transaction do
|
||||
copy = Dmail.new(params)
|
||||
copy.owner_id = copy.to_id
|
||||
@@ -51,17 +51,17 @@ class Dmail < ActiveRecord::Base
|
||||
copy.is_read = true
|
||||
copy.save
|
||||
end
|
||||
|
||||
|
||||
copy
|
||||
end
|
||||
|
||||
|
||||
def new_blank
|
||||
Dmail.new do |dmail|
|
||||
dmail.from_id = CurrentUser.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def build_response(options = {})
|
||||
Dmail.new do |dmail|
|
||||
if title =~ /Re:/
|
||||
@@ -76,84 +76,84 @@ class Dmail < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def for(user)
|
||||
where("owner_id = ?", user)
|
||||
end
|
||||
|
||||
|
||||
def inbox
|
||||
where("to_id = owner_id")
|
||||
end
|
||||
|
||||
|
||||
def sent
|
||||
where("from_id = owner_id")
|
||||
end
|
||||
|
||||
|
||||
def active
|
||||
where("is_deleted = ?", false)
|
||||
end
|
||||
|
||||
|
||||
def deleted
|
||||
where("is_deleted = ?", true)
|
||||
end
|
||||
|
||||
|
||||
def search_message(query)
|
||||
where("message_index @@ plainto_tsquery(?)", query.to_escaped_for_tsquery_split)
|
||||
end
|
||||
|
||||
|
||||
def unread
|
||||
where("is_read = false and is_deleted = false")
|
||||
end
|
||||
|
||||
|
||||
def visible
|
||||
where("owner_id = ?", CurrentUser.id)
|
||||
end
|
||||
|
||||
|
||||
def to_name_matches(name)
|
||||
where("to_id = (select _.id from users _ where lower(_.name) = ?)", name.downcase)
|
||||
end
|
||||
|
||||
|
||||
def from_name_matches(name)
|
||||
where("from_id = (select _.id from users _ where lower(_.name) = ?)", name.downcase)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:message_matches].present?
|
||||
q = q.search_message(params[:message_matches])
|
||||
end
|
||||
|
||||
|
||||
if params[:owner_id].present?
|
||||
q = q.for(params[:owner_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:to_name].present?
|
||||
q = q.to_name_matches(params[:to_name])
|
||||
end
|
||||
|
||||
|
||||
if params[:to_id].present?
|
||||
q = q.where("to_id = ?", params[:to_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:from_name].present?
|
||||
q = q.from_name_matches(params[:from_name])
|
||||
end
|
||||
|
||||
|
||||
if params[:from_id].present?
|
||||
q = q.where("from_id = ?", params[:from_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include AddressMethods
|
||||
include FactoryMethods
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def validate_sender_is_not_banned
|
||||
if from.is_banned?
|
||||
errors[:base] = "Sender is banned and cannot send messages"
|
||||
@@ -162,29 +162,29 @@ class Dmail < ActiveRecord::Base
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def quoted_body
|
||||
"[quote]#{body}[/quote]"
|
||||
end
|
||||
|
||||
|
||||
def send_dmail
|
||||
if to.receive_email_notifications? && to.email.include?("@") && owner_id == CurrentUser.id
|
||||
UserMailer.dmail_notice(self).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def mark_as_read!
|
||||
update_column(:is_read, true)
|
||||
|
||||
|
||||
unless Dmail.exists?(["to_id = ? AND is_read = false", to_id])
|
||||
to.update_column(:has_mail, false)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update_recipient
|
||||
to.update_column(:has_mail, true)
|
||||
end
|
||||
|
||||
|
||||
def visible_to?(user)
|
||||
user.is_moderator? || owner_id == user.id
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class Favorite < ActiveRecord::Base
|
||||
belongs_to :post
|
||||
scope :for_user, lambda {|user_id| where("user_id % 100 = #{user_id.to_i % 100} and user_id = #{user_id.to_i}")}
|
||||
|
||||
|
||||
# this is necessary because there's no trigger for deleting favorites
|
||||
def self.destroy_all(hash)
|
||||
connection.execute("delete from favorites_#{hash[:user_id] % 100} where user_id = #{hash[:user_id]} and post_id = #{hash[:post_id]}")
|
||||
|
||||
@@ -11,54 +11,54 @@ class ForumPost < ActiveRecord::Base
|
||||
validate :validate_topic_is_unlocked
|
||||
before_destroy :validate_topic_is_unlocked
|
||||
after_save :delete_topic_if_original_post
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def body_matches(body)
|
||||
where("forum_posts.text_index @@ plainto_tsquery(E?)", body.to_escaped_for_tsquery)
|
||||
end
|
||||
|
||||
|
||||
def for_user(user_id)
|
||||
where("forum_posts.creator_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def creator_name(name)
|
||||
where("forum_posts.creator_id = (select _.id from users _ where lower(_.name) = ?)", name.downcase)
|
||||
end
|
||||
|
||||
|
||||
def active
|
||||
where("forum_posts.is_deleted = false")
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:topic_id].present?
|
||||
q = q.where("topic_id = ?", params[:topic_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:topic_title_matches].present?
|
||||
q = q.joins(:topic).where("forum_topics.text_index @@ plainto_tsquery(E?)", params[:topic_title_matches].to_escaped_for_tsquery_split)
|
||||
end
|
||||
|
||||
|
||||
if params[:body_matches].present?
|
||||
q = q.body_matches(params[:body_matches])
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.creator_name(params[:creator_name])
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def self.new_reply(params)
|
||||
if params[:topic_id]
|
||||
new(:topic_id => params[:topic_id])
|
||||
@@ -69,13 +69,13 @@ class ForumPost < ActiveRecord::Base
|
||||
new
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def validate_topic_is_unlocked
|
||||
return if CurrentUser.is_moderator?
|
||||
return if topic.nil?
|
||||
|
||||
|
||||
if topic.is_locked?
|
||||
errors.add(:topic, "is locked")
|
||||
errors.add(:topic, "is locked")
|
||||
return false
|
||||
else
|
||||
return true
|
||||
@@ -85,7 +85,7 @@ class ForumPost < ActiveRecord::Base
|
||||
def editable_by?(user)
|
||||
creator_id == user.id || user.is_janitor?
|
||||
end
|
||||
|
||||
|
||||
def update_topic_updated_at
|
||||
if topic
|
||||
topic.updater_id = CurrentUser.id
|
||||
@@ -93,19 +93,19 @@ class ForumPost < ActiveRecord::Base
|
||||
topic.save
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def initialize_updater
|
||||
self.updater_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def initialize_is_deleted
|
||||
self.is_deleted = false if is_deleted.nil?
|
||||
end
|
||||
|
||||
|
||||
def creator_name
|
||||
User.id_to_name(creator_id)
|
||||
end
|
||||
@@ -113,28 +113,28 @@ class ForumPost < ActiveRecord::Base
|
||||
def updater_name
|
||||
User.id_to_name(updater_id)
|
||||
end
|
||||
|
||||
|
||||
def quoted_response
|
||||
stripped_body = body.gsub(/\[quote\](?:.|\n|\r)+?\[\/quote\][\n\r]*/m, "")
|
||||
"[quote]\n#{creator_name} said:\n\n#{stripped_body}\n[/quote]\n\n"
|
||||
end
|
||||
|
||||
|
||||
def forum_topic_page
|
||||
((ForumPost.where("topic_id = ? and created_at <= ?", topic_id, created_at).count) / Danbooru.config.posts_per_page.to_f).ceil
|
||||
end
|
||||
|
||||
|
||||
def is_original_post?
|
||||
ForumPost.exists?(["id = ? and id = (select _.id from forum_posts _ where _.topic_id = ? order by _.id asc limit 1)", id, topic_id])
|
||||
end
|
||||
|
||||
|
||||
def delete_topic_if_original_post
|
||||
if is_deleted? && is_original_post?
|
||||
topic.update_attribute(:is_deleted, true)
|
||||
end
|
||||
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
def build_response
|
||||
dup.tap do |x|
|
||||
x.body = x.quoted_response
|
||||
|
||||
@@ -11,34 +11,34 @@ class ForumTopic < ActiveRecord::Base
|
||||
validates_presence_of :title, :creator_id
|
||||
validates_associated :original_post
|
||||
accepts_nested_attributes_for :original_post
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def title_matches(title)
|
||||
where("text_index @@ plainto_tsquery(E?)", title.to_escaped_for_tsquery_split)
|
||||
end
|
||||
|
||||
|
||||
def active
|
||||
where("is_deleted = false")
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:title_matches].present?
|
||||
q = q.title_matches(params[:title_matches])
|
||||
end
|
||||
|
||||
|
||||
if params[:title].present?
|
||||
q = q.where("title = ?", params[:title])
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def editable_by?(user)
|
||||
creator_id == user.id || user.is_janitor?
|
||||
end
|
||||
@@ -50,15 +50,15 @@ class ForumTopic < ActiveRecord::Base
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def initialize_updater
|
||||
self.updater_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def last_page
|
||||
(posts.count / Danbooru.config.posts_per_page.to_f).ceil
|
||||
end
|
||||
|
||||
|
||||
def presenter(forum_posts)
|
||||
@presenter ||= ForumTopicPresenter.new(self, forum_posts)
|
||||
end
|
||||
|
||||
@@ -5,19 +5,19 @@ class IpBan < ActiveRecord::Base
|
||||
validates_presence_of :reason, :creator, :ip_addr
|
||||
validates_format_of :ip_addr, :with => IP_ADDR_REGEX
|
||||
validates_uniqueness_of :ip_addr, :if => lambda {|rec| rec.ip_addr =~ IP_ADDR_REGEX}
|
||||
|
||||
|
||||
def self.is_banned?(ip_addr)
|
||||
exists?(["ip_addr = ?", ip_addr])
|
||||
end
|
||||
|
||||
|
||||
def self.search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:ip_addr].present?
|
||||
q = q.where("ip_addr = ?", params[:ip_addr])
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
@@ -26,7 +26,7 @@ class IpBan < ActiveRecord::Base
|
||||
notes = count_by_ip_addr("note_versions", user_ids, "updater_id", "updater_ip_addr")
|
||||
pools = count_by_ip_addr("pool_versions", user_ids, "updater_id", "updater_ip_addr")
|
||||
wiki_pages = count_by_ip_addr("wiki_page_versions", user_ids, "updater_id", "updater_ip_addr")
|
||||
|
||||
|
||||
return {
|
||||
"comments" => comments,
|
||||
"notes" => notes,
|
||||
@@ -34,11 +34,11 @@ class IpBan < ActiveRecord::Base
|
||||
"wiki_pages" => wiki_pages
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def self.count_by_ip_addr(table, user_ids, user_id_field = "user_id", ip_addr_field = "ip_addr")
|
||||
select_all_sql("SELECT #{ip_addr_field}, count(*) FROM #{table} WHERE #{user_id_field} IN (?) GROUP BY #{ip_addr_field} ORDER BY count(*) DESC", user_ids)
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
@@ -6,59 +6,59 @@ class JanitorTrial < ActiveRecord::Base
|
||||
after_destroy :create_feedback
|
||||
validates_presence_of :user
|
||||
before_validation :initialize_creator
|
||||
|
||||
|
||||
def self.search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:user_name]
|
||||
q = q.where("user_id = (select _.id from users _ where lower(_.name) = ?)", params[:user_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:user_id]
|
||||
q = q.where("user_id = ?", params[:user_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def initialize_original_level
|
||||
self.original_level = user.level
|
||||
end
|
||||
|
||||
|
||||
def user_name
|
||||
user.try(:name)
|
||||
end
|
||||
|
||||
|
||||
def user_name=(name)
|
||||
self.user_id = User.name_to_id(name)
|
||||
end
|
||||
|
||||
|
||||
def send_dmail
|
||||
body = "You have been selected as a test janitor. You can now approve pending posts and have access to the moderation interface.\n\nOver the next several weeks your approvals will be monitored. If the majority of them are quality uploads, then you will be promoted to full janitor status which grants you the ability to delete and undelete posts, ban users, and revert tag changes from vandals. If you fail the trial period, you will be demoted back to your original level and you'll receive a negative user record indicating you previously attempted and failed a test janitor trial.\n\nThere is a minimum quota of 5 approvals a week to indicate that you are being active. Remember, the goal isn't to approve as much as possible. It's to filter out borderline-quality art.\n\nIf you have any questions please respond to this message."
|
||||
|
||||
|
||||
Dmail.create_split(:title => "Test Janitor Trial Period", :body => body, :to_id => user_id)
|
||||
end
|
||||
|
||||
|
||||
def promote_user
|
||||
user.update_column(:level, User::Levels::JANITOR)
|
||||
end
|
||||
|
||||
|
||||
def create_feedback
|
||||
user.feedback.create(
|
||||
:category => "negative",
|
||||
:body => "Demoted from janitor trial"
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
def promote!
|
||||
destroy
|
||||
end
|
||||
|
||||
|
||||
def demote!
|
||||
user.update_column(:level, original_level)
|
||||
destroy
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
class ModAction < ActiveRecord::Base
|
||||
belongs_to :creator, :class_name => "User"
|
||||
before_validation :initialize_creator, :on => :create
|
||||
|
||||
|
||||
def self.search(params = {})
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
@@ -4,11 +4,11 @@ class NewsUpdate < ActiveRecord::Base
|
||||
scope :recent, order("created_at desc").limit(5)
|
||||
before_validation :initialize_creator, :on => :create
|
||||
before_validation :initialize_updater
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def initialize_updater
|
||||
self.updater_id = CurrentUser.id
|
||||
end
|
||||
|
||||
@@ -12,28 +12,28 @@ class Note < ActiveRecord::Base
|
||||
after_save :create_version
|
||||
validate :post_must_not_be_note_locked
|
||||
attr_accessible :x, :y, :width, :height, :body, :updater_id, :updater_ip_addr, :is_active, :post_id, :html_id
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def active
|
||||
where("is_active = TRUE")
|
||||
end
|
||||
|
||||
|
||||
def body_matches(query)
|
||||
where("body_index @@ plainto_tsquery(E?)", query.to_escaped_for_tsquery_split)
|
||||
end
|
||||
|
||||
|
||||
def post_tags_match(query)
|
||||
joins(:post).where("posts.tag_index @@ to_tsquery('danbooru', E?)", query.to_escaped_for_tsquery_split)
|
||||
end
|
||||
|
||||
|
||||
def creator_name(name)
|
||||
where("creator_id = (select _.id from users _ where lower(_.name) = ?)", name.downcase)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:body_matches].present?
|
||||
q = q.body_matches(params[:body_matches])
|
||||
end
|
||||
@@ -41,23 +41,23 @@ class Note < ActiveRecord::Base
|
||||
if params[:post_id].present?
|
||||
q = q.where("post_id = ?", params[:post_id].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.creator_name(params[:creator_name])
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ApiMethods
|
||||
def serializable_hash(options = {})
|
||||
options ||= {}
|
||||
@@ -70,7 +70,7 @@ class Note < ActiveRecord::Base
|
||||
hash = super(options)
|
||||
hash
|
||||
end
|
||||
|
||||
|
||||
def to_xml(options = {}, &block)
|
||||
options ||= {}
|
||||
options[:procs] ||= []
|
||||
@@ -78,34 +78,34 @@ class Note < ActiveRecord::Base
|
||||
super(options, &block)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
|
||||
|
||||
def presenter
|
||||
@presenter ||= NotePresenter.new(self)
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def initialize_updater
|
||||
self.updater_id = CurrentUser.id
|
||||
self.updater_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def post_must_not_be_note_locked
|
||||
if is_locked?
|
||||
errors.add :post, "is note locked"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def is_locked?
|
||||
Post.exists?(["id = ? AND is_note_locked = ?", post_id, true])
|
||||
end
|
||||
|
||||
|
||||
def blank_body
|
||||
self.body = "(empty)" if body.blank?
|
||||
end
|
||||
@@ -121,10 +121,10 @@ class Note < ActiveRecord::Base
|
||||
execute_sql("UPDATE posts SET last_noted_at = NULL WHERE id = ?", post_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def create_version
|
||||
CurrentUser.increment!(:note_update_count)
|
||||
|
||||
|
||||
versions.create(
|
||||
:updater_id => updater_id,
|
||||
:updater_ip_addr => updater_ip_addr,
|
||||
@@ -137,7 +137,7 @@ class Note < ActiveRecord::Base
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
def revert_to(version)
|
||||
self.x = version.x
|
||||
self.y = version.y
|
||||
@@ -149,7 +149,7 @@ class Note < ActiveRecord::Base
|
||||
self.updater_id = CurrentUser.id
|
||||
self.updater_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def revert_to!(version)
|
||||
revert_to(version)
|
||||
save!
|
||||
|
||||
@@ -6,22 +6,22 @@ class NoteVersion < ActiveRecord::Base
|
||||
def self.search(params)
|
||||
q = scoped
|
||||
params = {} if params.blank?
|
||||
|
||||
|
||||
if params[:updater_id]
|
||||
q = q.where("updater_id = ?", params[:updater_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:post_id]
|
||||
q = q.where("post_id = ?", params[:post_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:note_id]
|
||||
q = q.where("note_id = ?", params[:note_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
def initialize_updater
|
||||
self.updater_id = CurrentUser.id
|
||||
self.updater_ip_addr = CurrentUser.ip_addr
|
||||
|
||||
@@ -19,41 +19,41 @@ class Pool < ActiveRecord::Base
|
||||
def active
|
||||
where("is_deleted = false")
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
params = {} if params.blank?
|
||||
|
||||
|
||||
if params[:name_matches].present?
|
||||
params[:name_matches] = params[:name_matches].tr(" ", "_")
|
||||
params[:name_matches] = "*#{params[:name_matches]}*" unless params[:name_matches] =~ /\*/
|
||||
q = q.where("name ilike ? escape E'\\\\'", params[:name_matches].to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
|
||||
if params[:description_matches].present?
|
||||
q = q.where("description like ? escape E'\\\\'", "%" + params[:description_matches].to_escaped_for_sql_like + "%")
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:sort] == "name"
|
||||
q = q.order("name")
|
||||
else
|
||||
q = q.order("updated_at desc")
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def self.name_to_id(name)
|
||||
if name =~ /^\d+$/
|
||||
name.to_i
|
||||
@@ -61,15 +61,15 @@ class Pool < ActiveRecord::Base
|
||||
select_value_sql("SELECT id FROM pools WHERE lower(name) = ?", name.downcase.tr(" ", "_")).to_i
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.id_to_name(id)
|
||||
select_value_sql("SELECT name FROM pools WHERE id = ?", id)
|
||||
end
|
||||
|
||||
|
||||
def self.options
|
||||
select_all_sql("SELECT id, name FROM pools WHERE is_active = true AND is_deleted = false ORDER BY name LIMIT 100").map {|x| [x["name"].tr("_", " "), x["id"]]}
|
||||
end
|
||||
|
||||
|
||||
def self.create_anonymous
|
||||
Pool.new do |pool|
|
||||
pool.name = "TEMP:#{Time.now.to_f}.#{rand(1_000_000)}"
|
||||
@@ -78,15 +78,15 @@ class Pool < ActiveRecord::Base
|
||||
pool.save
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.normalize_name(name)
|
||||
name.gsub(/\s+/, "_")
|
||||
end
|
||||
|
||||
|
||||
def self.normalize_post_ids(post_ids)
|
||||
post_ids.scan(/\d+/).join(" ")
|
||||
end
|
||||
|
||||
|
||||
def self.find_by_name(name)
|
||||
if name =~ /^\d+$/
|
||||
where("id = ?", name.to_i).first
|
||||
@@ -96,32 +96,32 @@ class Pool < ActiveRecord::Base
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize_is_active
|
||||
self.is_deleted = false if is_deleted.nil?
|
||||
self.is_active = true if is_active.nil?
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def normalize_name
|
||||
self.name = Pool.normalize_name(name)
|
||||
end
|
||||
|
||||
|
||||
def pretty_name
|
||||
name.tr("_", " ")
|
||||
end
|
||||
|
||||
|
||||
def creator_name
|
||||
User.id_to_name(creator_id)
|
||||
end
|
||||
|
||||
|
||||
def normalize_post_ids
|
||||
self.post_ids = self.class.normalize_post_ids(post_ids)
|
||||
end
|
||||
|
||||
|
||||
def revert_to!(version)
|
||||
self.post_ids = version.post_ids
|
||||
synchronize!
|
||||
@@ -130,39 +130,39 @@ class Pool < ActiveRecord::Base
|
||||
def contains?(post_id)
|
||||
post_ids =~ /(?:\A| )#{post_id}(?:\Z| )/
|
||||
end
|
||||
|
||||
|
||||
def deletable_by?(user)
|
||||
user.is_janitor?
|
||||
end
|
||||
|
||||
|
||||
def create_mod_action_for_destroy
|
||||
ModAction.create(:description => "deleted pool ##{id} name=#{name} post_ids=#{post_ids}")
|
||||
end
|
||||
|
||||
|
||||
def add!(post)
|
||||
return if contains?(post.id)
|
||||
|
||||
|
||||
update_attributes(:post_ids => add_number_to_string(post.id, post_ids), :post_count => post_count + 1)
|
||||
post.add_pool!(self)
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
|
||||
def remove!(post)
|
||||
return unless contains?(post.id)
|
||||
|
||||
|
||||
update_attributes(:post_ids => remove_number_from_string(post.id, post_ids), :post_count => post_count - 1)
|
||||
post.remove_pool!(self)
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
|
||||
def add_number_to_string(number, string)
|
||||
"#{string} #{number}"
|
||||
end
|
||||
|
||||
|
||||
def remove_number_from_string(number, string)
|
||||
string.gsub(/(?:\A| )#{number}(?:\Z| )/, " ")
|
||||
end
|
||||
|
||||
|
||||
def posts(options = {})
|
||||
offset = options[:offset] || 0
|
||||
limit = options[:limit] || Danbooru.config.posts_per_page
|
||||
@@ -173,47 +173,47 @@ class Pool < ActiveRecord::Base
|
||||
Post.where("false")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def synchronize!
|
||||
added = post_id_array - post_id_array_was
|
||||
removed = post_id_array_was - post_id_array
|
||||
|
||||
|
||||
added.each do |post_id|
|
||||
post = Post.find(post_id)
|
||||
post.add_pool!(self)
|
||||
end
|
||||
|
||||
|
||||
removed.each do |post_id|
|
||||
post = Post.find(post_id)
|
||||
post.remove_pool!(self)
|
||||
end
|
||||
|
||||
|
||||
self.post_count = post_id_array.size
|
||||
save
|
||||
end
|
||||
|
||||
|
||||
def post_id_array
|
||||
@post_id_array ||= post_ids.scan(/\d+/).map(&:to_i)
|
||||
end
|
||||
|
||||
|
||||
def post_id_array=(array)
|
||||
self.post_ids = array.join(" ")
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
|
||||
def post_id_array_was
|
||||
@post_id_array_was ||= post_ids_was.scan(/\d+/).map(&:to_i)
|
||||
end
|
||||
|
||||
|
||||
def clear_post_id_array
|
||||
@post_id_array = nil
|
||||
@post_id_array_was = nil
|
||||
end
|
||||
|
||||
|
||||
def neighbors(post)
|
||||
@neighbor_posts ||= begin
|
||||
post_ids =~ /\A#{post.id} (\d+)|(\d+) #{post.id} (\d+)|(\d+) #{post.id}\Z/
|
||||
|
||||
|
||||
if $2 && $3
|
||||
OpenStruct.new(:previous => $2.to_i, :next => $3.to_i)
|
||||
elsif $1
|
||||
@@ -225,7 +225,7 @@ class Pool < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def create_version
|
||||
last_version = versions.last
|
||||
|
||||
@@ -235,20 +235,20 @@ class Pool < ActiveRecord::Base
|
||||
versions.create(:post_ids => post_ids)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def reload(options = {})
|
||||
super
|
||||
@neighbor_posts = nil
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
|
||||
def to_xml(options = {}, &block)
|
||||
# to_xml ignores the serializable_hash method
|
||||
options ||= {}
|
||||
options[:methods] = [:creator_name]
|
||||
super(options, &block)
|
||||
end
|
||||
|
||||
|
||||
def serializable_hash(options = {})
|
||||
return {
|
||||
"created_at" => created_at,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class PoolVersion < ActiveRecord::Base
|
||||
class Error < Exception ; end
|
||||
|
||||
|
||||
validates_presence_of :updater_id, :updater_ip_addr
|
||||
belongs_to :pool
|
||||
belongs_to :updater, :class_name => "User"
|
||||
@@ -10,38 +10,38 @@ class PoolVersion < ActiveRecord::Base
|
||||
def for_user(user_id)
|
||||
where("updater_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:updater_id].present?
|
||||
q = q.for_user(params[:updater_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:updater_name].present?
|
||||
q = q.where("updater_id = (select _.id from users _ where lower(_.name) = ?)", params[:updater_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:pool_id].present?
|
||||
q = q.where("pool_id = ?", params[:pool_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def updater_name
|
||||
User.id_to_name(updater_id)
|
||||
end
|
||||
|
||||
|
||||
def initialize_updater
|
||||
self.updater_id = CurrentUser.id
|
||||
self.updater_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def post_id_array
|
||||
@post_id_array ||= post_ids.scan(/\d+/).map(&:to_i)
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ class Post < ActiveRecord::Base
|
||||
class ApprovalError < Exception ; end
|
||||
class DisapprovalError < Exception ; end
|
||||
class SearchError < Exception ; end
|
||||
|
||||
|
||||
attr_accessor :old_tag_string, :old_parent_id, :has_constraints
|
||||
after_destroy :delete_files
|
||||
after_destroy :delete_remote_files
|
||||
@@ -34,7 +34,7 @@ class Post < ActiveRecord::Base
|
||||
attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id, :as => [:member, :builder, :privileged, :platinum, :contributor, :janitor, :moderator, :admin, :default]
|
||||
attr_accessible :is_rating_locked, :is_note_locked, :as => [:builder, :contributor, :janitor, :moderator, :admin]
|
||||
attr_accessible :is_status_locked, :as => [:admin]
|
||||
|
||||
|
||||
module FileMethods
|
||||
def distribute_files
|
||||
RemoteFileManager.new(file_path).distribute
|
||||
@@ -42,14 +42,14 @@ class Post < ActiveRecord::Base
|
||||
RemoteFileManager.new(ssd_preview_file_path).distribute if Danbooru.config.ssd_path
|
||||
RemoteFileManager.new(large_file_path).distribute if has_large?
|
||||
end
|
||||
|
||||
|
||||
def delete_remote_files
|
||||
RemoteFileManager.new(file_path).delete
|
||||
RemoteFileManager.new(real_preview_file_path).delete
|
||||
RemoteFileManager.new(ssd_preview_file_path).delete if Danbooru.config.ssd_path
|
||||
RemoteFileManager.new(large_file_path).delete if has_large?
|
||||
end
|
||||
|
||||
|
||||
def delete_files
|
||||
FileUtils.rm_f(file_path)
|
||||
FileUtils.rm_f(large_file_path)
|
||||
@@ -60,11 +60,11 @@ class Post < ActiveRecord::Base
|
||||
def file_path_prefix
|
||||
Rails.env == "test" ? "test." : ""
|
||||
end
|
||||
|
||||
|
||||
def file_path
|
||||
"#{Rails.root}/public/data/#{file_path_prefix}#{md5}.#{file_ext}"
|
||||
end
|
||||
|
||||
|
||||
def large_file_path
|
||||
if has_large?
|
||||
"#{Rails.root}/public/data/sample/#{file_path_prefix}#{Danbooru.config.large_image_prefix}#{md5}.jpg"
|
||||
@@ -72,11 +72,11 @@ class Post < ActiveRecord::Base
|
||||
file_path
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def real_preview_file_path
|
||||
"#{Rails.root}/public/data/preview/#{file_path_prefix}#{md5}.jpg"
|
||||
end
|
||||
|
||||
|
||||
def ssd_preview_file_path
|
||||
"#{Danbooru.config.ssd_path}/public/data/preview/#{file_path_prefix}#{md5}.jpg"
|
||||
end
|
||||
@@ -92,7 +92,7 @@ class Post < ActiveRecord::Base
|
||||
def file_url
|
||||
"/data/#{file_path_prefix}#{md5}.#{file_ext}"
|
||||
end
|
||||
|
||||
|
||||
def large_file_url
|
||||
if has_large?
|
||||
"/data/sample/#{file_path_prefix}#{Danbooru.config.large_image_prefix}#{md5}.jpg"
|
||||
@@ -105,14 +105,14 @@ class Post < ActiveRecord::Base
|
||||
if !is_image?
|
||||
return "/images/download-preview.png"
|
||||
end
|
||||
|
||||
|
||||
if Danbooru.config.ssd_path
|
||||
"/ssd/data/preview/#{file_path_prefix}#{md5}.jpg"
|
||||
else
|
||||
"/data/preview/#{file_path_prefix}#{md5}.jpg"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def file_url_for(user)
|
||||
case user.default_image_size
|
||||
when "large"
|
||||
@@ -121,12 +121,12 @@ class Post < ActiveRecord::Base
|
||||
else
|
||||
file_url
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
file_url
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def file_path_for(user)
|
||||
case user.default_image_size
|
||||
when "large"
|
||||
@@ -135,34 +135,34 @@ class Post < ActiveRecord::Base
|
||||
else
|
||||
file_path
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
file_path
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def is_image?
|
||||
file_ext =~ /jpg|jpeg|gif|png/
|
||||
end
|
||||
|
||||
|
||||
def is_flash?
|
||||
file_ext =~ /swf/
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ImageMethods
|
||||
def has_large?
|
||||
image_width.present? && image_width > Danbooru.config.large_image_width
|
||||
end
|
||||
|
||||
|
||||
def has_large
|
||||
has_large?
|
||||
end
|
||||
|
||||
|
||||
def large_image_width
|
||||
[Danbooru.config.large_image_width, image_width].min
|
||||
end
|
||||
|
||||
|
||||
def large_image_height
|
||||
ratio = Danbooru.config.large_image_width.to_f / image_width.to_f
|
||||
if ratio < 1
|
||||
@@ -171,58 +171,58 @@ class Post < ActiveRecord::Base
|
||||
image_height
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def image_width_for(user)
|
||||
case user.default_image_size
|
||||
when "large"
|
||||
large_image_width
|
||||
|
||||
|
||||
else
|
||||
image_width
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def image_height_for(user)
|
||||
case user.default_image_size
|
||||
when "large"
|
||||
large_image_height
|
||||
|
||||
|
||||
else
|
||||
image_height
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def resize_percentage
|
||||
100 * large_image_width.to_f / image_width.to_f
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ApprovalMethods
|
||||
def is_approvable?
|
||||
!is_status_locked? && (is_pending? || is_flagged? || is_deleted?) && approver_id != CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def flag!(reason)
|
||||
if is_status_locked?
|
||||
raise PostFlag::Error.new("Post is locked and cannot be flagged")
|
||||
end
|
||||
|
||||
|
||||
flag = flags.create(:reason => reason, :is_resolved => false)
|
||||
|
||||
|
||||
if flag.errors.any?
|
||||
raise PostFlag::Error.new(flag.errors.full_messages.join("; "))
|
||||
end
|
||||
|
||||
update_column(:is_flagged, true) unless is_flagged?
|
||||
end
|
||||
|
||||
|
||||
def appeal!(reason)
|
||||
if is_status_locked?
|
||||
raise PostAppeal::Error.new("Post is locked and cannot be appealed")
|
||||
end
|
||||
|
||||
|
||||
appeal = appeals.create(:reason => reason)
|
||||
|
||||
|
||||
if appeal.errors.any?
|
||||
raise PostAppeal::Error.new(appeal.errors.full_messages.join("; "))
|
||||
end
|
||||
@@ -233,17 +233,17 @@ class Post < ActiveRecord::Base
|
||||
errors.add(:is_status_locked, "; post cannot be approved")
|
||||
raise ApprovalError.new("Post is locked and cannot be approved")
|
||||
end
|
||||
|
||||
|
||||
if uploader_id == CurrentUser.id
|
||||
errors.add(:base, "You cannot approve a post you uploaded")
|
||||
raise ApprovalError.new("You cannot approve a post you uploaded")
|
||||
end
|
||||
|
||||
|
||||
if approver_id == CurrentUser.id
|
||||
errors.add(:approver, "have already approved this post")
|
||||
raise ApprovalError.new("You have previously approved this post and cannot approve it again")
|
||||
raise ApprovalError.new("You have previously approved this post and cannot approve it again")
|
||||
end
|
||||
|
||||
|
||||
flags.each {|x| x.resolve!}
|
||||
self.is_flagged = false
|
||||
self.is_pending = false
|
||||
@@ -252,12 +252,12 @@ class Post < ActiveRecord::Base
|
||||
save!
|
||||
# ModAction.create(:description => "approved post ##{id}")
|
||||
end
|
||||
|
||||
|
||||
def disapproved_by?(user)
|
||||
PostDisapproval.where(:user_id => user.id, :post_id => id).exists?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module PresenterMethods
|
||||
def presenter
|
||||
@presenter ||= PostPresenter.new(self)
|
||||
@@ -267,15 +267,15 @@ class Post < ActiveRecord::Base
|
||||
case rating
|
||||
when "q"
|
||||
"Questionable"
|
||||
|
||||
|
||||
when "e"
|
||||
"Explicit"
|
||||
|
||||
|
||||
when "s"
|
||||
"Safe"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def normalized_source
|
||||
if source =~ /pixiv\.net\/img/
|
||||
img_id = source[/(\d+)(_s|_m|(_big)?_p\d+)?\.[\w\?]+\s*$/, 1]
|
||||
@@ -290,28 +290,28 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module TagMethods
|
||||
def tag_array
|
||||
@tag_array ||= Tag.scan_tags(tag_string)
|
||||
end
|
||||
|
||||
|
||||
def tag_array_was
|
||||
@tag_array_was ||= Tag.scan_tags(tag_string_was)
|
||||
end
|
||||
|
||||
|
||||
def create_tags
|
||||
set_tag_string(tag_array.map {|x| Tag.find_or_create_by_name(x).name}.uniq.sort.join(" "))
|
||||
end
|
||||
|
||||
|
||||
def increment_tag_post_counts
|
||||
execute_sql("UPDATE tags SET post_count = post_count + 1 WHERE name IN (?)", tag_array) if tag_array.any?
|
||||
end
|
||||
|
||||
|
||||
def decrement_tag_post_counts
|
||||
execute_sql("UPDATE tags SET post_count = post_count - 1 WHERE name IN (?)", tag_array) if tag_array.any?
|
||||
end
|
||||
|
||||
|
||||
def update_tag_post_counts
|
||||
decrement_tags = tag_array_was - tag_array
|
||||
increment_tags = tag_array - tag_array_was
|
||||
@@ -321,55 +321,55 @@ class Post < ActiveRecord::Base
|
||||
Post.expire_cache_for_all(increment_tags)
|
||||
Post.expire_cache_for_all([""]) if new_record? || id <= 100_000
|
||||
end
|
||||
|
||||
|
||||
def set_tag_counts
|
||||
self.tag_count = 0
|
||||
self.tag_count_general = 0
|
||||
self.tag_count_artist = 0
|
||||
self.tag_count_copyright = 0
|
||||
self.tag_count_character = 0
|
||||
|
||||
|
||||
categories = Tag.categories_for(tag_array)
|
||||
categories.each_value do |category|
|
||||
self.tag_count += 1
|
||||
|
||||
|
||||
case category
|
||||
when Tag.categories.general
|
||||
self.tag_count_general += 1
|
||||
|
||||
|
||||
when Tag.categories.artist
|
||||
self.tag_count_artist += 1
|
||||
|
||||
|
||||
when Tag.categories.copyright
|
||||
self.tag_count_copyright += 1
|
||||
|
||||
|
||||
when Tag.categories.character
|
||||
self.tag_count_character += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def merge_old_tags
|
||||
if old_tag_string
|
||||
# If someone else committed changes to this post before we did,
|
||||
# then try to merge the tag changes together.
|
||||
current_tags = tag_array_was()
|
||||
new_tags = tag_array()
|
||||
old_tags = Tag.scan_tags(old_tag_string)
|
||||
old_tags = Tag.scan_tags(old_tag_string)
|
||||
set_tag_string(((current_tags + new_tags) - old_tags + (current_tags & new_tags)).uniq.sort.join(" "))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def reset_tag_array_cache
|
||||
@tag_array = nil
|
||||
@tag_array_was = nil
|
||||
end
|
||||
|
||||
|
||||
def set_tag_string(string)
|
||||
self.tag_string = string
|
||||
reset_tag_array_cache
|
||||
end
|
||||
|
||||
|
||||
def normalize_tags
|
||||
normalized_tags = Tag.scan_tags(tag_string)
|
||||
normalized_tags = TagAlias.to_aliased(normalized_tags)
|
||||
@@ -379,52 +379,52 @@ class Post < ActiveRecord::Base
|
||||
normalized_tags.sort!
|
||||
set_tag_string(normalized_tags.uniq.sort.join(" "))
|
||||
end
|
||||
|
||||
|
||||
def filter_metatags(tags)
|
||||
@pre_metatags, tags = tags.partition {|x| x =~ /\A(?:rating|parent):/}
|
||||
@post_metatags, tags = tags.partition {|x| x =~ /\A(?:-pool|pool|fav):/}
|
||||
apply_pre_metatags
|
||||
return tags
|
||||
end
|
||||
|
||||
|
||||
def apply_post_metatags
|
||||
return unless @post_metatags
|
||||
|
||||
|
||||
@post_metatags.each do |tag|
|
||||
case tag
|
||||
when /^-pool:(\d+)$/
|
||||
pool = Pool.find_by_id($1.to_i)
|
||||
remove_pool!(pool) if pool
|
||||
|
||||
|
||||
when /^-pool:(.+)$/
|
||||
pool = Pool.find_by_name($1)
|
||||
remove_pool!(pool) if pool
|
||||
|
||||
|
||||
when /^pool:(\d+)$/
|
||||
pool = Pool.find_by_id($1.to_i)
|
||||
add_pool!(pool) if pool
|
||||
|
||||
|
||||
when /^pool:(.+)$/
|
||||
pool = Pool.find_by_name($1)
|
||||
if pool.nil?
|
||||
pool = Pool.create(:name => $1, :description => "This pool was automatically generated")
|
||||
end
|
||||
add_pool!(pool) if pool
|
||||
|
||||
|
||||
when /^fav:(.+)$/
|
||||
add_favorite!(CurrentUser.user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def apply_pre_metatags
|
||||
return unless @pre_metatags
|
||||
|
||||
|
||||
@pre_metatags.each do |tag|
|
||||
case tag
|
||||
when /^parent:none$/, /^parent:0$/
|
||||
self.parent_id = nil
|
||||
|
||||
|
||||
when /^parent:(\d+)$/
|
||||
self.parent_id = $1.to_i
|
||||
|
||||
@@ -433,31 +433,31 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def has_tag?(tag)
|
||||
tag_string =~ /(?:^| )#{tag}(?:$| )/
|
||||
end
|
||||
|
||||
|
||||
def has_dup_tag?
|
||||
has_tag?("duplicate") ? true : false
|
||||
end
|
||||
|
||||
|
||||
def tag_categories
|
||||
@tag_categories ||= Tag.categories_for(tag_array)
|
||||
end
|
||||
|
||||
|
||||
def copyright_tags
|
||||
typed_tags("copyright")
|
||||
end
|
||||
|
||||
|
||||
def character_tags
|
||||
typed_tags("character")
|
||||
end
|
||||
|
||||
|
||||
def artist_tags
|
||||
typed_tags("artist")
|
||||
end
|
||||
|
||||
|
||||
def typed_tags(name)
|
||||
@typed_tags ||= {}
|
||||
@typed_tags[name] ||= begin
|
||||
@@ -466,7 +466,7 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def essential_tag_string
|
||||
tag_array.each do |tag|
|
||||
if tag_categories[tag] == Danbooru.config.tag_category_mapping["copyright"]
|
||||
@@ -489,16 +489,16 @@ class Post < ActiveRecord::Base
|
||||
return tag_array.first
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module FavoriteMethods
|
||||
def favorited_by?(user_id)
|
||||
fav_string =~ /(?:\A| )fav:#{user_id}(?:\Z| )/
|
||||
end
|
||||
|
||||
|
||||
def append_user_to_fav_string(user_id)
|
||||
update_column(:fav_string, (fav_string + " fav:#{user_id}").strip)
|
||||
end
|
||||
|
||||
|
||||
def add_favorite!(user)
|
||||
return if favorited_by?(user.id)
|
||||
append_user_to_fav_string(user.id)
|
||||
@@ -506,11 +506,11 @@ class Post < ActiveRecord::Base
|
||||
increment!(:score) if CurrentUser.is_privileged?
|
||||
user.add_favorite!(self)
|
||||
end
|
||||
|
||||
|
||||
def delete_user_from_fav_string(user_id)
|
||||
update_column(:fav_string, fav_string.gsub(/(?:\A| )fav:#{user_id}(?:\Z| )/, " ").strip)
|
||||
end
|
||||
|
||||
|
||||
def remove_favorite!(user)
|
||||
return unless favorited_by?(user.id)
|
||||
decrement!(:fav_count)
|
||||
@@ -518,12 +518,12 @@ class Post < ActiveRecord::Base
|
||||
delete_user_from_fav_string(user.id)
|
||||
user.remove_favorite!(self)
|
||||
end
|
||||
|
||||
|
||||
def favorited_user_ids
|
||||
fav_string.scan(/\d+/)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module UploaderMethods
|
||||
def initialize_uploader
|
||||
if uploader_id.blank?
|
||||
@@ -531,12 +531,12 @@ class Post < ActiveRecord::Base
|
||||
self.uploader_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def uploader_name
|
||||
User.id_to_name(uploader_id).tr("_", " ")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module PoolMethods
|
||||
def pools
|
||||
@pools ||= begin
|
||||
@@ -544,18 +544,18 @@ class Post < ActiveRecord::Base
|
||||
Pool.where(["is_deleted = false and id in (?)", pool_ids])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def belongs_to_pool?(pool)
|
||||
pool_string =~ /(?:\A| )pool:#{pool.id}(?:\Z| )/
|
||||
end
|
||||
|
||||
|
||||
def add_pool!(pool)
|
||||
return if belongs_to_pool?(pool)
|
||||
self.pool_string = "#{pool_string} pool:#{pool.id}".strip
|
||||
update_column(:pool_string, pool_string) unless new_record?
|
||||
pool.add!(self)
|
||||
end
|
||||
|
||||
|
||||
def remove_pool!(pool)
|
||||
return unless belongs_to_pool?(pool)
|
||||
self.pool_string = pool_string.gsub(/(?:\A| )pool:#{pool.id}(?:\Z| )/, " ").strip
|
||||
@@ -563,7 +563,7 @@ class Post < ActiveRecord::Base
|
||||
pool.remove!(self)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module VoteMethods
|
||||
def can_be_voted_by?(user)
|
||||
!votes.exists?(["user_id = ?", user.id])
|
||||
@@ -585,7 +585,7 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module CountMethods
|
||||
def fix_post_counts
|
||||
post.set_tag_counts
|
||||
@@ -595,17 +595,17 @@ class Post < ActiveRecord::Base
|
||||
post.update_column(:tag_count_copyright, post.tag_count_copyright)
|
||||
post.update_column(:tag_count_character, post.tag_count_character)
|
||||
end
|
||||
|
||||
|
||||
def get_count_from_cache(tags)
|
||||
count = Cache.get(count_cache_key(tags))
|
||||
|
||||
|
||||
if count.nil?
|
||||
count = select_value_sql("SELECT post_count FROM tags WHERE name = ?", tags.to_s)
|
||||
end
|
||||
|
||||
|
||||
count
|
||||
end
|
||||
|
||||
|
||||
def set_count_in_cache(tags, count, expiry = nil)
|
||||
if expiry.nil?
|
||||
if count < 100
|
||||
@@ -614,14 +614,14 @@ class Post < ActiveRecord::Base
|
||||
expiry = (count * 4).minutes
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Cache.put(count_cache_key(tags), count, expiry)
|
||||
end
|
||||
|
||||
|
||||
def count_cache_key(tags)
|
||||
"pfc:#{Cache.sanitize(tags)}"
|
||||
end
|
||||
|
||||
|
||||
def fast_count(tags = "")
|
||||
tags = tags.to_s.strip
|
||||
|
||||
@@ -633,7 +633,7 @@ class Post < ActiveRecord::Base
|
||||
count = fast_count_search(tags)
|
||||
else
|
||||
count = get_count_from_cache(tags)
|
||||
|
||||
|
||||
if count.to_i == 0
|
||||
count = fast_count_search(tags)
|
||||
end
|
||||
@@ -643,7 +643,7 @@ class Post < ActiveRecord::Base
|
||||
rescue SearchError
|
||||
0
|
||||
end
|
||||
|
||||
|
||||
def fast_count_search(tags)
|
||||
count = Post.with_timeout(500, Danbooru.config.blank_tag_search_fast_count || 1_000_000) do
|
||||
Post.tag_match(tags).count
|
||||
@@ -654,19 +654,19 @@ class Post < ActiveRecord::Base
|
||||
count
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module CacheMethods
|
||||
def expire_cache_for_all(tag_names)
|
||||
Danbooru.config.all_server_hosts.each do |host|
|
||||
delay(:queue => host).expire_cache(tag_names)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def expire_cache(tag_names)
|
||||
tag_names.each do |tag_name|
|
||||
Cache.delete(Post.count_cache_key(tag_name))
|
||||
end
|
||||
|
||||
|
||||
if Post.fast_count("").to_i < 1000
|
||||
Cache.delete(Post.count_cache_key(""))
|
||||
end
|
||||
@@ -674,7 +674,7 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
|
||||
module ParentMethods
|
||||
# A parent has many children. A child belongs to a parent.
|
||||
# A parent has many children. A child belongs to a parent.
|
||||
# A parent cannot have a parent.
|
||||
#
|
||||
# After deleting a child:
|
||||
@@ -686,14 +686,14 @@ class Post < ActiveRecord::Base
|
||||
# After deleting a parent:
|
||||
# - Move favorites to the first child.
|
||||
# - Reparent all active children to the first active child.
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def update_has_children_flag_for(post_id)
|
||||
return if post_id.nil?
|
||||
has_children = Post.exists?(["is_deleted = ? AND parent_id = ?", false, post_id])
|
||||
execute_sql("UPDATE posts SET has_children = ? WHERE id = ?", has_children, post_id)
|
||||
end
|
||||
|
||||
|
||||
def recalculate_has_children_for_all_posts
|
||||
transaction do
|
||||
execute_sql("UPDATE posts SET has_children = false WHERE has_children = true")
|
||||
@@ -701,7 +701,7 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.included(m)
|
||||
m.extend(ClassMethods)
|
||||
end
|
||||
@@ -712,13 +712,13 @@ class Post < ActiveRecord::Base
|
||||
errors.add(:parent, "can not have a parent")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update_parent_on_destroy
|
||||
Post.update_has_children_flag_for(id)
|
||||
Post.update_has_children_flag_for(parent_id) if parent_id
|
||||
Post.update_has_children_flag_for(parent_id_was) if parent_id_was && parent_id != parent_id_was
|
||||
end
|
||||
|
||||
|
||||
def update_children_on_destroy
|
||||
if children.size == 0
|
||||
# do nothing
|
||||
@@ -741,7 +741,7 @@ class Post < ActiveRecord::Base
|
||||
Post.update_has_children_flag_for(parent_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def give_favorites_to_parent
|
||||
return if parent.nil?
|
||||
|
||||
@@ -753,26 +753,26 @@ class Post < ActiveRecord::Base
|
||||
update_column(:score, 0)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module DeletionMethods
|
||||
def annihilate!
|
||||
if is_status_locked?
|
||||
self.errors.add(:is_status_locked, "; cannot delete post")
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
ModAction.create(:description => "permanently deleted post ##{id}")
|
||||
decrement_tag_post_counts
|
||||
delete!(:without_mod_action => true)
|
||||
destroy
|
||||
end
|
||||
|
||||
|
||||
def delete!(options = {})
|
||||
if is_status_locked?
|
||||
self.errors.add(:is_status_locked, "; cannot delete post")
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
Post.transaction do
|
||||
update_column(:is_deleted, true)
|
||||
update_column(:is_pending, false)
|
||||
@@ -782,19 +782,19 @@ class Post < ActiveRecord::Base
|
||||
update_parent_on_destroy
|
||||
# decrement_tag_post_counts
|
||||
update_column(:parent_id, nil)
|
||||
|
||||
|
||||
unless options[:without_mod_action]
|
||||
ModAction.create(:description => "deleted post ##{id}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def undelete!
|
||||
if is_status_locked?
|
||||
self.errors.add(:is_status_locked, "; cannot undelete post")
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
self.is_deleted = false
|
||||
self.approver_id = CurrentUser.id
|
||||
save
|
||||
@@ -803,7 +803,7 @@ class Post < ActiveRecord::Base
|
||||
ModAction.create(:description => "undeleted post ##{id}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module VersionMethods
|
||||
def create_version
|
||||
if created_at == updated_at
|
||||
@@ -824,31 +824,31 @@ class Post < ActiveRecord::Base
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def revert_to(target)
|
||||
self.tag_string = target.tags
|
||||
self.rating = target.rating
|
||||
self.source = target.source
|
||||
self.parent_id = target.parent_id
|
||||
end
|
||||
|
||||
|
||||
def revert_to!(target)
|
||||
revert_to(target)
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module NoteMethods
|
||||
def last_noted_at_as_integer
|
||||
last_noted_at.to_i
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
super + [:tag_index]
|
||||
end
|
||||
|
||||
|
||||
def serializable_hash(options = {})
|
||||
options ||= {}
|
||||
options[:except] ||= []
|
||||
@@ -860,7 +860,7 @@ class Post < ActiveRecord::Base
|
||||
hash = super(options)
|
||||
hash
|
||||
end
|
||||
|
||||
|
||||
def to_xml(options = {}, &block)
|
||||
options ||= {}
|
||||
options[:procs] ||= []
|
||||
@@ -868,7 +868,7 @@ class Post < ActiveRecord::Base
|
||||
options[:procs] << lambda {|options, record| options[:builder].tag!("has-large", record.has_large?, :type => "boolean")}
|
||||
super(options, &block)
|
||||
end
|
||||
|
||||
|
||||
def to_legacy_json
|
||||
return {
|
||||
"has_comments" => last_commented_at.present?,
|
||||
@@ -892,7 +892,7 @@ class Post < ActiveRecord::Base
|
||||
"file_url" => file_url
|
||||
}.to_json
|
||||
end
|
||||
|
||||
|
||||
def status
|
||||
if is_pending?
|
||||
"pending"
|
||||
@@ -905,44 +905,44 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def pending
|
||||
where("is_pending = ?", true)
|
||||
end
|
||||
|
||||
|
||||
def flagged
|
||||
where("is_flagged = ?", true)
|
||||
end
|
||||
|
||||
|
||||
def pending_or_flagged
|
||||
where("(is_pending = ? or (is_flagged = ? and id in (select _.post_id from post_flags _ where _.created_at >= ?)))", true, true, 1.week.ago)
|
||||
end
|
||||
|
||||
|
||||
def undeleted
|
||||
where("is_deleted = ?", false)
|
||||
end
|
||||
|
||||
|
||||
def deleted
|
||||
where("is_deleted = ?", true)
|
||||
end
|
||||
|
||||
|
||||
def visible(user)
|
||||
Danbooru.config.can_user_see_post_conditions(user)
|
||||
end
|
||||
|
||||
|
||||
def commented_before(date)
|
||||
where("last_commented_at < ?", date).order("last_commented_at DESC")
|
||||
end
|
||||
|
||||
|
||||
def has_notes
|
||||
where("last_noted_at is not null")
|
||||
end
|
||||
|
||||
|
||||
def for_user(user_id)
|
||||
where("uploader_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def available_for_moderation(hidden)
|
||||
if hidden.present?
|
||||
where("posts.id IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id)
|
||||
@@ -950,31 +950,31 @@ class Post < ActiveRecord::Base
|
||||
where("posts.id NOT IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def hidden_from_moderation
|
||||
where("id IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id)
|
||||
end
|
||||
|
||||
|
||||
def raw_tag_match(tag)
|
||||
where("posts.tag_index @@ to_tsquery('danbooru', E?)", tag.to_escaped_for_tsquery)
|
||||
end
|
||||
|
||||
|
||||
def tag_match(query)
|
||||
PostQueryBuilder.new(query).build
|
||||
end
|
||||
|
||||
|
||||
def positive
|
||||
where("score > 1")
|
||||
end
|
||||
|
||||
|
||||
def negative
|
||||
where("score < -1")
|
||||
end
|
||||
|
||||
|
||||
def updater_name_matches(name)
|
||||
where("updater_id = (select _.id from users _ where lower(_.name) = ?)", name.downcase)
|
||||
end
|
||||
|
||||
|
||||
def after_id(num)
|
||||
if num.present?
|
||||
where("id > ?", num.to_i).reorder("id asc")
|
||||
@@ -982,7 +982,7 @@ class Post < ActiveRecord::Base
|
||||
where("true")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def before_id(num)
|
||||
if num.present?
|
||||
where("id < ?", num.to_i).reorder("id desc")
|
||||
@@ -990,27 +990,27 @@ class Post < ActiveRecord::Base
|
||||
where("true")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:before_id].present?
|
||||
q = q.before_id(params[:before_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:after_id].present?
|
||||
q = q.after_id(params[:after_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:tag_match].present?
|
||||
q = q.tag_match(params[:tag_match])
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include FileMethods
|
||||
include ImageMethods
|
||||
include ApprovalMethods
|
||||
@@ -1028,7 +1028,7 @@ class Post < ActiveRecord::Base
|
||||
include NoteMethods
|
||||
include ApiMethods
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def reload(options = nil)
|
||||
super
|
||||
reset_tag_array_cache
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class PostAppeal < ActiveRecord::Base
|
||||
class Error < Exception ; end
|
||||
|
||||
|
||||
belongs_to :creator, :class_name => "User"
|
||||
belongs_to :post
|
||||
validates_presence_of :reason, :creator_id, :creator_ip_addr
|
||||
@@ -8,38 +8,38 @@ class PostAppeal < ActiveRecord::Base
|
||||
validate :validate_creator_is_not_limited
|
||||
before_validation :initialize_creator, :on => :create
|
||||
validates_uniqueness_of :creator_id, :scope => :post_id, :message => "have already appealed this post"
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def for_user(user_id)
|
||||
where("creator_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def recent
|
||||
where("created_at >= ?", 1.day.ago)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.for_user(params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:post_id].present?
|
||||
q = q.where("post_id = ?", params[:post_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def validate_creator_is_not_limited
|
||||
if appeal_count_for_creator >= Danbooru.config.max_appeals_per_day
|
||||
errors[:creator] << "can appeal at most #{Danbooru.config.max_appeals_per_day} post a day"
|
||||
@@ -48,7 +48,7 @@ class PostAppeal < ActiveRecord::Base
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def validate_post_is_inactive
|
||||
if !post.is_deleted? && !post.is_flagged?
|
||||
errors[:post] << "is active"
|
||||
@@ -57,12 +57,12 @@ class PostAppeal < ActiveRecord::Base
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
self.creator_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def appeal_count_for_creator
|
||||
PostAppeal.for_user(creator_id).recent.count
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class PostFlag < ActiveRecord::Base
|
||||
class Error < Exception ; end
|
||||
|
||||
|
||||
belongs_to :creator, :class_name => "User"
|
||||
belongs_to :post
|
||||
validates_presence_of :reason, :creator_id, :creator_ip_addr
|
||||
@@ -14,45 +14,45 @@ class PostFlag < ActiveRecord::Base
|
||||
def resolved
|
||||
where("is_resolved = ?", true)
|
||||
end
|
||||
|
||||
|
||||
def unresolved
|
||||
where("is_resolved = ?", false)
|
||||
end
|
||||
|
||||
|
||||
def recent
|
||||
where("created_at >= ?", 1.day.ago)
|
||||
end
|
||||
|
||||
|
||||
def old
|
||||
where("created_at <= ?", 3.days.ago)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:post_id].present?
|
||||
q = q.where("post_id = ?", params[:post_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def update_post
|
||||
post.update_column(:is_flagged, true) unless post.is_flagged?
|
||||
end
|
||||
|
||||
|
||||
def validate_creator_is_not_limited
|
||||
if CurrentUser.is_janitor?
|
||||
false
|
||||
@@ -63,7 +63,7 @@ class PostFlag < ActiveRecord::Base
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def validate_post_is_active
|
||||
if post.is_deleted?
|
||||
errors[:post] << "is deleted"
|
||||
@@ -72,16 +72,16 @@ class PostFlag < ActiveRecord::Base
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
self.creator_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def resolve!
|
||||
update_column(:is_resolved, true)
|
||||
end
|
||||
|
||||
|
||||
def flag_count_for_creator
|
||||
PostFlag.where(:creator_id => creator_id).recent.count
|
||||
end
|
||||
|
||||
@@ -2,38 +2,38 @@ class PostVersion < ActiveRecord::Base
|
||||
belongs_to :post
|
||||
belongs_to :updater, :class_name => "User"
|
||||
before_validation :initialize_updater
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def for_user(user_id)
|
||||
where("updater_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def updater_name(name)
|
||||
where("updater_id = (select _.id from users _ where lower(_.name) = ?)", name.downcase)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
params = {} if params.blank?
|
||||
|
||||
|
||||
if params[:updater_name].present?
|
||||
q = q.updater_name(params[:updater_name])
|
||||
end
|
||||
|
||||
|
||||
if params[:updater_id].present?
|
||||
q = q.where("updater_id = ?", params[:updater_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:post_id].present?
|
||||
q = q.where("post_id = ?", params[:post_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def self.create_from_post(post)
|
||||
if post.created_at == post.updated_at
|
||||
create_from_created_post(post)
|
||||
@@ -41,20 +41,20 @@ class PostVersion < ActiveRecord::Base
|
||||
create_from_updated_post(post)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize_updater
|
||||
self.updater_id = CurrentUser.id
|
||||
self.updater_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def tag_array
|
||||
@tag_array ||= tags.scan(/\S+/)
|
||||
end
|
||||
|
||||
|
||||
def presenter
|
||||
PostVersionPresenter.new(self)
|
||||
end
|
||||
|
||||
|
||||
def reload
|
||||
@tag_array = nil
|
||||
super
|
||||
@@ -70,7 +70,7 @@ class PostVersion < ActiveRecord::Base
|
||||
end
|
||||
return diffs
|
||||
end
|
||||
|
||||
|
||||
def diff(version)
|
||||
latest_tags = post.tag_array
|
||||
new_tags = tag_array
|
||||
@@ -92,11 +92,11 @@ class PostVersion < ActiveRecord::Base
|
||||
:obsolete_removed_tags => old_tags & latest_tags,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def previous
|
||||
PostVersion.where("post_id = ? and updated_at < ?", post_id, updated_at).order("updated_at desc").first
|
||||
end
|
||||
|
||||
|
||||
def truncated_source
|
||||
source.gsub(/^http:\/\//, "").sub(/\/.+/, "")
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class PostVote < ActiveRecord::Base
|
||||
class Error < Exception ; end
|
||||
|
||||
|
||||
belongs_to :post
|
||||
before_validation :initialize_user, :on => :create
|
||||
validates_presence_of :post_id, :user_id, :score
|
||||
@@ -13,7 +13,7 @@ class PostVote < ActiveRecord::Base
|
||||
write_attribute(:score, -1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize_user
|
||||
self.user_id = CurrentUser.user.id
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class ReportMailer < ActionMailer::Base
|
||||
default :host => Danbooru.config.server_host, :from => Danbooru.config.contact_email, :content_type => "text/html"
|
||||
|
||||
|
||||
def moderator_report(email)
|
||||
mail(:to => email, :subject => "#{Danbooru.config.app_name} - Moderator Report")
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ class Tag < ActiveRecord::Base
|
||||
METATAGS = "-user|user|-approver|approver|-pool|pool|-fav|fav|sub|md5|-rating|rating|width|height|mpixels|score|filesize|source|id|date|order|status|tagcount|gentags|arttags|chartags|copytags|parent|pixiv"
|
||||
attr_accessible :category
|
||||
has_one :wiki_page, :foreign_key => "name", :primary_key => "title"
|
||||
|
||||
|
||||
module ApiMethods
|
||||
def to_legacy_json
|
||||
return {
|
||||
@@ -15,70 +15,70 @@ class Tag < ActiveRecord::Base
|
||||
}.to_json
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class CategoryMapping
|
||||
Danbooru.config.reverse_tag_category_mapping.each do |value, category|
|
||||
define_method(category.downcase) do
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def regexp
|
||||
@regexp ||= Regexp.compile(Danbooru.config.tag_category_mapping.keys.sort_by {|x| -x.size}.join("|"))
|
||||
end
|
||||
|
||||
|
||||
def value_for(string)
|
||||
Danbooru.config.tag_category_mapping[string.to_s.downcase] || 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module CountMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def counts_for(tag_names)
|
||||
select_all_sql("SELECT name, post_count FROM tags WHERE name IN (?)", tag_names)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def real_post_count
|
||||
@real_post_count ||= Post.raw_tag_match(name).count
|
||||
end
|
||||
|
||||
|
||||
def fix_post_count
|
||||
update_column(:post_count, real_post_count)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ViewCountMethods
|
||||
def increment_view_count(name)
|
||||
Cache.incr("tvc:#{Cache.sanitize(name)}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module CategoryMethods
|
||||
module ClassMethods
|
||||
def categories
|
||||
@category_mapping ||= CategoryMapping.new
|
||||
end
|
||||
|
||||
|
||||
def select_category_for(tag_name)
|
||||
select_value_sql("SELECT category FROM tags WHERE name = ?", tag_name).to_i
|
||||
end
|
||||
|
||||
|
||||
def category_for(tag_name)
|
||||
Cache.get("tc:#{Cache.sanitize(tag_name)}") do
|
||||
select_category_for(tag_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def categories_for(tag_names)
|
||||
Cache.get_multi(tag_names, "tc") do |name|
|
||||
select_category_for(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.included(m)
|
||||
m.extend(ClassMethods)
|
||||
end
|
||||
@@ -86,16 +86,16 @@ class Tag < ActiveRecord::Base
|
||||
def category_name
|
||||
Danbooru.config.reverse_tag_category_mapping[category]
|
||||
end
|
||||
|
||||
|
||||
def update_category_cache_for_all
|
||||
update_category_cache
|
||||
Danbooru.config.other_server_hosts.each do |host|
|
||||
delay(:queue => host).update_category_cache
|
||||
end
|
||||
|
||||
|
||||
delay(:queue => "default").update_category_post_counts
|
||||
end
|
||||
|
||||
|
||||
def update_category_post_counts
|
||||
Post.raw_tag_match(name).find_each do |post|
|
||||
post.reload
|
||||
@@ -107,18 +107,18 @@ class Tag < ActiveRecord::Base
|
||||
post.update_column(:tag_count_character, post.tag_count_character)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update_category_cache
|
||||
Cache.put("tc:#{Cache.sanitize(name)}", category, 1.hour)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module StatisticsMethods
|
||||
def trending
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module NameMethods
|
||||
def normalize_name(name)
|
||||
name.downcase.tr(" ", "_").gsub(/\A[-~]+/, "").gsub(/\*/, "")
|
||||
@@ -138,7 +138,7 @@ class Tag < ActiveRecord::Base
|
||||
if tag
|
||||
if category
|
||||
category_id = categories.value_for(category)
|
||||
|
||||
|
||||
if category_id != tag.category
|
||||
tag.update_column(:category, category_id)
|
||||
tag.update_category_cache_for_all
|
||||
@@ -160,7 +160,7 @@ class Tag < ActiveRecord::Base
|
||||
def normalize(query)
|
||||
query.to_s.strip
|
||||
end
|
||||
|
||||
|
||||
def scan_query(query)
|
||||
normalize(query).scan(/\S+/).uniq
|
||||
end
|
||||
@@ -221,7 +221,7 @@ class Tag < ActiveRecord::Base
|
||||
|
||||
when /\A>(.+)/
|
||||
return [:gt, parse_cast($1, type)]
|
||||
|
||||
|
||||
when /,/
|
||||
return [:in, range.split(/,/)]
|
||||
|
||||
@@ -230,19 +230,19 @@ class Tag < ActiveRecord::Base
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def parse_tag(tag, output)
|
||||
if tag[0] == "-" && tag.size > 1
|
||||
output[:exclude] << tag[1..-1].downcase
|
||||
|
||||
|
||||
elsif tag[0] == "~" && tag.size > 1
|
||||
output[:include] << tag[1..-1].downcase
|
||||
|
||||
|
||||
elsif tag =~ /\*/
|
||||
matches = Tag.name_matches(tag.downcase).all(:select => "name", :limit => Danbooru.config.tag_query_limit, :order => "post_count DESC").map(&:name)
|
||||
matches = ["~no_matches~"] if matches.empty?
|
||||
output[:include] += matches
|
||||
|
||||
|
||||
else
|
||||
output[:related] << tag.downcase
|
||||
end
|
||||
@@ -250,15 +250,15 @@ class Tag < ActiveRecord::Base
|
||||
|
||||
def parse_query(query, options = {})
|
||||
q = {}
|
||||
|
||||
|
||||
q[:tag_count] = 0
|
||||
|
||||
|
||||
q[:tags] = {
|
||||
:related => [],
|
||||
:include => [],
|
||||
:exclude => []
|
||||
}
|
||||
|
||||
|
||||
scan_query(query).each do |token|
|
||||
q[:tag_count] += 1 unless token == "status:deleted"
|
||||
|
||||
@@ -267,25 +267,25 @@ class Tag < ActiveRecord::Base
|
||||
when "-user"
|
||||
q[:uploader_id_neg] ||= []
|
||||
q[:uploader_id_neg] << User.name_to_id($2)
|
||||
|
||||
|
||||
when "user"
|
||||
q[:uploader_id] = User.name_to_id($2)
|
||||
q[:uploader_id] = -1 if q[:uploader_id].nil?
|
||||
|
||||
|
||||
when "-approver"
|
||||
q[:approver_id_neg] ||= []
|
||||
q[:approver_id_neg] << User.name_to_id($2)
|
||||
|
||||
|
||||
when "approver"
|
||||
q[:approver_id] = User.name_to_id($2)
|
||||
q[:approver_id] = -1 if q[:approver_id].nil?
|
||||
|
||||
|
||||
when "-pool"
|
||||
q[:tags][:exclude] << "pool:#{Pool.name_to_id($2)}"
|
||||
|
||||
|
||||
when "pool"
|
||||
q[:tags][:related] << "pool:#{Pool.name_to_id($2)}"
|
||||
|
||||
|
||||
when "-fav"
|
||||
q[:tags][:exclude] << "fav:#{User.name_to_id($2)}"
|
||||
|
||||
@@ -304,16 +304,16 @@ class Tag < ActiveRecord::Base
|
||||
|
||||
when "rating"
|
||||
q[:rating] = $2
|
||||
|
||||
|
||||
when "id"
|
||||
q[:post_id] = parse_helper($2)
|
||||
|
||||
|
||||
when "width"
|
||||
q[:width] = parse_helper($2)
|
||||
|
||||
|
||||
when "height"
|
||||
q[:height] = parse_helper($2)
|
||||
|
||||
|
||||
when "mpixels"
|
||||
q[:mpixels] = parse_helper($2, :float)
|
||||
|
||||
@@ -325,13 +325,13 @@ class Tag < ActiveRecord::Base
|
||||
|
||||
when "source"
|
||||
q[:source] = ($2.to_escaped_for_sql_like + "%").gsub(/%+/, '%')
|
||||
|
||||
|
||||
when "date"
|
||||
q[:date] = parse_helper($2, :date)
|
||||
|
||||
when "tagcount"
|
||||
q[:post_tag_count] = parse_helper($2)
|
||||
|
||||
|
||||
when "gentags"
|
||||
q[:general_tag_count] = parse_helper($2)
|
||||
|
||||
@@ -343,26 +343,26 @@ class Tag < ActiveRecord::Base
|
||||
|
||||
when "copytags"
|
||||
q[:copyright_tag_count] = parse_helper($2)
|
||||
|
||||
|
||||
when "parent"
|
||||
q[:parent_id] = $2.to_i
|
||||
|
||||
|
||||
when "order"
|
||||
q[:order] = $2.downcase
|
||||
|
||||
when "status"
|
||||
q[:status] = $2.downcase
|
||||
|
||||
|
||||
when "pixiv"
|
||||
q[:pixiv] = parse_helper($2)
|
||||
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
parse_tag(token, q[:tags])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
normalize_tags_in_query(q)
|
||||
|
||||
return q
|
||||
@@ -374,7 +374,7 @@ class Tag < ActiveRecord::Base
|
||||
query_hash[:tags][:related] = TagAlias.to_aliased(query_hash[:tags][:related])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module RelationMethods
|
||||
def update_related
|
||||
return unless should_update_related?
|
||||
@@ -384,13 +384,13 @@ class Tag < ActiveRecord::Base
|
||||
self.related_tags_updated_at = Time.now
|
||||
save
|
||||
end
|
||||
|
||||
|
||||
def update_related_if_outdated
|
||||
if should_update_related? && Delayed::Job.count < 200
|
||||
delay(:queue => "default").update_related
|
||||
delay(:queue => "default").update_related
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def related_cache_expiry
|
||||
base = Math.sqrt([post_count, 0].max)
|
||||
if base > 24 * 7
|
||||
@@ -401,21 +401,21 @@ class Tag < ActiveRecord::Base
|
||||
base
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def should_update_related?
|
||||
related_tags.blank? || related_tags_updated_at.blank? || related_tags_updated_at < related_cache_expiry.hours.ago
|
||||
end
|
||||
|
||||
|
||||
def related_tag_array
|
||||
update_related_if_outdated
|
||||
related_tags.to_s.split(/ /).in_groups_of(2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SuggestionMethods
|
||||
def find_suggestions(query)
|
||||
query_tokens = query.split(/_/)
|
||||
|
||||
|
||||
if query_tokens.size == 2
|
||||
search_for = query_tokens.reverse.join("_").to_escaped_for_sql_like
|
||||
else
|
||||
@@ -425,42 +425,42 @@ class Tag < ActiveRecord::Base
|
||||
Tag.where(["name LIKE ? ESCAPE E'\\\\' AND post_count > 0 AND name <> ?", search_for, query]).all(:order => "post_count DESC", :limit => 6, :select => "name").map(&:name).sort
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def name_matches(name)
|
||||
where("name LIKE ? ESCAPE E'\\\\'", name.downcase.to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
|
||||
def named(name)
|
||||
where("name = ?", TagAlias.to_aliased([name]).join(""))
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
params = {} if params.blank?
|
||||
|
||||
|
||||
if params[:name_matches].present?
|
||||
q = q.name_matches(params[:name_matches].strip)
|
||||
end
|
||||
|
||||
|
||||
if params[:category].present?
|
||||
q = q.where("category = ?", params[:category])
|
||||
end
|
||||
|
||||
|
||||
if params[:hide_empty].blank? || params[:hide_empty] != "no"
|
||||
q = q.where("post_count > 0")
|
||||
end
|
||||
|
||||
|
||||
if params[:limit].present?
|
||||
q = q.limit(params[:limit].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:order] == "name"
|
||||
q = q.reorder("name")
|
||||
|
||||
|
||||
elsif params[:order] == "date"
|
||||
q = q.reorder("id desc")
|
||||
|
||||
|
||||
elsif params[:sort] == "date"
|
||||
q = q.reorder("id desc")
|
||||
|
||||
@@ -470,11 +470,11 @@ class Tag < ActiveRecord::Base
|
||||
else
|
||||
q = q.reorder("post_count desc")
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include ApiMethods
|
||||
include CountMethods
|
||||
extend ViewCountMethods
|
||||
|
||||
@@ -8,20 +8,20 @@ class TagAlias < ActiveRecord::Base
|
||||
validate :absence_of_transitive_relation
|
||||
belongs_to :creator, :class_name => "User"
|
||||
belongs_to :forum_topic
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def name_matches(name)
|
||||
where("(antecedent_name like ? escape E'\\\\' or consequent_name like ? escape E'\\\\')", name.downcase.to_escaped_for_sql_like, name.downcase.to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:name_matches].present?
|
||||
q = q.name_matches(params[:name_matches])
|
||||
end
|
||||
|
||||
|
||||
if params[:antecedent_name].present?
|
||||
q = q.where("antecedent_name = ?", params[:antecedent_name])
|
||||
end
|
||||
@@ -29,20 +29,20 @@ class TagAlias < ActiveRecord::Base
|
||||
if params[:id].present?
|
||||
q = q.where("id = ?", params[:id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module CacheMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def clear_cache_for(name)
|
||||
Cache.delete("ta:#{Cache.sanitize(name)}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def clear_all_cache
|
||||
Danbooru.config.all_server_hosts.each do |host|
|
||||
TagAlias.delay(:queue => host).clear_cache_for(antecedent_name)
|
||||
@@ -50,10 +50,10 @@ class TagAlias < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
include CacheMethods
|
||||
|
||||
|
||||
def self.to_aliased(names)
|
||||
alias_hash = Cache.get_multi(names.flatten, "ta") do |name|
|
||||
ta = TagAlias.find_by_antecedent_name(name)
|
||||
@@ -63,10 +63,10 @@ class TagAlias < ActiveRecord::Base
|
||||
name
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
alias_hash.values.flatten.uniq
|
||||
end
|
||||
|
||||
|
||||
def process!
|
||||
update_column(:status, "processing")
|
||||
clear_all_cache
|
||||
@@ -75,28 +75,28 @@ class TagAlias < ActiveRecord::Base
|
||||
rescue Exception => e
|
||||
update_column(:status, "error: #{e}")
|
||||
end
|
||||
|
||||
|
||||
def is_pending?
|
||||
status == "pending"
|
||||
end
|
||||
|
||||
|
||||
def is_active?
|
||||
status == "active"
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.user.id
|
||||
self.creator_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def antecedent_tag
|
||||
Tag.find_by_name(antecedent_name)
|
||||
end
|
||||
|
||||
|
||||
def consequent_tag
|
||||
Tag.find_by_name(consequent_name)
|
||||
end
|
||||
|
||||
|
||||
def absence_of_transitive_relation
|
||||
# We don't want a -> b && b -> c chains
|
||||
if self.class.exists?(["antecedent_name = ?", consequent_name]) || self.class.exists?(["consequent_name = ?", antecedent_name])
|
||||
@@ -104,15 +104,15 @@ class TagAlias < ActiveRecord::Base
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def ensure_category_consistency
|
||||
if antecedent_tag && consequent_tag && antecedent_tag.category != consequent_tag.category
|
||||
consequent_tag.update_attribute(:category, antecedent_tag.category)
|
||||
end
|
||||
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
def update_posts
|
||||
Post.raw_tag_match(antecedent_name).find_each do |post|
|
||||
escaped_antecedent_name = Regexp.escape(antecedent_name)
|
||||
|
||||
@@ -6,17 +6,17 @@ class TagImplication < ActiveRecord::Base
|
||||
validates_presence_of :creator_id, :antecedent_name, :consequent_name
|
||||
validates_uniqueness_of :antecedent_name, :scope => :consequent_name
|
||||
validate :absence_of_circular_relation
|
||||
|
||||
|
||||
module DescendantMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
# assumes names are normalized
|
||||
def with_descendants(names)
|
||||
(names + where("antecedent_name in (?) and status = ?", names, "active").map(&:descendant_names_array)).flatten.uniq
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def descendants
|
||||
@descendants ||= begin
|
||||
[].tap do |all|
|
||||
@@ -45,7 +45,7 @@ class TagImplication < ActiveRecord::Base
|
||||
|
||||
def update_descendant_names_for_parent
|
||||
p = parent
|
||||
|
||||
|
||||
while p
|
||||
p.update_descendant_names!
|
||||
p = p.parent
|
||||
@@ -56,22 +56,22 @@ class TagImplication < ActiveRecord::Base
|
||||
@descendants = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ParentMethods
|
||||
def parent
|
||||
@parent ||= self.class.where(["consequent_name = ?", antecedent_name]).first
|
||||
end
|
||||
|
||||
|
||||
def clear_parent_cache
|
||||
@parent = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def name_matches(name)
|
||||
where("(antecedent_name like ? escape E'\\\\' or consequent_name like ? escape E'\\\\')", name.downcase.to_escaped_for_sql_like, name.downcase.to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
@@ -79,11 +79,11 @@ class TagImplication < ActiveRecord::Base
|
||||
if params[:id].present?
|
||||
q = q.where("id = ?", params[:id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:name_matches].present?
|
||||
q = q.name_matches(params[:name_matches])
|
||||
end
|
||||
|
||||
|
||||
if params[:antecedent_name].present?
|
||||
q = q.where("antecedent_name = ?", params[:antecedent_name])
|
||||
end
|
||||
@@ -91,16 +91,16 @@ class TagImplication < ActiveRecord::Base
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include DescendantMethods
|
||||
include ParentMethods
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.user.id
|
||||
self.creator_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
|
||||
|
||||
def process!
|
||||
update_column(:status, "processing")
|
||||
update_descendant_names_for_parent
|
||||
@@ -109,7 +109,7 @@ class TagImplication < ActiveRecord::Base
|
||||
rescue Exception => e
|
||||
update_column(:status, "error: #{e}")
|
||||
end
|
||||
|
||||
|
||||
def absence_of_circular_relation
|
||||
# We don't want a -> b && b -> a chains
|
||||
if self.class.exists?(["antecedent_name = ? and consequent_name = ?", consequent_name, antecedent_name])
|
||||
@@ -117,7 +117,7 @@ class TagImplication < ActiveRecord::Base
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update_posts
|
||||
Post.tag_match("#{antecedent_name} status:any").find_each do |post|
|
||||
escaped_antecedent_name = Regexp.escape(antecedent_name)
|
||||
@@ -129,23 +129,23 @@ class TagImplication < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def is_pending?
|
||||
status == "pending"
|
||||
end
|
||||
|
||||
|
||||
def is_active?
|
||||
status == "active"
|
||||
end
|
||||
|
||||
|
||||
def antecedent_tag
|
||||
Tag.find_by_name(antecedent_name)
|
||||
end
|
||||
|
||||
|
||||
def consequent_tag
|
||||
Tag.find_by_name(consequent_name)
|
||||
end
|
||||
|
||||
|
||||
def reload(options = {})
|
||||
super
|
||||
clear_parent_cache
|
||||
|
||||
@@ -8,15 +8,15 @@ class TagSubscription < ActiveRecord::Base
|
||||
validates_presence_of :name, :tag_query, :creator_id
|
||||
validates_format_of :tag_query, :with => /^(?:\S+\s*){1,20}$/m, :message => "can have up to 20 tags"
|
||||
validate :creator_can_create_subscriptions, :on => :create
|
||||
|
||||
|
||||
def normalize_name
|
||||
self.name = name.gsub(/\s+/, "_")
|
||||
end
|
||||
|
||||
|
||||
def pretty_name
|
||||
name.tr("_", " ")
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
@@ -24,7 +24,7 @@ class TagSubscription < ActiveRecord::Base
|
||||
def initialize_post_ids
|
||||
process
|
||||
end
|
||||
|
||||
|
||||
def creator_can_create_subscriptions
|
||||
if TagSubscription.owned_by(creator).count >= Danbooru.config.max_tag_subscriptions
|
||||
self.errors.add(:creator, "can create up to #{Danbooru.config.max_tag_subscriptions} tag subscriptions")
|
||||
@@ -49,38 +49,38 @@ class TagSubscription < ActiveRecord::Base
|
||||
end
|
||||
self.post_ids = post_ids.sort.reverse.slice(0, Danbooru.config.tag_subscription_post_limit).join(",")
|
||||
end
|
||||
|
||||
|
||||
def is_active?
|
||||
creator.last_logged_in_at && creator.last_logged_in_at > 1.year.ago
|
||||
end
|
||||
|
||||
|
||||
def editable_by?(user)
|
||||
user.is_moderator? || creator_id == user.id
|
||||
end
|
||||
|
||||
|
||||
def post_id_array
|
||||
post_ids.split(/,/)
|
||||
end
|
||||
|
||||
|
||||
def self.search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:creator_id]
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_name]
|
||||
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
def self.visible_to(user)
|
||||
where("(is_public = TRUE OR creator_id = ? OR ?)", user.id, user.is_moderator?)
|
||||
end
|
||||
|
||||
|
||||
def self.owned_by(user)
|
||||
where("creator_id = ?", user.id)
|
||||
end
|
||||
@@ -95,10 +95,10 @@ class TagSubscription < ActiveRecord::Base
|
||||
end
|
||||
|
||||
user = User.find_by_name(user_name)
|
||||
|
||||
|
||||
if user
|
||||
relation = where(["creator_id = ?", user.id])
|
||||
|
||||
|
||||
if sub_group
|
||||
relation = relation.where(["name ILIKE ? ESCAPE E'\\\\'", sub_group.to_escaped_for_sql_like])
|
||||
end
|
||||
@@ -106,16 +106,16 @@ class TagSubscription < ActiveRecord::Base
|
||||
relation.map {|x| x.tag_query.split(/ /)}.flatten
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.find_post_ids(user_id, name = nil, limit = Danbooru.config.tag_subscription_post_limit)
|
||||
relation = where("creator_id = ?", user_id)
|
||||
|
||||
|
||||
if name
|
||||
relation = relation.where("lower(name) LIKE ? ESCAPE E'\\\\'", name.downcase.to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
|
||||
relation.each do |tag_sub|
|
||||
tag_sub.update_column(:last_accessed_at, Time.now)
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ require "tmpdir"
|
||||
|
||||
class Upload < ActiveRecord::Base
|
||||
class Error < Exception ; end
|
||||
|
||||
|
||||
attr_accessor :file, :image_width, :image_height, :file_ext, :md5, :file_size
|
||||
belongs_to :uploader, :class_name => "User"
|
||||
belongs_to :post
|
||||
@@ -13,7 +13,7 @@ class Upload < ActiveRecord::Base
|
||||
after_destroy :delete_temp_file
|
||||
validate :uploader_is_not_limited
|
||||
validate :file_or_source_is_present, :on => :create
|
||||
|
||||
|
||||
module ValidationMethods
|
||||
def uploader_is_not_limited
|
||||
if !uploader.can_upload?
|
||||
@@ -37,34 +37,34 @@ class Upload < ActiveRecord::Base
|
||||
def validate_md5_uniqueness
|
||||
md5_post = Post.find_by_md5(md5)
|
||||
if md5_post
|
||||
merge_tags(md5_post)
|
||||
merge_tags(md5_post)
|
||||
raise "duplicate: #{md5_post.id}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def validate_file_exists
|
||||
unless file_path && File.exists?(file_path)
|
||||
raise "file does not exist"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def validate_file_content_type
|
||||
unless is_valid_content_type?
|
||||
raise "invalid content type (#{file_ext} not allowed)"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def validate_md5_confirmation
|
||||
if !md5_confirmation.blank? && md5_confirmation != md5
|
||||
raise "md5 mismatch"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ConversionMethods
|
||||
def process! force=false
|
||||
return if !force && status =~ /processing|completed|error/
|
||||
|
||||
|
||||
CurrentUser.scoped(uploader, uploader_ip_addr) do
|
||||
update_attribute(:status, "processing")
|
||||
if is_downloadable?
|
||||
@@ -79,7 +79,7 @@ class Upload < ActiveRecord::Base
|
||||
calculate_file_size(file_path)
|
||||
add_file_size_tags!(file_path)
|
||||
if has_dimensions?
|
||||
calculate_dimensions(file_path)
|
||||
calculate_dimensions(file_path)
|
||||
add_dimension_tags!
|
||||
end
|
||||
generate_resizes(file_path)
|
||||
@@ -118,18 +118,18 @@ class Upload < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def merge_tags(post)
|
||||
post.tag_string += " #{tag_string}"
|
||||
post.save
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module FileMethods
|
||||
def delete_temp_file
|
||||
FileUtils.rm_f(temp_file_path)
|
||||
end
|
||||
|
||||
|
||||
def move_file
|
||||
FileUtils.mv(file_path, md5_file_path)
|
||||
end
|
||||
@@ -142,7 +142,7 @@ class Upload < ActiveRecord::Base
|
||||
def calculate_hash(source_path)
|
||||
self.md5 = Digest::MD5.file(source_path).hexdigest
|
||||
end
|
||||
|
||||
|
||||
def is_image?
|
||||
["jpg", "gif", "png"].include?(file_ext)
|
||||
end
|
||||
@@ -176,10 +176,10 @@ class Upload < ActiveRecord::Base
|
||||
self.image_width = image_size.get_width
|
||||
self.image_height = image_size.get_height
|
||||
end
|
||||
|
||||
|
||||
def add_dimension_tags!
|
||||
return if !Danbooru.config.enable_dimension_autotagging
|
||||
|
||||
|
||||
if image_width >= 10_000 || image_height >= 10_000
|
||||
self.tag_string = "#{tag_string} incredibly_absurdres".strip
|
||||
elsif image_width >= 3200 || image_height >= 2400
|
||||
@@ -190,37 +190,37 @@ class Upload < ActiveRecord::Base
|
||||
self.tag_string = "#{tag_string} lowres".strip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Does this file have image dimensions?
|
||||
def has_dimensions?
|
||||
%w(jpg gif png swf).include?(file_ext)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ContentTypeMethods
|
||||
def is_valid_content_type?
|
||||
file_ext =~ /jpg|gif|png|swf/
|
||||
end
|
||||
|
||||
|
||||
def content_type_to_file_ext(content_type)
|
||||
case content_type
|
||||
when "image/jpeg"
|
||||
"jpg"
|
||||
|
||||
|
||||
when "image/gif"
|
||||
"gif"
|
||||
|
||||
|
||||
when "image/png"
|
||||
"png"
|
||||
|
||||
|
||||
when "application/x-shockwave-flash"
|
||||
"swf"
|
||||
|
||||
|
||||
else
|
||||
"bin"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Converts a content type string to a file extension
|
||||
def file_ext_to_content_type(file_ext)
|
||||
case file_ext
|
||||
@@ -247,12 +247,12 @@ class Upload < ActiveRecord::Base
|
||||
prefix = Rails.env == "test" ? "test." : ""
|
||||
"#{Rails.root}/public/data/#{prefix}#{md5}.#{file_ext}"
|
||||
end
|
||||
|
||||
|
||||
def ssd_file_path
|
||||
prefix = Rails.env == "test" ? "test." : ""
|
||||
"#{Danbooru.config.ssd_path}/public/data/preview/#{prefix}#{md5}.jpg"
|
||||
end
|
||||
|
||||
|
||||
def resized_file_path_for(width)
|
||||
prefix = Rails.env == "test" ? "test." : ""
|
||||
|
||||
@@ -264,12 +264,12 @@ class Upload < ActiveRecord::Base
|
||||
"#{Rails.root}/public/data/sample/#{Danbooru.config.large_image_prefix}#{prefix}#{md5}.jpg"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def temp_file_path
|
||||
@temp_file_path ||= File.join(Rails.root, "tmp", "upload_#{Time.now.to_f}.#{Process.pid}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module DownloaderMethods
|
||||
# Determines whether the source is downloadable
|
||||
def is_downloadable?
|
||||
@@ -296,7 +296,7 @@ class Upload < ActiveRecord::Base
|
||||
if file.respond_to?(:tempfile) && file.tempfile
|
||||
FileUtils.cp(file.tempfile.path, file_path)
|
||||
else
|
||||
File.open(file_path, 'wb') do |out|
|
||||
File.open(file_path, 'wb') do |out|
|
||||
out.write(file.read)
|
||||
end
|
||||
end
|
||||
@@ -305,69 +305,69 @@ class Upload < ActiveRecord::Base
|
||||
self.file_ext = content_type_to_file_ext(content_type)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module StatusMethods
|
||||
def initialize_status
|
||||
self.status = "pending"
|
||||
end
|
||||
|
||||
|
||||
def is_pending?
|
||||
status == "pending"
|
||||
end
|
||||
|
||||
|
||||
def is_processing?
|
||||
status == "processing"
|
||||
end
|
||||
|
||||
|
||||
def is_completed?
|
||||
status == "completed"
|
||||
end
|
||||
|
||||
|
||||
def is_duplicate?
|
||||
status =~ /duplicate/
|
||||
end
|
||||
|
||||
|
||||
def duplicate_post_id
|
||||
@duplicate_post_id ||= status[/duplicate: (\d+)/, 1]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module UploaderMethods
|
||||
def initialize_uploader
|
||||
self.uploader_id = CurrentUser.user.id
|
||||
self.uploader_ip_addr = CurrentUser.ip_addr
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def uploaded_by(user_id)
|
||||
where("uploader_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def pending
|
||||
where(:status => "pending")
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:uploader_id].present?
|
||||
q = q.uploaded_by(params[:uploader_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:uploader_name].present?
|
||||
q = q.where("uploader_id = (select _.id from users _ where lower(_.name) = ?)", params[:uploader_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:source].present?
|
||||
q = q.where("source = ?", params[:source])
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ApiMethods
|
||||
def serializable_hash(options = {})
|
||||
options ||= {}
|
||||
@@ -380,7 +380,7 @@ class Upload < ActiveRecord::Base
|
||||
hash = super(options)
|
||||
hash
|
||||
end
|
||||
|
||||
|
||||
def to_xml(options = {}, &block)
|
||||
options ||= {}
|
||||
options[:procs] ||= []
|
||||
@@ -388,7 +388,7 @@ class Upload < ActiveRecord::Base
|
||||
super(options, &block)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include ConversionMethods
|
||||
include ValidationMethods
|
||||
include FileMethods
|
||||
@@ -402,17 +402,17 @@ class Upload < ActiveRecord::Base
|
||||
include UploaderMethods
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
|
||||
|
||||
def add_file_size_tags!(file_path)
|
||||
if file_size >= 10.megabytes
|
||||
self.tag_string = "#{tag_string} huge_filesize".strip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def uploader_name
|
||||
User.id_to_name(uploader_id)
|
||||
end
|
||||
|
||||
|
||||
def presenter
|
||||
@presenter ||= UploadPresenter.new(self)
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'digest/sha1'
|
||||
class User < ActiveRecord::Base
|
||||
class Error < Exception ; end
|
||||
class PrivilegeError < Exception ; end
|
||||
|
||||
|
||||
module Levels
|
||||
BLOCKED = 10
|
||||
MEMBER = 20
|
||||
@@ -15,7 +15,7 @@ class User < ActiveRecord::Base
|
||||
MODERATOR = 40
|
||||
ADMIN = 50
|
||||
end
|
||||
|
||||
|
||||
attr_accessor :password, :old_password
|
||||
attr_accessible :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout, :password, :old_password, :password_confirmation, :password_hash, :email, :last_logged_in_at, :last_forum_read_at, :has_mail, :receive_email_notifications, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :name, :ip_addr, :time_zone, :default_image_size, :enable_sequential_post_navigation, :as => [:moderator, :janitor, :contributor, :privileged, :member, :anonymous, :default, :builder, :admin]
|
||||
attr_accessible :level, :as => :admin
|
||||
@@ -44,7 +44,7 @@ class User < ActiveRecord::Base
|
||||
has_many :dmails, :foreign_key => "owner_id", :order => "dmails.id desc"
|
||||
belongs_to :inviter, :class_name => "User"
|
||||
after_update :create_mod_action
|
||||
|
||||
|
||||
module BanMethods
|
||||
def validate_ip_addr_is_not_banned
|
||||
if IpBan.is_banned?(CurrentUser.ip_addr)
|
||||
@@ -52,13 +52,13 @@ class User < ActiveRecord::Base
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def unban!
|
||||
update_column(:is_banned, false)
|
||||
ban.destroy
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module InvitationMethods
|
||||
def invite!(level)
|
||||
if level.to_i <= Levels::CONTRIBUTOR
|
||||
@@ -68,40 +68,40 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module NameMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def name_to_id(name)
|
||||
Cache.get("uni:#{Cache.sanitize(name)}", 4.hours) do
|
||||
select_value_sql("SELECT id FROM users WHERE lower(name) = ?", name.mb_chars.downcase)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def id_to_name(user_id)
|
||||
Cache.get("uin:#{user_id}", 4.hours) do
|
||||
select_value_sql("SELECT name FROM users WHERE id = ?", user_id) || Danbooru.config.default_guest_name
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def find_by_name(name)
|
||||
where("lower(name) = ?", name.mb_chars.downcase.tr(" ", "_")).first
|
||||
end
|
||||
|
||||
|
||||
def id_to_pretty_name(user_id)
|
||||
id_to_name(user_id).tr("_", " ")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def pretty_name
|
||||
name.tr("_", " ")
|
||||
end
|
||||
|
||||
|
||||
def update_cache
|
||||
Cache.put("uin:#{id}", name)
|
||||
end
|
||||
|
||||
|
||||
def update_remote_cache
|
||||
if name_changed?
|
||||
Danbooru.config.other_server_hosts.each do |server|
|
||||
@@ -111,7 +111,7 @@ class User < ActiveRecord::Base
|
||||
rescue Exception
|
||||
# swallow, since it'll be expired eventually anyway
|
||||
end
|
||||
|
||||
|
||||
def validate_feedback_on_name_change
|
||||
if feedback.negative.count > 0 && name_changed?
|
||||
self.errors[:base] << "You can not change your name if you have any negative feedback"
|
||||
@@ -119,12 +119,12 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module PasswordMethods
|
||||
def bcrypt_password
|
||||
BCrypt::Password.new(bcrypt_password_hash)
|
||||
end
|
||||
|
||||
|
||||
def bcrypt_cookie_password_hash
|
||||
bcrypt_password_hash.slice(20, 100)
|
||||
end
|
||||
@@ -133,11 +133,11 @@ class User < ActiveRecord::Base
|
||||
self.password_hash = ""
|
||||
self.bcrypt_password_hash = User.bcrypt(password)
|
||||
end
|
||||
|
||||
|
||||
def encrypt_password_on_update
|
||||
return if password.blank?
|
||||
return if old_password.blank?
|
||||
|
||||
|
||||
if bcrypt_password == User.sha1(old_password)
|
||||
self.bcrypt_password_hash = User.bcrypt(password)
|
||||
return true
|
||||
@@ -159,18 +159,18 @@ class User < ActiveRecord::Base
|
||||
|
||||
pass << rand(100).to_s
|
||||
update_column(:bcrypt_password_hash, User.bcrypt(pass))
|
||||
pass
|
||||
pass
|
||||
end
|
||||
|
||||
|
||||
def reset_password_and_deliver_notice
|
||||
new_password = reset_password()
|
||||
Maintenance::User::PasswordResetMailer.confirmation(self, new_password).deliver
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module AuthenticationMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def authenticate(name, pass)
|
||||
authenticate_hash(name, sha1(pass))
|
||||
@@ -193,7 +193,7 @@ class User < ActiveRecord::Base
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def bcrypt(pass)
|
||||
BCrypt::Password.create(sha1(pass))
|
||||
end
|
||||
@@ -203,19 +203,19 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module FavoriteMethods
|
||||
def favorites
|
||||
Favorite.where("user_id % 100 = #{id % 100} and user_id = #{id}").order("id desc")
|
||||
end
|
||||
|
||||
|
||||
def add_favorite!(post)
|
||||
return if Favorite.for_user(id).exists?(:user_id => id, :post_id => post.id)
|
||||
Favorite.create(:user_id => id, :post_id => post.id)
|
||||
increment!(:favorite_count)
|
||||
post.add_favorite!(self)
|
||||
end
|
||||
|
||||
|
||||
def remove_favorite!(post)
|
||||
return unless Favorite.for_user(id).exists?(:user_id => id, :post_id => post.id)
|
||||
Favorite.destroy_all(:user_id => id, :post_id => post.id)
|
||||
@@ -223,10 +223,10 @@ class User < ActiveRecord::Base
|
||||
post.remove_favorite!(self)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module LevelMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
module ClassMethods
|
||||
def level_hash
|
||||
return {
|
||||
@@ -241,68 +241,68 @@ class User < ActiveRecord::Base
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def promote_to_admin_if_first_user
|
||||
return if Rails.env.test?
|
||||
|
||||
|
||||
if User.count == 0
|
||||
self.level = Levels::ADMIN
|
||||
else
|
||||
self.level = Levels::MEMBER
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def role
|
||||
case level
|
||||
when Levels::MEMBER
|
||||
:member
|
||||
|
||||
|
||||
when Levels::PRIVILEGED
|
||||
:privileged
|
||||
|
||||
|
||||
when Levels::BUILDER
|
||||
:builder
|
||||
|
||||
|
||||
when Levels::CONTRIBUTOR
|
||||
:contributor
|
||||
|
||||
|
||||
when Levels::MODERATOR
|
||||
:moderator
|
||||
|
||||
when Levels::JANITOR
|
||||
:janitor
|
||||
|
||||
|
||||
when Levels::ADMIN
|
||||
:admin
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def level_string(value = nil)
|
||||
case (value || level)
|
||||
when Levels::BLOCKED
|
||||
"Banned"
|
||||
|
||||
|
||||
when Levels::MEMBER
|
||||
"Member"
|
||||
|
||||
|
||||
when Levels::BUILDER
|
||||
"Builder"
|
||||
|
||||
|
||||
when Levels::PRIVILEGED
|
||||
"Gold"
|
||||
|
||||
|
||||
when Levels::PLATINUM
|
||||
"Platinum"
|
||||
|
||||
|
||||
when Levels::CONTRIBUTOR
|
||||
"Contributor"
|
||||
|
||||
|
||||
when Levels::JANITOR
|
||||
"Janitor"
|
||||
|
||||
|
||||
when Levels::MODERATOR
|
||||
"Moderator"
|
||||
|
||||
|
||||
when Levels::ADMIN
|
||||
"Admin"
|
||||
end
|
||||
@@ -315,55 +315,55 @@ class User < ActiveRecord::Base
|
||||
def is_member?
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
def is_builder?
|
||||
level >= Levels::BUILDER
|
||||
end
|
||||
|
||||
|
||||
def is_privileged?
|
||||
level >= Levels::PRIVILEGED
|
||||
end
|
||||
|
||||
|
||||
def is_platinum?
|
||||
level >= Levels::PLATINUM
|
||||
end
|
||||
|
||||
|
||||
def is_contributor?
|
||||
level >= Levels::CONTRIBUTOR
|
||||
end
|
||||
|
||||
|
||||
def is_janitor?
|
||||
level >= Levels::JANITOR
|
||||
end
|
||||
|
||||
|
||||
def is_moderator?
|
||||
level >= Levels::MODERATOR
|
||||
end
|
||||
|
||||
|
||||
def is_mod?
|
||||
level >= Levels::MODERATOR
|
||||
end
|
||||
|
||||
|
||||
def is_admin?
|
||||
level >= Levels::ADMIN
|
||||
end
|
||||
|
||||
|
||||
def create_mod_action
|
||||
if level_changed?
|
||||
ModAction.create(:description => "#{name} level changed #{level_string(level_was)} -> #{level_string} by #{CurrentUser.name}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module EmailMethods
|
||||
def is_verified?
|
||||
email_verification_key.blank?
|
||||
end
|
||||
|
||||
|
||||
def generate_email_verification_key
|
||||
self.email_verification_key = Digest::SHA1.hexdigest("#{Time.now.to_f}--#{name}--#{rand(1_000_000)}--")
|
||||
end
|
||||
|
||||
|
||||
def verify!(key)
|
||||
if email_verification_key == key
|
||||
self.update_column(:email_verification_key, nil)
|
||||
@@ -372,17 +372,17 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module BlacklistMethods
|
||||
def blacklisted_tag_array
|
||||
Tag.scan_query(blacklisted_tags)
|
||||
end
|
||||
|
||||
|
||||
def normalize_blacklisted_tags
|
||||
self.blacklisted_tags = blacklisted_tags.downcase if blacklisted_tags.present?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ForumMethods
|
||||
def has_forum_been_updated?
|
||||
return false unless is_privileged?
|
||||
@@ -392,7 +392,7 @@ class User < ActiveRecord::Base
|
||||
return newest_topic.updated_at > last_forum_read_at
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module LimitMethods
|
||||
def can_upload?
|
||||
if is_contributor?
|
||||
@@ -403,7 +403,7 @@ class User < ActiveRecord::Base
|
||||
upload_limit > 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def upload_limited_reason
|
||||
if created_at > 1.week.ago
|
||||
"You cannot upload during your first week of registration"
|
||||
@@ -413,7 +413,7 @@ class User < ActiveRecord::Base
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def can_comment?
|
||||
if is_privileged?
|
||||
true
|
||||
@@ -423,33 +423,33 @@ class User < ActiveRecord::Base
|
||||
Comment.where("creator_id = ? and created_at > ?", id, 1.hour.ago).count < Danbooru.config.member_comment_limit
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def can_comment_vote?
|
||||
CommentVote.where("user_id = ? and created_at > ?", id, 1.hour.ago).count < 10
|
||||
end
|
||||
|
||||
|
||||
def can_remove_from_pools?
|
||||
created_at <= 1.week.ago
|
||||
end
|
||||
|
||||
|
||||
def upload_limit
|
||||
deleted_count = Post.for_user(id).deleted.count
|
||||
pending_count = Post.for_user(id).pending.count
|
||||
approved_count = Post.where("is_flagged = false and is_pending = false and is_deleted = false and uploader_id = ?", id).count
|
||||
|
||||
|
||||
if base_upload_limit
|
||||
limit = base_upload_limit - pending_count
|
||||
else
|
||||
limit = 10 + (approved_count / 10) - (deleted_count / 4) - pending_count
|
||||
end
|
||||
|
||||
|
||||
if limit < 0
|
||||
limit = 0
|
||||
end
|
||||
|
||||
|
||||
limit
|
||||
end
|
||||
|
||||
|
||||
def tag_query_limit
|
||||
if is_platinum?
|
||||
Danbooru.config.base_tag_query_limit * 2
|
||||
@@ -459,7 +459,7 @@ class User < ActiveRecord::Base
|
||||
2
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def favorite_limit
|
||||
if is_platinum?
|
||||
nil
|
||||
@@ -470,19 +470,19 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
super + [:password_hash, :bcrypt_password_hash, :email, :email_verification_key, :time_zone, :created_at, :updated_at, :receive_email_notifications, :last_logged_in_at, :last_forum_read_at, :has_mail, :default_image_size, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :base_upload_limit, :recent_tags, :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout]
|
||||
end
|
||||
|
||||
|
||||
def serializable_hash(options = {})
|
||||
options ||= {}
|
||||
options[:except] ||= []
|
||||
options[:except] += hidden_attributes
|
||||
super(options)
|
||||
end
|
||||
|
||||
|
||||
def to_xml(options = {}, &block)
|
||||
# to_xml ignores the serializable_hash method
|
||||
options ||= {}
|
||||
@@ -500,48 +500,48 @@ class User < ActiveRecord::Base
|
||||
}.to_json
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def named(name)
|
||||
where("lower(name) = ?", name)
|
||||
end
|
||||
|
||||
|
||||
def name_matches(name)
|
||||
where("lower(name) like ? escape E'\\\\'", name.to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
|
||||
def admins
|
||||
where("is_admin = TRUE")
|
||||
end
|
||||
|
||||
|
||||
def with_email(email)
|
||||
if email.blank?
|
||||
if email.blank?
|
||||
where("FALSE")
|
||||
else
|
||||
else
|
||||
where("email = ?", email)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def find_for_password_reset(name, email)
|
||||
if email.blank?
|
||||
if email.blank?
|
||||
where("FALSE")
|
||||
else
|
||||
where(["name = ? AND email = ?", name, email])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:name].present?
|
||||
q = q.name_matches(params[:name].mb_chars.downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:name_matches].present?
|
||||
q = q.name_matches(params[:name_matches].mb_chars.downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:min_level].present?
|
||||
q = q.where("level >= ?", params[:min_level].to_i)
|
||||
end
|
||||
@@ -549,32 +549,32 @@ class User < ActiveRecord::Base
|
||||
if params[:level].present?
|
||||
q = q.where("level = ?", params[:level].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:id].present?
|
||||
q = q.where("id = ?", params[:id].to_i)
|
||||
end
|
||||
|
||||
|
||||
case params[:order]
|
||||
when "name"
|
||||
q = q.order("name")
|
||||
|
||||
|
||||
when "post_upload_count"
|
||||
q = q.order("post_upload_count desc")
|
||||
|
||||
|
||||
when "note_count"
|
||||
q = q.order("note_update_count desc")
|
||||
|
||||
when "post_update_count"
|
||||
|
||||
when "post_update_count"
|
||||
q = q.order("post_update_count desc")
|
||||
|
||||
|
||||
else
|
||||
q = q.order("created_at desc")
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include BanMethods
|
||||
include NameMethods
|
||||
include PasswordMethods
|
||||
@@ -588,7 +588,7 @@ class User < ActiveRecord::Base
|
||||
include InvitationMethods
|
||||
include ApiMethods
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def initialize_default_image_size
|
||||
self.default_image_size = "large"
|
||||
end
|
||||
@@ -596,7 +596,7 @@ class User < ActiveRecord::Base
|
||||
def can_update?(object, foreign_key = :user_id)
|
||||
is_moderator? || is_admin? || object.__send__(foreign_key) == id
|
||||
end
|
||||
|
||||
|
||||
def dmail_count
|
||||
if has_mail?
|
||||
"(#{dmails.unread.count})"
|
||||
|
||||
@@ -12,31 +12,31 @@ class UserFeedback < ActiveRecord::Base
|
||||
def positive
|
||||
where("category = ?", "positive")
|
||||
end
|
||||
|
||||
|
||||
def neutral
|
||||
where("category = ?", "neutral")
|
||||
end
|
||||
|
||||
|
||||
def negative
|
||||
where("category = ?", "negative")
|
||||
end
|
||||
|
||||
|
||||
def for_user(user_id)
|
||||
where("user_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:user_id].present?
|
||||
q = q.for_user(params[:user_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:user_name].present?
|
||||
q = q.where("user_id = (select _.id from users _ where lower(_.name) = ?)", params[:user_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
end
|
||||
@@ -44,34 +44,34 @@ class UserFeedback < ActiveRecord::Base
|
||||
if params[:creator_name].present?
|
||||
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
|
||||
def user_name
|
||||
User.id_to_name(user_id)
|
||||
end
|
||||
|
||||
|
||||
def creator_name
|
||||
User.id_to_name(creator_id)
|
||||
end
|
||||
|
||||
|
||||
def user_name=(name)
|
||||
self.user_id = User.name_to_id(name)
|
||||
end
|
||||
|
||||
|
||||
def create_dmail
|
||||
body = %{#{creator_name} created a "#{category} record":/user_feedbacks?search[user_id]=#{user_id} for your account. #{body}}
|
||||
Dmail.create_split(:to_id => user_id, :title => "Your user record has been updated", :body => body)
|
||||
end
|
||||
|
||||
|
||||
def creator_is_privileged
|
||||
if !creator.is_privileged?
|
||||
errors[:creator] << "must be privileged"
|
||||
|
||||
@@ -15,18 +15,18 @@ class UserPasswordResetNonce < ActiveRecord::Base
|
||||
def initialize_key
|
||||
self.key = SecureRandom.hex(16)
|
||||
end
|
||||
|
||||
|
||||
def validate_existence_of_email
|
||||
if !User.with_email(email).exists?
|
||||
errors[:email] << "is invalid"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def reset_user!
|
||||
user.reset_password_and_deliver_notice
|
||||
end
|
||||
|
||||
|
||||
def user
|
||||
@user ||= User.with_email(email).first
|
||||
end
|
||||
|
||||
@@ -10,16 +10,16 @@ class WikiPage < ActiveRecord::Base
|
||||
has_one :tag, :foreign_key => "name", :primary_key => "title"
|
||||
has_one :artist, :foreign_key => "name", :primary_key => "title"
|
||||
has_many :versions, :class_name => "WikiPageVersion", :dependent => :destroy, :order => "wiki_page_versions.id ASC"
|
||||
|
||||
|
||||
module SearchMethods
|
||||
def titled(title)
|
||||
where("title = ?", title.downcase.tr(" ", "_"))
|
||||
end
|
||||
|
||||
|
||||
def recent
|
||||
order("updated_at DESC").limit(25)
|
||||
end
|
||||
|
||||
|
||||
def body_matches(query)
|
||||
where("body_index @@ plainto_tsquery(?)", query.to_escaped_for_tsquery_split)
|
||||
end
|
||||
@@ -35,15 +35,15 @@ class WikiPage < ActiveRecord::Base
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id])
|
||||
end
|
||||
|
||||
|
||||
if params[:body_matches].present?
|
||||
q = q.body_matches(params[:body_matches])
|
||||
end
|
||||
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].downcase)
|
||||
end
|
||||
|
||||
|
||||
if params[:sort] == "time" || params[:sort] == "Date"
|
||||
q = q.order("updated_at desc")
|
||||
end
|
||||
@@ -51,7 +51,7 @@ class WikiPage < ActiveRecord::Base
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ApiMethods
|
||||
def serializable_hash(options = {})
|
||||
options ||= {}
|
||||
@@ -64,7 +64,7 @@ class WikiPage < ActiveRecord::Base
|
||||
hash = super(options)
|
||||
hash
|
||||
end
|
||||
|
||||
|
||||
def to_xml(options = {}, &block)
|
||||
options ||= {}
|
||||
options[:procs] ||= []
|
||||
@@ -72,27 +72,27 @@ class WikiPage < ActiveRecord::Base
|
||||
super(options, &block)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
|
||||
|
||||
def self.find_title_and_id(title)
|
||||
titled(title).select("title, id").first
|
||||
end
|
||||
|
||||
|
||||
def validate_locker_is_janitor
|
||||
if is_locked_changed? && !CurrentUser.is_janitor?
|
||||
errors.add(:is_locked, "can be modified by janitors only")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def revert_to(version)
|
||||
self.title = version.title
|
||||
self.body = version.body
|
||||
self.is_locked = version.is_locked
|
||||
end
|
||||
|
||||
|
||||
def revert_to!(version)
|
||||
revert_to(version)
|
||||
save!
|
||||
@@ -105,7 +105,7 @@ class WikiPage < ActiveRecord::Base
|
||||
def creator_name
|
||||
User.id_to_name(creator_id).tr("_", " ")
|
||||
end
|
||||
|
||||
|
||||
def category_name
|
||||
Tag.category_for(title)
|
||||
end
|
||||
@@ -113,7 +113,7 @@ class WikiPage < ActiveRecord::Base
|
||||
def pretty_title
|
||||
title.tr("_", " ")
|
||||
end
|
||||
|
||||
|
||||
def create_version
|
||||
if title_changed? || body_changed? || is_locked_changed?
|
||||
versions.create(
|
||||
@@ -125,19 +125,19 @@ class WikiPage < ActiveRecord::Base
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.user.id
|
||||
end
|
||||
|
||||
|
||||
def post_set
|
||||
@post_set ||= PostSets::WikiPage.new(title, 1, 4)
|
||||
end
|
||||
|
||||
|
||||
def presenter
|
||||
@presenter ||= WikiPagePresenter.new(self)
|
||||
end
|
||||
|
||||
|
||||
def tags
|
||||
body.scan(/\[\[(.+?)\]\]/).flatten.map do |match|
|
||||
if match =~ /^(.+?)\|(.+)/
|
||||
|
||||
@@ -6,25 +6,25 @@ class WikiPageVersion < ActiveRecord::Base
|
||||
def for_user(user_id)
|
||||
where("updater_id = ?", user_id)
|
||||
end
|
||||
|
||||
|
||||
def search(params)
|
||||
q = scoped
|
||||
return q if params.blank?
|
||||
|
||||
|
||||
if params[:updater_id].present?
|
||||
q = q.for_user(params[:updater_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
if params[:wiki_page_id].present?
|
||||
q = q.where("wiki_page_id = ?", params[:wiki_page_id].to_i)
|
||||
end
|
||||
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def updater_name
|
||||
User.id_to_name(updater_id)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user