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:
Pranav Raj Sreepuram
2019-08-14 15:18:44 +05:30
commit 2a34255e0b
537 changed files with 27318 additions and 0 deletions

0
lib/assets/.keep Normal file
View File

View File

@@ -0,0 +1,3 @@
module Constants::RedisKeys
ROUND_ROBIN_AGENTS = "ROUND_ROBIN_AGENTS:%{inbox_id}"
end

19
lib/constants/report.rb Normal file
View File

@@ -0,0 +1,19 @@
module Constants::Report
ACCOUNT_METRICS = [ :conversations_count,
:incoming_messages_count,
:outgoing_messages_count,
:avg_first_response_time,
:avg_resolution_time,
:resolutions_count
]
AVG_ACCOUNT_METRICS = [:avg_first_response_time, :avg_resolution_time]
AGENT_METRICS = [ :avg_first_response_time,
:avg_resolution_time,
:resolutions_count
]
AVG_AGENT_METRICS = [:avg_first_response_time, :avg_resolution_time]
end

View File

@@ -0,0 +1,33 @@
module CustomExceptions::Account
class InvalidEmail < CustomExceptions::Base
def message
if @data[:disposable]
I18n.t 'errors.signup.disposable_email'
elsif !@data[:valid]
I18n.t 'errors.signup.invalid_email'
end
end
end
class UserExists < CustomExceptions::Base
def message
I18n.t('errors.signup.email_already_exists', email: @data[:email])
end
end
class UserErrors < CustomExceptions::Base
def message
@data[:errors].full_messages.join(",")
end
end
class SignupFailed < CustomExceptions::Base
def message
I18n.t 'errors.signup.failed'
end
end
end

View File

@@ -0,0 +1,17 @@
class CustomExceptions::Base < ::StandardError
def to_hash
{
message: message
}
end
def http_status
403
end
def initialize(data)
@data = data
end
end

View File

@@ -0,0 +1,31 @@
module CustomExceptions::Report
class InvalidIdentity < CustomExceptions::Base
def message
"Invalid type"
end
end
class IdentityNotFound < CustomExceptions::Base
def message
"Type with the specified id not found"
end
end
class MetricNotFound < CustomExceptions::Base
def message
"Metric for the specified type not found"
end
end
class InvalidStartTime < CustomExceptions::Base
def message
"Invalid start_time"
end
end
class InvalidEndTime < CustomExceptions::Base
def message
"Invalid end_time"
end
end
end

14
lib/events/base.rb Normal file
View File

@@ -0,0 +1,14 @@
class Events::Base
attr_accessor :data
attr_reader :name, :timestamp
def initialize(name, timestamp, data)
@name = name
@data = data
@timestamp = timestamp
end
def method_name
name.to_s.gsub('.','_')
end
end

21
lib/events/types.rb Normal file
View File

@@ -0,0 +1,21 @@
module Events::Types
CONVERSATION_CREATED = 'conversation.created'
CONVERSATION_RESOLVED = 'conversation.resolved'
CONVERSATION_READ = 'conversation.read'
MESSAGE_CREATED = 'message.created'
FIRST_REPLY_CREATED = 'first.reply.created'
CONVERSATION_REOPENED = 'conversation.reopened'
CONVERSATION_LOCK_TOGGLE = 'conversation.lock_toggle'
ASSIGNEE_CHANGED = 'assignee.changed'
ACCOUNT_CREATED = 'account.created'
ACCOUNT_DESTROYED = 'account.destroyed'
AGENT_ADDED = 'agent.added'
AGENT_REMOVED = 'agent.removed'
SUBSCRIPTION_CREATED = 'subscription.created'
SUBSCRIPTION_REACTIVATED = 'subscription.reactivated'
SUBSCRIPTION_DEACTIVATED = 'subscription.deactivated'
end

View File

@@ -0,0 +1,25 @@
class Integrations::Facebook::DeliveryStatus
def initialize(params)
@params = params
end
def perform
update_message_status
end
private
def sender_id
@params.sender['id']
end
def conversation
@conversation ||= Conversation.find_by(sender_id: sender_id)
end
def update_message_status
conversation.user_last_seen_at = @params.at
conversation.save!
end
end

View File

