FEATURE: New rule filter to send message when topic tags change (#162)
This commit is contained in:
parent
75cf4136e9
commit
a92108b69b
|
@ -37,7 +37,8 @@ class DiscourseChatIntegration::Rule < DiscourseChatIntegration::PluginModel
|
|||
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
|
||||
WHEN value::json->>'filter' = 'tag_added' THEN 4
|
||||
WHEN value::json->>'filter' = 'follow' THEN 5
|
||||
END
|
||||
",
|
||||
)
|
||||
|
@ -47,7 +48,7 @@ class DiscourseChatIntegration::Rule < DiscourseChatIntegration::PluginModel
|
|||
|
||||
validates :filter,
|
||||
inclusion: {
|
||||
in: %w[thread watch follow mute],
|
||||
in: %w[thread watch follow tag_added mute],
|
||||
message: "%{value} is not a valid filter",
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,14 @@ module DiscourseChatIntegration
|
|||
# Abort if the chat_user doesn't have permission to see the post
|
||||
return if !guardian.can_see?(post)
|
||||
|
||||
# Abort if the post is blank, or is non-regular (e.g. a "topic closed" notification)
|
||||
return if post.blank? || post.post_type != Post.types[:regular]
|
||||
# Abort if the post is blank
|
||||
return if post.blank?
|
||||
|
||||
# Abort if post is not either regular, or a 'tags_changed' small action
|
||||
if (post.post_type != Post.types[:regular]) &&
|
||||
!(post.post_type == Post.types[:small_action] && post.action_code == "tags_changed")
|
||||
return
|
||||
end
|
||||
|
||||
topic = post.topic
|
||||
return if topic.blank?
|
||||
|
@ -46,6 +52,33 @@ module DiscourseChatIntegration
|
|||
end
|
||||
end
|
||||
|
||||
if post.action_code == "tags_changed"
|
||||
# Post is a small_action post regarding tags changing for the topic. Check if any tags were _added_
|
||||
# and if so, corresponding rules with `filter: tag_added`
|
||||
tags_added = post.custom_fields["tags_added"]
|
||||
tags_added = [tags_added].compact if !tags_added.is_a?(Array)
|
||||
return if tags_added.blank?
|
||||
|
||||
tags_removed = post.custom_fields["tags_removed"]
|
||||
tags_removed = [tags_removed].compact if !tags_removed.is_a?(Array)
|
||||
|
||||
unchanged_tags = topic.tags.map(&:name) - tags_added - tags_removed
|
||||
|
||||
matching_rules =
|
||||
matching_rules.select do |rule|
|
||||
# Only rules that match this post, are ones where the filter is "tag_added"
|
||||
next false if rule.filter != "tag_added"
|
||||
next true if rule.tags.blank?
|
||||
|
||||
# Skip if the topic already has one of the tags in the rule, applied
|
||||
next false if unchanged_tags.any? && (unchanged_tags & rule.tags).any?
|
||||
|
||||
# We don't need to do any additional filtering here because topics are filtered
|
||||
# by tag later
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
# If tagging is enabled, thow away rules that don't apply to this topic
|
||||
if SiteSetting.tagging_enabled
|
||||
topic_tags = topic.tags.present? ? topic.tags.pluck(:name) : []
|
||||
|
@ -59,7 +92,7 @@ module DiscourseChatIntegration
|
|||
|
||||
# Sort by order of precedence
|
||||
t_prec = { "group_message" => 0, "group_mention" => 1, "normal" => 2 } # Group things win
|
||||
f_prec = { "mute" => 0, "thread" => 1, "watch" => 2, "follow" => 3 } #(mute always wins; thread beats watch beats follow)
|
||||
f_prec = { "mute" => 0, "thread" => 1, "watch" => 2, "follow" => 3, "tag_added" => 4 } #(mute always wins; thread beats watch beats follow)
|
||||
sort_func =
|
||||
proc { |a, b| [t_prec[a.type], f_prec[a.filter]] <=> [t_prec[b.type], f_prec[b.filter]] }
|
||||
matching_rules = matching_rules.sort(&sort_func)
|
||||
|
|
|
@ -46,6 +46,11 @@ export default class Rule extends RestModel {
|
|||
name: I18n.t("chat_integration.filter.follow"),
|
||||
icon: "circle",
|
||||
},
|
||||
{
|
||||
id: "tag_added",
|
||||
name: I18n.t("chat_integration.filter.tag_added"),
|
||||
icon: "tag",
|
||||
},
|
||||
{
|
||||
id: "mute",
|
||||
name: I18n.t("chat_integration.filter.mute"),
|
||||
|
|
|
@ -36,6 +36,7 @@ en:
|
|||
mute: 'Mute'
|
||||
follow: 'First post only'
|
||||
watch: 'All posts and replies'
|
||||
tag_added: 'Tag added to topic'
|
||||
thread: 'All posts with threaded replies'
|
||||
rule_table:
|
||||
filter: "Filter"
|
||||
|
|
|
@ -345,6 +345,69 @@ RSpec.describe DiscourseChatIntegration::Manager do
|
|||
|
||||
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
||||
end
|
||||
|
||||
describe "with create_small_action_post_for_tag_changes enabled" do
|
||||
fab!(:admin) { Fabricate(:admin) }
|
||||
fab!(:additional_tag) { Fabricate(:tag) }
|
||||
|
||||
before { SiteSetting.create_post_for_category_and_tag_changes = true }
|
||||
|
||||
def set_new_tags_and_return_small_action_post(tags)
|
||||
PostRevisor.new(tagged_first_post).revise!(admin, tags: tags)
|
||||
|
||||
tagged_topic.ordered_posts.last
|
||||
end
|
||||
|
||||
it "should notify when rule is set up for tag additions for a category with no tag filter" do
|
||||
post = set_new_tags_and_return_small_action_post([tag.name, additional_tag.name])
|
||||
|
||||
DiscourseChatIntegration::Rule.create!(
|
||||
channel: chan1,
|
||||
filter: "tag_added",
|
||||
category_id: category.id,
|
||||
)
|
||||
|
||||
manager.trigger_notifications(post.id)
|
||||
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
||||
end
|
||||
|
||||
it "notifies when topic has a tag added that matches the rule" do
|
||||
post = set_new_tags_and_return_small_action_post([tag.name, additional_tag.name])
|
||||
|
||||
DiscourseChatIntegration::Rule.create!(
|
||||
channel: chan1,
|
||||
filter: "tag_added",
|
||||
category_id: category.id,
|
||||
tags: [additional_tag.name],
|
||||
)
|
||||
|
||||
manager.trigger_notifications(post.id)
|
||||
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
||||
end
|
||||
|
||||
it "doesn't notify when topic has an unchanged tag present in the rule, even if a new tag is added" do
|
||||
post = set_new_tags_and_return_small_action_post([tag.name, additional_tag.name])
|
||||
|
||||
DiscourseChatIntegration::Rule.create!(
|
||||
channel: chan1,
|
||||
filter: "tag_added",
|
||||
category_id: category.id,
|
||||
tags: [tag.name],
|
||||
)
|
||||
|
||||
manager.trigger_notifications(post.id)
|
||||
expect(provider.sent_to_channel_ids).to contain_exactly
|
||||
end
|
||||
|
||||
it "doesn't notify for small action 'tags_changed' posts unless a matching rule exists" do
|
||||
post = set_new_tags_and_return_small_action_post([additional_tag.name])
|
||||
|
||||
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "watch", category_id: nil) # Wildcard watch
|
||||
|
||||
manager.trigger_notifications(post.id)
|
||||
expect(provider.sent_to_channel_ids).to contain_exactly
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue