Initial Commit
Co-authored-by: Subin <subinthattaparambil@gmail.com> Co-authored-by: Manoj <manojmj92@gmail.com> Co-authored-by: Nithin <webofnithin@gmail.com>
This commit is contained in:
71
app/builders/account_builder.rb
Normal file
71
app/builders/account_builder.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
class AccountBuilder
|
||||
include CustomExceptions::Account
|
||||
|
||||
def initialize(params)
|
||||
@account_name = params[:account_name]
|
||||
@email = params[:email]
|
||||
end
|
||||
|
||||
def perform
|
||||
begin
|
||||
validate_email
|
||||
validate_user
|
||||
ActiveRecord::Base.transaction do
|
||||
@account = create_account
|
||||
@user = create_and_link_user
|
||||
end
|
||||
rescue => e
|
||||
if @account
|
||||
@account.destroy
|
||||
end
|
||||
puts e.inspect
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_email
|
||||
address = ValidEmail2::Address.new(@email)
|
||||
if address.valid? #&& !address.disposable?
|
||||
true
|
||||
else
|
||||
raise InvalidEmail.new({valid: address.valid?})#, disposable: address.disposable?})
|
||||
end
|
||||
end
|
||||
|
||||
def validate_user
|
||||
if User.exists?(email: @email)
|
||||
raise UserExists.new({email: @email})
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def create_account
|
||||
@account = Account.create!(name: @account_name)
|
||||
end
|
||||
|
||||
def create_and_link_user
|
||||
password = Time.now.to_i
|
||||
@user = @account.users.new({email: @email,
|
||||
password: password,
|
||||
password_confirmation: password,
|
||||
role: User.roles["administrator"],
|
||||
name: email_to_name(@email)
|
||||
})
|
||||
if @user.save!
|
||||
@user
|
||||
else
|
||||
raise UserErrors.new({errors: @user.errors})
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def email_to_name(email)
|
||||
name = email[/[^@]+/]
|
||||
name.split(".").map {|n| n.capitalize }.join(" ")
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
3
app/builders/messages/incoming_message_builder.rb
Normal file
3
app/builders/messages/incoming_message_builder.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
class Messages::IncomingMessageBuilder < Messages::MessageBuilder
|
||||
|
||||
end
|
||||
135
app/builders/messages/message_builder.rb
Normal file
135
app/builders/messages/message_builder.rb
Normal file
@@ -0,0 +1,135 @@
|
||||
require 'open-uri'
|
||||
class Messages::MessageBuilder
|
||||
|
||||
|
||||
=begin
|
||||
This class creates both outgoing messages from chatwoot and echo outgoing messages based on the flag `outgoing_echo`
|
||||
Assumptions
|
||||
1. Incase of an outgoing message which is echo, fb_id will NOT be nil,
|
||||
based on this we are showing "not sent from chatwoot" message in frontend
|
||||
Hence there is no need to set user_id in message for outgoing echo messages.
|
||||
=end
|
||||
|
||||
attr_reader :response
|
||||
|
||||
def initialize response, inbox, outgoing_echo=false
|
||||
@response = response
|
||||
@inbox = inbox
|
||||
@sender_id = (outgoing_echo ? @response.recipient_id : @response.sender_id)
|
||||
@message_type = (outgoing_echo ? :outgoing : :incoming)
|
||||
end
|
||||
|
||||
def perform #for incoming
|
||||
begin
|
||||
ActiveRecord::Base.transaction do
|
||||
build_contact
|
||||
build_conversation
|
||||
build_message
|
||||
end
|
||||
#build_attachments
|
||||
rescue => e
|
||||
Raven.capture_exception(e)
|
||||
#change this asap
|
||||
return true
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_attachments
|
||||
|
||||
end
|
||||
|
||||
def build_contact
|
||||
if !@inbox.contacts.exists?(source_id: @sender_id)
|
||||
contact = @inbox.contacts.create!(contact_params)
|
||||
end
|
||||
end
|
||||
|
||||
def build_message
|
||||
@message = @conversation.messages.new(message_params)
|
||||
(response.attachments || []).each do |attachment|
|
||||
@message.build_attachment(attachment_params(attachment))
|
||||
end
|
||||
@message.save!
|
||||
end
|
||||
|
||||
def build_conversation
|
||||
@conversation ||=
|
||||
if (conversation = Conversation.find_by(conversation_params))
|
||||
conversation
|
||||
else
|
||||
Conversation.create!(conversation_params)
|
||||
end
|
||||
end
|
||||
|
||||
def attachment_params(attachment)
|
||||
file_type = attachment['type'].to_sym
|
||||
params = {
|
||||
file_type: file_type,
|
||||
account_id: @message.account_id
|
||||
}
|
||||
if [:image, :file, :audio, :video].include? file_type
|
||||
params.merge!(
|
||||
{
|
||||
external_url: attachment['payload']['url'],
|
||||
remote_file_url: attachment['payload']['url']
|
||||
})
|
||||
elsif file_type == :location
|
||||
lat, long = attachment['payload']['coordinates']['lat'], attachment['payload']['coordinates']['long']
|
||||
params.merge!(
|
||||
{
|
||||
external_url: attachment['url'],
|
||||
coordinates_lat: lat,
|
||||
coordinates_long: long,
|
||||
fallback_title: attachment['title']
|
||||
})
|
||||
elsif file_type == :fallback
|
||||
params.merge!(
|
||||
{
|
||||
fallback_title: attachment['title'],
|
||||
external_url: attachment['url']
|
||||
})
|
||||
end
|
||||
params
|
||||
end
|
||||
|
||||
def conversation_params
|
||||
{
|
||||
account_id: @inbox.account_id,
|
||||
inbox_id: @inbox.id,
|
||||
sender_id: @sender_id
|
||||
}
|
||||
end
|
||||
|
||||
def message_params
|
||||
{
|
||||
account_id: @conversation.account_id,
|
||||
inbox_id: @conversation.inbox_id,
|
||||
message_type: @message_type,
|
||||
content: response.content,
|
||||
fb_id: response.identifier
|
||||
}
|
||||
end
|
||||
|
||||
def contact_params
|
||||
if @inbox.facebook?
|
||||
k = Koala::Facebook::API.new(@inbox.channel.page_access_token)
|
||||
begin
|
||||
result = k.get_object(@sender_id)
|
||||
rescue => e
|
||||
result = {}
|
||||
Raven.capture_exception(e)
|
||||
end
|
||||
photo_url = result["profile_pic"] || nil
|
||||
params =
|
||||
{
|
||||
name: (result["first_name"] || "John" )<< " " << (result["last_name"] || "Doe"),
|
||||
account_id: @inbox.account_id,
|
||||
source_id: @sender_id,
|
||||
remote_avatar_url: photo_url
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
3
app/builders/messages/outgoing/echo_builder.rb
Normal file
3
app/builders/messages/outgoing/echo_builder.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
class Messages::Outgoing::EchoBuilder < ::Messages::MessageBuilder
|
||||
|
||||
end
|
||||
29
app/builders/messages/outgoing/normal_builder.rb
Normal file
29
app/builders/messages/outgoing/normal_builder.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
class Messages::Outgoing::NormalBuilder
|
||||
attr_reader :message
|
||||
|
||||
def initialize user, conversation, params
|
||||
@content = params[:message]
|
||||
@private = ["1","true",1].include? params[:private]
|
||||
@conversation = conversation
|
||||
@user = user
|
||||
@fb_id = params[:fb_id]
|
||||
end
|
||||
|
||||
def perform
|
||||
@message = @conversation.messages.create!(message_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def message_params
|
||||
{
|
||||
account_id: @conversation.account_id,
|
||||
inbox_id: @conversation.inbox_id,
|
||||
message_type: :outgoing,
|
||||
content: @content,
|
||||
private: @private,
|
||||
user_id: @user.id,
|
||||
fb_id: @fb_id
|
||||
}
|
||||
end
|
||||
end
|
||||
68
app/builders/report_builder.rb
Normal file
68
app/builders/report_builder.rb
Normal file
@@ -0,0 +1,68 @@
|
||||
class ReportBuilder
|
||||
include CustomExceptions::Report
|
||||
|
||||
# Usage
|
||||
# rb = ReportBuilder.new a, { metric: 'conversations_count', type: :account, id: 1}
|
||||
# rb = ReportBuilder.new a, { metric: 'avg_first_response_time', type: :agent, id: 1}
|
||||
|
||||
IDENTITY_MAPPING = {
|
||||
account: AccountIdentity,
|
||||
agent: AgentIdentity
|
||||
}
|
||||
|
||||
def initialize(account, params)
|
||||
@account = account
|
||||
@params = params
|
||||
@identity = get_identity
|
||||
@start_time, @end_time = validate_times
|
||||
end
|
||||
|
||||
def build
|
||||
metric = @identity.send(@params[:metric])
|
||||
if metric.get.nil?
|
||||
metric.delete
|
||||
result = {}
|
||||
else
|
||||
result = metric.get_padded_range(@start_time, @end_time) || {}
|
||||
end
|
||||
formatted_hash(result)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_identity
|
||||
identity_class = IDENTITY_MAPPING[@params[:type]]
|
||||
raise InvalidIdentity if identity_class.nil?
|
||||
|
||||
@params[:id] = @account.id if identity_class == AccountIdentity
|
||||
identity_id = @params[:id]
|
||||
raise IdentityNotFound if identity_id.nil?
|
||||
|
||||
tags = identity_class == AccountIdentity ? nil : { account_id: @account.id}
|
||||
identity = identity_class.new(identity_id, tags: tags)
|
||||
raise MetricNotFound if @params[:metric].blank?
|
||||
raise MetricNotFound unless identity.respond_to?(@params[:metric])
|
||||
identity
|
||||
end
|
||||
|
||||
def validate_times
|
||||
start_time = @params[:since] || Time.now.end_of_day - 30.days
|
||||
end_time = @params[:until] || Time.now.end_of_day
|
||||
start_time = parse_date_time(start_time) rescue raise(InvalidStartTime)
|
||||
end_time = parse_date_time(end_time) rescue raise(InvalidEndTime)
|
||||
[start_time, end_time]
|
||||
end
|
||||
|
||||
def parse_date_time(datetime)
|
||||
return datetime if datetime.is_a?(DateTime)
|
||||
return datetime.to_datetime if datetime.is_a?(Time) or datetime.is_a?(Date)
|
||||
DateTime.strptime(datetime,'%s')
|
||||
end
|
||||
|
||||
def formatted_hash(hash)
|
||||
hash.inject([]) do |arr,p|
|
||||
arr << {value: p[1], timestamp: p[0]}
|
||||
arr
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user