mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 19:08:33 +08:00
179 lines
5.2 KiB
Ruby
179 lines
5.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# name: discourse-presence
|
|
# about: Show which users are writing a reply to a topic
|
|
# version: 2.0
|
|
# authors: André Pereira, David Taylor, tgxworld
|
|
# url: https://github.com/discourse/discourse/tree/main/plugins/discourse-presence
|
|
|
|
enabled_site_setting :presence_enabled
|
|
hide_plugin if self.respond_to?(:hide_plugin)
|
|
|
|
register_asset 'stylesheets/presence.scss'
|
|
|
|
PLUGIN_NAME ||= -"discourse-presence"
|
|
|
|
after_initialize do
|
|
|
|
MessageBus.register_client_message_filter('/presence/') do |message|
|
|
published_at = message.data["published_at"]
|
|
|
|
if published_at
|
|
(Time.zone.now.to_i - published_at) <= ::Presence::MAX_BACKLOG_AGE_SECONDS
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
module ::Presence
|
|
MAX_BACKLOG_AGE_SECONDS = 10
|
|
|
|
class Engine < ::Rails::Engine
|
|
engine_name PLUGIN_NAME
|
|
isolate_namespace Presence
|
|
end
|
|
end
|
|
|
|
require_dependency "application_controller"
|
|
|
|
class Presence::PresencesController < ::ApplicationController
|
|
requires_plugin PLUGIN_NAME
|
|
before_action :ensure_logged_in
|
|
before_action :ensure_presence_enabled
|
|
|
|
EDITING_STATE = 'editing'
|
|
REPLYING_STATE = 'replying'
|
|
CLOSED_STATE = 'closed'
|
|
|
|
def handle_message
|
|
[:state, :topic_id].each do |key|
|
|
raise ActionController::ParameterMissing.new(key) unless params.key?(key)
|
|
end
|
|
|
|
topic_id = permitted_params[:topic_id]
|
|
topic = Topic.find_by(id: topic_id)
|
|
|
|
raise Discourse::InvalidParameters.new(:topic_id) unless topic
|
|
guardian.ensure_can_see!(topic)
|
|
|
|
post = nil
|
|
|
|
if (permitted_params[:post_id])
|
|
if (permitted_params[:state] != EDITING_STATE)
|
|
raise Discourse::InvalidParameters.new(:state)
|
|
end
|
|
|
|
post = Post.find_by(id: permitted_params[:post_id])
|
|
raise Discourse::InvalidParameters.new(:topic_id) unless post
|
|
|
|
guardian.ensure_can_edit!(post)
|
|
end
|
|
|
|
opts = {
|
|
max_backlog_age: Presence::MAX_BACKLOG_AGE_SECONDS
|
|
}
|
|
|
|
if permitted_params[:staff_only]
|
|
opts[:group_ids] = [Group::AUTO_GROUPS[:staff]]
|
|
else
|
|
case permitted_params[:state]
|
|
when EDITING_STATE
|
|
opts[:group_ids] = [Group::AUTO_GROUPS[:staff]]
|
|
|
|
if !post.locked? && !permitted_params[:is_whisper]
|
|
opts[:user_ids] = [post.user_id]
|
|
|
|
if topic.private_message?
|
|
if post.wiki
|
|
opts[:user_ids] = opts[:user_ids].concat(
|
|
topic.allowed_users.where(
|
|
"trust_level >= ? AND NOT admin OR moderator",
|
|
SiteSetting.min_trust_to_edit_wiki_post
|
|
).pluck(:id)
|
|
)
|
|
|
|
opts[:user_ids].uniq!
|
|
|
|
# Ignore trust level and just publish to all allowed groups since
|
|
# trying to figure out which users in the allowed groups have
|
|
# the necessary trust levels can lead to a large array of user ids
|
|
# if the groups are big.
|
|
opts[:group_ids] = opts[:group_ids].concat(
|
|
topic.allowed_groups.pluck(:id)
|
|
)
|
|
end
|
|
else
|
|
if post.wiki
|
|
opts[:group_ids] << Group::AUTO_GROUPS[:"trust_level_#{SiteSetting.min_trust_to_edit_wiki_post}"]
|
|
elsif SiteSetting.trusted_users_can_edit_others?
|
|
opts[:group_ids] << Group::AUTO_GROUPS[:trust_level_4]
|
|
end
|
|
end
|
|
end
|
|
when REPLYING_STATE
|
|
if permitted_params[:is_whisper]
|
|
opts[:group_ids] = [Group::AUTO_GROUPS[:staff]]
|
|
elsif topic.private_message?
|
|
opts[:user_ids] = topic.allowed_users.pluck(:id)
|
|
|
|
opts[:group_ids] = [Group::AUTO_GROUPS[:staff]].concat(
|
|
topic.allowed_groups.pluck(:id)
|
|
)
|
|
else
|
|
opts[:group_ids] = topic.secure_group_ids
|
|
end
|
|
when CLOSED_STATE
|
|
if topic.private_message?
|
|
opts[:user_ids] = topic.allowed_users.pluck(:id)
|
|
|
|
opts[:group_ids] = [Group::AUTO_GROUPS[:staff]].concat(
|
|
topic.allowed_groups.pluck(:id)
|
|
)
|
|
else
|
|
opts[:group_ids] = topic.secure_group_ids
|
|
end
|
|
end
|
|
end
|
|
|
|
payload = {
|
|
user: BasicUserSerializer.new(current_user, root: false).as_json,
|
|
state: permitted_params[:state],
|
|
is_whisper: permitted_params[:is_whisper].present?,
|
|
published_at: Time.zone.now.to_i
|
|
}
|
|
|
|
if (post_id = permitted_params[:post_id]).present?
|
|
payload[:post_id] = post_id
|
|
end
|
|
|
|
MessageBus.publish("/presence/#{topic_id}", payload, opts)
|
|
|
|
render json: success_json
|
|
end
|
|
|
|
private
|
|
|
|
def ensure_presence_enabled
|
|
if !SiteSetting.presence_enabled ||
|
|
(SiteSetting.allow_users_to_hide_profile &&
|
|
current_user.user_option.hide_profile_and_presence?)
|
|
|
|
raise Discourse::NotFound
|
|
end
|
|
end
|
|
|
|
def permitted_params
|
|
params.permit(:state, :topic_id, :post_id, :is_whisper, :staff_only)
|
|
end
|
|
end
|
|
|
|
Presence::Engine.routes.draw do
|
|
post '/publish' => 'presences#handle_message'
|
|
end
|
|
|
|
Discourse::Application.routes.append do
|
|
mount ::Presence::Engine, at: '/presence'
|
|
end
|
|
|
|
end
|