2019-05-12 22:37:49 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-07-05 18:00:58 -04:00
|
|
|
module DiscourseChat
|
|
|
|
module Helper
|
2017-08-01 15:53:39 -04:00
|
|
|
|
2017-07-19 11:57:33 -04:00
|
|
|
def self.process_command(channel, tokens)
|
|
|
|
guardian = DiscourseChat::Manager.guardian
|
|
|
|
|
|
|
|
provider = channel.provider
|
|
|
|
|
|
|
|
cmd = tokens.shift if tokens.size >= 1
|
|
|
|
|
|
|
|
error_text = I18n.t("chat_integration.provider.#{provider}.parse_error")
|
|
|
|
|
|
|
|
case cmd
|
|
|
|
when "watch", "follow", "mute"
|
|
|
|
return error_text if tokens.empty?
|
|
|
|
# If the first token in the command is a tag, this rule applies to all categories
|
|
|
|
category_name = tokens[0].start_with?('tag:') ? nil : tokens.shift
|
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
if category_name
|
2017-07-19 11:57:33 -04:00
|
|
|
category = Category.find_by(slug: category_name)
|
|
|
|
unless category
|
|
|
|
cat_list = (CategoryList.new(guardian).categories.map(&:slug)).join(', ')
|
2017-08-01 15:53:39 -04:00
|
|
|
return I18n.t("chat_integration.provider.#{provider}.not_found.category", name: category_name, list: cat_list)
|
2017-07-19 11:57:33 -04:00
|
|
|
end
|
|
|
|
else
|
|
|
|
category = nil # All categories
|
|
|
|
end
|
|
|
|
|
|
|
|
tags = []
|
|
|
|
# Every remaining token must be a tag. If not, abort and send help text
|
|
|
|
while tokens.size > 0
|
|
|
|
token = tokens.shift
|
|
|
|
if token.start_with?('tag:')
|
|
|
|
tag_name = token.sub(/^tag:/, '')
|
|
|
|
else
|
2017-10-03 05:42:07 -04:00
|
|
|
return error_text
|
2017-07-19 11:57:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
tag = Tag.find_by(name: tag_name)
|
2017-10-03 05:42:07 -04:00
|
|
|
|
|
|
|
unless tag
|
2017-07-19 11:57:33 -04:00
|
|
|
return I18n.t("chat_integration.provider.#{provider}.not_found.tag", name: tag_name)
|
|
|
|
end
|
|
|
|
tags.push(tag.name)
|
|
|
|
end
|
|
|
|
|
|
|
|
category_id = category.nil? ? nil : category.id
|
2017-08-01 15:53:39 -04:00
|
|
|
case DiscourseChat::Helper.smart_create_rule(channel: channel, filter: cmd, category_id: category_id, tags: tags)
|
2017-07-19 11:57:33 -04:00
|
|
|
when :created
|
2017-10-03 05:42:07 -04:00
|
|
|
I18n.t("chat_integration.provider.#{provider}.create.created")
|
2017-07-19 11:57:33 -04:00
|
|
|
when :updated
|
2017-10-03 05:42:07 -04:00
|
|
|
I18n.t("chat_integration.provider.#{provider}.create.updated")
|
2017-07-19 11:57:33 -04:00
|
|
|
else
|
2017-10-03 05:42:07 -04:00
|
|
|
I18n.t("chat_integration.provider.#{provider}.create.error")
|
2017-07-19 11:57:33 -04:00
|
|
|
end
|
|
|
|
when "remove"
|
|
|
|
return error_text unless tokens.size == 1
|
|
|
|
|
|
|
|
rule_number = tokens[0].to_i
|
|
|
|
return error_text unless rule_number.to_s == tokens[0] # Check we were given a number
|
|
|
|
|
|
|
|
if DiscourseChat::Helper.delete_by_index(channel, rule_number)
|
2017-10-03 05:42:07 -04:00
|
|
|
I18n.t("chat_integration.provider.#{provider}.delete.success")
|
2017-07-19 11:57:33 -04:00
|
|
|
else
|
2017-10-03 05:42:07 -04:00
|
|
|
I18n.t("chat_integration.provider.#{provider}.delete.error")
|
2017-07-19 11:57:33 -04:00
|
|
|
end
|
|
|
|
when "status"
|
|
|
|
return DiscourseChat::Helper.status_for_channel(channel)
|
|
|
|
when "help"
|
2017-10-03 05:42:07 -04:00
|
|
|
I18n.t("chat_integration.provider.#{provider}.help")
|
2017-07-19 11:57:33 -04:00
|
|
|
else
|
2017-10-03 05:42:07 -04:00
|
|
|
error_text
|
2017-07-19 11:57:33 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-07-05 20:11:26 -04:00
|
|
|
# Produce a string with a list of all rules associated with a channel
|
2017-08-01 15:53:39 -04:00
|
|
|
def self.status_for_channel(channel)
|
|
|
|
rules = channel.rules.order_by_precedence
|
2017-07-13 17:13:03 -04:00
|
|
|
provider = channel.provider
|
2017-07-05 18:00:58 -04:00
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
text = I18n.t("chat_integration.provider.#{provider}.status.header") + "\n"
|
2017-07-05 18:00:58 -04:00
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
i = 1
|
|
|
|
rules.each do |rule|
|
2017-07-05 18:00:58 -04:00
|
|
|
category_id = rule.category_id
|
2017-08-01 14:16:47 -04:00
|
|
|
|
|
|
|
case rule.type
|
|
|
|
when "normal"
|
|
|
|
if category_id.nil?
|
|
|
|
category_name = I18n.t("chat_integration.all_categories")
|
|
|
|
else
|
|
|
|
category = Category.find_by(id: category_id)
|
|
|
|
if category
|
|
|
|
category_name = category.slug
|
|
|
|
else
|
|
|
|
category_name = I18n.t("chat_integration.deleted_category")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
when "group_mention", "group_message"
|
|
|
|
group = Group.find_by(id: rule.group_id)
|
|
|
|
if group
|
|
|
|
category_name = I18n.t("chat_integration.#{rule.type}_template", name: group.name)
|
2017-07-05 18:00:58 -04:00
|
|
|
else
|
2017-08-01 14:16:47 -04:00
|
|
|
category_name = I18n.t("chat_integration.deleted_group")
|
2017-07-05 18:00:58 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
text << I18n.t("chat_integration.provider.#{provider}.status.rule_string",
|
2017-10-03 05:42:07 -04:00
|
|
|
index: i,
|
|
|
|
filter: rule.filter,
|
|
|
|
category: category_name
|
|
|
|
)
|
2017-07-05 18:00:58 -04:00
|
|
|
|
2017-10-03 05:42:07 -04:00
|
|
|
if SiteSetting.tagging_enabled && (!rule.tags.nil?)
|
2017-07-05 18:00:58 -04:00
|
|
|
text << I18n.t("chat_integration.provider.#{provider}.status.rule_string_tags_suffix", tags: rule.tags.join(', '))
|
|
|
|
end
|
|
|
|
|
|
|
|
text << "\n"
|
2017-08-01 15:53:39 -04:00
|
|
|
i += 1
|
|
|
|
end
|
2017-07-05 18:00:58 -04:00
|
|
|
|
|
|
|
if rules.size == 0
|
|
|
|
text << I18n.t("chat_integration.provider.#{provider}.status.no_rules")
|
|
|
|
end
|
2017-10-03 05:42:07 -04:00
|
|
|
|
|
|
|
text
|
2017-08-01 15:53:39 -04:00
|
|
|
end
|
2017-07-05 18:00:58 -04:00
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
# Delete a rule based on its (1 based) index as seen in the
|
2017-07-06 16:36:50 -04:00
|
|
|
# status_for_channel function
|
2017-07-13 17:13:03 -04:00
|
|
|
def self.delete_by_index(channel, index)
|
2017-07-18 16:36:07 -04:00
|
|
|
rules = channel.rules.order_by_precedence
|
2017-08-01 15:53:39 -04:00
|
|
|
return false if index < (1) || index > (rules.size)
|
|
|
|
return :deleted if rules[index - 1].destroy
|
2017-07-06 16:36:50 -04:00
|
|
|
end
|
|
|
|
|
2017-07-05 20:11:26 -04:00
|
|
|
# Create a rule for a specific channel
|
2017-08-01 15:53:39 -04:00
|
|
|
# Designed to be used by provider's "Slash commands"
|
|
|
|
# Will intelligently adjust existing rules to avoid duplicates
|
2017-07-05 20:11:26 -04:00
|
|
|
# Returns
|
|
|
|
# :updated if an existing rule has been updated
|
|
|
|
# :created if a new rule has been created
|
|
|
|
# false if there was an error
|
2017-08-01 15:53:39 -04:00
|
|
|
def self.smart_create_rule(channel:, filter:, category_id: nil, tags: nil)
|
2017-09-04 08:14:15 -04:00
|
|
|
existing_rules = DiscourseChat::Rule.with_channel(channel).with_type('normal')
|
2017-07-05 20:11:26 -04:00
|
|
|
|
|
|
|
# Select the ones that have the same category
|
|
|
|
same_category = existing_rules.select { |rule| rule.category_id == category_id }
|
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
same_category_and_tags = same_category.select { |rule| (rule.tags.nil? ? [] : rule.tags.sort) == (tags.nil? ? [] : tags.sort) }
|
2017-07-05 20:11:26 -04:00
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
if same_category_and_tags.size > 0
|
2017-07-05 20:11:26 -04:00
|
|
|
# These rules have exactly the same criteria as what we're trying to create
|
|
|
|
the_rule = same_category_and_tags.shift # Take out the first one
|
|
|
|
|
|
|
|
same_category_and_tags.each do |rule| # Destroy all the others - they're duplicates
|
2017-08-01 15:53:39 -04:00
|
|
|
rule.destroy
|
2017-07-05 20:11:26 -04:00
|
|
|
end
|
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
return :updated if the_rule.update(filter: filter) # Update the filter
|
2017-07-05 20:11:26 -04:00
|
|
|
return false # Error, probably validation
|
|
|
|
end
|
|
|
|
|
|
|
|
same_category_and_filters = same_category.select { |rule| rule.filter == filter }
|
2017-08-01 15:53:39 -04:00
|
|
|
|
|
|
|
if same_category_and_filters.size > 0
|
2017-07-05 20:11:26 -04:00
|
|
|
# These rules are exactly the same, except for tags. Let's combine the tags together
|
|
|
|
tags = [] if tags.nil?
|
|
|
|
same_category_and_filters.each do |rule|
|
|
|
|
tags = tags | rule.tags unless rule.tags.nil? # Append the tags together, avoiding duplicates by magic
|
|
|
|
end
|
|
|
|
|
|
|
|
the_rule = same_category_and_filters.shift # Take out the first one
|
|
|
|
|
2017-08-01 15:53:39 -04:00
|
|
|
if the_rule.update(tags: tags) # Update the tags
|
2017-07-05 20:11:26 -04:00
|
|
|
same_category_and_filters.each do |rule| # Destroy all the others - they're duplicates
|
|
|
|
rule.destroy
|
|
|
|
end
|
|
|
|
return :updated
|
|
|
|
end
|
|
|
|
|
|
|
|
return false # Error
|
|
|
|
end
|
|
|
|
|
|
|
|
# This rule is unique! Create a new one:
|
2017-07-13 17:13:03 -04:00
|
|
|
return :created if Rule.new(channel: channel, filter: filter, category_id: category_id, tags: tags).save
|
2017-10-03 05:42:07 -04:00
|
|
|
false
|
2017-07-05 20:11:26 -04:00
|
|
|
end
|
|
|
|
|
2017-07-24 11:13:53 -04:00
|
|
|
def self.save_transcript(transcript)
|
|
|
|
secret = SecureRandom.hex
|
2017-10-03 05:42:07 -04:00
|
|
|
redis_key = "chat_integration:transcript:#{secret}"
|
|
|
|
$redis.setex(redis_key, 3600, transcript)
|
|
|
|
secret
|
2017-07-24 11:13:53 -04:00
|
|
|
end
|
|
|
|
|
2017-07-05 18:00:58 -04:00
|
|
|
end
|
|
|
|
end
|