diff --git a/plugins/automation/config/locales/client.en.yml b/plugins/automation/config/locales/client.en.yml index 91109ef8ea4..22e12b7f07f 100644 --- a/plugins/automation/config/locales/client.en.yml +++ b/plugins/automation/config/locales/client.en.yml @@ -222,6 +222,10 @@ en: 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: + trigger_on_modes: + tags_added_or_removed: Tags added or removed + tags_added: Tags added + tags_removed: Tags removed fields: watching_categories: label: Watching categories @@ -229,6 +233,8 @@ en: watching_tags: label: Watching tags description: Will trigger only if the topic has any of these tags + trigger_on: + label: Trigger on trigger_with_pms: label: Trigger with PMs description: Will trigger even if the tags were changed in a PM diff --git a/plugins/automation/lib/discourse_automation/event_handlers.rb b/plugins/automation/lib/discourse_automation/event_handlers.rb index 0ce2903efa5..031bd65a444 100644 --- a/plugins/automation/lib/discourse_automation/event_handlers.rb +++ b/plugins/automation/lib/discourse_automation/event_handlers.rb @@ -243,6 +243,17 @@ module DiscourseAutomation next if (changed_tags & watching_tags["value"]).empty? end + trigger_on = automation.trigger_field("trigger_on")["value"] + + if trigger_on == Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED && added_tags.empty? + next + end + + if trigger_on == Triggers::TopicTagsChanged::TriggerOn::TAGS_REMOVED && + removed_tags.empty? + next + end + automation.trigger!( "kind" => name, "topic" => topic, diff --git a/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb b/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb index 092d4bd20a7..9cbd5ce119b 100644 --- a/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb +++ b/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb @@ -1,8 +1,46 @@ # frozen_string_literal: true +module DiscourseAutomation + module Triggers + module TopicTagsChanged + module TriggerOn + TAGS_ADDED_OR_REMOVED = "tags_added_or_removed" + TAGS_ADDED = "tags_added" + TAGS_REMOVED = "tags_removed" + + MODES = [ + { + id: TAGS_ADDED_OR_REMOVED, + name: + "discourse_automation.triggerables.topic_tags_changed.trigger_on_modes.tags_added_or_removed", + }, + { + id: TAGS_ADDED, + name: + "discourse_automation.triggerables.topic_tags_changed.trigger_on_modes.tags_added", + }, + { + id: TAGS_REMOVED, + name: + "discourse_automation.triggerables.topic_tags_changed.trigger_on_modes.tags_removed", + }, + ] + end + end + end +end + DiscourseAutomation::Triggerable.add(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED) do field :watching_categories, component: :categories field :watching_tags, component: :tags + field :trigger_on, + component: :choices, + extra: { + content: DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::MODES, + }, + default_value: + DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED_OR_REMOVED, + required: true field :trigger_with_pms, component: :boolean placeholder :topic_url diff --git a/plugins/automation/spec/triggers/topic_tags_changed_spec.rb b/plugins/automation/spec/triggers/topic_tags_changed_spec.rb index a0474ea4cc8..75e80cc0d7a 100644 --- a/plugins/automation/spec/triggers/topic_tags_changed_spec.rb +++ b/plugins/automation/spec/triggers/topic_tags_changed_spec.rb @@ -328,5 +328,79 @@ describe DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED do end expect(list.length).to eq(1) end + + context "with TAGS_ADDED set in trigger_on field" do + it "should fire if tag is added" do + automation.upsert_field!( + "trigger_on", + "choices", + { value: DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED }, + target: "trigger", + ) + + topic_0 = Fabricate(:topic, user: user, tags: []) + + 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 not fire if tag is removed" do + automation.upsert_field!( + "trigger_on", + "choices", + { value: DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED }, + target: "trigger", + ) + + topic_0 = Fabricate(:topic, user: user, tags: [cool_tag]) + + list = + capture_contexts { DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), []) } + + expect(list.length).to eq(0) + end + end + + context "with TAGS_REMOVED set in trigger_on field" do + it "should fire if tag is removed" do + automation.upsert_field!( + "trigger_on", + "choices", + { value: DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_REMOVED }, + target: "trigger", + ) + + topic_0 = Fabricate(:topic, user: user, tags: [cool_tag]) + + 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 tag is added" do + automation.upsert_field!( + "trigger_on", + "choices", + { value: DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_REMOVED }, + target: "trigger", + ) + + topic_0 = Fabricate(:topic, user: user, tags: []) + + 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 end end