Feature: Slack integration (#783)

- Integrations architecture
- Slack integration
This commit is contained in:
Subin T P
2020-06-12 23:12:47 +05:30
committed by GitHub
parent 4f3b483066
commit ed1c871633
44 changed files with 867 additions and 7 deletions

View File

@@ -0,0 +1,18 @@
class Api::V1::Accounts::Integrations::AppsController < Api::V1::Accounts::BaseController
before_action :fetch_apps, only: [:index]
before_action :fetch_app, only: [:show]
def index; end
def show; end
private
def fetch_apps
@apps = Integrations::App.all
end
def fetch_app
@app = Integrations::App.find(id: params[:id])
end
end

View File

@@ -0,0 +1,36 @@
class Api::V1::Accounts::Integrations::SlackController < Api::V1::Accounts::BaseController
before_action :fetch_hook, only: [:update, :destroy]
def create
builder = Integrations::Slack::HookBuilder.new(
account: current_account,
code: params[:code],
inbox_id: params[:inbox_id]
)
@hook = builder.perform
render json: @hook
end
def update
builder = Integrations::Slack::ChannelBuilder.new(
hook: @hook, channel: params[:channel]
)
builder.perform
render json: @hook
end
def destroy
@hook.destroy
head :ok
end
private
def fetch_hook
@hook = Integrations::Hook.find(params[:id])
end
end

View File

@@ -0,0 +1,7 @@
class Api::V1::Integrations::WebhooksController < ApplicationController
def create
builder = Integrations::Slack::IncomingMessageBuilder.new(params)
response = builder.perform
render json: response
end
end

View File

@@ -9,7 +9,7 @@ class AsyncDispatcher < BaseDispatcher
end
def listeners
listeners = [EventListener.instance, WebhookListener.instance]
listeners = [EventListener.instance, WebhookListener.instance, HookListener.instance]
listeners
end
end

11
app/jobs/hook_job.rb Normal file
View File

@@ -0,0 +1,11 @@
class HookJob < ApplicationJob
queue_as :integrations
def perform(hook, message)
return unless hook.slack?
Integrations::Slack::OutgoingMessageBuilder.perform(hook, message)
rescue StandardError => e
Raven.capture_exception(e)
end
end

View File

@@ -0,0 +1,10 @@
class HookListener < BaseListener
def message_created(event)
message = extract_message_and_account(event)[0]
return unless message.reportable?
message.account.hooks.each do |hook|
HookJob.perform_later(hook, message)
end
end
end

View File

@@ -47,6 +47,7 @@ class Account < ApplicationRecord
has_many :webhooks, dependent: :destroy
has_many :labels, dependent: :destroy
has_many :notification_settings, dependent: :destroy
has_many :hooks, dependent: :destroy, class_name: 'Integrations::Hook'
has_flags ACCOUNT_SETTINGS_FLAGS.merge(column: 'settings_flags').merge(DEFAULT_QUERY_SETTING)
enum locale: LANGUAGES_CONFIG.map { |key, val| [val[:iso_639_1_code], key] }.to_h

View File

@@ -5,6 +5,7 @@
# id :integer not null, primary key
# additional_attributes :jsonb
# agent_last_seen_at :datetime
# identifier :string
# locked :boolean default(FALSE)
# status :integer default("open"), not null
# user_last_seen_at :datetime

View File

@@ -42,6 +42,7 @@ class Inbox < ApplicationRecord
has_one :agent_bot_inbox, dependent: :destroy
has_one :agent_bot, through: :agent_bot_inbox
has_many :webhooks, dependent: :destroy
has_many :hooks, dependent: :destroy, class_name: 'Integrations::Hook'
after_destroy :delete_round_robin_agents

View File

@@ -0,0 +1,5 @@
module Integrations
def self.table_name_prefix
'integrations_'
end
end

View File

@@ -0,0 +1,51 @@
class Integrations::App
attr_accessor :params
def initialize(params)
@params = params
end
def id
params[:id]
end
def name
params[:name]
end
def description
params[:description]
end
def logo
params[:logo]
end
def fields
params[:fields]
end
def button
params[:button]
end
def enabled?(account)
account.hooks.where(app_id: id).exists?
end
class << self
def apps
Hashie::Mash.new(APPS_CONFIG)
end
def all
apps.values.each_with_object([]) do |app, result|
result << new(app)
end
end
def find(params)
all.detect { |app| app.id == params[:id] }
end
end
end

View File

@@ -0,0 +1,36 @@
# == Schema Information
#
# Table name: integrations_hooks
#
# id :bigint not null, primary key
# access_token :string
# hook_type :integer default("account")
# settings :text
# status :integer default("disabled")
# created_at :datetime not null
# updated_at :datetime not null
# account_id :integer
# app_id :string
# inbox_id :integer
# reference_id :string
#
class Integrations::Hook < ApplicationRecord
validates :account_id, presence: true
validates :app_id, presence: true
enum status: { disabled: 0, enabled: 1 }
belongs_to :account
belongs_to :inbox, optional: true
has_secure_token :access_token
enum hook_type: { account: 0, inbox: 1 }
def app
@app ||= Integrations::App.find(id: app_id)
end
def slack?
app_id == 'cw_slack'
end
end

View File

@@ -0,0 +1,7 @@
json.array! @apps do |app|
json.id app.id
json.name app.name
json.logo app.logo
json.enabled app.enabled?(@current_account)
json.button app.button
end

View File

@@ -0,0 +1,7 @@
json.id @app.id
json.name @app.name
json.logo @app.logo
json.description @app.description
json.fields @app.fields
json.enabled @app.enabled?(@current_account)
json.button @app.button