142 lines
3.6 KiB
Ruby
142 lines
3.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class DiscourseChatIntegration::Rule < DiscourseChatIntegration::PluginModel
|
|
# Setup ActiveRecord::Store to use the JSON field to read/write these values
|
|
store :value, accessors: %i[channel_id type group_id category_id tags filter], coder: JSON
|
|
|
|
scope :with_type, ->(type) { where("value::json->>'type'=?", type.to_s) }
|
|
scope :with_channel, ->(channel) { with_channel_id(channel.id) }
|
|
scope :with_channel_id, ->(channel_id) { where("value::json->>'channel_id'=?", channel_id.to_s) }
|
|
|
|
scope :with_category_id,
|
|
->(category_id) do
|
|
if category_id.nil?
|
|
where(
|
|
"(value::json->'category_id') IS NULL OR json_typeof(value::json->'category_id')='null'",
|
|
)
|
|
else
|
|
where("value::json->>'category_id'=?", category_id.to_s)
|
|
end
|
|
end
|
|
|
|
scope :with_group_ids,
|
|
->(group_id) { where("value::json->>'group_id' IN (?)", group_id.map!(&:to_s)) }
|
|
|
|
scope :order_by_precedence,
|
|
-> do
|
|
order(
|
|
"
|
|
CASE
|
|
WHEN value::json->>'type' = 'group_mention' THEN 1
|
|
WHEN value::json->>'type' = 'group_message' THEN 2
|
|
ELSE 3
|
|
END
|
|
",
|
|
"
|
|
CASE
|
|
WHEN value::json->>'filter' = 'mute' THEN 1
|
|
WHEN value::json->>'filter' = 'thread' THEN 2
|
|
WHEN value::json->>'filter' = 'watch' THEN 3
|
|
WHEN value::json->>'filter' = 'tag_added' THEN 4
|
|
WHEN value::json->>'filter' = 'follow' THEN 5
|
|
END
|
|
",
|
|
)
|
|
end
|
|
|
|
after_initialize :init_filter
|
|
|
|
validates :filter,
|
|
inclusion: {
|
|
in: %w[thread watch follow tag_added mute],
|
|
message: "%{value} is not a valid filter",
|
|
}
|
|
|
|
validates :type,
|
|
inclusion: {
|
|
in: %w[normal group_message group_mention],
|
|
message: "%{value} is not a valid filter",
|
|
}
|
|
|
|
validate :channel_valid?, :category_valid?, :group_valid?, :tags_valid?
|
|
|
|
def self.key_prefix
|
|
"rule:".freeze
|
|
end
|
|
|
|
# We never want an empty array, set it to nil instead
|
|
def tags=(array)
|
|
if array.nil? || array.empty?
|
|
super(nil)
|
|
else
|
|
super(array)
|
|
end
|
|
end
|
|
|
|
# These are only allowed to be integers
|
|
%w[channel_id category_id group_id].each do |name|
|
|
define_method "#{name}=" do |val|
|
|
if val.nil? || val.blank?
|
|
super(nil)
|
|
else
|
|
super(val.to_i)
|
|
end
|
|
end
|
|
end
|
|
|
|
# Mock foreign key
|
|
# Could return nil
|
|
def channel
|
|
DiscourseChatIntegration::Channel.find_by(id: channel_id)
|
|
end
|
|
|
|
def channel=(val)
|
|
self.channel_id = val.id
|
|
end
|
|
|
|
private
|
|
|
|
def channel_valid?
|
|
if !(DiscourseChatIntegration::Channel.where(id: channel_id).exists?)
|
|
errors.add(:channel_id, "#{channel_id} is not a valid channel id")
|
|
end
|
|
end
|
|
|
|
def category_valid?
|
|
if type != "normal" && !category_id.nil?
|
|
errors.add(:category_id, "cannot be specified for that type of rule")
|
|
end
|
|
|
|
return unless type == "normal"
|
|
|
|
if !(category_id.nil? || Category.where(id: category_id).exists?)
|
|
errors.add(:category_id, "#{category_id} is not a valid category id")
|
|
end
|
|
end
|
|
|
|
def group_valid?
|
|
if type == "normal" && !group_id.nil?
|
|
errors.add(:group_id, "cannot be specified for that type of rule")
|
|
end
|
|
|
|
return if type == "normal"
|
|
|
|
if !Group.where(id: group_id).exists?
|
|
errors.add(:group_id, "#{group_id} is not a valid group id")
|
|
end
|
|
end
|
|
|
|
def tags_valid?
|
|
return if tags.nil?
|
|
|
|
tags.each do |tag|
|
|
errors.add(:tags, "#{tag} is not a valid tag") if !Tag.where(name: tag).exists?
|
|
end
|
|
end
|
|
|
|
def init_filter
|
|
self.filter ||= "watch"
|
|
self.type ||= "normal"
|
|
end
|
|
end
|