Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: add chat integration reference post #216

Merged
merged 26 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
af5e7e8
FEATURE: Add chat integration reference post
Grubba27 Aug 29, 2024
c5d7568
DEV: change how `excerpt` method works
Grubba27 Aug 29, 2024
3c237ec
feature: Add `send_chat_integration_message` scriptable
Grubba27 Aug 30, 2024
b316558
DEV: Add `get_channel_by_name` to every provider
Grubba27 Sep 3, 2024
846996d
DEV: Add `get_channel_name` to all providers
Grubba27 Sep 3, 2024
8c1513d
DEV: Add removal of old migration data
Grubba27 Sep 4, 2024
3d54fd1
DEV: solve review comments
Grubba27 Sep 4, 2024
6987ca3
DEV: update test locale strings
Grubba27 Sep 4, 2024
96b91bf
DEV: remove empty line to trigger lint
Grubba27 Sep 4, 2024
42e6830
DEV: lint applied
Grubba27 Sep 4, 2024
1df0946
DEV: Add tests for automation integration
Grubba27 Sep 5, 2024
f3eda71
DEV: add rails logger for when automatio error occurs
Grubba27 Sep 5, 2024
96f8da9
DEV: move migration to be SQL only
Grubba27 Sep 5, 2024
5144318
DEV: update migration with correct table names
Grubba27 Sep 5, 2024
b865868
DEV: Update migrate_tag_added_filter_to_all_providers to use smaller …
Grubba27 Sep 6, 2024
d5c0774
DEV: update comments in migration file
Grubba27 Sep 6, 2024
620a5a9
DEV: update indentation in client.en.yml
Grubba27 Sep 10, 2024
2e07334
DEV: update with review comments
Grubba27 Sep 10, 2024
e4d464e
Update spec/lib/discourse_chat_integration/chat_integration_reference…
Grubba27 Sep 10, 2024
86979fb
Update spec/lib/discourse_chat_integration/chat_integration_reference…
Grubba27 Sep 10, 2024
3d46798
Update spec/lib/discourse_chat_integration/chat_integration_reference…
Grubba27 Sep 10, 2024
94bdec9
Update spec/integration/automation_spec.rb
Grubba27 Sep 10, 2024
3ea5b6c
Update lib/discourse_chat_integration/chat_integration_reference_post.rb
Grubba27 Sep 10, 2024
4f681a8
DEV: update specs with review comments
Grubba27 Sep 10, 2024
fa2a8eb
DEV: update typos in tests
Grubba27 Sep 10, 2024
9a60a45
DEV: inlined functions for getting channel name for provider in migra…
Grubba27 Sep 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that valid indentation here? Maybe it's github tripping

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2024-09-10 at 11 24 50 It took me a print to find that it was actually with weird but valid indentation

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
@@ -0,0 +1,93 @@
# frozen_string_literal: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't have any rails class in a migration, it should be all sql, if we change these class, migrations are borked

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ^. You'll have to inline whatever DiscourseChatIntegration::Provider.constants resolves to.

class MigrateTagAddedFilterToAllProviders < ActiveRecord::Migration[7.1]
def up
if defined?(DiscourseAutomation)
begin
# Trash old migration
if 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

DiscourseChatIntegration::Rule
.where("value::json->>'filter'=?", "tag_added")
.each do |rule|
channel_id = rule.channel_id
channel = DiscourseChatIntegration::Channel.find(channel_id)
# channel names are unique but built from the provider
provider_name = channel.provider
provider = DiscourseChatIntegration::Provider.get_by_name(provider_name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think even this should be avoided, we should harcode everything in migrations

channel_name = provider.get_channel_name(channel)

category_id = rule.category_id
tags = rule.tags

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

automation.save!

# Triggers:
# Watching categories

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

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

# Watching tags

metadata = (tags ? { "value" => tags } : {})
automation.upsert_field!("watching_tags", "tags", metadata, target: "trigger")

# Script options:
# Provider
automation.upsert_field!(
"provider",
"choices",
{ "value" => provider_name },
target: "script",
)

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

def down
if defined?(DiscourseAutomation)
DiscourseAutomation::Automation
.where(script: "send_chat_integration_message")
.where(trigger: "topic_tags_changed")
.where(name: "When tags change in topic")
.destroy_all
end
end
end
75 changes: 75 additions & 0 deletions lib/discourse_chat_integration/chat_integration_reference_post.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

module DiscourseChatIntegration
class ChatIntegrationReferencePost
def initialize(context)
@context = context
@user = context["user"]
@topic = context["topic"]
@kind = context["kind"]
@raw = context["raw"] if context["raw"].present?
@created_at = Time.zone.now
Grubba27 marked this conversation as resolved.
Show resolved Hide resolved
end

def id
@topic.posts.empty? ? @topic.id : @topic.posts.first.id
end

def user
@user
end

def topic
@topic
end

def full_url
@topic.posts.empty? ? @topic.full_url : @topic.posts.first.full_url
end

def excerpt(maxlength = nil, options = {})
cooked = PrettyText.cook(raw, { user_id: user.id })
maxlength ||= SiteSetting.post_excerpt_maxlength
PrettyText.excerpt(cooked, maxlength, options)
end

def is_first_post?
topic.try(:highest_post_number) == 0
end

def created_at
@created_at
end

def raw
if @raw.nil? && @kind == DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED
tag_list_to_raw = ->(tag_list) do
tag_list.sort.map { |tag_name| "##{tag_name}" }.join(", ")
end

added_tags = @context["added_tags"]
removed_tags = @context["removed_tags"]

@raw =
if added_tags.present? && removed_tags.present?
I18n.t(
"chat_integration.topic_tag_changed.added_and_removed",
added: tag_list_to_raw.call(added_tags),
removed: tag_list_to_raw.call(removed_tags),
)
elsif added_tags.present?
I18n.t(
"chat_integration.topic_tag_changed.added",
added: tag_list_to_raw.call(added_tags),
)
elsif removed_tags.present?
I18n.t(
"chat_integration.topic_tag_changed.removed",
removed: tag_list_to_raw.call(removed_tags),
)
end
end
@raw
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Provider
module DiscordProvider
PROVIDER_NAME = "discord".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_discord_enabled

CHANNEL_IDENTIFIER_KEY = "name".freeze
CHANNEL_PARAMETERS = [
{ key: "name", regex: '^\S+' },
{
Expand Down Expand Up @@ -94,6 +94,18 @@ def self.trigger_notification(post, channel, rule)
)
end
end

def self.get_channel_by_name(name)
CvX marked this conversation as resolved.
Show resolved Hide resolved
DiscourseChatIntegration::Channel
.with_provider(PROVIDER_NAME)
.with_data_value(CHANNEL_IDENTIFIER_KEY, name)
.first
end

# used in the MigrateTagAddedFilterToAllProviders migration
def self.get_channel_name(channel)
channel.data[CHANNEL_IDENTIFIER_KEY]
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module DiscourseChatIntegration::Provider::FlowdockProvider
PROVIDER_NAME = "flowdock".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_flowdock_enabled
CHANNEL_IDENTIFIER_KEY = "flow_token".freeze # this is really weird but is the only way to identify a channel in this provider
CHANNEL_PARAMETERS = [{ key: "flow_token", regex: '^\S+', unique: true, hidden: true }]

def self.send_message(url, message)
Expand Down Expand Up @@ -60,4 +61,16 @@ def self.trigger_notification(post, channel, rule)
}
end
end

def self.get_channel_by_name(name)
DiscourseChatIntegration::Channel
.with_provider(PROVIDER_NAME)
.with_data_value(CHANNEL_IDENTIFIER_KEY, name)
.first
end

# used in the MigrateTagAddedFilterToAllProviders migration
def self.get_channel_name(channel)
channel.data[CHANNEL_IDENTIFIER_KEY]
end
end
13 changes: 13 additions & 0 deletions lib/discourse_chat_integration/provider/gitter/gitter_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Provider
module GitterProvider
PROVIDER_NAME = "gitter".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_gitter_enabled
CHANNEL_IDENTIFIER_KEY = "name".freeze
CHANNEL_PARAMETERS = [
{ key: "name", regex: '^\S+$', unique: true },
{
Expand Down Expand Up @@ -43,6 +44,18 @@ def self.gitter_message(post)

"[__#{display_name}__ - #{topic.title} - #{category_name}](#{post.full_url})"
end

def self.get_channel_by_name(name)
DiscourseChatIntegration::Channel
.with_provider(PROVIDER_NAME)
.with_data_value(CHANNEL_IDENTIFIER_KEY, name)
.first
end

# used in the MigrateTagAddedFilterToAllProviders migration
def self.get_channel_name(channel)
channel.data[CHANNEL_IDENTIFIER_KEY]
end
end
end
end
13 changes: 13 additions & 0 deletions lib/discourse_chat_integration/provider/google/google_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Provider
module GoogleProvider
PROVIDER_NAME = "google".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_google_enabled
CHANNEL_IDENTIFIER_KEY = "name".freeze
CHANNEL_PARAMETERS = [
{ key: "name", regex: '^\S+$', unique: true },
{
Expand Down Expand Up @@ -107,6 +108,18 @@ def self.get_message(post)
],
}
end

def self.get_channel_by_name(name)
DiscourseChatIntegration::Channel
.with_provider(PROVIDER_NAME)
.with_data_value(CHANNEL_IDENTIFIER_KEY, name)
.first
end

# used in the MigrateTagAddedFilterToAllProviders migration
def self.get_channel_name(channel)
channel.data[CHANNEL_IDENTIFIER_KEY]
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module DiscourseChatIntegration::Provider::GroupmeProvider
PROVIDER_NAME = "groupme".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_groupme_enabled
CHANNEL_IDENTIFIER_KEY = "groupme_instance_name".freeze
CHANNEL_PARAMETERS = [{ key: "groupme_instance_name", regex: '[\s\S]*', unique: true }]

def self.generate_groupme_message(post)
Expand Down Expand Up @@ -84,4 +85,16 @@ def self.trigger_notification(post, channel, rule)
data_package = generate_groupme_message(post)
self.send_via_webhook(data_package, channel)
end

def self.get_channel_by_name(name)
DiscourseChatIntegration::Channel
.with_provider(PROVIDER_NAME)
.with_data_value(CHANNEL_IDENTIFIER_KEY, name)
.first
end

# used in the MigrateTagAddedFilterToAllProviders migration
def self.get_channel_name(channel)
channel.data[CHANNEL_IDENTIFIER_KEY]
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Provider
module GuildedProvider
PROVIDER_NAME = "guilded".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_guilded_enabled

CHANNEL_IDENTIFIER_KEY = "name".freeze
CHANNEL_PARAMETERS = [
{ key: "name", regex: '^\S+' },
{
Expand Down Expand Up @@ -92,6 +92,18 @@ def self.ensure_protocol(url)
return url if !url.start_with?("//")
"http:#{url}"
end

def self.get_channel_by_name(name)
DiscourseChatIntegration::Channel
.with_provider(PROVIDER_NAME)
.with_data_value(CHANNEL_IDENTIFIER_KEY, name)
.first
end

# used in the MigrateTagAddedFilterToAllProviders migration
def self.get_channel_name(channel)
channel.data[CHANNEL_IDENTIFIER_KEY]
end
end
end
end
13 changes: 13 additions & 0 deletions lib/discourse_chat_integration/provider/matrix/matrix_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Provider
module MatrixProvider
PROVIDER_NAME = "matrix".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_matrix_enabled
CHANNEL_IDENTIFIER_KEY = "name".freeze
CHANNEL_PARAMETERS = [
{ key: "name", regex: '^\S+' },
{ key: "room_id", regex: '^\!\S+:\S+$', unique: true, hidden: true },
Expand Down Expand Up @@ -88,6 +89,18 @@ def self.trigger_notification(post, channel, rule)
end
end
end

def self.get_channel_by_name(name)
CvX marked this conversation as resolved.
Show resolved Hide resolved
DiscourseChatIntegration::Channel
.with_provider(PROVIDER_NAME)
.with_data_value(CHANNEL_IDENTIFIER_KEY, name)
.first
end

# used in the MigrateTagAddedFilterToAllProviders migration
def self.get_channel_name(channel)
channel.data[CHANNEL_IDENTIFIER_KEY]
end
end
end
end
Loading