This commit is contained in:
Darren Clarke 2023-07-18 12:26:57 +00:00
parent 7ca5f2d45a
commit f901f203b0
302 changed files with 9897 additions and 10332 deletions

View file

@ -9,12 +9,12 @@
"lint": "eslint index.js"
},
"dependencies": {
"@babel/core": "7.22.5",
"@babel/preset-env": "7.22.5",
"@babel/core": "7.22.9",
"@babel/preset-env": "7.22.9",
"@babel/preset-typescript": "7.22.5"
},
"peerDependencies": {},
"devDependencies": {
"eslint": "^8.43.0"
"eslint": "^8.45.0"
}
}

View file

@ -10,26 +10,26 @@
},
"dependencies": {
"@rushstack/eslint-patch": "^1.3.2",
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/parser": "^5.60.0",
"@typescript-eslint/eslint-plugin": "^6.1.0",
"@typescript-eslint/parser": "^6.1.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-xo-space": "^0.34.0",
"eslint-plugin-cypress": "^2.13.3",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "^27.2.2",
"eslint-plugin-jest": "^27.2.3",
"eslint-plugin-no-use-extend-native": "^0.5.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-unicorn": "47.0.0",
"@babel/eslint-parser": "7.22.5"
"eslint-plugin-unicorn": "48.0.0",
"@babel/eslint-parser": "7.22.9"
},
"peerDependencies": {
"eslint": "^7.32.0",
"typescript": "^4.9.5"
},
"devDependencies": {
"eslint": "^8.43.0",
"jest": "^29.5.0",
"typescript": "^5.1.3"
"eslint": "^8.45.0",
"jest": "^29.6.1",
"typescript": "^5.1.6"
}
}

View file

@ -9,7 +9,7 @@
"private": false,
"devDependencies": {
"@hapi/basic": "^7.0.2",
"@types/jest": "^29.5.2",
"@types/jest": "^29.5.3",
"babel-preset-link": "*",
"eslint-config-link": "*",
"jest-config-link": "*",

View file

@ -9,8 +9,8 @@
"node": ">=14"
},
"dependencies": {
"@types/jest": "^29.5.2",
"jest": "^29.5.0",
"@types/jest": "^29.5.3",
"jest": "^29.6.1",
"jest-junit": "^16.0.0"
},
"peerDependencies": {}

View file

@ -25,7 +25,7 @@
"pg-monitor": "^2.0.0",
"tsc-watch": "^6.0.4",
"typedoc": "^0.24.8",
"typescript": "^5.1.3"
"typescript": "^5.1.6"
},
"dependencies": {
"@digiresilience/hapi-nextauth": "*",
@ -39,13 +39,13 @@
"@promster/hapi": "^8.0.6",
"@promster/server": "^7.0.8",
"@promster/types": "^3.2.5",
"@types/convict": "^6.1.2",
"@types/convict": "^6.1.3",
"@types/hapi__glue": "^6.1.6",
"@types/hapi__hapi": "^20.0.13",
"@types/hapi__inert": "^5.2.6",
"@types/hapi__vision": "^5.5.4",
"@types/hapipal__schmervice": "^2.0.3",
"chalk": "^5.2.0",
"chalk": "^5.3.0",
"commander": "^11.0.0",
"convict": "^6.2.4",
"decamelcase-keys": "^1.1.1",
@ -57,7 +57,7 @@
"next-auth": "^4.22.1",
"pg-promise": "^11.5.0",
"pino": "^8.14.1",
"pino-pretty": "^10.0.0",
"pino-pretty": "^10.0.1",
"prom-client": "^14.x.x",
"uuid": "^9.0.0"
}

View file

@ -10,16 +10,16 @@
"@digiresilience/montar": "*"
},
"devDependencies": {
"@babel/core": "7.22.5",
"@babel/preset-env": "7.22.5",
"@babel/core": "7.22.9",
"@babel/preset-env": "7.22.9",
"@babel/preset-typescript": "7.22.5",
"eslint": "^8.43.0",
"pino-pretty": "^10.0.0",
"prettier": "^2.8.8",
"eslint": "^8.45.0",
"pino-pretty": "^10.0.1",
"prettier": "^3.0.0",
"ts-node": "^10.9.1",
"tsc-watch": "^6.0.4",
"typedoc": "^0.24.8",
"typescript": "^5.1.3"
"typescript": "^5.1.6"
},
"files": [
"build",

View file

@ -16,19 +16,19 @@
"pg-promise": "^11.5.0"
},
"devDependencies": {
"@babel/core": "7.22.5",
"@babel/preset-env": "7.22.5",
"@babel/core": "7.22.9",
"@babel/preset-env": "7.22.9",
"@babel/preset-typescript": "7.22.5",
"@types/jest": "^29.5.2",
"eslint": "^8.43.0",
"jest": "^29.5.0",
"@types/jest": "^29.5.3",
"eslint": "^8.45.0",
"jest": "^29.6.1",
"jest-junit": "^16.0.0",
"pino-pretty": "^10.0.0",
"prettier": "^2.8.8",
"pino-pretty": "^10.0.1",
"prettier": "^3.0.0",
"ts-node": "^10.9.1",
"tsc-watch": "^6.0.4",
"typedoc": "^0.24.8",
"typescript": "^5.1.3"
"typescript": "^5.1.6"
},
"scripts": {
"build": "tsc -p tsconfig.json",

View file

@ -23,7 +23,7 @@
"node": ">=14"
},
"devDependencies": {
"@types/jest": "^29.5.2",
"@types/jest": "^29.5.3",
"babel-preset-link": "*",
"eslint-config-link": "*",
"jest-config-link": "*",

View file

@ -39,7 +39,7 @@
"backoff": "^2.5.0",
"camelcase-keys": "^8.0.2",
"eventemitter3": "^5.0.1",
"snakecase-keys": "^5.4.5",
"snakecase-keys": "^5.4.6",
"ts-custom-error": "^3.3.1",
"uuid": "^9.0.0"
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
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')
doc = File.open('public/assets/images/icons.svg') { |f| Nokogiri::XML(f) }

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
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')
doc = File.open('public/assets/images/icons.svg') { |f| Nokogiri::XML(f) }

View file

@ -44,13 +44,17 @@ class PGP < ActiveRecord::Migration[5.2]
frontend: true
)
create_table :pgp_keypairs do |t|
t.string :fingerprint, limit: 250, null: false
t.binary :public_key, limit: 10.megabytes, null: false
t.binary :private_key, limit: 10.megabytes, null: true
t.string :private_key_secret, limit: 500, null: true
t.timestamps limit: 3, null: false
begin
create_table :pgp_keypairs do |t|
t.string :fingerprint, limit: 250, null: false
t.binary :public_key, limit: 10.megabytes, null: false
t.binary :private_key, limit: 10.megabytes, null: true
t.string :private_key_secret, limit: 500, null: true
t.timestamps limit: 3, null: false
end
add_index :pgp_keypairs, [:fingerprint], unique: true
rescue StandardError => e
puts "NOTICE: #{e.message}"
end
add_index :pgp_keypairs, [:fingerprint], unique: true
end
end