Skip to content

Commit

Permalink
Feature: add chat integration reference post (#216)
Browse files Browse the repository at this point in the history
* FEATURE: Add chat integration reference post

This class works similar to a post but it is not a post.

* DEV: change how `excerpt` method works

* feature: Add `send_chat_integration_message` scriptable

add `send_chat_integration_message` scriptable that uses the rules to send a message to the chat provider
add locale strings for the new scriptable
update `ChatIntegrationReferencePost` `excerpt` method
add tests for `ChatIntegrationReferencePost`

* DEV: Add `get_channel_by_name` to every provider

This makes using `trigger_notification` easier with every provider as well.

* DEV: Add `get_channel_name` to all providers

This method gets the name of the channel based on how the provider identifies it.
Updates channel_name in locales yaml
Adds migrate_tag_added_filter_to_all_providers.rb to move all existing rules to use Automation

* DEV: Add removal of old migration data

Update small action locales with strings from core

* DEV: solve review comments

* DEV: update test locale strings

* DEV: remove empty line to trigger lint

* DEV: lint applied

* DEV: Add tests for automation integration

* DEV: add rails logger for when automatio error occurs

* DEV: move migration to be SQL only

Update provider helper to use hashes instead of dot notation

* DEV: update migration with correct table names

* DEV: Update migrate_tag_added_filter_to_all_providers to use smaller SQL queries

Commented out migrate_tag_added_from_filter_to_automation.rb

* DEV: update comments in migration file

* DEV: update indentation in client.en.yml

* DEV: update with review comments

* Update spec/lib/discourse_chat_integration/chat_integration_reference_post_spec.rb

Co-authored-by: Jarek Radosz <[email protected]>

* Update spec/lib/discourse_chat_integration/chat_integration_reference_post_spec.rb

Co-authored-by: Jarek Radosz <[email protected]>

* Update spec/lib/discourse_chat_integration/chat_integration_reference_post_spec.rb

Co-authored-by: Jarek Radosz <[email protected]>

* Update spec/integration/automation_spec.rb

Co-authored-by: Jarek Radosz <[email protected]>

* Update lib/discourse_chat_integration/chat_integration_reference_post.rb

Co-authored-by: Jarek Radosz <[email protected]>

* DEV: update specs with review comments

* DEV: update typos in tests

* DEV: inlined functions for getting channel name for provider in migration

---------

Co-authored-by: Jarek Radosz <[email protected]>
  • Loading branch information
Grubba27 and CvX authored Sep 11, 2024
1 parent b36dded commit 3f8b67d
Show file tree
Hide file tree
Showing 39 changed files with 837 additions and 76 deletions.
9 changes: 9 additions & 0 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,12 @@ en:
label: URL
channel:
label: Channel

send_chat_integration_message:
title: Send Chat-Integration message
fields:
channel_name:
label: Channel name
description: "You can find the channel name in the Chat Integration settings"
provider:
label: Provider
8 changes: 8 additions & 0 deletions config/locales/server.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ en:
scriptables:
send_slack_message:
title: Send Slack message
send_chat_integration_message:
title: Send Chat-Integration message
chat_integration:

all_categories: "(all categories)"
Expand All @@ -134,6 +136,12 @@ en:
group_mention_template: "mentions of: @%{name}"
group_message_template: "messages to: @%{name}"


topic_tag_changed:
added_and_removed: "Added %{added} and removed %{removed}"
added: "Added %{added}"
removed: "Removed %{removed}"

provider:

#######################################
Expand Down
Original file line number Diff line number Diff line change
@@ -1,92 +1,96 @@
# frozen_string_literal: true

# The next migration file is a migration that migrates the tag_added filter to an automation.
# this one uses ActiveRecord which is not recommended for migrations.

class MigrateTagAddedFromFilterToAutomation < ActiveRecord::Migration[7.1]
def up
if defined?(DiscourseAutomation) &&
DiscourseChatIntegration::Channel.with_provider("slack").exists?
begin
DiscourseChatIntegration::Rule
.where("value::json->>'filter'=?", "tag_added")
.each do |rule|
channel_id = rule.value["channel_id"]
channel_name =
DiscourseChatIntegration::Channel.find(channel_id).value["data"]["identifier"] # it _must_ have a channel_id
# if defined?(DiscourseAutomation) &&
# DiscourseChatIntegration::Channel.with_provider("slack").exists?
# begin
# DiscourseChatIntegration::Rule
# .where("value::json->>'filter'=?", "tag_added")
# .each do |rule|
# channel_id = rule.value["channel_id"]
# channel_name =
# DiscourseChatIntegration::Channel.find(channel_id).value["data"]["identifier"] # it _must_ have a channel_id

category_id = rule.value["category_id"]
tags = rule.value["tags"]
# category_id = rule.value["category_id"]
# tags = rule.value["tags"]

automation =
DiscourseAutomation::Automation.new(
script: "send_slack_message",
trigger: "topic_tags_changed",
name: "When tags change in topic",
enabled: true,
last_updated_by_id: Discourse.system_user.id,
)
# automation =
# DiscourseAutomation::Automation.new(
# script: "send_slack_message",
# trigger: "topic_tags_changed",
# name: "When tags change in topic",
# enabled: true,
# last_updated_by_id: Discourse.system_user.id,
# )

automation.save!
# automation.save!

# Triggers:
# Watching categories
# # Triggers:
# # Watching categories

metadata = (category_id ? { "value" => [category_id] } : {})
# metadata = (category_id ? { "value" => [category_id] } : {})

automation.upsert_field!(
"watching_categories",
"categories",
metadata,
target: "trigger",
)
# automation.upsert_field!(
# "watching_categories",
# "categories",
# metadata,
# target: "trigger",
# )

# Watching tags
# # Watching tags

metadata = (tags ? { "value" => tags } : {})
# metadata = (tags ? { "value" => tags } : {})

automation.upsert_field!("watching_tags", "tags", metadata, target: "trigger")
# automation.upsert_field!("watching_tags", "tags", metadata, target: "trigger")

# Script options:
# Message
automation.upsert_field!(
"message",
"message",
{ "value" => "${ADDED_AND_REMOVED}" },
target: "script",
)
# # Script options:
# # Message
# automation.upsert_field!(
# "message",
# "message",
# { "value" => "${ADDED_AND_REMOVED}" },
# target: "script",
# )

# URL
automation.upsert_field!(
"url",
"text",
{ "value" => Discourse.current_hostname },
target: "script",
)
# # URL
# automation.upsert_field!(
# "url",
# "text",
# { "value" => Discourse.current_hostname },
# target: "script",
# )

# Channel
automation.upsert_field!(
"channel",
"text",
{ "value" => channel_name },
target: "script",
)
end
rescue StandardError
Rails.logger.warn("Failed to migrate tag_added rules to automations")
end
end
# # Channel
# automation.upsert_field!(
# "channel",
# "text",
# { "value" => channel_name },
# target: "script",
# )
# end
# rescue StandardError
# Rails.logger.warn("Failed to migrate tag_added rules to automations")
# end
# end
end

def down
if defined?(DiscourseAutomation) &&
DiscourseChatIntegration::Channel.with_provider("slack").exists?
DiscourseAutomation::Automation
.where(script: "send_slack_message", trigger: "topic_tags_changed")
.each do |automation|
# if is the same name as created and message is the same
if automation.name == "When tags change in topic" &&
automation.fields.where(name: "message").first.metadata["value"] ==
"${ADDED_AND_REMOVED}"
automation.destroy!
end
end
end
# if defined?(DiscourseAutomation) &&
# DiscourseChatIntegration::Channel.with_provider("slack").exists?
# DiscourseAutomation::Automation
# .where(script: "send_slack_message", trigger: "topic_tags_changed")
# .each do |automation|
# # if is the same name as created and message is the same
# if automation.name == "When tags change in topic" &&
# automation.fields.where(name: "message").first.metadata["value"] ==
# "${ADDED_AND_REMOVED}"
# automation.destroy!
# end
# end
# end
end
end
153 changes: 153 additions & 0 deletions db/migrate/20240903184807_migrate_tag_added_filter_to_all_providers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# frozen_string_literal: true
class MigrateTagAddedFilterToAllProviders < ActiveRecord::Migration[7.1]
def up
if defined?(DiscourseAutomation)
begin
slack_usage_rows = DB.query <<~SQL
SELECT plugin_store_rows.* FROM plugin_store_rows
WHERE plugin_store_rows.type_name = 'JSON'
AND plugin_store_rows.plugin_name = 'discourse-chat-integration'
AND (key LIKE 'channel:%')
AND (value::json->>'provider'='slack')
SQL

old_migration_delete = <<~SQL
DELETE FROM discourse_automation_automations
WHERE id IN (
SELECT a.id
FROM discourse_automation_automations a
JOIN discourse_automation_fields f ON f.automation_id = a.id
WHERE a.script = 'send_slack_message'
AND a.trigger = 'topic_tags_changed'
AND a.name = 'When tags change in topic'
AND f.name = 'message'
AND f.metadata->>'value' = '${ADDED_AND_REMOVED}'
)
SQL
# Trash old migration
DB.exec old_migration_delete if slack_usage_rows.count > 0

rules_with_tag_added = <<~SQL
SELECT value
FROM plugin_store_rows
WHERE plugin_name = 'discourse-chat-integration'
AND key LIKE 'rule:%'
AND value::json->>'filter' = 'tag_added'
SQL

channel_query = <<~SQL
SELECT *
FROM plugin_store_rows
WHERE type_name = 'JSON'
AND plugin_name = 'discourse-chat-integration'
AND key LIKE 'channel:%'
AND id = :channel_id
LIMIT 1
SQL

automation_creation = <<~SQL
INSERT INTO discourse_automation_automations (script, trigger, name, enabled, last_updated_by_id, created_at, updated_at)
VALUES ('send_chat_integration_message', 'topic_tags_changed', 'When tags change in topic', true, -1, NOW(), NOW())
RETURNING id
SQL

create_automation_field = <<~SQL
INSERT INTO discourse_automation_fields (automation_id, name, component, metadata, target, created_at, updated_at)
VALUES (:automation_id, :name, :component, :metadata, :target, NOW(), NOW())
SQL

provider_identifier_map = {
"groupme" => "groupme_instance_name",
"discord" => "name",
"guilded" => "name",
"mattermost" => "identifier",
"matrix" => "name",
"teams" => "name",
"zulip" => "stream",
"powerautomate" => "name",
"rocketchat" => "identifier",
"gitter" => "name",
"telegram" => "name",
"flowdock" => "flow_token",
"google" => "name",
"webex" => "name",
"slack" => "identifier",
}

DB
.query(rules_with_tag_added)
.each do |row|
rule = JSON.parse(row.value).with_indifferent_access

channel =
JSON.parse(
DB.query(channel_query, channel_id: rule[:channel_id]).first.value,
).with_indifferent_access

provider_name = channel[:provider]
channel_name = channel[:data][provider_identifier_map[provider_name]]

category_id = rule[:category_id]
tags = rule[:tags]

automation_id = DB.query(automation_creation).first.id

# Triggers:
# Watching categories
metadata = (category_id ? { "value" => [category_id] } : {}).to_json
DB.exec(
create_automation_field,
automation_id: automation_id,
name: "watching_categories",
component: "categories",
metadata: metadata,
target: "trigger",
)

# Watching tags
metadata = (tags.present? ? { "value" => tags } : {}).to_json
DB.exec(
create_automation_field,
automation_id: automation_id,
name: "watching_tags",
component: "tags",
metadata: metadata,
target: "trigger",
)

# Script options:
# Provider
DB.exec(
create_automation_field,
automation_id: automation_id,
name: "provider",
component: "choices",
metadata: { "value" => provider_name }.to_json,
target: "script",
)

# Channel name
DB.exec(
create_automation_field,
automation_id: automation_id,
name: "channel_name",
component: "text",
metadata: { "value" => channel_name }.to_json,
target: "script",
)
end
rescue StandardError
puts "Error migrating tag_added filters to all providers"
end
end
end

def down
DB.exec <<~SQL if defined?(DiscourseAutomation)
DELETE FROM discourse_automation_automations
WHERE script = 'send_chat_integration_message'
AND trigger = 'topic_tags_changed'
AND name = 'When tags change in topic'
SQL
end
end
Loading

0 comments on commit 3f8b67d

Please sign in to comment.