mirror of
https://github.com/discourse/discourse-chat-integration.git
synced 2025-03-06 17:59:29 +00:00
When creating a new Discourse post from slack with the `post` feature, record the slack `ts` thread ID for the resulting topic post using an HTML comment to pass the `ts` through. When notifying slack of new Discourse posts, record the slack `ts` thread ID in the post's topic if it has not yet been recorded. (Normally, this will be done for the topic post, except where notifications are being posted for old topics before this feature was created.) Add a new rule filter `thread` which posts threaded responses to slack if there is a `ts` recorded for the post topic. Modify the `trigger_notifications` interface to enable other integrations to implement similar functionality. Present the `thread` rule in the help text and admin UI only for the slack providers. https://meta.discourse.org/t/optionally-threading-posts-to-parent-topic-in-slack-integration/150759
132 lines
3.4 KiB
Ruby
132 lines
3.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class DiscourseChat::Rule < DiscourseChat::PluginModel
|
|
# Setup ActiveRecord::Store to use the JSON field to read/write these values
|
|
store :value, accessors: [ :channel_id, :type, :group_id, :category_id, :tags, :filter ], coder: JSON
|
|
|
|
scope :with_type, ->(type) { where("value::json->>'type'=?", type.to_s) }
|
|
scope :with_channel, ->(channel) { with_channel_id(channel.id) }
|
|
scope :with_channel_id, ->(channel_id) { where("value::json->>'channel_id'=?", channel_id.to_s) }
|
|
|
|
scope :with_category_id, ->(category_id) do
|
|
if category_id.nil?
|
|
where("(value::json->'category_id') IS NULL OR json_typeof(value::json->'category_id')='null'")
|
|
else
|
|
where("value::json->>'category_id'=?", category_id.to_s)
|
|
end
|
|
end
|
|
|
|
scope :with_group_ids, ->(group_id) do
|
|
where("value::json->>'group_id' IN (?)", group_id.map!(&:to_s))
|
|
end
|
|
|
|
scope :order_by_precedence, -> {
|
|
order("
|
|
CASE
|
|
WHEN value::json->>'type' = 'group_mention' THEN 1
|
|
WHEN value::json->>'type' = 'group_message' THEN 2
|
|
ELSE 3
|
|
END
|
|
",
|
|
"
|
|
CASE
|
|
WHEN value::json->>'filter' = 'mute' THEN 1
|
|
WHEN value::json->>'filter' = 'thread' THEN 2
|
|
WHEN value::json->>'filter' = 'watch' THEN 3
|
|
WHEN value::json->>'filter' = 'follow' THEN 4
|
|
END
|
|
")
|
|
}
|
|
|
|
after_initialize :init_filter
|
|
|
|
validates :filter, inclusion: { in: %w(thread watch follow mute),
|
|
message: "%{value} is not a valid filter" }
|
|
|
|
validates :type, inclusion: { in: %w(normal group_message group_mention),
|
|
message: "%{value} is not a valid filter" }
|
|
|
|
validate :channel_valid?, :category_valid?, :group_valid?, :tags_valid?
|
|
|
|
def self.key_prefix
|
|
'rule:'.freeze
|
|
end
|
|
|
|
# We never want an empty array, set it to nil instead
|
|
def tags=(array)
|
|
if array.nil? || array.empty?
|
|
super(nil)
|
|
else
|
|
super(array)
|
|
end
|
|
end
|
|
|
|
# These are only allowed to be integers
|
|
%w(channel_id category_id group_id).each do |name|
|
|
define_method "#{name}=" do |val|
|
|
if val.nil? || val.blank?
|
|
super(nil)
|
|
else
|
|
super(val.to_i)
|
|
end
|
|
end
|
|
end
|
|
|
|
# Mock foreign key
|
|
# Could return nil
|
|
def channel
|
|
DiscourseChat::Channel.find_by(id: channel_id)
|
|
end
|
|
|
|
def channel=(val)
|
|
self.channel_id = val.id
|
|
end
|
|
|
|
private
|
|
|
|
def channel_valid?
|
|
if !(DiscourseChat::Channel.where(id: channel_id).exists?)
|
|
errors.add(:channel_id, "#{channel_id} is not a valid channel id")
|
|
end
|
|
end
|
|
|
|
def category_valid?
|
|
if type != 'normal' && !category_id.nil?
|
|
errors.add(:category_id, "cannot be specified for that type of rule")
|
|
end
|
|
|
|
return unless type == 'normal'
|
|
|
|
if !(category_id.nil? || Category.where(id: category_id).exists?)
|
|
errors.add(:category_id, "#{category_id} is not a valid category id")
|
|
end
|
|
end
|
|
|
|
def group_valid?
|
|
if type == 'normal' && !group_id.nil?
|
|
errors.add(:group_id, "cannot be specified for that type of rule")
|
|
end
|
|
|
|
return if type == 'normal'
|
|
|
|
if !Group.where(id: group_id).exists?
|
|
errors.add(:group_id, "#{group_id} is not a valid group id")
|
|
end
|
|
end
|
|
|
|
def tags_valid?
|
|
return if tags.nil?
|
|
|
|
tags.each do |tag|
|
|
if !Tag.where(name: tag).exists?
|
|
errors.add(:tags, "#{tag} is not a valid tag")
|
|
end
|
|
end
|
|
end
|
|
|
|
def init_filter
|
|
self.filter ||= 'watch'
|
|
self.type ||= 'normal'
|
|
end
|
|
end
|