eBooru/app/models/post_flag.rb

192 lines
5.2 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
class PostFlag < ApplicationRecord
class Error < Exception;
end
2013-03-19 08:10:10 -04:00
2019-09-04 02:06:30 -04:00
COOLDOWN_PERIOD = 1.days
MAPPED_REASONS = Danbooru.config.flag_reasons.map { |i| [i[:name], i[:reason]] }.to_h
belongs_to_creator :class_name => "User"
user_status_counter :post_flag_count
belongs_to :post
validate :validate_creator_is_not_limited, on: :create
validate :validate_post
validate :validate_reason
validate :update_reason, on: :create
2019-09-05 08:59:51 -04:00
validates :reason, presence: true
2011-03-29 13:56:30 -04:00
before_save :update_post
after_create :create_post_event
after_commit :index_post
2013-01-10 17:45:52 -05:00
scope :by_users, -> { where.not(creator: User.system) }
scope :by_system, -> { where(creator: User.system) }
scope :in_cooldown, -> { by_users.where("created_at >= ?", COOLDOWN_PERIOD.ago) }
attr_accessor :parent_id, :reason_name, :force_flag
2013-01-10 17:45:52 -05:00
module SearchMethods
def post_tags_match(query)
where(post_id: Post.tag_match_sql(query))
end
2013-01-10 17:45:52 -05:00
def resolved
where("is_resolved = ?", true)
end
2013-03-19 08:10:10 -04:00
2013-01-10 17:45:52 -05:00
def unresolved
where("is_resolved = ?", false)
end
2013-03-19 08:10:10 -04:00
2013-08-13 13:33:25 -04:00
def for_creator(user_id)
where("creator_id = ?", user_id)
end
2013-03-19 08:10:10 -04:00
2013-01-10 17:45:52 -05:00
def search(params)
q = super
2013-03-19 08:10:10 -04:00
q = q.attribute_matches(:reason, params[:reason_matches])
q = q.attribute_matches(:is_resolved, params[:is_resolved])
2014-11-30 16:10:17 -05:00
q = q.where_user(:creator_id, :creator, params) do |condition, user_ids|
condition.where.not(creator_id: user_ids.reject { |user_id| CurrentUser.can_view_flagger?(user_id) })
2013-01-11 17:13:55 -05:00
end
2013-03-19 08:10:10 -04:00
2013-02-19 12:27:17 -05:00
if params[:post_id].present?
q = q.where(post_id: params[:post_id].split(",").map(&:to_i))
2013-01-10 17:45:52 -05:00
end
2013-03-19 08:10:10 -04:00
if params[:post_tags_match].present?
q = q.post_tags_match(params[:post_tags_match])
end
if params[:ip_addr].present?
q = q.where("creator_ip_addr <<= ?", params[:ip_addr])
end
case params[:type]
when "flag"
q = q.where(is_deletion: false)
when "deletion"
q = q.where(is_deletion: true)
end
2023-07-07 08:32:57 -04:00
q.apply_basic_order(params)
2013-01-10 17:45:52 -05:00
end
end
2013-03-19 08:10:10 -04:00
module ApiMethods
def hidden_attributes
list = super
unless CurrentUser.can_view_flagger_on_post?(self)
list += [:creator_id]
end
super + list
end
def method_attributes
super + [:type]
end
end
2013-01-10 17:45:52 -05:00
extend SearchMethods
include ApiMethods
2013-03-19 08:10:10 -04:00
def type
return :deletion if is_deletion
:flag
end
2011-03-29 13:56:30 -04:00
def update_post
2013-02-22 21:13:11 -05:00
post.update_column(:is_flagged, true) unless post.is_flagged?
end
def index_post
2020-03-10 14:38:04 -04:00
post.update_index
2011-03-29 13:56:30 -04:00
end
2013-03-19 08:10:10 -04:00
def validate_creator_is_not_limited
return if is_deletion
if creator.no_flagging?
2021-02-07 20:16:52 -05:00
errors.add(:creator, "cannot flag posts")
end
return if creator.is_janitor?
2019-09-04 02:06:30 -04:00
allowed = creator.can_post_flag_with_reason
if allowed != true
errors.add(:creator, User.throttle_reason(allowed))
return false
end
flag = post.flags.in_cooldown.last
if flag.present?
errors.add(:post, "cannot be flagged more than once every #{COOLDOWN_PERIOD.inspect} (last flagged: #{flag.created_at.to_fs(:long)})")
end
end
2013-03-19 08:10:10 -04:00
def validate_post
errors.add(:post, "is locked and cannot be flagged") if post.is_status_locked? && !(creator.is_admin? || force_flag)
2021-02-07 20:16:52 -05:00
errors.add(:post, "is deleted") if post.is_deleted?
end
def validate_reason
case reason_name
when 'deletion'
# You're probably looking at this line as you get this validation failure
2021-01-10 19:38:09 -05:00
errors.add(:reason, "is not one of the available choices") unless is_deletion
when 'inferior'
unless parent_post.present?
2021-01-10 19:38:09 -05:00
errors.add(:parent_id, "must exist")
return false
end
errors.add(:parent_id, "cannot be set to the post being flagged") if parent_post.id == post.id
when 'uploading_guidelines'
errors.add(:reason, "cannot be used. The post is grandfathered") unless post.flaggable_for_guidelines?
else
2021-02-07 20:16:52 -05:00
errors.add(:reason, "is not one of the available choices") unless MAPPED_REASONS.key?(reason_name)
end
end
def update_reason
case reason_name
when 'deletion'
# NOP
when 'inferior'
return unless parent_post
2020-10-09 16:55:39 -04:00
old_parent_id = post.parent_id
post.update_column(:parent_id, parent_post.id)
# Fix handling when parent/child is currently inverted. See #258
if parent_post.parent_id == post.id
parent_post.update_column(:parent_id, nil)
post.update_has_children_flag
end
2020-10-09 16:55:39 -04:00
# Update parent flags on parent post
parent_post.update_has_children_flag
# Update parent flags on old parent post, if it exists
2023-12-03 09:36:37 -05:00
Post.find(old_parent_id).update_has_children_flag if old_parent_id && parent_post.id != old_parent_id
self.reason = "Inferior version/duplicate of post ##{parent_post.id}"
else
self.reason = MAPPED_REASONS[reason_name]
end
end
2011-03-30 14:13:42 -04:00
def resolve!
2011-07-16 19:20:02 -04:00
update_column(:is_resolved, true)
2011-03-30 14:13:42 -04:00
end
2013-03-19 08:10:10 -04:00
def parent_post
@parent_post ||= begin
Post.where('id = ?', parent_id).first
rescue
nil
end
end
def create_post_event
# Deletions also create flags, but they create a deletion event instead
PostEvent.add(post.id, CurrentUser.user, :flag_created, { reason: reason }) unless is_deletion
end
end