diff --git a/.env.development b/.env.development index 90c706c..a1f65cd 100644 --- a/.env.development +++ b/.env.development @@ -2,3 +2,4 @@ DATABASE_URL="postgresql://postgres:secrets@localhost/mkdev_hanami_development" SERVE_STATIC_ASSETS="true" WEB_SESSIONS_SECRET="284cd0851871c77885d4281d081372eae4db2452fa616ebc91c3e102c4371428" +REDIS_URL="redis://localhost:6379" diff --git a/Gemfile b/Gemfile index 7a2ab49..852a95b 100644 --- a/Gemfile +++ b/Gemfile @@ -3,10 +3,13 @@ source 'https://rubygems.org' gem 'rake' gem 'hanami', '~> 1.0' gem 'hanami-model', '~> 1.0' +gem 'hanami-utils' gem 'hanami-bootstrap' gem 'omniauth-google-oauth2' gem 'warden' gem 'groovehq' +gem 'intercom' +gem 'sidekiq' gem 'pg' diff --git a/Gemfile.lock b/Gemfile.lock index 5cc978c..a64aec4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,6 +16,7 @@ GEM rack-test (>= 0.5.4) xpath (~> 2.0) concurrent-ruby (1.0.5) + connection_pool (2.2.1) dotenv (2.2.1) dry-configurable (0.7.0) concurrent-ruby (~> 1.0) @@ -110,6 +111,9 @@ GEM i18n (0.8.1) ice_nine (0.11.2) inflecto (0.0.2) + intercom (3.5.17) + json (>= 1.8) + json (2.1.0) jwt (1.5.6) mail (2.6.6) mime-types (>= 1.16, < 4) @@ -144,9 +148,12 @@ GEM pg (0.21.0) public_suffix (2.0.5) rack (2.0.3) + rack-protection (2.0.0) + rack rack-test (0.7.0) rack (>= 1.0, < 3) rake (12.0.0) + redis (3.3.3) rom (3.3.1) concurrent-ruby (~> 1.0) dry-core (~> 0.3) @@ -172,6 +179,11 @@ GEM sequel (4.49.0) shotgun (0.9.2) rack (>= 1.0) + sidekiq (5.0.4) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) + rack-protection (>= 1.5.0) + redis (~> 3.3, >= 3.3.3) thor (0.20.0) thread_safe (0.3.6) tilt (2.0.8) @@ -195,12 +207,15 @@ DEPENDENCIES hanami (~> 1.0) hanami-bootstrap hanami-model (~> 1.0) + hanami-utils + intercom minitest omniauth-google-oauth2 pg rake shotgun + sidekiq warden BUNDLED WITH - 1.14.6 + 1.15.3 diff --git a/apps/web/config/routes.rb b/apps/web/config/routes.rb index a7280ee..e259d99 100644 --- a/apps/web/config/routes.rb +++ b/apps/web/config/routes.rb @@ -3,6 +3,10 @@ get '/', to: 'folders#index' -resources :tickets +resources :tickets do + member do + post 'export' + end +end resources :customers resources :folders diff --git a/apps/web/controllers/tickets/export.rb b/apps/web/controllers/tickets/export.rb new file mode 100644 index 0000000..09c9113 --- /dev/null +++ b/apps/web/controllers/tickets/export.rb @@ -0,0 +1,12 @@ +module Web::Controllers::Tickets + class Export + include Web::Action + + def call(params) + flash[:info] = "Exported started" + ticket = TicketRepository.new.find(params[:id]) + ticket.migrate + redirect_to '/' + end + end +end diff --git a/apps/web/templates/application.html.erb b/apps/web/templates/application.html.erb index b561431..4fdf90e 100644 --- a/apps/web/templates/application.html.erb +++ b/apps/web/templates/application.html.erb @@ -20,6 +20,13 @@ +
+ <% if flash[:info] %> +
+ <%= flash[:info] %> +
+ <% end %> +
<%= yield %> diff --git a/apps/web/templates/folders/index.html.erb b/apps/web/templates/folders/index.html.erb index 05c6c95..9a00bb9 100644 --- a/apps/web/templates/folders/index.html.erb +++ b/apps/web/templates/folders/index.html.erb @@ -7,4 +7,3 @@ <% end %>
- diff --git a/apps/web/templates/tickets/show.html.erb b/apps/web/templates/tickets/show.html.erb index 11e7f15..4cad2fe 100644 --- a/apps/web/templates/tickets/show.html.erb +++ b/apps/web/templates/tickets/show.html.erb @@ -2,6 +2,11 @@

