FEATURE: Added trigger for topic tags changed (#28176)

* FEATURE: Added trigger for topic tags changed

* DEV: register new file in plugin.rb

* DEV: update to use already existing `:topic_tags_changed` event

* DEV: Add tests to topic_tags_changed trigger

remove `watching_user` field

* DEV: add more tests to topic_tags_changed_spec.rb

* DEV: update tests and implementation for topic tags changed automation trigger

* DEV: update checking for tags changed automation

* DEV: Update argument application for `handle_topic_tags_changed`
This commit is contained in:
Gabriel Grubba 2024-08-02 09:58:51 -03:00 committed by GitHub
parent 7977ae61f7
commit ec46487870
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 193 additions and 0 deletions

View File

@ -203,6 +203,14 @@ en:
valid_trust_levels:
label: Valid trust levels
description: Will trigger only if post is created by user in these trust levels, defaults to any trust level
topic_tags_changed:
fields:
watching_categories:
label: Watching categories
description: Will trigger only if the topic is in one of these categories
watching_tags:
label: Watching tags
description: Will trigger only if the topic has any of these tags
after_post_cook:
fields:
valid_trust_levels:

View File

@ -50,6 +50,9 @@ en:
pm_created:
title: Personal message created
description: When a valid PM is created the automation will be triggered
topic_tags_changed:
title: Topic tags changed
description: When the tags of a topic are changed the automation will be triggered
topic:
title: Topic
description: The associated script will only be used on the specified topic, this is usefull for scripts doing validation for example

View File

@ -195,6 +195,36 @@ module DiscourseAutomation
end
end
def self.handle_topic_tags_changed(topic, old_tag_names, new_tag_names)
name = DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED
DiscourseAutomation::Automation
.where(trigger: name, enabled: true)
.find_each do |automation|
watching_categories = automation.trigger_field("watching_categories")
if watching_categories["value"]
next if !watching_categories["value"].include?(topic.category_id)
end
watching_tags = automation.trigger_field("watching_tags")
if watching_tags["value"]
should_skip = false
watching_tags["value"].each do |tag|
should_skip = true if !old_tag_names.empty? && !old_tag_names.include?(tag)
should_skip = true if !new_tag_names.empty? && !new_tag_names.include?(tag)
end
next if should_skip
end
automation.trigger!(
"kind" => name,
"topic" => topic,
"removed_tags" => old_tag_names,
"added_tags" => new_tag_names,
)
end
end
def self.handle_after_post_cook(post, cooked)
return cooked if post.post_type != Post.types[:regular] || post.post_number > 1

View File

@ -6,6 +6,7 @@ module DiscourseAutomation
API_CALL = "api_call"
CATEGORY_CREATED_EDITED = "category_created_edited"
PM_CREATED = "pm_created"
TOPIC_TAGS_CHANGED = "topic_tags_changed"
POINT_IN_TIME = "point_in_time"
POST_CREATED_EDITED = "post_created_edited"
RECURRING = "recurring"

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
DiscourseAutomation::Triggerable.add(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED) do
field :watching_categories, component: :categories
field :watching_tags, component: :tags
end

View File

@ -72,6 +72,7 @@ after_initialize do
lib/discourse_automation/triggers/recurring
lib/discourse_automation/triggers/stalled_topic
lib/discourse_automation/triggers/stalled_wiki
lib/discourse_automation/triggers/topic_tags_changed
lib/discourse_automation/triggers/topic
lib/discourse_automation/triggers/user_added_to_group
lib/discourse_automation/triggers/user_badge_granted
@ -181,6 +182,14 @@ after_initialize do
DiscourseAutomation::EventHandlers.handle_pm_created(topic) if topic.private_message?
end
on(:topic_tags_changed) do |topic, tags|
DiscourseAutomation::EventHandlers.handle_topic_tags_changed(
topic,
tags[:old_tag_names],
tags[:new_tag_names],
)
end
on(:post_created) do |post|
DiscourseAutomation::EventHandlers.handle_post_created_edited(post, :create)
end

View File

@ -0,0 +1,136 @@
# frozen_string_literal: true
describe DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED do
before { SiteSetting.discourse_automation_enabled = true }
fab!(:cool_tag) { Fabricate(:tag) }
fab!(:bad_tag) { Fabricate(:tag) }
fab!(:category)
fab!(:user)
fab!(:automation) do
Fabricate(:automation, trigger: DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED)
end
before do
SiteSetting.tagging_enabled = true
SiteSetting.create_tag_allowed_groups = Group::AUTO_GROUPS[:everyone]
SiteSetting.tag_topic_allowed_groups = Group::AUTO_GROUPS[:everyone]
end
context "when watching a cool tag" do
before do
automation.upsert_field!(
"watching_tags",
"tags",
{ value: [cool_tag.name] },
target: "trigger",
)
automation.reload
end
it "should fire the trigger if the tag is added" do
topic_0 = Fabricate(:topic, user: user, tags: [], category: category)
list =
capture_contexts do
DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [cool_tag.name])
end
expect(list.length).to eq(1)
expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED)
end
it "should fire the trigger if the tag is removed" do
topic_0 = Fabricate(:topic, user: user, tags: [cool_tag], category: category)
list =
capture_contexts { DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), []) }
expect(list.length).to eq(1)
expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED)
end
it "should not fire if the tag is not present" do
topic_0 = Fabricate(:topic, user: user, tags: [], category: category)
list =
capture_contexts do
DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [bad_tag.name])
end
expect(list.length).to eq(0)
end
end
context "when watching a category" do
before do
automation.upsert_field!(
"watching_categories",
"categories",
{ value: [category.id] },
target: "trigger",
)
automation.reload
end
it "should fire the trigger if the tag is added" do
topic_0 = Fabricate(:topic, user: user, tags: [], category: category)
topic_1 = Fabricate(:topic, user: user, tags: [], category: Fabricate(:category))
list =
capture_contexts do
DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [bad_tag.name])
DiscourseTagging.tag_topic_by_names(topic_1, Guardian.new(user), [bad_tag.name])
end
expect(list.length).to eq(1)
expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED)
end
it "should fire the trigger if the tag is removed" do
topic_0 = Fabricate(:topic, user: user, tags: [cool_tag], category: category)
list =
capture_contexts { DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), []) }
expect(list.length).to eq(1)
expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED)
end
it "should not fire if not the watching category" do
topic_0 = Fabricate(:topic, user: user, tags: [], category: Fabricate(:category))
list =
capture_contexts do
DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [cool_tag.name])
end
expect(list.length).to eq(0)
end
end
context "when without any watching tags or categories" do
it "should fire the trigger if the tag is added" do
topic_0 = Fabricate(:topic, user: user, tags: [], category: category)
list =
capture_contexts do
DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [cool_tag.name])
end
expect(list.length).to eq(1)
expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED)
end
it "should fire the trigger if the tag is removed" do
topic_0 = Fabricate(:topic, user: user, tags: [cool_tag], category: category)
list =
capture_contexts { DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), []) }
expect(list.length).to eq(1)
expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED)
end
end
end