exotel 0.1.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,4 +4,4 @@ rvm:
4
4
  - 1.8.7
5
5
  - 1.9.2
6
6
  - 1.9.3
7
- - ree
7
+ #- ree
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- exotel (0.1)
4
+ exotel (0.2)
5
5
  httparty (>= 0.9.0)
6
6
 
7
7
  GEM
@@ -9,11 +9,14 @@ GEM
9
9
  specs:
10
10
  addressable (2.3.2)
11
11
  crack (0.3.1)
12
- httparty (0.9.0)
12
+ httparty (0.10.2)
13
13
  multi_json (~> 1.0)
14
- multi_xml
14
+ multi_xml (>= 0.5.2)
15
+ metaclass (0.0.1)
16
+ mocha (0.13.0)
17
+ metaclass (~> 0.0.1)
15
18
  multi_json (1.5.0)
16
- multi_xml (0.5.1)
19
+ multi_xml (0.5.2)
17
20
  webmock (1.9.0)
18
21
  addressable (>= 2.2.7)
19
22
  crack (>= 0.1.7)
@@ -24,4 +27,5 @@ PLATFORMS
24
27
  DEPENDENCIES
25
28
  bundler (>= 1.0.0)
26
29
  exotel!
30
+ mocha
27
31
  webmock
data/README.md CHANGED
@@ -1,30 +1,55 @@
1
1
  # exotel - A ruby wrapper for the Exotel API