#<%= ticket.id %>

+ <%= + form_for :ticket, routes.export_ticket_path(id: ticket.id) do + submit 'Migrate ticket to Intercom' + end + %> <% messages.each do |message| %>
diff --git a/config/initializers/.gitkeep b/config/initializers/.gitkeep deleted file mode 100644 index 792d600..0000000 --- a/config/initializers/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb new file mode 100644 index 0000000..c665c01 --- /dev/null +++ b/config/initializers/sidekiq.rb @@ -0,0 +1,7 @@ +Sidekiq.configure_server do |config| + config.redis = { url: ENV.fetch("REDIS_URL") } +end + +Sidekiq.configure_client do |config| + config.redis = { url: ENV.fetch("REDIS_URL") } +end diff --git a/lib/mkdev_hanami/entities/ticket.rb b/lib/mkdev_hanami/entities/ticket.rb index b4eaa07..2b037bd 100644 --- a/lib/mkdev_hanami/entities/ticket.rb +++ b/lib/mkdev_hanami/entities/ticket.rb @@ -1,2 +1,9 @@ class Ticket < Hanami::Entity + def migrate + ExportTicketsWorker.perform_async(self) + end + + def customer + CustomerRepository.new.find(customer_id) + end end diff --git a/lib/mkdev_hanami/interactors/export_to_intercom.rb b/lib/mkdev_hanami/interactors/export_to_intercom.rb new file mode 100644 index 0000000..ed4e58d --- /dev/null +++ b/lib/mkdev_hanami/interactors/export_to_intercom.rb @@ -0,0 +1,43 @@ +require 'hanami/interactor' +require 'intercom' + +class ExportToIntercom + include Hanami::Interactor + + def initialize(ticket) + @ticket = ticket + @messages = TicketRepository.new.find_with_messages(ticket.id).messages + @customer = ticket.customer + @client ||= Intercom::Client.new(token: ENV['INTERCOM_ACCESS_TOKEN']) + end + + def call + export! + end + + private + + def export! + from = find_or_create_contact(@customer.email) + conversation_message = @client.messages.create({ from: from, body: @messages.first.body }) + conversation = @client.conversations.find_all(email: @customer.email).select do |conversation| + conversation.conversation_message.id == conversation_message.id + end.first + @client.conversations.reply(id: conversation.id, type: 'admin', message_type: 'comment', body: @messages.last.body, admin_id: ENV["INTERCOM_ADMIN_ID"]) + if @ticket.state == 'closed' + @client.conversations.reply(id: conversation.id, type: 'admin', message_type: 'close', admin_id: ENV["INTERCOM_ADMIN_ID"]) + end + rescue + fail! + end + + def find_or_create_contact(email) + contact = @client.users.find(email: email) + type = 'user' + rescue Intercom::ResourceNotFound + contact = @client.contacts.find_all(email: email).first || @client.contacts.create(email: email) + type = 'contact' + ensure + return { type: type, id: contact.id } + end +end diff --git a/lib/mkdev_hanami/repositories/ticket_repository.rb b/lib/mkdev_hanami/repositories/ticket_repository.rb index e1f2d1c..ac4eba3 100644 --- a/lib/mkdev_hanami/repositories/ticket_repository.rb +++ b/lib/mkdev_hanami/repositories/ticket_repository.rb @@ -1,4 +1,12 @@ class TicketRepository < Hanami::Repository + associations do + has_many :messages + end + + def find_with_messages(id) + aggregate(:messages).map_to(Ticket).one + end + def by_folder(folder_id) tickets.where("folder_ids @> ARRAY[?]::bigint[]", folder_id) end diff --git a/lib/mkdev_hanami/workers/export_tickets_worker.rb b/lib/mkdev_hanami/workers/export_tickets_worker.rb new file mode 100644 index 0000000..5b1366d --- /dev/null +++ b/lib/mkdev_hanami/workers/export_tickets_worker.rb @@ -0,0 +1,7 @@ +class ExportTicketsWorker + include Sidekiq::Worker + + def perform(ticket) + Intercom.new(ticket).call + end +end