diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index 6311ccb08d16a..7e84c890bd1b4 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -3,7 +3,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro include DateRangeHelper include HmacConcern - before_action :conversation, except: [:index, :meta, :search, :create, :filter] + before_action :conversation, except: [:index, :meta, :search, :create, :filter, :ticket] before_action :inbox, :contact, :contact_inbox, only: [:create] def index diff --git a/app/views/mailers/digitaltolk_mailer/send_email.erb b/app/views/mailers/digitaltolk_mailer/send_email.erb new file mode 100644 index 0000000000000..5a6b9632a58b5 --- /dev/null +++ b/app/views/mailers/digitaltolk_mailer/send_email.erb @@ -0,0 +1,17 @@ +

You just got a form submission!

+
+ +Form +
<%= @form_name %>
+ +
+Site +
Digitaltolk
+ +
+
Submitted content
+<% if @content.present? %> + <% @content.each do |key, value| %> +
<%= key %>: <%= value %>
+ <% end %> +<% end %> \ No newline at end of file diff --git a/app/workers/digitaltolk_email_worker.rb b/app/workers/digitaltolk_email_worker.rb new file mode 100644 index 0000000000000..d8ec759d016ea --- /dev/null +++ b/app/workers/digitaltolk_email_worker.rb @@ -0,0 +1,10 @@ +class DigitaltolkEmailWorker + include Sidekiq::Worker + sidekiq_options queue: :mailers, retry: 3 + + def perform(params) + data = JSON.parse(params).with_indifferent_access + + Digitaltolk::DigitaltolkMailer.send_email(data).deliver_later + end +end diff --git a/config/routes.rb b/config/routes.rb index f224f39f7103e..0e83f63a4854c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -81,6 +81,7 @@ get :meta get :search post :filter + post :ticket end scope module: :conversations do resources :messages, only: [:index, :create, :destroy] do @@ -106,7 +107,6 @@ post :unread post :custom_attributes get :attachments - post :ticket end end diff --git a/lib/digitaltolk/add_conversation_service.rb b/lib/digitaltolk/add_conversation_service.rb new file mode 100644 index 0000000000000..5ae833f074cd2 --- /dev/null +++ b/lib/digitaltolk/add_conversation_service.rb @@ -0,0 +1,69 @@ +class Digitaltolk::AddConversationService + attr_accessor :inbox_id, :params + + def initialize(inbox_id, params) + @inbox_id = inbox_id + @params = params + end + + def perform + find_or_create_contact + + ConversationBuilder.new(params: ActionController::Parameters.new(conversation_params), contact_inbox: @contact_inbox).perform + end + + private + + def inbox + @inbox ||= Inbox.find_by(id: @inbox_id) + end + + def find_or_create_contact + @contact = inbox.contacts.find_by(email: email_address) + + if @contact.present? + @contact_inbox = ContactInbox.find_by(inbox: @inbox, contact: @contact) + else + create_contact + end + end + + def create_contact + @contact_inbox = ::ContactInboxWithContactBuilder.new( + source_id: email_address, + inbox: inbox, + contact_attributes: { + name: identify_contact_name, + email: email_address, + additional_attributes: { + source_id: "email:" + } + } + ).perform + @contact = @contact_inbox.contact + end + + def email_address + params.dig(:email) + end + + def identify_contact_name + email_address.split('@').first + end + + def conversation_params + { + account_id: params.dig(:account_id), + assignee_id: params.dig(:assignee_id), + contact_id: @contact.id, + inbox_id: params.dig(:inbox_id), + source_id: params.dig(:email), + additional_attributes: { + mail_subject: params.dig(:subject) + }, + message: { + content: params.dig(:content) + } + } + end +end \ No newline at end of file diff --git a/lib/digitaltolk/add_message_service.rb b/lib/digitaltolk/add_message_service.rb new file mode 100644 index 0000000000000..28810e29f5baa --- /dev/null +++ b/lib/digitaltolk/add_message_service.rb @@ -0,0 +1,35 @@ +class Digitaltolk::AddMessageService + attr_accessor :sender, :conversation, :content, :is_incoming + + def initialize(sender, conversation, content, is_incoming = false) + @conversation = conversation + @content = content + @sender = sender + @is_incoming = is_incoming + end + + def perform + return unless @conversation.present? + + create_message + end + + private + + def create_message + return unless content.present? + + Messages::MessageBuilder.new(sender, @conversation, message_params).perform + end + + def message_type + is_incoming ? 'incoming' : 'outgoing' + end + + def message_params + { + message_type: message_type, + content: content + } + end +end \ No newline at end of file diff --git a/lib/digitaltolk/digitaltolk_mailer.rb b/lib/digitaltolk/digitaltolk_mailer.rb new file mode 100644 index 0000000000000..22503cd275ec8 --- /dev/null +++ b/lib/digitaltolk/digitaltolk_mailer.rb @@ -0,0 +1,22 @@ +class Digitaltolk::DigitaltolkMailer < ApplicationMailer + def send_email(params) + return unless smtp_config_set_or_development? + return unless params.dig(:to).present? + return unless params.dig(:from).present? + + @form_name = params.dig(:form_name) + @content = params.dig(:data) + + email_params = { + to: params.dig(:to), + reply_to: params.dig(:from), + subject: params.dig(:subject) + } + + mail(email_params) do |format| + format.html do + render 'mailers/digitaltolk_mailer/send_email', layout: false + end + end + end +end \ No newline at end of file diff --git a/lib/digitaltolk/fix_invalid_conversation.rb b/lib/digitaltolk/fix_invalid_conversation.rb index 3d33b31c9dfbd..776bec845755b 100644 --- a/lib/digitaltolk/fix_invalid_conversation.rb +++ b/lib/digitaltolk/fix_invalid_conversation.rb @@ -31,6 +31,10 @@ def fix_conversation_contact def fix_message_email conversation.messages.incoming.where("content_attributes::text LIKE '%#{Digitaltolk::MailHelper::INVALID_LOOPIA_EMAIL}%'").each do |msg| + next if msg.blank? + next if msg.content_attributes.blank? + next if msg.content_attributes.dig(:email, :from).blank? + msg.content_attributes[:email][:from] = [email_from_body] msg.save end @@ -51,7 +55,7 @@ def email_from_body match = first_message.content.to_s.match(email_regex) return if match.nil? - @email_from_body = match[0] + @email_from_body = match.first end def find_or_create_original_contact diff --git a/lib/digitaltolk/mail_helper.rb b/lib/digitaltolk/mail_helper.rb index 7928a9c3cbaf8..e11c3ced764b3 100644 --- a/lib/digitaltolk/mail_helper.rb +++ b/lib/digitaltolk/mail_helper.rb @@ -6,7 +6,7 @@ def self.email_from_body(html_content) return if html_content.blank? match = html_content.to_s.match(EMAIL_REGEX) - match[0] + match.first rescue nil end diff --git a/lib/digitaltolk/send_email_ticket_service.rb b/lib/digitaltolk/send_email_ticket_service.rb index a7a15fba476ff..2d8d529f7ce4a 100644 --- a/lib/digitaltolk/send_email_ticket_service.rb +++ b/lib/digitaltolk/send_email_ticket_service.rb @@ -1,6 +1,9 @@ class Digitaltolk::SendEmailTicketService attr_accessor :account, :user, :params, :errors, :conversation + CUSTOMER_TYPE = 2 + TRANSLATOR_TYPE = 3 + def initialize(account, user, params) @account = account @user = user @@ -9,9 +12,19 @@ def initialize(account, user, params) end def perform - find_conversation - validate - create_message + begin + ActiveRecord::Base.transaction do + validate_params + find_or_create_conversation if @errors.blank? + validate_data if @errors.blank? + create_message if @errors.blank? + end + rescue StandardError => e + Rails.logger.error e + Rails.logger.error e.backtrace.first + @errors << e.message + end + result_data end @@ -26,54 +39,85 @@ def result_data def result_json(success, message) { success: success, - message: message + message: message, + conversation_id: @conversation&.id } end def conversations - @account.where(conversation_id: account) + inbox.conversations + end + + def conversation_params + { + subject: params.dig(:title), + content: params.dig(:body), + inbox_id: params.dig(:inbox_id), + email: params.dig(:requester, :email), + assignee_id: nil, + account_id: @account.id, + } + end + + def find_or_create_conversation + if for_customer? + @conversation = conversations.where("custom_attributes ->> 'booking_id' = ?", booking_id).last + elsif for_translator? + @conversation = Digitaltolk::AddConversationService.new(inbox_id, conversation_params).perform + end + end + + def for_customer? + recipient_type.to_i == CUSTOMER_TYPE + end + + def for_translator? + recipient_type.to_i == TRANSLATOR_TYPE end - def find_conversation - @conversation = Conversation.where("custom_attributes ->> 'booking_id' = ?", booking_id).last + def recipient_type + params.dig(:recipient_type) + end + + def inbox + @inbox ||= @account.inboxes.find_by(id: inbox_id) + end + + def inbox_id + params.dig(:inbox_id) end def booking_id - params.dig(:booking_id) + params.dig(:booking_id).to_s end - def validate + def validate_params if booking_id.blank? - @errors << "Parameter booking_id is required." + @errors << "Parameter booking_id is required" end - #validate email address + if recipient_type.blank? + @errors << "Recipient Type is required" + elsif !for_customer? && !for_translator? + @errors << "Unknown recipient_type #{recipient_type}" + end - if @conversation.blank? - @errors << "Conversation with booking number #{booking_id} not found" + if inbox.blank? + @errors << "Inbox with id #{inbox_id} was not found" end end - def create_message - return if @errors.present? - - @message = @conversation.messages.build(message_params) - @message.save! + def validate_data + @errors << invalid_booking_message if @conversation.blank? end - def message_type - 'outgoing' + def invalid_booking_message + "Conversation with booking ID #{booking_id} not found" end - def message_params - { - account_id: @conversation.account_id, - inbox_id: @conversation.inbox_id, - message_type: message_type, - content: @params[:body], - private: false, - sender: user, - content_type: 'input_email', - } + def create_message + return if @errors.present? + + @message = Digitaltolk::AddMessageService.new(@user, @conversation, @params.dig(:body), true).perform end end \ No newline at end of file diff --git a/lib/digitaltolk/webflow_service.rb b/lib/digitaltolk/webflow_service.rb index 42ced9751c711..705994b0a93e8 100644 --- a/lib/digitaltolk/webflow_service.rb +++ b/lib/digitaltolk/webflow_service.rb @@ -1,13 +1,129 @@ class Digitaltolk::WebflowService attr_accessor :params + INFO_EMAIL = 'info@digitaltolk.se' + WEBFORM_EMAIL = 'webformular@digitaltolk.se' + def initialize(params) @params = params end def perform - puts '----------------------------------------------' - puts "webflow_params: #{params}" - puts '----------------------------------------------' + # temporary disable + return false + + unless form_submission? + Rails.logger.error "Error: webflow trigger type not supported '#{trigger_event}'" + return + end + + process_webflow_submission + rescue StandardError => e + Rails.logger.error e + Rails.logger.error e.backtrace.first + end + + private + + def process_webflow_submission + if from_email.blank? + Rails.logger.error 'blank from email' + return + end + + emails.each_with_index do |recipient_email, index| + next if recipient_email.blank? + + second_interval = (10 * (index + 1)) + Rails.logger.info "Sent webform email for #{from_email}" + DigitaltolkEmailWorker.perform_in(second_interval.seconds, email_params(recipient_email).to_json) + end + end + + def emails + [INFO_EMAIL, WEBFORM_EMAIL] + end + + def webflow_params + @params.dig(:params, :webflow) + end + + def email_params(to) + { + 'to': to, + 'from': from_email, + 'subject': subject, + 'data': form_data, + 'form_name': form_name + } end + + def form_data + webflow_params.dig(:payload, :data) + end + + def form_name + webflow_params.dig(:payload, :name) + end + + def from_email + form_data.dig('Email-kom') + end + + def subject + 'You have a new form submission on your Webflow site!' + end + + def trigger_event + webflow_params.dig(:triggerType) + end + + def form_submission? + trigger_event.to_s.downcase == 'form_submission' + end + + # def test_webhook_data + # data = { + # "params": { + # "triggerType": "form_submission", + # "payload": { + # "name": "Info kontakt", + # "siteId": "6476e981f6a8eff9068d9af2", + # "data": { + # "Name-kom": "Test JM", + # "Email-kom": "jmanuel.derecho@gmail.com", + # "phone-kom": "", + # "Bok.nr.": "#3364311", + # "Subject": "Mejl för tolk", + # "Meddelande": "Hej! Har bokat tolk men ser inte tolkens mejladress någonstans. Behöver den för att skicka video länk." + # }, + # "submittedAt": "2024-02-01T15:35:45.897Z", + # "id": "65bbba510f02b427c7024707", + # "formId": "64dd32123cda9a590ffbf718" + # }, + # "controller": "webhooks/webflow", + # "action": "process_payload", + # "webflow": { + # "triggerType": "form_submission", + # "payload": { + # "name": "Info kontakt", + # "siteId": "6476e981f6a8eff9068d9af2", + # "data": { + # "Name-kom": "Test JM", + # "Email-kom": "jmanuel.derecho@gmail.com", + # "phone-kom": "", + # "Bok.nr.": "#3364311", + # "Subject": "Mejl för tolk", + # "Meddelande": "Hej! Har bokat tolk men ser inte tolkens mejladress någonstans. Behöver den för att skicka video länk." + # }, + # "submittedAt": "2024-02-01T15:35:45.897Z", + # "id": "65bbba510f02b427c7024707", + # "formId": "64dd32123cda9a590ffbf718" + # } + # } + # } + # } + + # ActionController::Parameters.new(data) + # end end \ No newline at end of file