Allow approvers to bypass the rule that you can't flag a post again if it was flagged less than 3 days ago. This rule was intended to prevent flag warring among regular users, which hopefully shouldn't be a problem among approvers. It was also useless because approvers could always just directly delete the post even if they couldn't flag it. Allowing approvers to reflag posts allows them to reinstate flags that were accidentally approved.
125 lines
3.6 KiB
Ruby
125 lines
3.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class PostFlag < ApplicationRecord
|
|
module Reasons
|
|
UNAPPROVED = "Unapproved in three days"
|
|
REJECTED = "Unapproved in three days after returning to moderation queue%"
|
|
end
|
|
|
|
belongs_to :creator, class_name: "User"
|
|
belongs_to :post
|
|
|
|
before_validation { post.lock! }
|
|
validates :reason, presence: true, length: { in: 1..140 }
|
|
validate :validate_creator_is_not_limited, on: :create
|
|
validate :validate_post, on: :create
|
|
validates :creator_id, uniqueness: { scope: :post_id, on: :create, unless: :is_deletion, message: "have already flagged this post" }
|
|
before_save :update_post
|
|
after_create :prune_disapprovals
|
|
attr_accessor :is_deletion
|
|
|
|
enum status: {
|
|
pending: 0,
|
|
succeeded: 1,
|
|
rejected: 2,
|
|
}
|
|
|
|
scope :by_users, -> { where.not(creator: User.system) }
|
|
scope :by_system, -> { where(creator: User.system) }
|
|
scope :in_cooldown, -> { by_users.where("created_at >= ?", Danbooru.config.moderation_period.ago) }
|
|
scope :expired, -> { pending.where("post_flags.created_at < ?", Danbooru.config.moderation_period.ago) }
|
|
scope :active, -> { pending.or(rejected.in_cooldown) }
|
|
|
|
module SearchMethods
|
|
def creator_matches(creator, searcher)
|
|
return none if creator.nil?
|
|
|
|
policy = Pundit.policy!(searcher, PostFlag.unscoped.new(creator: creator))
|
|
|
|
if policy.can_view_flagger?
|
|
where(creator: creator).where.not(post: searcher.posts)
|
|
else
|
|
none
|
|
end
|
|
end
|
|
|
|
def category_matches(category)
|
|
case category
|
|
when "normal"
|
|
where("reason NOT IN (?) AND reason NOT LIKE ?", [Reasons::UNAPPROVED], Reasons::REJECTED)
|
|
when "unapproved"
|
|
where(reason: Reasons::UNAPPROVED)
|
|
when "rejected"
|
|
where("reason LIKE ?", Reasons::REJECTED)
|
|
when "deleted"
|
|
where("reason = ? OR reason LIKE ?", Reasons::UNAPPROVED, Reasons::REJECTED)
|
|
else
|
|
none
|
|
end
|
|
end
|
|
|
|
def search(params)
|
|
q = search_attributes(params, :id, :created_at, :updated_at, :reason, :status, :post)
|
|
q = q.text_attribute_matches(:reason, params[:reason_matches])
|
|
|
|
if params[:creator_id].present?
|
|
flagger = User.find(params[:creator_id])
|
|
q = q.creator_matches(flagger, CurrentUser.user)
|
|
elsif params[:creator_name].present?
|
|
flagger = User.find_by_name(params[:creator_name])
|
|
q = q.creator_matches(flagger, CurrentUser.user)
|
|
end
|
|
|
|
if params[:category]
|
|
q = q.category_matches(params[:category])
|
|
end
|
|
|
|
q.apply_default_order(params)
|
|
end
|
|
end
|
|
|
|
extend SearchMethods
|
|
|
|
def category
|
|
case reason
|
|
when Reasons::UNAPPROVED
|
|
:unapproved
|
|
when /#{Reasons::REJECTED.gsub("%", ".*")}/
|
|
:rejected
|
|
else
|
|
:normal
|
|
end
|
|
end
|
|
|
|
def prune_disapprovals
|
|
return if is_deletion
|
|
PostDisapproval.where(post: post).delete_all
|
|
end
|
|
|
|
def update_post
|
|
post.update_column(:is_flagged, true) unless post.is_flagged?
|
|
end
|
|
|
|
def validate_creator_is_not_limited
|
|
errors.add(:creator, "have reached your flag limit") if creator.is_flag_limited? && !is_deletion
|
|
end
|
|
|
|
def validate_post
|
|
errors.add(:post, "is pending and cannot be flagged") if post.is_pending? && !is_deletion
|
|
errors.add(:post, "is deleted and cannot be flagged") if post.is_deleted? && !is_deletion
|
|
|
|
flag = post.flags.in_cooldown.last
|
|
if !is_deletion && !creator.is_approver? && flag.present?
|
|
errors.add(:post, "cannot be flagged more than once every #{Danbooru.config.moderation_period.inspect} (last flagged: #{flag.created_at.to_formatted_s(:long)})")
|
|
end
|
|
end
|
|
|
|
def uploader_id
|
|
post.uploader_id
|
|
end
|
|
|
|
def self.available_includes
|
|
[:post]
|
|
end
|
|
end
|