2
- [![Build Status](https://travis-ci.org/vijendra/exotel.png?branch=master)](https://travis-ci.org/vijendra/exotel)
3
- ======
4
- # Installation
2
+ [![Build Status](https://travis-ci.org/vijendra/exotel.png?branch=master)](https://travis-ci.org/vijendra/exotel) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/vijendra/exotel)
3
+
4
+ ## Installation
5
5
  gem install exotel
6
6
 
7
- ======
8
- # Usage
9
- # Configure authentication keys
7
+ ## Usage
8
+ **Configure authentication keys**
9
+
10
10
  Exotel.configure do |c|
11
11
  c.exotel_sid = "Your exotel sid"
12
12
  c.exotel_token = "Your exotel token"
13
13
  end
14
14
 
15
- #To send SMS
16
- sms = Exotel::Sms.new
17
- response = sms.send(from: 'FROM_NUMBER', to: 'TO_NUMBER', body: 'MESSAGE BODY')
18
- sms_id = response.sid
15
+ **To send SMS**
16
+
17
+ response = Exotel::Sms.send(:from => 'FROM_NUMBER', :to => 'TO_NUMBER', :body => 'MESSAGE BODY')
18
+ sms_id = response.sid #sid is used to find the delivery status and other details of the message in future.
19
+
20
+ **To get the details/check the delivery status of a sms**
21
+
22
+ sms = Exotel::Sms.details(sms_id)
23
+ status = response.status
24
+ date_sent = response.date_sent
19
25
 
20
- #To get the details
21
- sms = Exotel::Sms.new
22
- response = sms.details(sms_id)
26
+ **To connect a customer to an agent in your company**
27
+
28
+ response = Exotel::Call.connect_to_agent(:to => 'Your Exotel Virtual Number', :from => 'The customer phone number that will be called', :caller_id => 'Your Exotel Number', :call_type => 'trans or promo')
29
+ call_id = response.sid #sid is used to find the details of the call. Ex: Total price of teh call.
30
+
31
+ For complete details about the parameters refer exotel api doc.
32
+ http://goo.gl/nx4Tf
33
+
34
+ **To connect a customer to an existing App/Flow**
35
+
36
+ response = Exotel::Call.connect_to_agent(:to => 'Your Exotel Virtual Number', :from => 'The customer phone number that will be called', :caller_id => 'Your Exotel Number', :call_type => 'trans or promo'. :flow_id => 'App/Flow id to be connected')
37
+ call_id = response.sid #sid is used to find the details of the call. Ex: Total price of teh call.
38
+
39
+ For complete details about the parameters refer exotel api doc.
40
+ http://goo.gl/0zxMx
41
+
42
+ **To get the details of a call**
43
+
44
+ sms = Exotel::Call.details(call_id)
45
+ price = response.price
23
46
  status = response.status
24
- ======
25
- # Run tests
47
+ duration = response.duration
48
+
49
+ **DND numbers**
50
+
51
+ response.status = 'DND'
52
+ response.message will be some thing like 'Call to ****** cannot be made because of TRAI NDNC regulations'
53
+
54
+ ## Run tests
26
55
  rake test
27
-
28
- ======
29
- # TODO
30
- Cover exotel call
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.add_development_dependency "bundler", ">= 1.0.0"
18
18
  s.add_development_dependency "webmock"
19
+ s.add_development_dependency "mocha"
19
20
  if RUBY_VERSION == "1.8.7"
20
21
  s.add_development_dependency 'minitest', '3.2.0'
21
22
  end
@@ -2,6 +2,7 @@ require 'httparty'
2
2
  require 'exotel/version'
3
3
  require 'exotel/config'
4
4
  require 'exotel/sms'
5
+ require 'exotel/call'
5
6
  require 'exotel/response'
6
7
 
7
8
  module Exotel
@@ -0,0 +1,100 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'httparty'
3
+ module Exotel
4
+ class Call
5
+ include HTTParty
6
+ base_uri "https://twilix.exotel.in/v1/Accounts"
7
+
8
+ def initialize; end
9
+
10
+ #TODO check if this is a good decision to provide a wrapper.
11
+ def self.connect_to_flow(params={})
12
+ self.new.connect_to_flow(params)
13
+ end
14
+
15
+ def self.connect_to_agent(params={})
16
+ self.new.connect_to_agent(params)
17
+ end
18
+
19
+ def self.details(params={})
20
+ self.new.details(params)
21
+ end
22
+
23
+ def connect_to_flow(params={})
24
+ if valid?(params, {:type => 'flow'})
25
+ params = transfrom_params(params, {:type => 'flow'})
26
+ make_call(params)
27
+ end
28
+ end
29
+
30
+ def connect_to_agent(params={})
31
+ if valid?(params, {:type => 'agent'})
32
+ params = transfrom_params(params, {:type => 'agent'})
33
+ make_call(params)
34
+ end
35
+ end
36
+
37
+ def details(sid)
38
+ response = self.class.get("/#{Exotel.exotel_sid}/Calls/#{sid}", :basic_auth => auth)
39
+ handle_response(response)
40
+ end
41
+
42
+ protected
43
+
44
+ def make_call(params)
45
+ response = self.class.post(URI.escape("/#{Exotel.exotel_sid}/Calls/connect"), {:body => params, :basic_auth => auth })
46
+ handle_response(response)
47
+ end
48
+
49
+ def valid?(params, options)
50
+ mandatory_keys = [:from, :to, :caller_id, :call_type]
51
+ mandatory_keys << :flow_id if options[:type] == 'flow'
52
+
53
+ unless mandatory_keys.all?{|key| params.keys.include?(key)}
54
+ raise Exotel::ParamsError, "Missing one or many required parameters."
55
+ end
56
+ valid_call_type?(params)
57
+ return true
58
+ end
59
+
60
+ def valid_call_type?(params)
61
+ raise Exotel::ParamsError, "Call Type is not valid" unless ['trans', 'promo'].include?(params[:call_type])
62
+ end
63
+
64
+ def auth
65
+ {:username => Exotel.exotel_sid, :password => Exotel.exotel_token}
66
+ end
67
+
68
+ def flow_url(flow_id)
69
+ "http://my.exotel.in/exoml/start/#{flow_id}"
70
+ end
71
+
72
+ def transfrom_params(params, options)
73
+ if options[:type] == 'flow'
74
+ #Construct flow url and delete flow_id.
75
+ params = params.merge(:URL => flow_url(params[:flow_id]))
76
+ params.delete(:flow_id)
77
+ end
78
+
79
+ #Keys are converted to camelcase
80
+ params.inject({}){ |h, (key, value)| h[camelcase_key(key)] = value; h }
81
+ end
82
+
83
+ def camelcase_key(key)
84
+ key.to_s.split('_').map(&:capitalize).join.to_sym #Input: call_type, Output: :CallType
85
+ end
86
+
87
+ def handle_response(response)
88
+ case response.code.to_i
89
+ when 200...300 then Exotel::Response.new(response)
90
+ when 401 then raise Exotel::AuthenticationError, "#{response.body} Verify your sid and token."
91
+ when 403 then Exotel::Response.new(response)
92
+ else
93
+ raise Exotel::UnexpectedError, response.body
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+
@@ -10,6 +10,8 @@ module Exotel
10
10
  class AuthenticationError < StandardError; end
11
11
 
12
12
  class UnexpectedError < StandardError; end
13
+
14
+ class ParamsError < StandardError; end
13
15
  end
14
16
 
15
17
 
@@ -1,21 +1,45 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  module Exotel
3
3
  class Response
4
- attr_accessor :sid, :date_created, :date_updated, :status, :date_sent, :to, :from, :body
5
4
 
6
5
  def initialize(response)
7
6
  #To handle unexpected parsing from httparty
8
7
  response = MultiXml.parse(response) unless response.is_a?(Hash)
9
-
10
- sms = response['TwilioResponse']['SMSMessage']
11
- @sid = sms['Sid']
12
- @date_created = sms['DateCreated']
13
- @date_updated = sms['DateUpdated']
14
- @status = sms['Status']
15
- @date_sent = sms['DateSent']
16
- @to = sms['To']
17
- @from = sms['From']
18
- @body = sms['Body']
8
+ response_base = response['TwilioResponse']
9
+ unless response_base.include?('RestException')
10
+ set_response_data(response_base)
11
+ else
12
+ set_response_error(response_base)
13
+ end
14
+ end
15
+
16
+ def set_response_data(response_base)
17
+ (response_base['Call'] or response_base['SMSMessage']).each do |key, value|
18
+ set_variable(key, value)
19
+ end
20
+ end
21
+
22
+ def set_response_error(response_base)
23
+ response_base['RestException'].each do |key, value|
24
+ set_variable(key, value)
25
+ instance_variable_set('@status', 'DND') #Override
26
+ end
27
+ end
28
+
29
+ def set_variable(key, value)
30
+ attr_name = underscore_format(key)
31
+ self.class.send(:attr_accessor, attr_name) #Set accessors dynamically
32
+ instance_variable_set("@#{attr_name}", value)
33
+ end
34
+
35
+ protected
36
+
37
+ #TODO: CamelCase to underscore: check if we have to add this to string class.
38
+ def underscore_format(string)
39
+ string.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
40
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
41
+ tr("-", "_").
42
+ downcase
19
43
  end
20
44
  end
21
45
  end
@@ -5,14 +5,22 @@ module Exotel
5
5
  include HTTParty
6
6
  base_uri "https://twilix.exotel.in/v1/Accounts"
7
7
 
8
- def initialize
8
+ def initialize; end
9
+
10
+ def self.send(params={})
11
+ self.new.send(params)
12
+ end
13
+
14
+ def self.details(params={})
15
+ self.new.details(params)
9
16
  end
10
17
 
11
18
  def send(params={})
12
- fields = {:From => params[:from], :To => params[:to], :Body => params[:body]}
13
- options = {:body => fields, :basic_auth => auth }
14
- response = self.class.post("/#{Exotel.exotel_sid}/Sms/send", options)
15
- handle_response(response)
19
+ if valid?(params)
20
+ params = transfrom_params(params)
21
+ response = self.class.post("/#{Exotel.exotel_sid}/Sms/send", {:body => params, :basic_auth => auth })
22
+ handle_response(response)
23
+ end
16
24
  end
17
25
 
18
26
  def details(sid)
@@ -22,6 +30,19 @@ module Exotel
22
30
 
23
31
  protected
24
32
 
33
+ def valid?(params)
34
+ unless [:from, :to, :body].all?{|key| params.keys.include?(key)}
35
+ raise Exotel::ParamsError, "Missing one or many required parameters."
36
+ else
37
+ true
38
+ end
39
+ end
40
+
41
+ def transfrom_params(params)
42
+ #Keys are converted to camelcase
43
+ params.inject({}){ |h, (key, value)| h[key.to_s.capitalize.to_sym] = value; h }
44
+ end
45
+
25
46
  def auth
26
47
  {:username => Exotel.exotel_sid, :password => Exotel.exotel_token}
27
48
  end
@@ -1,3 +1,3 @@
1
1
  module Exotel
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2'
3
3
  end
@@ -0,0 +1,105 @@
1
+ require 'helper'
2
+
3
+ describe Exotel::Call do
4
+ it 'should have a version' do
5
+ Exotel::Call.must_include HTTParty
6
+ end
7
+
8
+ it 'should have the correct base_uri' do
9
+ Exotel::Call.base_uri.must_equal "https://twilix.exotel.in/v1/Accounts"
10
+ end
11
+
12
+ describe '.connect_to_flow' do
13
+ before do
14
+ @params = {:from => '01234', :to => '04321', :caller_id => '04321', :call_type => 'trans', :flow_id => '3432'}
15
+ end
16
+
17
+ it "should pass the call to an object" do
18
+ Exotel::Call.any_instance.expects(:connect_to_flow)
19
+ Exotel::Call.connect_to_flow
20
+ end
21
+
22
+ describe 'success' do
23
+ before do
24
+ base_path = File.expand_path(File.join(File.dirname(__FILE__), '..'))
25
+ stub_request(:post, "https://test_sid:test_token@twilix.exotel.in/v1/Accounts/#{Exotel.exotel_sid}/Calls/connect").
26
+ with(:body => {:From => '01234', :To => '04321', :CallerId => '04321', :CallType => 'trans', :Url => 'http://my.exotel.in/exoml/start/3432' }).
27
+ to_return(:status => 200, :body => File.new(base_path + '/fixtures/call.xml'))
28
+ end
29
+
30
+ it "should return the response object" do
31
+ call = Exotel::Call.new
32
+ response = call.connect_to_flow(@params)
33
+ response.class.must_equal Exotel::Response
34
+ end
35
+
36
+ it "should set the response object values" do
37
+ call = Exotel::Call.new
38
+ response = call.connect_to_flow(@params)
39
+ response.sid.must_equal 'CAe1644a7eed5088b159577c5802d8be38'
40
+ response.date_created.must_equal 'Tue, 10 Aug 2010 08:02:17'
41
+ response.date_updated.must_equal 'Tue, 10 Aug 2010 08:02:47'
42
+ response.start_time.must_equal 'Tue, 10 Aug 2010 08:02:31 +0000'
43
+ response.end_time.must_equal 'Tue, 10 Aug 2010 08:02:47 +0000'
44
+ response.status.must_equal 'completed'
45
+ response.from.must_equal '01234'
46
+ response.to.must_equal '04321'
47
+ end
48
+ end
49
+
50
+ describe 'autentication failed' do
51
+ before do
52
+ base_path = File.expand_path(File.join(File.dirname(__FILE__), '..'))
53
+ stub_request(:post, "https://test_sid:test_token@twilix.exotel.in/v1/Accounts/#{Exotel.exotel_sid}/Calls/connect").
54
+ with(:body => {:From => '01234', :To => '04321', :CallerId => '04321', :CallType => 'trans', :Url => 'http://my.exotel.in/exoml/start/3432'}).
55
+ to_return(:status => 401, :body => 'Authentication is required to view this page.')
56
+ end
57
+
58
+ it "should raise the authentication error" do
59
+ call = Exotel::Call.new
60
+ proc{call.connect_to_flow(@params)}.
61
+ must_raise Exotel::AuthenticationError
62
+ end
63
+ end
64
+
65
+ describe 'missing parameters' do
66
+ before do
67
+ @call = Exotel::Call.new
68
+ end
69
+
70
+ [:from, :to, :caller_id, :call_type, :flow_id].each do |param|
71
+ it "should raise the missing params error when #{param} is missing" do
72
+ @params.delete(param)
73
+ proc{@call.connect_to_flow(@params)}.must_raise Exotel::ParamsError
74
+ end
75
+ end
76
+
77
+ it "should raise the params exception for invalid :call_type" do
78
+ @params[:call_type] = 'invalid'
79
+ proc{@call.connect_to_flow(@params)}.must_raise Exotel::ParamsError
80
+ end
81
+ end
82
+ end
83
+
84
+ describe '#details' do
85
+ before do
86
+ base_path = File.expand_path(File.join(File.dirname(__FILE__), '..'))
87
+ stub_request(:get, "https://test_sid:test_token@twilix.exotel.in/v1/Accounts/#{Exotel.exotel_sid}/Calls/CAe1644a7eed5088b159577c5802d8be38").
88
+ to_return(:status => 200, :body => File.new(base_path + '/fixtures/call.xml'))
89
+ end
90
+
91
+ it "should return the response object" do
92
+ response = Exotel::Call.details('CAe1644a7eed5088b159577c5802d8be38')
93
+ response.class.must_equal Exotel::Response
94
+ end
95
+
96
+ it "should set the response object values" do
97
+ response = Exotel::Call.details('CAe1644a7eed5088b159577c5802d8be38')
98
+ response.sid.must_equal 'CAe1644a7eed5088b159577c5802d8be38'
99
+ response.status.must_equal 'completed'
100
+ response.price.must_equal '2.3'
101
+ end
102
+ end
103
+
104
+ end
105
+
@@ -23,7 +23,7 @@ describe Exotel::Sms do
23
23
  before do
24
24
  base_path = File.expand_path(File.join(File.dirname(__FILE__), '..'))
25
25
  stub_request(:post, "https://test_sid:test_token@twilix.exotel.in/v1/Accounts/#{Exotel.exotel_sid}/Sms/send").
26
- with(:body => "From=1234&To=4321&Body=Test%20sms").
26
+ with(:body => {:From => '1234', :To => '4321', :Body => 'Test sms'}).
27
27
  to_return(:status => 200, :body => File.new(base_path + '/fixtures/sms.xml'))
28
28
  end
29
29
 
@@ -51,16 +51,36 @@ describe Exotel::Sms do
51
51
  before do
52
52
  base_path = File.expand_path(File.join(File.dirname(__FILE__), '..'))
53
53
  stub_request(:post, "https://test_sid:test_token@twilix.exotel.in/v1/Accounts/#{Exotel.exotel_sid}/Sms/send").
54
- with(:body => "From=1234&To=4321&Body=Test%20sms").
54
+ with(:body => {:From => '1234', :To => '4321', :Body => 'Test sms'}).
55
55
  to_return(:status => 401, :body => 'Authentication is required to view this page.')
56
56
  end
57
57
 
58
- it "should return the response object" do
58
+ it "should raise the authentication error" do
59
59
  sms = Exotel::Sms.new
60
60
  proc{sms.send(:from => '1234', :to => '4321', :body => 'Test sms')}.
61
61
  must_raise Exotel::AuthenticationError
62
62
  end
63
63
  end
64
+
65
+ describe 'missing parameters' do
66
+ it "should raise the missing params error when :from is missing" do
67
+ sms = Exotel::Sms.new
68
+ proc{sms.send(:to => '4321', :body => 'Test sms')}.
69
+ must_raise Exotel::ParamsError
70
+ end
71
+
72
+ it "should raise the missing params error when :to is missing" do
73
+ sms = Exotel::Sms.new
74
+ proc{sms.send(:from => '1234', :body => 'Test sms')}.
75
+ must_raise Exotel::ParamsError
76
+ end
77
+
78
+ it "should raise the missing params error when :body is missing" do
79
+ sms = Exotel::Sms.new
80
+ proc{sms.send(:to => '4321', :from => '1234')}.
81
+ must_raise Exotel::ParamsError
82
+ end
83
+ end
64
84
  end
65
85
 
66
86
  describe '#details' do
@@ -98,7 +118,7 @@ describe Exotel::Sms do
98
118
  to_return(:status => 401, :body => 'Authentication is required to view this page.')
99
119
  end
100
120
 
101
- it "should return the response object" do
121
+ it "should raise the authentication error" do
102
122
  sms = Exotel::Sms.new
103
123
  proc{sms.details('SM872fb94e3b358913777cdb313f25b46f')}.
104
124
  must_raise Exotel::AuthenticationError
@@ -0,0 +1,28 @@
1
+ <TwilioResponse>
2
+ <Call>
3
+ <Sid>CAe1644a7eed5088b159577c5802d8be38</Sid>
4
+ <DateCreated>Tue, 10 Aug 2010 08:02:17</DateCreated>
5
+ <DateUpdated>Tue, 10 Aug 2010 08:02:47</DateUpdated>
6
+ <ParentCallSid/>
7
+ <AccountSid>AC5ea872f6da5a21de157d80997a64bd33</AccountSid>
8
+ <To>04321</To>
9
+ <From>01234</From>
10
+ <PhoneNumberSid></PhoneNumberSid>
11
+ <Status>completed</Status>
12
+ <StartTime>Tue, 10 Aug 2010 08:02:31 +0000</StartTime>
13
+ <EndTime>Tue, 10 Aug 2010 08:02:47 +0000</EndTime>
14
+ <Duration>16</Duration>
15
+ <Price>2.3</Price>
16
+ <Flags>
17
+ <Flag>outbound-api</Flag>
18
+ </Flags>
19
+ <ApiVersion>2008-08-01</ApiVersion>
20
+ <ForwardedFrom/>
21
+ <CallerName/>
22
+ <Uri>/2010-04-01/Accounts/AC5ea872f6da5a21de157d80997a64bd33/Calls/CAe1644a7eed5088b159577c5802d8be38</Uri>
23
+ <SubresourceUris>
24
+ <Notifications>/2010-04-01/Accounts/AC5ea872f6da5a21de157d80997a64bd33/Calls/CAe1644a7eed5088b159577c5802d8be38/Notifications</Notifications>
25
+ <Recordings>/2010-04-01/Accounts/AC5ea872f6da5a21de157d80997a64bd33/Calls/CAe1644a7eed5088b159577c5802d8be38/Recordings</Recordings>
26
+ </SubresourceUris>
27
+ </Call>
28
+ </TwilioResponse>
@@ -0,0 +1,6 @@
1
+ <TwilioResponse>
2
+ <RestException>
3
+ <Status>403</Status>
4
+ <Message>Call to [01234] cannot be made because of TRAI NDNC regulations</Message>
5
+ </RestException>
6
+ </TwilioResponse>
@@ -1,6 +1,7 @@
1
1
  require 'minitest/spec'
2
2
  require 'minitest/autorun'
3
3
  require 'webmock/minitest'
4
+ require "mocha/setup"
4
5
  require 'exotel'
5
6
 
6
7
  Exotel.configure do |c|
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: exotel
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: "0.2"
6
6
  platform: ruby
7
7
  authors:
8
8
  - Vijendra Rao
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-12-21 00:00:00 Z
13
+ date: 2013-02-23 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -35,16 +35,27 @@ dependencies:
35
35
  type: :development
36
36
  version_requirements: *id002
37
37
  - !ruby/object:Gem::Dependency
38
- name: httparty
38
+ name: mocha
39
39
  prerelease: false
40
40
  requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: httparty
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
41
52
  none: false
42
53
  requirements:
43
54
  - - ">="
44
55
  - !ruby/object:Gem::Version
45
56
  version: 0.9.0
46
57
  type: :runtime
47
- version_requirements: *id003
58
+ version_requirements: *id004
48
59
  description: Exotel api wrapper.
49
60
  email:
50
61
  - vijendrakarkala@gmail.com
@@ -63,12 +74,16 @@ files:
63
74
  - Rakefile
64
75
  - exotel.gemspec
65
76
  - lib/exotel.rb
77
+ - lib/exotel/call.rb
66
78
  - lib/exotel/config.rb
67
79
  - lib/exotel/response.rb
68
80
  - lib/exotel/sms.rb
69
81
  - lib/exotel/version.rb
82
+ - test/exotel/call_test.rb
70
83
  - test/exotel/exotel_test.rb
71
84
  - test/exotel/sms_test.rb
85
+ - test/fixtures/call.xml
86
+ - test/fixtures/call_dnd.xml
72
87
  - test/fixtures/sms.xml
73
88
  - test/helper.rb
74
89
  homepage: https://github.com/vijendra/exotel