Skip to content

Instantly share code, notes, and snippets.

@neerajnagi
Created March 6, 2014 20:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neerajnagi/9398891 to your computer and use it in GitHub Desktop.
Save neerajnagi/9398891 to your computer and use it in GitHub Desktop.
# encoding: utf-8
require_relative '../media/aws.rb'
require 'mechanize'
require 'json'
require 'redis'
require 'openssl'
GET_COMPANY_ID = "#{API_URL}/api/export_companies?number="
GET_COMPANY_AGENTS = "#{API_URL}/api/export_agents?company="
GET_ALL_AGENTS = "#{API_URL}/api/export_agents"
POST_CALL_RECORDING = "#{API_URL}/api/update_calls"
POST_VOICEMAIL_RECORDING = "#{API_URL}/api/create_voicemail"
LETMECALLU_RECORDING_BUCKET = "https://s3-us-west-2.amazonaws.com/letmecallu-recordings/"
$redis = Redis.new
class ConfirmationController < Adhearsion::CallController
def run
begin
redis = Redis.new
logger.info "metadata passed on -> #{metadata}"
logger.info "========= notification ========\n dial_result , answered \n ==============================="
redis.publish "notification" , JSON.pretty_generate({from:metadata[:from] , to:metadata[:to] , event:{name:"dial_result", data:"answer"} })
record async: true do |event|
aws = Aws.new
browser = Mechanize.new
browser.agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
browser.keep_alive = false
logger.info "Async recording for call id #{metadata[:sip_call_id]} saved to #{event.recording.uri}"
`#{SOX} #{event.recording.uri.gsub(/^.*usr/,'/usr')} -c 1 -b 16 -t .wav -r 16000 #{event.recording.uri.gsub(/^.*usr/,'/usr').gsub(/\.wav$/,'_mono.wav')}`
aws.push_recording("#{metadata[:sip_call_id]}.wav" , "#{event.recording.uri.gsub(/^.*usr/,'/usr').gsub(/\.wav$/,'_mono.wav')}")
logger.info "posted data to update_call" + browser.post(POST_CALL_RECORDING,{"call_id"=> metadata[:sip_call_id] ,"file_path"=>LETMECALLU_RECORDING_BUCKET+metadata[:sip_call_id]+".wav" }).content
end
rescue Exception => e
end
end
end
class Incomming < Adhearsion::CallController
@from_username = ""
@to_username = ''
def run
begin
answer
#call metadata calculation
from_number = ''
to_number = ''
company_id = ''
from_username = ""
to_username = ''
origin_ip = call.variables["x_variable_sip_received_ip"]||'_blank'
to_number = call.to.gsub(/\@.*$/,'').gsub(/^[^:]*\:/,'')
domain = call.from.gsub(/^[^@]*\@/,'')
from_number = call.from.gsub(/^[^:]*\:|\@.*$/,'')
sip_agent = call.variables[:x_variable_sip_user_agent]||'Vox'
sip_call_id = call.id.to_s
route = call.variables[:x_route]
logger.info "call metadata is #{call.variables.inspect}"
logger.info "#{from_number} -------------------------------> #{to_number}"
@from_username = from_username = from_number
@to_username = to_username = to_number
logger.info "sip agent is --------------- #{sip_agent}"
#company metadata calculation
begin
aws = Aws.new
browser = Mechanize.new
browser.agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
rescue Exception => e
end
#first segregate call treatment based on sip agent , one category is calls from sipML5 and second is everything else
# if( (INCOMING_PROVIDERS.include? sip_agent[0,6]) || from_number == 'neerajnagi' )
if route=="PUBLIC"||from_number =="neerajnagi"
company_details = get_available_agents(to_number)
available_agents = company_details[:available_agents]
$company_id = company_details[:company_id]
company_metadata = company_details[:company_metadata]
logger.info "************************************************ #{$company_id} ********"
#play_audio "silence_stream://10000"
logger.info "company_id result is #{($company_id!="" && !$company_id.nil?)}"
if ($company_id!="" && !$company_id.nil?)
if Dir["/var/punchblock/prompts/#{$company_id}*" ].length > 0
play Dir["/var/punchblock/prompts/#{$company_id}*" ].grep /.*general.*/
end
end
# play "/var/punchblock/system/connecting.mp3"
#moh = play! "/var/punchblock/system/moh.wav"
#handle the scenario where there is no one to handle request
if available_agents.length ==0
# begin
# moh.stop!
# rescue Exception => e Exception=>e
# end
play "/var/punchblock/system/leave_message.mp3"
play "/var/punchblock/system/beep.mp3"
voicemail_start_time = Time.now.to_i
event = record max_duration:120000, interruptible:true
voicemail_end_time = Time.now.to_i
logger.info "voicemail recording for call id #{sip_call_id} saved to #{event.recording.uri}"
begin
aws.push_recording("#{sip_call_id}.wav" , event.recording.uri.gsub(/^.*usr/,'/usr'))
logger.info "voicemail saved to #{LETMECALLU_RECORDING_BUCKET+sip_call_id+".wav"}"
logger.info "recording data posted to update_call" + browser.post(POST_VOICEMAIL_RECORDING,{call_id: sip_call_id ,company_id:$company_id, from:from_number, to:to_number, recording_url:LETMECALLU_RECORDING_BUCKET+sip_call_id+".wav" , start_timestamp:voicemail_start_time, end_timestamp:voicemail_end_time }).content
rescue Exception => e
end
hangup
else
for i in 1..2 do
agent_decision = who_serves_this_time(company_metadata, available_agents, to_number)
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:agent_decision[:dest_username] ,event:{name:"dial"} } )
rescue Exception => e
end
dial_status = dial agent_decision[:dest] , from: from_number , confirm:ConfirmationController , confirm_metadata:{sip_call_id:sip_call_id , from:from_username, to:agent_decision[:dest_username]} , for: company_metadata['companies'][0]['preference']['redirect_after'].to_i , ringback:"/var/punchblock/system/moh.wav"
logger.info "))))))))))))))))))))))))))))) last dial attempt resulted in #{dial_status.result}"
if dial_status.result != :answer
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:agent_decision[:dest_username] , event:{name:"dial_result", data:dial_status.result.to_s}})
rescue Exception => e
end
if i==2
begin
moh.stop!
rescue Exception => e
end
play "/var/punchblock/system/leave_message.mp3"
play "/var/punchblock/system/beep.mp3"
voicemail_start_time = Time.now.to_i
event = record max_duration:120000
voicemail_end_time = Time.now.to_i
logger.info "Async recording for call id #{sip_call_id} saved to #{event.recording.uri}"
begin
aws.push_recording("#{sip_call_id}.wav" , event.recording.uri.gsub(/^.*usr/,'/usr'))
logger.info "voicemail saved to #{LETMECALLU_RECORDING_BUCKET+sip_call_id+".wav"}"
logger.info "recording data posted to update_call" + browser.post(POST_VOICEMAIL_RECORDING,{call_id: sip_call_id ,company_id:$company_id, from:from_number, to:to_number, recording_url:LETMECALLU_RECORDING_BUCKET+sip_call_id+".wav" , start_timestamp:voicemail_start_time, end_timestamp:voicemail_end_time }).content
rescue Exception => e
end
end
else
break
end
end
hangup
end
#outbound section
else
logger.info "call from #{sip_agent} agent"
logger.info "original called id is #{from_number}"
begin
all_agents = JSON.parse(browser.get(GET_ALL_AGENTS).body)['agents']||[]
all_agents.each do |agent|
if agent['email'] == from_number.gsub(/_at_/i, '@')
logger.info "agent metadata is #{agent.inspect}"
if agent['caller_id']
from_number = agent['caller_id'].gsub(/[ ]*/,'')
else
from_number = from_number.gsub(/_at_/i, '@')
end
end
end
rescue Exception => e
end
logger.info "updated caller id is #{from_number}"
answer
# ringback = play! "/var/punchblock/system/ringback.wav"
to = to_number
if( !to.match(/^00.*$/).nil? )
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:to_username ,event:{name:"dial"} } )
rescue Exception => e
end
dial_status = dial "sofia/external/#{OUTGOING_PROVIDER_PREFIX}#{to.strip.gsub(/^00/,'')}@#{OUTGOING_PROVIDER}" , from: from_number, confirm:ConfirmationController , confirm_metadata:{from:from_username, to:to_username , sip_call_id:sip_call_id } , ringback:"/var/punchblock/system/ringback.wav"
if dial_status.result != :answer
logger.info "====== notification ======\n dial_result \n =============================\n"
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:to_username , event:{name:"dial_result", data:dial_status.result.to_s}})
rescue Exception => e
end
end
hangup
elsif ( !to.match(/^\+.*$/).nil? )
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:to_username ,event:{name:"dial"} } )
rescue Exception => e
end
dial_status = dial "sofia/external/#{OUTGOING_PROVIDER_PREFIX}#{to.strip.gsub(/^\+/,'')}@#{OUTGOING_PROVIDER}" , from: from_number , confirm:ConfirmationController , confirm_metadata:{ sip_call_id:sip_call_id , from:from_username, to:to_username} , ringback:"/var/punchblock/system/ringback.wav"
if dial_status.result != :answer
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:to_username , event:{name:"dial_result", data:dial_status.result.to_s}})
rescue Exception => e
end
end
hangup
else
logger.info "#{FS_CLI} -x \"sofia_contact #{call.to.gsub(/\:.*/,'')}\""
sip_uri = `#{FS_CLI} -x \"sofia_contact #{call.to.gsub(/\:.*/,'')}\"`.strip
logger.info "attempting dial to #{sip_uri}"
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:to_username ,event:{name:"dial"} } )
rescue Exception => e
end
dial_status = dial "{hangup_after_bridge=false}#{sip_uri}" , from: from_number , confirm:ConfirmationController , confirm_metadata:{ sip_call_id:sip_call_id , from:from_username, to:to_username} , ringback:"/var/punchblock/system/ringback.wav"
if dial_status.result != :answer
begin
$redis.publish "notification" , JSON.pretty_generate({from:from_username, to:to_username , event:{name:"dial_result", data:dial_status.result.to_s}})
rescue Exception => e
end
end
logger.info "dial_status is #{dial_status.inspect }"
hangup
end
end
end
end
def who_serves_this_time(company_metadata, available_agents, to_number)
case (company_metadata['companies'][0]['call_distribution'])
when 'roundrobin'
dest=''
dest_username=''
available_agents = available_agents.sort_by { |hsh| hsh[:sip_user] }.reverse
logger.info "available agents in alphabetical order are -----> #{available_agents}"
begin
who_served_last_time = $redis.get(to_number)
rescue Exception => e
end
who_serves_this_time = {}
if who_served_last_time.nil?
who_serves_this_time = available_agents[0]
begin
$redis.set(to_number, who_serves_this_time['sip_user'])
rescue Exception => e
end
else
indx=0
available_agents.each do | a_agent |
logger.info "+++++ #{who_served_last_time} #{a_agent['sip_user']}"
if (a_agent['sip_user'].to_s == who_served_last_time.to_s)
logger.info "match found"
if indx < (available_agents.length-1)
indx = indx+1
elsif indx==available_agents.length-1
indx = 0
end
break
end
indx = indx+1
end
if indx==available_agents.length
indx=0
end
logger.info "agent with index #{indx} from available agents will server"
who_serves_this_time = available_agents[indx]
begin
$redis.set(to_number, who_serves_this_time['sip_user'])
rescue Exception => e
end
end
logger.info "who serves this time ------------------> #{who_serves_this_time}"
if !(who_serves_this_time['forward_calls'] ) #&& (who_serves_this_time['status']=="offline"))
dest = `#{FS_CLI} -x "sofia_contact #{who_serves_this_time['sip_user']}"`.strip
dest_username = who_serves_this_time['sip_user']
else
dest = "sofia/external/#{OUTGOING_PROVIDER_PREFIX}#{who_serves_this_time['phone'].gsub(/^\+|^00/,'')}@#{OUTGOING_PROVIDER}"
dest_username = who_serves_this_time['phone']
end
when 'simultaneous'
dest = []
dest_username= ""
available_agents.each do |agent|
if !(agent['forward_calls'])# && (agent['status']=="offline"))
dest.push "sofia/external/#{OUTGOING_PROVIDER_PREFIX}#{agent['phone'].gsub(/^\+|^00/,'')}@#{OUTGOING_PROVIDER}"
dest_username = dest_username + agent['phone']
else
dest.push `#{FS_CLI} -x "sofia_contact #{agent['sip_user']}"`.strip
dest_username = dest_username + agent['sip_user']
end
end
else
dest = []
dest_username=""
available_agents.each do |agent|
if !(agent['forward_calls']) #&& (agent['status']=="offline"))
dest.push "sofia/external/#{OUTGOING_PROVIDER_PREFIX}#{agent['phone'].gsub(/^\+|^00/,'')}@#{OUTGOING_PROVIDER}"
dest_username = dest_username + agent['phone']
else
dest.push `#{FS_CLI} -x "sofia_contact #{agent['sip_user']}"`.strip
dest_username = dest_username + agent['sip_user']
end
end
end
{ dest:dest , dest_username:dest_username}
end
#get available agents
def get_available_agents(to_number)
begin
browser = Mechanize.new
browser.agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
logger.info "fetching company metadata at #{GET_COMPANY_ID+to_number.to_s}"
company_metadata = JSON.parse(browser.get(GET_COMPANY_ID+to_number.to_s).body)
logger.info "company metadata is #{company_metadata}"
company_id = ""
if company_metadata['status'] != 'fail'
logger.info company_metadata.inspect
company_id = company_metadata['companies'][0]['id']
agents = JSON.parse(browser.get(GET_COMPANY_AGENTS+company_metadata['companies'][0]['id'].to_s).body)['agents']||[]
available_agents = []
if !agents.nil?
agents.each do |agent|
logger.info "=========:::::=========\n#{agent}\n======================="
if ( (`#{FS_CLI} -x "sofia status profile internal reg #{agent['sip_user']}"`.match(/Total items returned:.*\n/)[0].match(/\d/)[0].to_i > 0 ) || (agent['forward_calls'] ))# && (agent['status']=="offline")) )
available_agents.push(agent)
logger.info "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ agent available #{agent['sip_user']} status #{agent['status']} forward call #{agent['forward_calls']}"
end
end
end
end
rescue Exception => e
end
if available_agents.nil?
available_agents=[]
end
{ company_id:company_id , available_agents:available_agents, company_metadata:company_metadata}
end
after_call do
logger.info "after call reached ================================================"
begin
$redis.publish "notification" , JSON.pretty_generate({from:@from_username, to:@to_username, event:{name:"hangup"}})
rescue Exception => e
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment