mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
changed it so notify moderators goes to the moderators group allow admins to grant self moderation and revoke self moderation
222 lines
8.0 KiB
Ruby
222 lines
8.0 KiB
Ruby
require_dependency 'rate_limiter'
|
|
require_dependency 'system_message'
|
|
require_dependency 'trashable'
|
|
|
|
class PostAction < ActiveRecord::Base
|
|
class AlreadyActed < StandardError; end
|
|
|
|
include RateLimiter::OnCreateRecord
|
|
include Trashable
|
|
|
|
attr_accessible :post_action_type_id, :post_id, :user_id, :post, :user, :post_action_type, :message, :related_post_id
|
|
|
|
belongs_to :post
|
|
belongs_to :user
|
|
belongs_to :post_action_type
|
|
|
|
rate_limit :post_action_rate_limiter
|
|
|
|
validate :message_quality
|
|
|
|
def self.update_flagged_posts_count
|
|
posts_flagged_count = PostAction.joins(post: :topic)
|
|
.where('post_actions.post_action_type_id' => PostActionType.notify_flag_types.values,
|
|
'posts.deleted_at' => nil,
|
|
'topics.deleted_at' => nil)
|
|
.count('DISTINCT posts.id')
|
|
|
|
$redis.set('posts_flagged_count', posts_flagged_count)
|
|
user_ids = User.staff.select(:id).map {|u| u.id}
|
|
MessageBus.publish('/flagged_counts', { total: posts_flagged_count }, { user_ids: user_ids })
|
|
end
|
|
|
|
def self.flagged_posts_count
|
|
$redis.get('posts_flagged_count').to_i
|
|
end
|
|
|
|
def self.counts_for(collection, user)
|
|
return {} if collection.blank?
|
|
|
|
collection_ids = collection.map {|p| p.id}
|
|
|
|
user_id = user.present? ? user.id : 0
|
|
|
|
result = PostAction.where(post_id: collection_ids, user_id: user_id)
|
|
user_actions = {}
|
|
result.each do |r|
|
|
user_actions[r.post_id] ||= {}
|
|
user_actions[r.post_id][r.post_action_type_id] = r
|
|
end
|
|
|
|
user_actions
|
|
end
|
|
|
|
def self.count_per_day_for_type(sinceDaysAgo = 30, post_action_type)
|
|
unscoped.where(post_action_type_id: post_action_type).where('created_at > ?', sinceDaysAgo.days.ago).group('date(created_at)').order('date(created_at)').count
|
|
end
|
|
|
|
def self.clear_flags!(post, moderator_id, action_type_id = nil)
|
|
# -1 is the automatic system cleary
|
|
actions = if action_type_id
|
|
[action_type_id]
|
|
else
|
|
moderator_id == -1 ? PostActionType.auto_action_flag_types.values : PostActionType.flag_types.values
|
|
end
|
|
|
|
PostAction.update_all({ deleted_at: Time.zone.now, deleted_by: moderator_id }, { post_id: post.id, post_action_type_id: actions })
|
|
|
|
f = actions.map{|t| ["#{PostActionType.types[t]}_count", 0]}
|
|
|
|
Post.with_deleted.update_all(Hash[*f.flatten], id: post.id)
|
|
|
|
update_flagged_posts_count
|
|
end
|
|
|
|
def self.act(user, post, post_action_type_id, message = nil)
|
|
begin
|
|
title, target_usernames, target_group_names, subtype, body = nil
|
|
|
|
if message
|
|
[:notify_moderators, :notify_user].each do |k|
|
|
if post_action_type_id == PostActionType.types[k]
|
|
if k == :notify_moderators
|
|
target_group_names = target_moderators
|
|
else
|
|
target_usernames = post.user.username
|
|
end
|
|
title = I18n.t("post_action_types.#{k}.email_title",
|
|
title: post.topic.title)
|
|
body = I18n.t("post_action_types.#{k}.email_body",
|
|
message: message,
|
|
link: "#{Discourse.base_url}#{post.url}")
|
|
subtype = k == :notify_moderators ? TopicSubtype.notify_moderators : TopicSubtype.notify_user
|
|
end
|
|
end
|
|
end
|
|
|
|
related_post_id = nil
|
|
if target_usernames.present? || target_group_names.present?
|
|
related_post_id = PostCreator.new(user,
|
|
target_usernames: target_usernames,
|
|
target_group_names: target_group_names,
|
|
archetype: Archetype.private_message,
|
|
subtype: subtype,
|
|
title: title,
|
|
raw: body
|
|
).create.id
|
|
end
|
|
create( post_id: post.id,
|
|
user_id: user.id,
|
|
post_action_type_id: post_action_type_id,
|
|
message: message,
|
|
related_post_id: related_post_id )
|
|
rescue ActiveRecord::RecordNotUnique
|
|
# can happen despite being .create
|
|
# since already bookmarked
|
|
true
|
|
end
|
|
end
|
|
|
|
def self.remove_act(user, post, post_action_type_id)
|
|
if action = where(post_id: post.id, user_id: user.id, post_action_type_id: post_action_type_id).first
|
|
action.trash!
|
|
action.run_callbacks(:save)
|
|
end
|
|
end
|
|
|
|
def is_bookmark?
|
|
post_action_type_id == PostActionType.types[:bookmark]
|
|
end
|
|
|
|
def is_like?
|
|
post_action_type_id == PostActionType.types[:like]
|
|
end
|
|
|
|
def is_flag?
|
|
PostActionType.flag_types.values.include?(post_action_type_id)
|
|
end
|
|
|
|
def is_private_message?
|
|
post_action_type_id == PostActionType.types[:notify_user] ||
|
|
post_action_type_id == PostActionType.types[:notify_moderators]
|
|
end
|
|
# A custom rate limiter for this model
|
|
def post_action_rate_limiter
|
|
return unless is_flag? || is_bookmark? || is_like?
|
|
|
|
return @rate_limiter if @rate_limiter.present?
|
|
|
|
%w(like flag bookmark).each do |type|
|
|
if send("is_#{type}?")
|
|
@rate_limiter = RateLimiter.new(user, "create_#{type}:#{Date.today.to_s}", SiteSetting.send("max_#{type}s_per_day"), 1.day.to_i)
|
|
return @rate_limiter
|
|
end
|
|
end
|
|
end
|
|
|
|
def message_quality
|
|
return if message.blank?
|
|
sentinel = TextSentinel.title_sentinel(message)
|
|
errors.add(:message, I18n.t(:is_invalid)) unless sentinel.valid?
|
|
end
|
|
|
|
before_create do
|
|
post_action_type_ids = is_flag? ? PostActionType.flag_types.values : post_action_type_id
|
|
raise AlreadyActed if PostAction.where(user_id: user_id,
|
|
post_id: post_id,
|
|
post_action_type_id: post_action_type_ids,
|
|
deleted_at: nil)
|
|
.exists?
|
|
end
|
|
|
|
after_save do
|
|
# Update denormalized counts
|
|
post_action_type = PostActionType.types[post_action_type_id]
|
|
column = "#{post_action_type.to_s}_count"
|
|
delta = deleted_at.nil? ? 1 : -1
|
|
|
|
# Voting also changes the sort_order
|
|
if post_action_type == :vote
|
|
Post.update_all ["vote_count = vote_count + :delta, sort_order = :max - (vote_count + :delta)", delta: delta, max: Topic.max_sort_order], id: post_id
|
|
else
|
|
Post.update_all ["#{column} = #{column} + ?", delta], id: post_id
|
|
end
|
|
Topic.update_all ["#{column} = #{column} + ?", delta], id: post.topic_id
|
|
|
|
|
|
if PostActionType.notify_flag_types.values.include?(post_action_type_id)
|
|
PostAction.update_flagged_posts_count
|
|
end
|
|
|
|
if PostActionType.auto_action_flag_types.include?(post_action_type) && SiteSetting.flags_required_to_hide_post > 0
|
|
# automatic hiding of posts
|
|
flag_counts = exec_sql("SELECT SUM(CASE WHEN deleted_at IS NULL THEN 1 ELSE 0 END) AS new_flags,
|
|
SUM(CASE WHEN deleted_at IS NOT NULL THEN 1 ELSE 0 END) AS old_flags
|
|
FROM post_actions
|
|
WHERE post_id = ? AND post_action_type_id IN (?)", post.id, PostActionType.auto_action_flag_types.values).first
|
|
old_flags, new_flags = flag_counts['old_flags'].to_i, flag_counts['new_flags'].to_i
|
|
|
|
if new_flags >= SiteSetting.flags_required_to_hide_post
|
|
reason = old_flags > 0 ? Post.hidden_reasons[:flag_threshold_reached_again] : Post.hidden_reasons[:flag_threshold_reached]
|
|
Post.update_all(["hidden = true, hidden_reason_id = COALESCE(hidden_reason_id, ?)", reason], id: post_id)
|
|
Topic.update_all({ visible: false },
|
|
["id = :topic_id AND NOT EXISTS(SELECT 1 FROM POSTS WHERE topic_id = :topic_id AND NOT hidden)", topic_id: post.topic_id])
|
|
|
|
# inform user
|
|
if post.user
|
|
SystemMessage.create(post.user, :post_hidden,
|
|
url: post.url,
|
|
edit_delay: SiteSetting.cooldown_minutes_after_hiding_posts)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
protected
|
|
|
|
def self.target_moderators
|
|
Group[:moderators].name
|
|
end
|
|
|
|
end
|