Remove Rails Observer dependency
This commit is contained in:
parent
6e6cc22d2b
commit
b5ccd86660
13 changed files with 304 additions and 329 deletions
|
|
@ -59,6 +59,7 @@ services:
|
||||||
# context: .
|
# context: .
|
||||||
# dockerfile: ./apps/metamigo-frontend/Dockerfile
|
# dockerfile: ./apps/metamigo-frontend/Dockerfile
|
||||||
# image: registry.gitlab.com/digiresilience/link/link-stack/metamigo-frontend:${LINK_STACK_VERSION}
|
# image: registry.gitlab.com/digiresilience/link/link-stack/metamigo-frontend:${LINK_STACK_VERSION}
|
||||||
|
command: [ "frontend" ]
|
||||||
image: registry.gitlab.com/digiresilience/link/metamigo:develop
|
image: registry.gitlab.com/digiresilience/link/metamigo:develop
|
||||||
container_name: metamigo-frontend
|
container_name: metamigo-frontend
|
||||||
restart: ${RESTART}
|
restart: ${RESTART}
|
||||||
|
|
@ -78,8 +79,8 @@ services:
|
||||||
# context: .
|
# context: .
|
||||||
# dockerfile: ./apps/metamigo-cli/Dockerfile
|
# dockerfile: ./apps/metamigo-cli/Dockerfile
|
||||||
# image: registry.gitlab.com/digiresilience/link/link-stack/metamigo:${LINK_STACK_VERSION}
|
# image: registry.gitlab.com/digiresilience/link/link-stack/metamigo:${LINK_STACK_VERSION}
|
||||||
# container_name: metamigo-worker
|
|
||||||
image: registry.gitlab.com/digiresilience/link/metamigo:develop
|
image: registry.gitlab.com/digiresilience/link/metamigo:develop
|
||||||
|
container_name: metamigo-worker
|
||||||
restart: ${RESTART}
|
restart: ${RESTART}
|
||||||
command: [ "worker" ]
|
command: [ "worker" ]
|
||||||
environment: *common-metamigo-variables
|
environment: *common-metamigo-variables
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ RUN export PATH=~/.cargo/bin:$PATH && cargo build -p sequoia-openpgp-ffi;
|
||||||
|
|
||||||
WORKDIR ${ZAMMAD_DIR}
|
WORKDIR ${ZAMMAD_DIR}
|
||||||
RUN echo "gem 'ruby_openpgp', git: 'https://github.com/throneless-tech/ruby_openpgp', branch: 'signing-and-userids'" >> Gemfile.local
|
RUN echo "gem 'ruby_openpgp', git: 'https://github.com/throneless-tech/ruby_openpgp', branch: 'signing-and-userids'" >> Gemfile.local
|
||||||
RUN echo "gem 'rails-observers'" >> Gemfile.local
|
|
||||||
RUN bundle install --without test development mysql
|
RUN bundle install --without test development mysql
|
||||||
RUN sed -i '/^[[:space:]]*# create install ready file/ i\
|
RUN sed -i '/^[[:space:]]*# create install ready file/ i\
|
||||||
echo "about to reinstall..."\n\
|
echo "about to reinstall..."\n\
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"dev:metamigo": "dotenv -- turbo run dev --concurrency 30 --filter=!link --filter=!leafcutter",
|
"dev:metamigo": "dotenv -- turbo run dev --concurrency 30 --filter=!link --filter=!leafcutter",
|
||||||
"migrate": "dotenv -- npm run migrate --workspace=@digiresilience/metamigo-cli",
|
"migrate": "dotenv -- npm run migrate --workspace=@digiresilience/metamigo-cli",
|
||||||
"fmt": "turbo run fmt",
|
"fmt": "turbo run fmt",
|
||||||
"docker:all:up": "docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml -f docker-compose.link.yml up -d",
|
"docker:all:up": "CURRENT_UID=$(CURRENT_UID) docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml -f docker-compose.link.yml up -d",
|
||||||
"docker:all:down": "docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml -f docker-compose.link.yml down",
|
"docker:all:down": "docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml -f docker-compose.link.yml down",
|
||||||
"docker:all:build": "docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml -f docker-compose.link.yml up --build -d",
|
"docker:all:build": "docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml -f docker-compose.link.yml up --build -d",
|
||||||
"docker:link:dev:up": "docker compose -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.zammad.yml up -d",
|
"docker:link:dev:up": "docker compose -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml -f docker-compose.zammad.yml up -d",
|
||||||
|
|
@ -22,6 +22,9 @@
|
||||||
"docker:leafcutter:up": "docker compose -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml up -d",
|
"docker:leafcutter:up": "docker compose -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml up -d",
|
||||||
"docker:leafcutter:down": "docker compose -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml down",
|
"docker:leafcutter:down": "docker compose -f docker-compose.opensearch.yml -f docker-compose.leafcutter.yml down",
|
||||||
"docker:leafcutter:build": "docker compose -f docker-compose.leafcutter.yml up --build -d",
|
"docker:leafcutter:build": "docker compose -f docker-compose.leafcutter.yml up --build -d",
|
||||||
|
"docker:zammad:up": "docker compose -f docker-compose.zammad.yml up -d",
|
||||||
|
"docker:zammad:down": "docker compose -f docker-compose.zammad.yml down",
|
||||||
|
"docker:zammad:build": "docker compose -f docker-compose.zammad.yml up --build -d",
|
||||||
"docker:metamigo:dev:up": "docker compose -f docker-compose.metamigo-postgresql.yml -f docker-compose.zammad.yml up -d",
|
"docker:metamigo:dev:up": "docker compose -f docker-compose.metamigo-postgresql.yml -f docker-compose.zammad.yml up -d",
|
||||||
"docker:metamigo:dev:down": "docker compose -f docker-compose.metamigo-postgresql.yml -f docker-compose.zammad.yml down",
|
"docker:metamigo:dev:down": "docker compose -f docker-compose.metamigo-postgresql.yml -f docker-compose.zammad.yml down",
|
||||||
"docker:metamigo:up": "docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml up -d",
|
"docker:metamigo:up": "docker compose -f docker-compose.zammad.yml -f docker-compose.metamigo-postgresql.yml -f docker-compose.metamigo.yml up -d",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CommunicateCdrSignalJob < ApplicationJob
|
||||||
|
retry_on StandardError, attempts: 4, wait: lambda { |executions|
|
||||||
|
executions * 120.seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
def perform(article_id)
|
||||||
|
article = Ticket::Article.find(article_id)
|
||||||
|
|
||||||
|
# set retry count
|
||||||
|
article.preferences['delivery_retry'] ||= 0
|
||||||
|
article.preferences['delivery_retry'] += 1
|
||||||
|
|
||||||
|
ticket = Ticket.lookup(id: article.ticket_id)
|
||||||
|
unless ticket.preferences
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
unless ticket.preferences['cdr_signal']
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences['cdr_signal'] for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
unless ticket.preferences['cdr_signal']['bot_token']
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences['cdr_signal']['bot_token'] for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
unless ticket.preferences['cdr_signal']['chat_id']
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences['cdr_signal']['chat_id'] for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
channel = ::CdrSignal.bot_by_bot_token(ticket.preferences['cdr_signal']['bot_token'])
|
||||||
|
channel ||= ::Channel.lookup(id: ticket.preferences['channel_id'])
|
||||||
|
unless channel
|
||||||
|
log_error(article,
|
||||||
|
"No such channel for bot #{ticket.preferences['cdr_signal']['bot_token']} or channel id #{ticket.preferences['channel_id']}")
|
||||||
|
end
|
||||||
|
if channel.options[:bot_token].blank?
|
||||||
|
log_error(article,
|
||||||
|
"Channel.find(#{channel.id}) has no cdr signal api token!")
|
||||||
|
end
|
||||||
|
|
||||||
|
has_error = false
|
||||||
|
|
||||||
|
begin
|
||||||
|
result = channel.deliver(
|
||||||
|
to: ticket.preferences[:cdr_signal][:chat_id],
|
||||||
|
body: article.body
|
||||||
|
)
|
||||||
|
rescue StandardError => e
|
||||||
|
log_error(article, e.message)
|
||||||
|
has_error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
Rails.logger.debug { "send result: #{result}" }
|
||||||
|
|
||||||
|
if result.nil? || result[:error].present?
|
||||||
|
log_error(article, 'Delivering signal message failed!')
|
||||||
|
has_error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
return if has_error
|
||||||
|
|
||||||
|
article.to = result['result']['recipient']
|
||||||
|
article.from = result['result']['source']
|
||||||
|
|
||||||
|
message_id = format('%<source>s@%<timestamp>s', source: result['result']['source'],
|
||||||
|
timestamp: result['result']['timestamp'])
|
||||||
|
article.preferences['cdr_signal'] = {
|
||||||
|
timestamp: result['result']['timestamp'],
|
||||||
|
message_id: message_id,
|
||||||
|
from: result['result']['source'],
|
||||||
|
to: result['result']['recipient']
|
||||||
|
}
|
||||||
|
|
||||||
|
# set delivery status
|
||||||
|
article.preferences['delivery_status_message'] = nil
|
||||||
|
article.preferences['delivery_status'] = 'success'
|
||||||
|
article.preferences['delivery_status_date'] = Time.zone.now
|
||||||
|
|
||||||
|
article.message_id = "cdr_signal.#{message_id}"
|
||||||
|
|
||||||
|
article.save!
|
||||||
|
|
||||||
|
Rails.logger.info "Sent signal message to: '#{article.to}' (from #{article.from})"
|
||||||
|
|
||||||
|
article
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_error(local_record, message)
|
||||||
|
local_record.preferences['delivery_status'] = 'fail'
|
||||||
|
local_record.preferences['delivery_status_message'] =
|
||||||
|
message.encode!('UTF-8', 'UTF-8', invalid: :replace, replace: '?')
|
||||||
|
local_record.preferences['delivery_status_date'] = Time.zone.now
|
||||||
|
local_record.save
|
||||||
|
Rails.logger.error message
|
||||||
|
|
||||||
|
if local_record.preferences['delivery_retry'] > 3
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: local_record.ticket_id,
|
||||||
|
content_type: 'text/plain',
|
||||||
|
body: "Unable to send cdr signal message: #{message}",
|
||||||
|
internal: true,
|
||||||
|
sender: Ticket::Article::Sender.find_by(name: 'System'),
|
||||||
|
type: Ticket::Article::Type.find_by(name: 'note'),
|
||||||
|
preferences: {
|
||||||
|
delivery_article_id_related: local_record.id,
|
||||||
|
delivery_message: true
|
||||||
|
},
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
raise message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CommunicateCdrWhatsappJob < ApplicationJob
|
||||||
|
retry_on StandardError, attempts: 4, wait: lambda { |executions|
|
||||||
|
executions * 120.seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
def perform(article_id)
|
||||||
|
article = Ticket::Article.find(article_id)
|
||||||
|
|
||||||
|
# set retry count
|
||||||
|
article.preferences['delivery_retry'] ||= 0
|
||||||
|
article.preferences['delivery_retry'] += 1
|
||||||
|
|
||||||
|
ticket = Ticket.lookup(id: article.ticket_id)
|
||||||
|
unless ticket.preferences
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
unless ticket.preferences['cdr_whatsapp']
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences['cdr_whatsapp'] for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
unless ticket.preferences['cdr_whatsapp']['bot_token']
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences['cdr_whatsapp']['bot_token'] for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
unless ticket.preferences['cdr_whatsapp']['chat_id']
|
||||||
|
log_error(article,
|
||||||
|
"Can't find ticket.preferences['cdr_whatsapp']['chat_id'] for Ticket.find(#{article.ticket_id})")
|
||||||
|
end
|
||||||
|
channel = ::CdrSignal.bot_by_bot_token(ticket.preferences['cdr_whatsapp']['bot_token'])
|
||||||
|
channel ||= ::Channel.lookup(id: ticket.preferences['channel_id'])
|
||||||
|
unless channel
|
||||||
|
log_error(article,
|
||||||
|
"No such channel for bot #{ticket.preferences['cdr_whatsapp']['bot_token']} or channel id #{ticket.preferences['channel_id']}")
|
||||||
|
end
|
||||||
|
if channel.options[:bot_token].blank?
|
||||||
|
log_error(article,
|
||||||
|
"Channel.find(#{channel.id}) has no cdr whatsapp api token!")
|
||||||
|
end
|
||||||
|
|
||||||
|
has_error = false
|
||||||
|
|
||||||
|
begin
|
||||||
|
result = channel.deliver(
|
||||||
|
to: ticket.preferences[:cdr_whatsapp][:chat_id],
|
||||||
|
body: article.body
|
||||||
|
)
|
||||||
|
rescue StandardError => e
|
||||||
|
log_error(article, e.message)
|
||||||
|
has_error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
Rails.logger.debug { "send result: #{result}" }
|
||||||
|
|
||||||
|
if result.nil? || result[:error].present?
|
||||||
|
log_error(article, 'Delivering whatsapp message failed!')
|
||||||
|
has_error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
return if has_error
|
||||||
|
|
||||||
|
article.to = result['result']['recipient']
|
||||||
|
article.from = result['result']['source']
|
||||||
|
|
||||||
|
message_id = format('%<source>s@%<timestamp>s', source: result['result']['source'],
|
||||||
|
timestamp: result['result']['timestamp'])
|
||||||
|
article.preferences['cdr_whatsapp'] = {
|
||||||
|
timestamp: result['result']['timestamp'],
|
||||||
|
message_id: message_id,
|
||||||
|
from: result['result']['source'],
|
||||||
|
to: result['result']['recipient']
|
||||||
|
}
|
||||||
|
|
||||||
|
# set delivery status
|
||||||
|
article.preferences['delivery_status_message'] = nil
|
||||||
|
article.preferences['delivery_status'] = 'success'
|
||||||
|
article.preferences['delivery_status_date'] = Time.zone.now
|
||||||
|
|
||||||
|
article.message_id = "cdr_whatsapp.#{message_id}"
|
||||||
|
|
||||||
|
article.save!
|
||||||
|
|
||||||
|
Rails.logger.info "Sent whatsapp message to: '#{article.to}' (from #{article.from})"
|
||||||
|
|
||||||
|
article
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_error(local_record, message)
|
||||||
|
local_record.preferences['delivery_status'] = 'fail'
|
||||||
|
local_record.preferences['delivery_status_message'] =
|
||||||
|
message.encode!('UTF-8', 'UTF-8', invalid: :replace, replace: '?')
|
||||||
|
local_record.preferences['delivery_status_date'] = Time.zone.now
|
||||||
|
local_record.save
|
||||||
|
Rails.logger.error message
|
||||||
|
|
||||||
|
if local_record.preferences['delivery_retry'] > 3
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: local_record.ticket_id,
|
||||||
|
content_type: 'text/plain',
|
||||||
|
body: "Unable to send cdr whatsapp message: #{message}",
|
||||||
|
internal: true,
|
||||||
|
sender: Ticket::Article::Sender.find_by(name: 'System'),
|
||||||
|
type: Ticket::Article::Type.find_by(name: 'note'),
|
||||||
|
preferences: {
|
||||||
|
delivery_article_id_related: local_record.id,
|
||||||
|
delivery_message: true
|
||||||
|
},
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
raise message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Observer::Ticket::Article::CommunicateCdrSignal < ActiveRecord::Observer
|
|
||||||
observe 'ticket::_article'
|
|
||||||
|
|
||||||
def after_create(record)
|
|
||||||
# return if we run import mode
|
|
||||||
return true if Setting.get('import_mode')
|
|
||||||
|
|
||||||
# if sender is customer, do not communicate
|
|
||||||
return true unless record.sender_id
|
|
||||||
|
|
||||||
sender = Ticket::Article::Sender.lookup(id: record.sender_id)
|
|
||||||
return true if sender.nil?
|
|
||||||
return true if sender.name == 'Customer'
|
|
||||||
|
|
||||||
# only apply on signal messages
|
|
||||||
return true unless record.type_id
|
|
||||||
|
|
||||||
type = Ticket::Article::Type.lookup(id: record.type_id)
|
|
||||||
return true if type.name !~ /\Acdr_signal/i
|
|
||||||
|
|
||||||
Delayed::Job.enqueue(Observer::Ticket::Article::CommunicateCdrSignal::BackgroundJob.new(record.id))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Observer
|
|
||||||
module Ticket
|
|
||||||
module Article
|
|
||||||
class CommunicateCdrSignal
|
|
||||||
class BackgroundJob
|
|
||||||
def initialize(id)
|
|
||||||
@article_id = id
|
|
||||||
end
|
|
||||||
|
|
||||||
def perform
|
|
||||||
article = ::Ticket::Article.find(@article_id)
|
|
||||||
|
|
||||||
# set retry count
|
|
||||||
article.preferences['delivery_retry'] ||= 0
|
|
||||||
article.preferences['delivery_retry'] += 1
|
|
||||||
|
|
||||||
ticket = ::Ticket.lookup(id: article.ticket_id)
|
|
||||||
Rails.logger.debug { 'Signal background job' }
|
|
||||||
Rails.logger.debug { ticket.inspect }
|
|
||||||
Rails.logger.debug { article.inspect }
|
|
||||||
unless ticket.preferences
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
unless ticket.preferences['cdr_signal']
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences['cdr_signal'] for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
unless ticket.preferences['cdr_signal']['chat_id']
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences['cdr_signal']['chat_id'] for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
unless ticket.preferences['cdr_signal']['bot_token']
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences['cdr_signal']['bot_token'] for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
|
|
||||||
channel = ::CdrSignal.bot_by_bot_token(ticket.preferences['cdr_signal']['bot_token'])
|
|
||||||
Rails.logger.debug { "signal got channel for #{channel.inspect}" }
|
|
||||||
|
|
||||||
channel ||= ::Channel.lookup(id: ticket.preferences['channel_id'])
|
|
||||||
unless channel
|
|
||||||
log_error(article,
|
|
||||||
"No such channel for bot #{ticket.preferences['cdr_signal']['bot_token']} or channel id #{ticket.preferences['channel_id']}")
|
|
||||||
end
|
|
||||||
if channel.options[:bot_token].blank?
|
|
||||||
log_error(article,
|
|
||||||
"Channel.find(#{channel.id}) has no signal api token!")
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
result = channel.deliver(
|
|
||||||
to: ticket.preferences[:cdr_signal][:chat_id],
|
|
||||||
body: article.body
|
|
||||||
)
|
|
||||||
rescue StandardError => e
|
|
||||||
log_error(article, e.message)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
Rails.logger.debug { "send result: #{result}" }
|
|
||||||
|
|
||||||
if result.nil? || result[:error].present?
|
|
||||||
log_error(article, 'Delivering signal message failed!')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
article.to = result['result']['recipient']
|
|
||||||
article.from = result['result']['source']
|
|
||||||
|
|
||||||
message_id = format('%<source>s@%<timestamp>s', source: result['result']['source'],
|
|
||||||
timestamp: result['result']['timestamp'])
|
|
||||||
article.preferences['cdr_signal'] = {
|
|
||||||
timestamp: result['result']['timestamp'],
|
|
||||||
message_id: message_id,
|
|
||||||
from: result['result']['source'],
|
|
||||||
to: result['result']['recipient']
|
|
||||||
}
|
|
||||||
|
|
||||||
# set delivery status
|
|
||||||
article.preferences['delivery_status_message'] = nil
|
|
||||||
article.preferences['delivery_status'] = 'success'
|
|
||||||
article.preferences['delivery_status_date'] = Time.zone.now
|
|
||||||
|
|
||||||
article.message_id = "cdr_signal.#{message_id}"
|
|
||||||
|
|
||||||
article.save!
|
|
||||||
|
|
||||||
Rails.logger.info "Sent signal message to: '#{article.to}' (from #{article.from})"
|
|
||||||
|
|
||||||
article
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_error(local_record, message)
|
|
||||||
local_record.preferences['delivery_status'] = 'fail'
|
|
||||||
local_record.preferences['delivery_status_message'] =
|
|
||||||
message.encode('UTF-8', 'UTF-8', invalid: :replace, replace: '?')
|
|
||||||
local_record.preferences['delivery_status_date'] = Time.zone.now
|
|
||||||
local_record.save
|
|
||||||
Rails.logger.error message
|
|
||||||
|
|
||||||
if local_record.preferences['delivery_retry'] > 3
|
|
||||||
::Ticket::Article.create(
|
|
||||||
ticket_id: local_record.ticket_id,
|
|
||||||
content_type: 'text/plain',
|
|
||||||
body: "Unable to send signal message: #{message}",
|
|
||||||
internal: true,
|
|
||||||
sender: ::Ticket::Article::Sender.find_by(name: 'System'),
|
|
||||||
type: ::Ticket::Article::Type.find_by(name: 'note'),
|
|
||||||
preferences: {
|
|
||||||
delivery_article_id_related: local_record.id,
|
|
||||||
delivery_message: true
|
|
||||||
},
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
raise message
|
|
||||||
end
|
|
||||||
|
|
||||||
def max_attempts
|
|
||||||
4
|
|
||||||
end
|
|
||||||
|
|
||||||
def reschedule_at(current_time, attempts)
|
|
||||||
return current_time + attempts * 120.seconds if Rails.env.production?
|
|
||||||
|
|
||||||
current_time + 5.seconds
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Observer::Ticket::Article::CommunicateCdrWhatsapp < ActiveRecord::Observer
|
|
||||||
observe 'ticket::_article'
|
|
||||||
|
|
||||||
def after_create(record)
|
|
||||||
# return if we run import mode
|
|
||||||
return true if Setting.get('import_mode')
|
|
||||||
|
|
||||||
# if sender is customer, do not communicate
|
|
||||||
return true unless record.sender_id
|
|
||||||
|
|
||||||
sender = Ticket::Article::Sender.lookup(id: record.sender_id)
|
|
||||||
return true if sender.nil?
|
|
||||||
return true if sender.name == 'Customer'
|
|
||||||
|
|
||||||
# only apply on whatsapp messages
|
|
||||||
return true unless record.type_id
|
|
||||||
|
|
||||||
type = Ticket::Article::Type.lookup(id: record.type_id)
|
|
||||||
return true if type.name !~ /\Acdr_whatsapp/i
|
|
||||||
|
|
||||||
Delayed::Job.enqueue(Observer::Ticket::Article::CommunicateCdrWhatsapp::BackgroundJob.new(record.id))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Observer
|
|
||||||
module Ticket
|
|
||||||
module Article
|
|
||||||
class CommunicateCdrWhatsapp
|
|
||||||
class BackgroundJob
|
|
||||||
def initialize(id)
|
|
||||||
@article_id = id
|
|
||||||
end
|
|
||||||
|
|
||||||
def perform
|
|
||||||
article = ::Ticket::Article.find(@article_id)
|
|
||||||
|
|
||||||
# set retry count
|
|
||||||
article.preferences['delivery_retry'] ||= 0
|
|
||||||
article.preferences['delivery_retry'] += 1
|
|
||||||
|
|
||||||
ticket = ::Ticket.lookup(id: article.ticket_id)
|
|
||||||
Rails.logger.debug { 'Whatsapp background job' }
|
|
||||||
Rails.logger.debug { ticket.inspect }
|
|
||||||
Rails.logger.debug { article.inspect }
|
|
||||||
unless ticket.preferences
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
unless ticket.preferences['cdr_whatsapp']
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences['cdr_whatsapp'] for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
unless ticket.preferences['cdr_whatsapp']['chat_id']
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences['cdr_whatsapp']['chat_id'] for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
unless ticket.preferences['cdr_whatsapp']['bot_token']
|
|
||||||
log_error(article,
|
|
||||||
"Can't find ticket.preferences['cdr_whatsapp']['bot_token'] for Ticket.find(#{article.ticket_id})")
|
|
||||||
end
|
|
||||||
|
|
||||||
channel = ::CdrWhatsapp.bot_by_bot_token(ticket.preferences['cdr_whatsapp']['bot_token'])
|
|
||||||
Rails.logger.debug { "whatsapp got channel for #{channel.inspect}" }
|
|
||||||
|
|
||||||
channel ||= ::Channel.lookup(id: ticket.preferences['channel_id'])
|
|
||||||
unless channel
|
|
||||||
log_error(article,
|
|
||||||
"No such channel for bot #{ticket.preferences['cdr_whatsapp']['bot_token']} or channel id #{ticket.preferences['channel_id']}")
|
|
||||||
end
|
|
||||||
if channel.options[:bot_token].blank?
|
|
||||||
log_error(article,
|
|
||||||
"Channel.find(#{channel.id}) has no whatsapp api token!")
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
result = channel.deliver(
|
|
||||||
to: ticket.preferences[:cdr_whatsapp][:chat_id],
|
|
||||||
body: article.body
|
|
||||||
)
|
|
||||||
rescue StandardError => e
|
|
||||||
log_error(article, e.message)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
Rails.logger.debug { "send result: #{result}" }
|
|
||||||
|
|
||||||
if result.nil? || result[:error].present?
|
|
||||||
log_error(article, 'Delivering whatsapp message failed!')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
article.to = result['result']['recipient']
|
|
||||||
article.from = result['result']['source']
|
|
||||||
|
|
||||||
message_id = format('%<source>s@%<timestamp>s', source: result['result']['source'],
|
|
||||||
timestamp: result['result']['timestamp'])
|
|
||||||
article.preferences['cdr_whatsapp'] = {
|
|
||||||
timestamp: result['result']['timestamp'],
|
|
||||||
message_id: message_id,
|
|
||||||
from: result['result']['source'],
|
|
||||||
to: result['result']['recipient']
|
|
||||||
}
|
|
||||||
|
|
||||||
# set delivery status
|
|
||||||
article.preferences['delivery_status_message'] = nil
|
|
||||||
article.preferences['delivery_status'] = 'success'
|
|
||||||
article.preferences['delivery_status_date'] = Time.zone.now
|
|
||||||
|
|
||||||
article.message_id = "cdr_whatsapp.#{message_id}"
|
|
||||||
|
|
||||||
article.save!
|
|
||||||
|
|
||||||
Rails.logger.info "Sent whatsapp message to: '#{article.to}' (from #{article.from})"
|
|
||||||
|
|
||||||
article
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_error(local_record, message)
|
|
||||||
local_record.preferences['delivery_status'] = 'fail'
|
|
||||||
local_record.preferences['delivery_status_message'] =
|
|
||||||
message.encode('UTF-8', 'UTF-8', invalid: :replace, replace: '?')
|
|
||||||
local_record.preferences['delivery_status_date'] = Time.zone.now
|
|
||||||
local_record.save
|
|
||||||
Rails.logger.error message
|
|
||||||
|
|
||||||
if local_record.preferences['delivery_retry'] > 3
|
|
||||||
::Ticket::Article.create(
|
|
||||||
ticket_id: local_record.ticket_id,
|
|
||||||
content_type: 'text/plain',
|
|
||||||
body: "Unable to send whatsapp message: #{message}",
|
|
||||||
internal: true,
|
|
||||||
sender: ::Ticket::Article::Sender.find_by(name: 'System'),
|
|
||||||
type: ::Ticket::Article::Type.find_by(name: 'note'),
|
|
||||||
preferences: {
|
|
||||||
delivery_article_id_related: local_record.id,
|
|
||||||
delivery_message: true
|
|
||||||
},
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
raise message
|
|
||||||
end
|
|
||||||
|
|
||||||
def max_attempts
|
|
||||||
4
|
|
||||||
end
|
|
||||||
|
|
||||||
def reschedule_at(current_time, attempts)
|
|
||||||
return current_time + attempts * 120.seconds if Rails.env.production?
|
|
||||||
|
|
||||||
current_time + 5.seconds
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Ticket::Article::EnqueueCommunicateCdrSignalJob
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
after_create :ticket_article_enqueue_communicate_cdr_signal_job
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ticket_article_enqueue_communicate_cdr_signal_job
|
||||||
|
# return if we run import mode
|
||||||
|
return true if Setting.get('import_mode')
|
||||||
|
|
||||||
|
# if sender is customer, do not communicate
|
||||||
|
return true unless sender_id
|
||||||
|
|
||||||
|
sender = Ticket::Article::Sender.lookup(id: sender_id)
|
||||||
|
return true if sender.nil?
|
||||||
|
return true if sender.name == 'Customer'
|
||||||
|
|
||||||
|
# only apply on cdr signal messages
|
||||||
|
return true unless type_id
|
||||||
|
|
||||||
|
type = Ticket::Article::Type.lookup(id: type_id)
|
||||||
|
return true unless type.name.match?(/\Acdr_signal/i)
|
||||||
|
|
||||||
|
CommunicateCdrSignalJob.perform_later(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Ticket::Article::EnqueueCommunicateCdrWhatsappJob
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
after_create :ticket_article_enqueue_communicate_cdr_whatsapp_job
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ticket_article_enqueue_communicate_cdr_whatsapp_job
|
||||||
|
# return if we run import mode
|
||||||
|
return true if Setting.get('import_mode')
|
||||||
|
|
||||||
|
# if sender is customer, do not communicate
|
||||||
|
return true unless sender_id
|
||||||
|
|
||||||
|
sender = Ticket::Article::Sender.lookup(id: sender_id)
|
||||||
|
return true if sender.nil?
|
||||||
|
return true if sender.name == 'Customer'
|
||||||
|
|
||||||
|
# only apply on cdr whatsapp messages
|
||||||
|
return true unless type_id
|
||||||
|
|
||||||
|
type = Ticket::Article::Type.lookup(id: type_id)
|
||||||
|
return true unless type.name.match?(/\Acdr_whatspp/i)
|
||||||
|
|
||||||
|
CommunicateCdrWhatsappJob.perform_later(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Rails.application.config.after_initialize do
|
Rails.application.config.after_initialize do
|
||||||
Ticket::Article.add_observer Observer::Ticket::Article::CommunicateCdrSignal.instance
|
# Ticket::Article.add_observer Observer::Ticket::Article::CommunicateCdrSignal.instance
|
||||||
|
|
||||||
icon = File.read('public/assets/images/icons/cdr_signal.svg')
|
icon = File.read('public/assets/images/icons/cdr_signal.svg')
|
||||||
doc = File.open('public/assets/images/icons.svg') { |f| Nokogiri::XML(f) }
|
doc = File.open('public/assets/images/icons.svg') { |f| Nokogiri::XML(f) }
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Rails.application.config.after_initialize do
|
Rails.application.config.after_initialize do
|
||||||
Ticket::Article.add_observer Observer::Ticket::Article::CommunicateCdrWhatsapp.instance
|
# Ticket::Article.add_observer Observer::Ticket::Article::CommunicateCdrWhatsapp.instance
|
||||||
|
|
||||||
icon = File.read('public/assets/images/icons/cdr_whatsapp.svg')
|
icon = File.read('public/assets/images/icons/cdr_whatsapp.svg')
|
||||||
doc = File.open('public/assets/images/icons.svg') { |f| Nokogiri::XML(f) }
|
doc = File.open('public/assets/images/icons.svg') { |f| Nokogiri::XML(f) }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue