exotel_api 0.5.6 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da142fb4d136ef153225277bad396dae3cb76ecd
4
- data.tar.gz: fd5d01f94697116b3c83585cc72073a08b0a1c0d
3
+ metadata.gz: 779e025eb3f0db01bfe0e54bcc581e4fbd1b2ff5
4
+ data.tar.gz: 3c1ba244ca13984dc513aaf3645e78b72fdc544c
5
5
  SHA512:
6
- metadata.gz: e556c082d558160bd243495b30cbf9a7afce250ce7f9e87969a454b811e7531e4a3bb889f2eae52d19a07bba031613a3c7b4b05859f960bda25731931bea5fc6
7
- data.tar.gz: 51419f09b9bd37dbd8b6262b48547a5dcdeeebd74d3fc24c2193103d4ab58569f6a425a8529bcef06ec2634944190df7a4aac4c7c7886686e7cd96dff549dc47
6
+ metadata.gz: d0d4270095e19af98e8e04b524a9d93eb8e58ebb6acc1320edafc701a3be00daf11ccf3953a870c3024002d2538b6691f92455a334f2b9870f95ff43dce260ab
7
+ data.tar.gz: 35d78aaca1d821da9bd9ac91c70d419d451dea0af418f36f3d73228eddaa746795cd13f574b60cb7ae3f8bfd2ab6ed2f1178589db87ec774139fb7df0e3d6dba
@@ -1,19 +1,6 @@
1
1
  module ExotelApi
2
2
  class CallController < StartController
3
- #response - greeting,menu,connect
4
- def start
5
- begin
6
- _call = direction
7
- if _call.present?
8
- applet = "{\"select\":\"#{_call.start(params)}\"}" if defined?(_call.start)
9
- end
10
- rescue => e
11
- logger.error e.message
12
- logger.error e.backtrace.join("\n")
13
- end
14
- render :plain => applet, content_type: "text/html", status: 200
15
- end
16
- #response - list of URLS
3
+ #response - audio file or list of URLS of audio files
17
4
  def greeting
18
5
  begin
19
6
  _call = direction
@@ -26,7 +13,7 @@ module ExotelApi
26
13
  end
27
14
  render :plain => urls, content_type: "text/plain", :status => 200
28
15
  end
29
- #response - menu,connect
16
+ #response - switch case ivr_menu, hangup
30
17
  def after_greeting
31
18
  begin
32
19
  _call = direction
@@ -39,25 +26,25 @@ module ExotelApi
39
26
  end
40
27
  render :plain => applet, content_type: "text/html", status: 200
41
28
  end
42
- #response - phone
43
- def connect
29
+ #response - audio file or list of URLS of audio files
30
+ def ivr_menu
44
31
  begin
45
32
  _call = direction
46
33
  if _call.present?
47
- phones = _call.connect if defined?(_call.connect)
34
+ urls = _call.ivr_menu(params) if defined?(_call.ivr_menu)
48
35
  end
49
36
  rescue => e
50
37
  logger.error e.message
51
38
  logger.error e.backtrace.join("\n")
52
39
  end
53
- render :plain => phones, content_type: "text/plain", :status => 200
40
+ render :plain => urls, content_type: "text/plain", :status => 200
54
41
  end
55
- #response - nil
56
- def finish
42
+ #response - status 200 and plain ''
43
+ def keypress
57
44
  begin
58
45
  _call = direction
59
46
  if _call.present?
60
- _call.finish(params) if defined?(_call.finish)
47
+ _call.keypress(params) if defined?(_call.keypress)
61
48
  end
62
49
  rescue => e
63
50
  logger.error e.message
@@ -65,62 +52,57 @@ module ExotelApi
65
52
  end
66
53
  render :plain => '', content_type: "text/plain", :status => 200
67
54
  end
68
- #response - list of URLS
69
- def menu
55
+ #response - audio file or list of URLs of audio files
56
+ def after_keypress
70
57
  begin
71
58
  _call = direction
72
59
  if _call.present?
73
- urls = _call.menu(params) if defined?(_call.menu)
60
+ urls = _call.after_keypress(params) if defined?(_call.after_keypress)
74
61
  end
75
62
  rescue => e
76
63
  logger.error e.message
77
64
  logger.error e.backtrace.join("\n")
78
65
  end
79
- render :plain => urls, content_type: "text/plain", :status => 200
66
+ render :plain => urls, content_type: "text/plain", status: 200
80
67
  end
81
- #response - nil
82
- def dtmf
68
+ #response - switch case ivr_menu, hangup
69
+ def after_keypress_greeting
83
70
  begin
84
71
  _call = direction
85
72
  if _call.present?
86
- _call.dtmf_key(params) if defined?(_call.dtmf_key)
73
+ applet = "{\"select\":\"#{_call.after_keypress_greeting(params)}\"}" if defined?(_call.after_keypress_greeting)
87
74
  end
88
75
  rescue => e
89
76
  logger.error e.message
90
77
  logger.error e.backtrace.join("\n")
91
78
  end
92
- render :plain => '', content_type: "text/plain", :status => 200
79
+ render :plain => applet, content_type: "text/html", status: 200
93
80
  end
94
- #response - greeting,connect
95
- def after_dtmf
81
+ #response - status 200, 404 or 302 and plain ''
82
+ def play_again
96
83
  begin
97
84
  _call = direction
98
85
  if _call.present?
99
- applet = "{\"select\":\"#{_call.after_dtmf(params)}\"}" if defined?(_call.after_dtmf)
86
+ applet = "{\"select\":\"#{_call.play_again(params)}\"}" if defined?(_call.play_again)
100
87
  end
101
88
  rescue => e
102
89
  logger.error e.message
103
90
  logger.error e.backtrace.join("\n")
104
91
  end
105
- render :plain => applet, content_type: "text/html", status: 200
92
+ render :plain => applet, content_type: "text/plain", :status => 200
106
93
  end
107
- #response - status code 200,302
108
- def repeat
94
+ #response - status 200 and plain ''
95
+ def finish
109
96
  begin
110
97
  _call = direction
111
98
  if _call.present?
112
- answer = _call.play_again(params) if defined?(_call.play_again)
113
- if answer == 'yes'
114
- status = '200'
115
- else
116
- status = '302'
117
- end
99
+ _call.finish(params) if defined?(_call.finish)
118
100
  end
119
101
  rescue => e
120
102
  logger.error e.message
121
103
  logger.error e.backtrace.join("\n")
122
104
  end
123
- render :plain => '', content_type: "text/plain", :status => status
105
+ render :plain => '', content_type: "text/plain", :status => 200
124
106
  end
125
107
  end
126
108
  end
data/config/routes.rb CHANGED
@@ -1,41 +1,14 @@
1
1
  Rails.application.routes.draw do
2
2
  namespace :exotel_api do
3
- namespace :ivr do
4
- namespace :call do
5
- get 'greeting_and_menu'
6
- get 'dtmf'
7
- get 'closing'
8
- get 'repeat'
9
- post 'status'
10
- end
11
- end
12
-
13
3
  namespace :call do
14
- get 'start'
15
4
  get 'greeting'
16
5
  get 'after_greeting'
17
- namespace :after_greeting do
18
- get 'connect'
19
- namespace :connect do
20
- get 'status'
21
- end
22
- end
23
- get 'connect'
24
- namespace :connect do
25
- get 'status'
26
- end
6
+ get 'ivr_menu'
7
+ get 'keypress'
8
+ get 'after_keypress'
9
+ get 'after_keypress_greeting'
10
+ get 'play_again'
27
11
  post 'finish'
28
- get 'menu'
29
- get 'dtmf'
30
- get 'after_dtmf'
31
- namespace :after_dtmf do
32
- get 'greeting'
33
- get 'after_greeting'
34
- namespace :connect do
35
- get 'status'
36
- end
37
- end
38
- get 'repeat'
39
12
  end
40
13
  end
41
14
  end
@@ -0,0 +1,109 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'httparty'
3
+ module ExotelApi
4
+ class Call
5
+ include HTTParty
6
+ base_uri "https://twilix.exotel.in/v1/Accounts"
7
+ default_timeout 10
8
+
9
+ def initialize; end
10
+
11
+ #TODO check if this is a good decision to provide a wrapper.
12
+ def self.shoot(params={})
13
+ self.new.shoot(params)
14
+ end
15
+
16
+ def self.connect_to_flow(params={})
17
+ self.new.connect_to_flow(params)
18
+ end
19
+
20
+ def self.connect_to_agent(params={})
21
+ self.new.connect_to_agent(params)
22
+ end
23
+
24
+ def self.details(params={})
25
+ self.new.details(params)
26
+ end
27
+
28
+ def shoot(params={})
29
+ if valid?(params, {:type => 'flow'})
30
+ params = transfrom_params(params, {:type => 'flow'})
31
+ make_call(params)
32
+ end
33
+ end
34
+
35
+ def connect_to_flow(params={})
36
+ if valid?(params, {:type => 'flow'})
37
+ params = transfrom_params(params, {:type => 'flow'})
38
+ make_call(params)
39
+ end
40
+ end
41
+
42
+ def connect_to_agent(params={})
43
+ if valid?(params, {:type => 'agent'})
44
+ params = transfrom_params(params, {:type => 'agent'})
45
+ make_call(params)
46
+ end
47
+ end
48
+
49
+ def details(sid)
50
+ response = self.class.get("/#{ExotelApi.exotel_sid}/Calls/#{sid}", :basic_auth => auth)
51
+ handle_response(response)
52
+ end
53
+
54
+ protected
55
+
56
+ def make_call(params)
57
+ response = self.class.post(URI.escape("/#{ExotelApi.exotel_sid}/Calls/connect"), {:body => params, :basic_auth => auth })
58
+ handle_response(response)
59
+ end
60
+
61
+ def valid?(params, options)
62
+ mandatory_keys = [:from, :to, :caller_id, :call_type]
63
+ mandatory_keys << :flow_id if options[:type] == 'flow'
64
+
65
+ unless mandatory_keys.all?{|key| params.keys.include?(key)}
66
+ raise ExotelApi::ParamsError, "Missing one or many required parameters."
67
+ end
68
+ valid_call_type?(params)
69
+ return true
70
+ end
71
+
72
+ def valid_call_type?(params)
73
+ raise ExotelApi::ParamsError, "Call Type is not valid" unless ['trans', 'promo'].include?(params[:call_type])
74
+ end
75
+
76
+ def auth
77
+ {:username => ExotelApi.exotel_sid, :password => ExotelApi.exotel_token}
78
+ end
79
+
80
+ def flow_url(flow_id)
81
+ "http://my.exotel.in/exoml/start/#{flow_id}"
82
+ end
83
+
84
+ def transfrom_params(params, options)
85
+ if options[:type] == 'flow'
86
+ #Construct flow url and delete flow_id.
87
+ params = params.merge(:URL => flow_url(params[:flow_id]))
88
+ params.delete(:flow_id)
89
+ end
90
+
91
+ #Keys are converted to camelcase
92
+ params.inject({}){ |h, (key, value)| h[camelcase_key(key)] = value; h }
93
+ end
94
+
95
+ def camelcase_key(key)
96
+ key.to_s.split('_').map(&:capitalize).join.to_sym #Input: call_type, Output: :CallType
97
+ end
98
+
99
+ def handle_response(response)
100
+ case response.code.to_i
101
+ when 200...300 then ExotelApi::Response.new(response)
102
+ when 401 then raise ExotelApi::AuthenticationError, "#{response.body} Verify your sid and token."
103
+ when 403 then ExotelApi::Response.new(response)
104
+ else
105
+ raise ExotelApi::UnexpectedError, response.body
106
+ end
107
+ end
108
+ end
109
+ end
@@ -1,3 +1,3 @@
1
1
  module ExotelApi
2
- VERSION = "0.5.6"
2
+ VERSION = "0.6.1"
3
3
  end
data/lib/exotel_api.rb CHANGED
@@ -6,7 +6,7 @@ require 'exotel_api/engine'
6
6
  require 'exotel_api/config'
7
7
  require 'exotel_api/response'
8
8
  require 'exotel_api/metadata'
9
- require 'exotel_api/ivr/call'
9
+ require 'exotel_api/call'
10
10
 
11
11
  module ExotelApi
12
12
  # Your code goes here...
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exotel_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aashutosh Chaudhary
@@ -116,22 +116,16 @@ files:
116
116
  - LICENSE.txt
117
117
  - README.md
118
118
  - Rakefile
119
- - app/controllers/exotel_api/call/after_dtmf/connect_controller.rb
120
- - app/controllers/exotel_api/call/after_dtmf_controller.rb
121
- - app/controllers/exotel_api/call/after_greeting/connect_controller.rb
122
- - app/controllers/exotel_api/call/after_greeting_controller.rb
123
- - app/controllers/exotel_api/call/connect_controller.rb
124
119
  - app/controllers/exotel_api/call_controller.rb
125
- - app/controllers/exotel_api/ivr/call_controller.rb
126
120
  - app/controllers/exotel_api/start_controller.rb
127
121
  - bin/console
128
122
  - bin/setup
129
123
  - config/routes.rb
130
124
  - exotel_api.gemspec
131
125
  - lib/exotel_api.rb
126
+ - lib/exotel_api/call.rb
132
127
  - lib/exotel_api/config.rb
133
128
  - lib/exotel_api/engine.rb
134
- - lib/exotel_api/ivr/call.rb
135
129
  - lib/exotel_api/metadata.rb
136
130
  - lib/exotel_api/response.rb
137
131
  - lib/exotel_api/version.rb
@@ -1,21 +0,0 @@
1
- module ExotelApi
2
- module Call
3
- module AfterDtmf
4
- class ConnectController < StartController
5
- #response - nil
6
- def status
7
- begin
8
- _call = direction
9
- if _call.present?
10
- _call.status(params) if defined?(_call.status)
11
- end
12
- rescue => e
13
- logger.error e.message
14
- logger.error e.backtrace.join("\n")
15
- end
16
- render :plain => '', content_type: "text/plain", :status => 200
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,45 +0,0 @@
1
- module ExotelApi
2
- module Call
3
- class AfterDtmfController < StartController
4
- #response - list of URLs
5
- def greeting
6
- begin
7
- _call = direction
8
- if _call.present?
9
- urls = _call.greeting(params) if defined?(_call.greeting)
10
- end
11
- rescue => e
12
- logger.error e.message
13
- logger.error e.backtrace.join("\n")
14
- end
15
- render :plain => urls, content_type: "text/plain", :status => 200
16
- end
17
- #response - menu
18
- def after_greeting
19
- begin
20
- _call = direction
21
- if _call.present?
22
- applet = "{\"select\":\"#{_call.after_greeting(params)}\"}" if defined?(_call.after_greeting)
23
- end
24
- rescue => e
25
- logger.error e.message
26
- logger.error e.backtrace.join("\n")
27
- end
28
- render :plain => applet, content_type: "text/html", status: 200
29
- end
30
- #response - phones
31
- def connect
32
- begin
33
- _call = direction
34
- if _call.present?
35
- phones = _call.connect if defined?(_call.connect)
36
- end
37
- rescue => e
38
- logger.error e.message
39
- logger.error e.backtrace.join("\n")
40
- end
41
- render :plain => phones, content_type: "text/plain", :status => 200
42
- end
43
- end
44
- end
45
- end
@@ -1,21 +0,0 @@
1
- module ExotelApi
2
- module Call
3
- module AfterGreeting
4
- class ConnectController < StartController
5
- #response - nil
6
- def status
7
- begin
8
- _call = direction
9
- if _call.present?
10
- _call.status(params) if defined?(_call.status)
11
- end
12
- rescue => e
13
- logger.error e.message
14
- logger.error e.backtrace.join("\n")
15
- end
16
- render :plain => '', content_type: "text/plain", :status => 200
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,19 +0,0 @@
1
- module ExotelApi
2
- module Call
3
- class AfterGreetingController < StartController
4
- #response - phone
5
- def connect
6
- begin
7
- _call = direction
8
- if _call.present?
9
- phones = _call.connect if defined?(_call.connect)
10
- end
11
- rescue => e
12
- logger.error e.message
13
- logger.error e.backtrace.join("\n")
14
- end
15
- render :plain => phones, content_type: "text/plain", :status => 200
16
- end
17
- end
18
- end
19
- end
@@ -1,19 +0,0 @@
1
- module ExotelApi
2
- module Call
3
- class ConnectController < StartController
4
- #response - nil
5
- def status
6
- begin
7
- _call = direction
8
- if _call.present?
9
- _call.status(params) if defined?(_call.status)
10
- end
11
- rescue => e
12
- logger.error e.message
13
- logger.error e.backtrace.join("\n")
14
- end
15
- render :plain => '', content_type: "text/plain", :status => 200
16
- end
17
- end
18
- end
19
- end
@@ -1,86 +0,0 @@
1
- module ExotelApi
2
- class Ivr::CallController < ApplicationController
3
- skip_before_action :verify_authenticity_token, raise: false
4
- def greeting_and_menu
5
- begin
6
- _call = direction
7
- if _call.present?
8
- _call.update(status: 'completed')
9
- urls = _call.greeting_and_menu if defined?(_call.greeting_and_menu)
10
- end
11
- rescue => e
12
- logger.error e.message
13
- logger.error e.backtrace.join("\n")
14
- end
15
- render :plain => urls, content_type: "text/plain", :status => 200
16
- end
17
-
18
- def dtmf
19
- begin
20
- _call = direction
21
- if _call.present?
22
- _call.update(dtmf: params[:digits].parameterize.to_i)
23
- _call.dtmf_callback(params) if defined?(_call.dtmf_callback)
24
- end
25
- rescue => e
26
- logger.error e.message
27
- logger.error e.backtrace.join("\n")
28
- end
29
- render :plain => '', content_type: "text/plain", :status => 200
30
- end
31
-
32
- def closing
33
- begin
34
- _call = direction
35
- urls = _call.closing if _call.present? and defined?(_call.closing)
36
- rescue => e
37
- logger.error e.message
38
- logger.error e.backtrace.join("\n")
39
- end
40
- render :plain => urls, content_type: "text/plain", :status => 200
41
- end
42
-
43
- def status
44
- begin
45
- _call = direction
46
- if _call.present?
47
- _call.update(status: params[:Status])
48
- _call.status_callback(params) if defined?(_call.status_callback)
49
- end
50
- rescue => e
51
- logger.error e.message
52
- logger.error e.backtrace.join("\n")
53
- end
54
- render :plain => '', content_type: "text/plain", :status => 200
55
- end
56
-
57
- def repeat
58
- begin
59
- _call = direction
60
- if _call.present?
61
- status = _call.repeat_callback(params) if defined?(_call.repeat_callback)
62
- end
63
- rescue => e
64
- logger.error e.message
65
- logger.error e.backtrace.join("\n")
66
- end
67
- render :plain => '', content_type: "text/plain", :status => status
68
- end
69
-
70
- private
71
- def find_call
72
- if params[:CustomField].present?
73
- params[:CustomField].titleize.split.join.constantize::Call.find_by_call_sid(params[:CallSid])
74
- else
75
- eval(ExotelApi.status_callback_query)
76
- end
77
- end
78
- def direction
79
- if params[:Direction] == 'incoming'
80
- eval(ExotelApi.inbound_query)
81
- else
82
- find_call
83
- end
84
- end
85
- end
86
- end
@@ -1,111 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- require 'httparty'
3
- module ExotelApi
4
- module Ivr
5
- class Call
6
- include HTTParty
7
- base_uri "https://twilix.exotel.in/v1/Accounts"
8
- default_timeout 10
9
-
10
- def initialize; end
11
-
12
- #TODO check if this is a good decision to provide a wrapper.
13
- def self.shoot(params={})
14
- self.new.shoot(params)
15
- end
16
-
17
- def self.connect_to_flow(params={})
18
- self.new.connect_to_flow(params)
19
- end
20
-
21
- def self.connect_to_agent(params={})
22
- self.new.connect_to_agent(params)
23
- end
24
-
25
- def self.details(params={})
26
- self.new.details(params)
27
- end
28
-
29
- def shoot(params={})
30
- if valid?(params, {:type => 'flow'})
31
- params = transfrom_params(params, {:type => 'flow'})
32
- make_call(params)
33
- end
34
- end
35
-
36
- def connect_to_flow(params={})
37
- if valid?(params, {:type => 'flow'})
38
- params = transfrom_params(params, {:type => 'flow'})
39
- make_call(params)
40
- end
41
- end
42
-
43
- def connect_to_agent(params={})
44
- if valid?(params, {:type => 'agent'})
45
- params = transfrom_params(params, {:type => 'agent'})
46
- make_call(params)
47
- end
48
- end
49
-
50
- def details(sid)
51
- response = self.class.get("/#{ExotelApi.exotel_sid}/Calls/#{sid}", :basic_auth => auth)
52
- handle_response(response)
53
- end
54
-
55
- protected
56
-
57
- def make_call(params)
58
- response = self.class.post(URI.escape("/#{ExotelApi.exotel_sid}/Calls/connect"), {:body => params, :basic_auth => auth })
59
- handle_response(response)
60
- end
61
-
62
- def valid?(params, options)
63
- mandatory_keys = [:from, :to, :caller_id, :call_type]
64
- mandatory_keys << :flow_id if options[:type] == 'flow'
65
-
66
- unless mandatory_keys.all?{|key| params.keys.include?(key)}
67
- raise ExotelApi::ParamsError, "Missing one or many required parameters."
68
- end
69
- valid_call_type?(params)
70
- return true
71
- end
72
-
73
- def valid_call_type?(params)
74
- raise ExotelApi::ParamsError, "Call Type is not valid" unless ['trans', 'promo'].include?(params[:call_type])
75
- end
76
-
77
- def auth
78
- {:username => ExotelApi.exotel_sid, :password => ExotelApi.exotel_token}
79
- end
80
-
81
- def flow_url(flow_id)
82
- "http://my.exotel.in/exoml/start/#{flow_id}"
83
- end
84
-
85
- def transfrom_params(params, options)
86
- if options[:type] == 'flow'
87
- #Construct flow url and delete flow_id.
88
- params = params.merge(:URL => flow_url(params[:flow_id]))
89
- params.delete(:flow_id)
90
- end
91
-
92
- #Keys are converted to camelcase
93
- params.inject({}){ |h, (key, value)| h[camelcase_key(key)] = value; h }
94
- end
95
-
96
- def camelcase_key(key)
97
- key.to_s.split('_').map(&:capitalize).join.to_sym #Input: call_type, Output: :CallType
98
- end
99
-
100
- def handle_response(response)
101
- case response.code.to_i
102
- when 200...300 then ExotelApi::Response.new(response)
103
- when 401 then raise ExotelApi::AuthenticationError, "#{response.body} Verify your sid and token."
104
- when 403 then ExotelApi::Response.new(response)
105
- else
106
- raise ExotelApi::UnexpectedError, response.body
107
- end
108
- end
109
- end
110
- end
111
- end