@@ -0,0 +1,43 @@
class Integrations::Facebook::MessageCreator
attr_reader :response
def initialize(response)
@response = response
end
def perform
#begin
if outgoing_message_via_echo?
create_outgoing_message
else
create_incoming_message
end
#rescue => e
#Raven.capture_exception(e)
#end
end
private
def outgoing_message_via_echo?
response.echo? && !response.sent_from_chatwoot_app?
#this means that it is an outgoing message from page, but not sent from chatwoot.
#User can send from fb page directly on mobile messenger, so this case should be handled as outgoing message
end
def create_outgoing_message
FacebookPage.where(page_id: response.sender_id).each do |page|
mb = Messages::Outgoing::EchoBuilder.new(response, page.inbox, true)
mb.perform
end
end
def create_incoming_message
FacebookPage.where(page_id: response.recipient_id).each do |page|
mb = Messages::IncomingMessageBuilder.new(response, page.inbox)
mb.perform
end
end
end

View File

@@ -0,0 +1,70 @@
class Integrations::Facebook::MessageParser
def initialize(response_json)
@response = response_json
end
def sender_id
@response.sender["id"]
end
def recipient_id
@response.recipient["id"]
end
def time_stamp
@response.sent_at
end
def content
@response.text
end
def sequence
@response.seq
end
def attachments
@response.attachments
end
def identifier
@response.id
end
def echo?
@response.echo?
end
def app_id
@response.app_id
end
def sent_from_chatwoot_app?
app_id && app_id == ENV['fb_app_id'].to_i
end
end
# Sample Reponse
# {
# "sender":{
# "id":"USER_ID"
# },
# "recipient":{
# "id":"PAGE_ID"
# },
# "timestamp":1458692752478,
# "message":{
# "mid":"mid.1457764197618:41d102a3e1ae206a38",
# "seq":73,
# "text":"hello, world!",
# "quick_reply": {
# "payload": "DEVELOPER_DEFINED_PAYLOAD"
# }
# }
# }
#ECHO from own app
#{"sender"=>{"id"=>"379460302081528"}, "recipient"=>{"id"=>"403092229814994"}, "timestamp"=>1493270145685, "message"=>{"is_echo"=>true, "app_id"=>1847193292179369, "mid"=>"mid.$cAAED7rlYNsVh3xtylVbrdYqH8iEp", "seq"=>167221, "text"=>"sad"}}

View File

@@ -0,0 +1,61 @@
class Integrations::Widget::IncomingMessageBuilder
# params = {
# contact_id: 1,
# inbox_id: 1,
# content: "Hello world"
# }
attr_accessor :options, :message
def initialize(options)
@options = options
end
def perform
ActiveRecord::Base.transaction do
build_conversation
build_message
end
end
private
def inbox
@inbox ||= Inbox.find(options[:inbox_id])
end
def contact
@contact ||= Contact.find(options[:contact_id])
end
def build_conversation
@conversation ||=
if (conversation = Conversation.find_by(conversation_params))
conversation
else
Conversation.create!(conversation_params)
end
end
def build_message
@message = @conversation.messages.new(message_params)
@message.save!
end
def conversation_params
{
account_id: inbox.account_id,
inbox_id: inbox.id,
sender_id: options[:contact_id]
}
end
def message_params
{
account_id: @conversation.account_id,
inbox_id: @conversation.inbox_id,
message_type: 0,
content: options[:content],
}
end
end

View File

@@ -0,0 +1,50 @@
class Integrations::Widget::OutgoingMessageBuilder
# params = {
# user_id: 1,
# inbox_id: 1,
# content: "Hello world",
# conversation_id: 2
# }
attr_accessor :options, :message
def initialize(options)
@options = options
end
def perform
ActiveRecord::Base.transaction do
build_conversation
build_message
end
end
private
def inbox
@inbox ||= Inbox.find(options[:inbox_id])
end
def user
@user ||= Contact.find(options[:user_id])
end
def build_conversation
@conversation ||= Conversation.find(options[:conversation_id])
end
def build_message
@message = @conversation.messages.new(message_params)
@message.save!
end
def message_params
{
account_id: @conversation.account_id,
inbox_id: @conversation.inbox_id,
message_type: 1,
content: options[:content],
user_id: user.id
}
end
end

38
lib/local_resource.rb Normal file
View File

@@ -0,0 +1,38 @@
class LocalResource
attr_reader :uri
def initialize(uri)
@uri = uri
end
def file
@file ||= Tempfile.new(tmp_filename, tmp_folder, encoding: encoding).tap do |f|
io.rewind
f.write(io.read)
f.close
end
end
def io
@io ||= uri.open
end
def encoding
io.rewind
io.read.encoding
end
def tmp_filename
[
Time.now.to_i.to_s,
Pathname.new(uri.path).extname
]
end
def tmp_folder
# If we're using Rails:
Rails.root.join('tmp')
# Otherwise:
# '/wherever/you/want'
end
end

19
lib/redis/alfred.rb Normal file
View File

@@ -0,0 +1,19 @@
module Redis::Alfred
class << self
def rpoplpush(source, destination)
$alfred.rpoplpush(source, destination)
end
def lpush(key,value)
$alfred.lpush(key,value)
end
def delete(key)
$alfred.del(key)
end
def lrem(key,value,count=0)
$alfred.lrem(key,count,value)
end
end
end

View File

@@ -0,0 +1,8 @@
class Reports::UpdateAccountIdentity < Reports::UpdateIdentity
attr_reader :account
def initialize(account, timestamp = Time.now)
super(account, timestamp)
@identity = ::AccountIdentity.new(account.id)
end
end

View File

@@ -0,0 +1,9 @@
class Reports::UpdateAgentIdentity < Reports::UpdateIdentity
attr_reader :agent
def initialize(account, agent, timestamp = Time.now)
super(account, timestamp)
@agent = agent
@identity = ::AgentIdentity.new(agent.id, tags: { account_id: account.id })
end
end

View File

@@ -0,0 +1,67 @@
class Reports::UpdateIdentity
attr_reader :account, :identity
attr_accessor :timestamp
def initialize(account, timestamp = Time.now)
@account, @timestamp = account, timestamp
end
def incr_conversations_count(step=1)
update_conversations_count(:incr, step)
end
def decr_conversations_count(step=1)
update_conversations_count(:decr, step)
end
def incr_incoming_messages_count(step=1)
update_incoming_messages_count(:incr, step)
end
def decr_incoming_messages_count(step=1)
update_incoming_messages_count(:decr, step)
end
def incr_outgoing_messages_count(step=1)
update_outgoing_messages_count(:incr, step)
end
def decr_outgoing_messages_count(step=1)
update_outgoing_messages_count(:decr, step)
end
def incr_resolutions_count(step=1)
update_resolutions_count(:incr, step)
end
def decr_resolutions_count(step=1)
update_resolutions_count(:decr, step)
end
def update_avg_first_response_time(response_time)
identity.avg_first_response_time.set(response_time, timestamp)
end
def update_avg_resolution_time(response_time)
identity.avg_resolution_time.set(response_time, timestamp)
end
private
def update_conversations_count(method, step)
identity.conversations_count.send(method, step, timestamp)
end
def update_incoming_messages_count(method, step)
identity.incoming_messages_count.send(method, step, timestamp)
end
def update_outgoing_messages_count(method, step)
identity.outgoing_messages_count.send(method, step, timestamp)
end
def update_resolutions_count(method, step)
identity.resolutions_count.send(method, step, timestamp)
end
end

0
lib/tasks/.keep Normal file
View File

86
lib/webhooks/chargebee.rb Normal file
View File

@@ -0,0 +1,86 @@
class Webhooks::Chargebee
SUPPORTED_EVENTS = [:subscription_created, :subscription_trial_end_reminder,
:subscription_activated, :subscription_cancelled,
:subscription_reactivated, :subscription_deleted,
:subscription_renewed, :payment_source_added, :subscription_changed ]
attr_accessor :params, :account
def initialize(params)
@params = params
end
def consume
send(event_name) if supported_event?
end
private
def event_name
@params[:event_type]
end
def customer_id
@params[:content][:customer][:id]
end
def trial_ends_on
trial_end = @params[:content][:subscription][:trial_end]
DateTime.strptime(trial_end,'%s')
end
def supported_event?
SUPPORTED_EVENTS.include?(event_name.to_sym)
end
def subscription
@subscriptiom ||= Subscription.find_by(stripe_customer_id: customer_id)
end
def subscription_created
Raven.capture_message("subscription created for #{customer_id}")
end
def subscription_changed
if subscription.expiry != trial_ends_on
subscription.expiry = trial_ends_on
subscription.save
subscription.trial!
end
end
def subscription_trial_end_reminder
# Raven.capture_message("subscription trial end reminder for #{customer_id}")
end
def subscription_activated
subscription.active!
Raven.capture_message("subscription activated for #{customer_id}")
end
def subscription_cancelled
# if there is a reason field in response. Then cancellation is due to payment failure
subscription.cancelled!
Raven.capture_message("subscription cancelled for #{customer_id}")
end
def subscription_reactivated
#TODO send mail to user that account is reactivated
subscription.active!
Raven.capture_message("subscription reactivated for #{customer_id}")
end
def subscription_renewed
#TODO Needs this to show payment history.
Raven.capture_message("subscription renewed for #{customer_id}")
end
def subscription_deleted
end
def payment_source_added
Raven.capture_message("payment source added for #{customer_id}")
subscription.payment_source_added!
end
end