asterisk-ari 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +20 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +8 -0
- data/asterisk-ari.gemspec +28 -0
- data/lib/ari.rb +2 -0
- data/lib/ari/client.rb +1441 -0
- data/lib/ari/errors.rb +38 -0
- data/lib/ari/http_services.rb +87 -0
- data/lib/ari/json.rb +23 -0
- data/lib/ari/response.rb +18 -0
- data/lib/ari/version.rb +3 -0
- data/spec/ari/client_spec.rb +158 -0
- data/spec/ari/errors_spec.rb +25 -0
- data/spec/ari/http_service_spec.rb +18 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_applications_list_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_asterisk_get_info_returns_data.yml +39 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_bridges_create_returns_data.yml +147 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_bridges_list_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_channels_list_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_device_states_list_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_endpoints_list_by_tech_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_endpoints_list_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_endpoints_send_message_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_global_var_asterisk_set_global_var_and_asterisk_get_global_var_returns_data.yml +73 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_recordings_list_stored_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_sounds_get_returns_data.yml +38 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_sounds_list_with_params_returns_data.yml +395 -0
- data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_sounds_list_without_params_returns_data.yml +395 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/config.yml +4 -0
- data/spec/support/config_loader.rb +2 -0
- data/spec/support/vcr.rb +14 -0
- metadata +164 -0
data/lib/ari/errors.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module ARI
|
2
|
+
|
3
|
+
class ARIError < StandardError; end
|
4
|
+
|
5
|
+
class Error < ARIError
|
6
|
+
attr_accessor :error_info, :response_body
|
7
|
+
|
8
|
+
def initialize(response_body = "", error_info = nil)
|
9
|
+
if response_body && response_body.is_a?(String)
|
10
|
+
@response_body = response_body.strip
|
11
|
+
else
|
12
|
+
@response_body = ''
|
13
|
+
end
|
14
|
+
if error_info.nil?
|
15
|
+
begin
|
16
|
+
error_info = ARI::JSON.load(response_body.to_s)
|
17
|
+
rescue
|
18
|
+
error_info ||= {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@error_info = error_info
|
22
|
+
message = @response_body
|
23
|
+
super(message)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# handle 5xx response
|
28
|
+
class ServerError < Error
|
29
|
+
def initialize(response_body, error_info)
|
30
|
+
@response_body = response_body
|
31
|
+
@error_info = error_info
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# handle 4xx response
|
36
|
+
class APIError < Error; end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "ari/json"
|
2
|
+
require "ari/response"
|
3
|
+
require "cgi"
|
4
|
+
|
5
|
+
module ARI
|
6
|
+
module HTTPService
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
def self.server(options = {})
|
11
|
+
options[:host]
|
12
|
+
end
|
13
|
+
end# end class_eval
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module NetHTTPService
|
18
|
+
require "net/http" unless defined?(Net::HTTP)
|
19
|
+
require "net/https"
|
20
|
+
|
21
|
+
METHODS = {
|
22
|
+
:get => Net::HTTP::Get,
|
23
|
+
:post => Net::HTTP::Post,
|
24
|
+
:put => Net::HTTP::Put,
|
25
|
+
:delete => Net::HTTP::Delete
|
26
|
+
}
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.class_eval do
|
30
|
+
|
31
|
+
include ARI::HTTPService
|
32
|
+
|
33
|
+
def self.make_request(path, args, verb, options = {})
|
34
|
+
args.merge!({:method => verb})
|
35
|
+
|
36
|
+
http = create_http(server(options), options)
|
37
|
+
http.use_ssl = true if options[:port].to_i == 443
|
38
|
+
|
39
|
+
result = http.start do |http|
|
40
|
+
request = case verb.to_sym
|
41
|
+
when :get
|
42
|
+
METHODS[verb.to_sym].new "#{path}?#{encode_params(args)}"
|
43
|
+
else
|
44
|
+
request = METHODS[verb.to_sym].new path
|
45
|
+
request.set_form_data args
|
46
|
+
request
|
47
|
+
end
|
48
|
+
# basic auth
|
49
|
+
if options[:username] && options[:password]
|
50
|
+
request.basic_auth(options[:username], options[:password])
|
51
|
+
end
|
52
|
+
response, body = http.request(request)
|
53
|
+
ARI::Response.new(response.code.to_i, response.body, response)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def self.encode_params(param_hash)
|
60
|
+
((param_hash || {}).collect do |key_and_value|
|
61
|
+
key_and_value[1] = ARI::JSON.dump(key_and_value[1]) if key_and_value[1].class != String
|
62
|
+
"#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
|
63
|
+
end).join("&")
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.create_http(server, options)
|
67
|
+
if options[:proxy]
|
68
|
+
proxy = URI.parse(options[:proxy])
|
69
|
+
http = Net::HTTP.new \
|
70
|
+
server, options[:port],
|
71
|
+
proxy.host, proxy.port,
|
72
|
+
proxy.user, proxy.password
|
73
|
+
else
|
74
|
+
http = Net::HTTP.new server, options[:port]
|
75
|
+
end
|
76
|
+
if options[:timeout]
|
77
|
+
http.open_timeout = options[:timeout]
|
78
|
+
http.read_timeout = options[:timeout]
|
79
|
+
end
|
80
|
+
http
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
data/lib/ari/json.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
|
3
|
+
module ARI
|
4
|
+
module JSON
|
5
|
+
|
6
|
+
def self.dump(*args)
|
7
|
+
if MultiJson.respond_to?(:dump)
|
8
|
+
MultiJson.dump(*args)
|
9
|
+
else
|
10
|
+
MultiJson.encode(*args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load(*args)
|
15
|
+
if MultiJson.respond_to?(:load)
|
16
|
+
MultiJson.load(*args)
|
17
|
+
else
|
18
|
+
MultiJson.decode(*args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/ari/response.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module ARI
|
2
|
+
# @!attribute [r] status
|
3
|
+
# @return [Integer] http status
|
4
|
+
# @!attribute [r] body
|
5
|
+
# @return [String] response body
|
6
|
+
# @!attribute [r] headers
|
7
|
+
# @return [String] response headers
|
8
|
+
class Response
|
9
|
+
|
10
|
+
def initialize(status, body, headers)
|
11
|
+
@status = status
|
12
|
+
@body = body
|
13
|
+
@headers = headers
|
14
|
+
end
|
15
|
+
attr_reader :status, :body, :headers
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/ari/version.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ARI::Client do
|
4
|
+
before(:each) do
|
5
|
+
@client ||= ARI::Client.new({
|
6
|
+
:host => SPEC_CONF["host"],
|
7
|
+
:port => SPEC_CONF["port"],
|
8
|
+
:username => SPEC_CONF["username"],
|
9
|
+
:password => SPEC_CONF["password"]
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
it "has an attr_reader for host" do
|
14
|
+
@client.host.should == SPEC_CONF["host"]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has an attr_reader for port" do
|
18
|
+
@client.port.should == SPEC_CONF["port"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "has an attr_reader for username" do
|
22
|
+
@client.username.should == SPEC_CONF["username"]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "has an attr_reader for password" do
|
26
|
+
@client.password.should == SPEC_CONF["password"]
|
27
|
+
end
|
28
|
+
|
29
|
+
context "api request", :vcr do
|
30
|
+
describe "#asterisk_get_info" do
|
31
|
+
it "returns data" do
|
32
|
+
result = @client.asterisk_get_info
|
33
|
+
result["build"].nil?.should == false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
context "global_var" do
|
37
|
+
describe "#asterisk_set_global_var and #asterisk_get_global_var" do
|
38
|
+
it "returns data" do
|
39
|
+
key = "FOO"
|
40
|
+
value = "BAR"
|
41
|
+
result = @client.asterisk_set_global_var({:variable => key, :value => value})
|
42
|
+
result.should == ""
|
43
|
+
result = @client.asterisk_get_global_var({:variable => key})
|
44
|
+
result["value"].should == value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#bridges_list" do
|
50
|
+
it "returns data" do
|
51
|
+
result = @client.bridges_list
|
52
|
+
result.is_a?(Array).should == true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#bridges_create" do
|
57
|
+
it "returns data" do
|
58
|
+
bridge_id = "1409571774"
|
59
|
+
bridge_name = "bridge_name"
|
60
|
+
bridge_type = "mixing"
|
61
|
+
result = @client.bridges_create({:type => "mixing", :bridgeId => bridge_id, :name => bridge_name})
|
62
|
+
result["bridge_type"].should == bridge_type
|
63
|
+
result["id"].should == bridge_id
|
64
|
+
result["name"].should == bridge_name
|
65
|
+
|
66
|
+
new_bridge_type = "holding"
|
67
|
+
result = @client.bridges_create_or_update_with_id(bridge_id, {:type => new_bridge_type})
|
68
|
+
result["bridge_type"].should == new_bridge_type
|
69
|
+
result["id"].should == bridge_id
|
70
|
+
# result["name"].should == bridge_name
|
71
|
+
|
72
|
+
result = @client.bridges_get(bridge_id)
|
73
|
+
result["bridge_type"].should == new_bridge_type
|
74
|
+
result["id"].should == bridge_id
|
75
|
+
# result["name"].should == bridge_name
|
76
|
+
|
77
|
+
result = @client.bridges_destroy(bridge_id)
|
78
|
+
result.should == ""
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#channels_list" do
|
83
|
+
it "returns data" do
|
84
|
+
result = @client.channels_list
|
85
|
+
result.is_a?(Array).should == true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#endpoints_list" do
|
90
|
+
it "returns data" do
|
91
|
+
result = @client.endpoints_list
|
92
|
+
result.is_a?(Array).should == true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#endpoints_send_message" do
|
97
|
+
it "returns data" do
|
98
|
+
result = @client.endpoints_send_message({:to => "SIP", :from => "IAX2", :body => "body"})
|
99
|
+
result.should == ""
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#endpoints_list_by_tech" do
|
104
|
+
it "returns data" do
|
105
|
+
result = @client.endpoints_list_by_tech("SIP")
|
106
|
+
result.is_a?(Array).should == true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#recordings_list_stored" do
|
111
|
+
it "returns data" do
|
112
|
+
result = @client.recordings_list_stored
|
113
|
+
result.is_a?(Array).should == true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#sounds_list" do
|
118
|
+
context "without params" do
|
119
|
+
it "returns data" do
|
120
|
+
result = @client.sounds_list
|
121
|
+
result.is_a?(Array).should == true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
context "with params" do
|
125
|
+
it "returns data" do
|
126
|
+
result = @client.sounds_list({:lang => "en"})
|
127
|
+
result.is_a?(Array).should == true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#sounds_get" do
|
133
|
+
it "returns data" do
|
134
|
+
id = "vm-torerecord"
|
135
|
+
result = @client.sounds_get(id)
|
136
|
+
result["id"].should == id
|
137
|
+
result["text"].nil?.should == false
|
138
|
+
result["formats"].nil?.should == false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "#applications_list" do
|
143
|
+
it "returns data" do
|
144
|
+
result = @client.applications_list
|
145
|
+
result.is_a?(Array).should == true
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#device_states_list" do
|
150
|
+
it "returns data" do
|
151
|
+
result = @client.device_states_list
|
152
|
+
result.is_a?(Array).should == true
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ARI::Error do
|
4
|
+
it "is a ARI::ARIError" do
|
5
|
+
ARI::Error.new(nil, nil).should be_a(ARI::ARIError)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ARI::ARIError do
|
10
|
+
it "is a StandardError" do
|
11
|
+
ARI::ARIError.new.should be_a(StandardError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ARI::APIError do
|
16
|
+
it "is a ARI::APIError" do
|
17
|
+
ARI::APIError.new({}).should be_a(ARI::APIError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ARI::ServerError do
|
22
|
+
it "is a ARI::Error" do
|
23
|
+
ARI::ServerError.new(nil, nil).should be_a(ARI::ServerError)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class FakeHTTPService
|
4
|
+
include ARI::HTTPService
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ARI::HTTPService do
|
8
|
+
|
9
|
+
describe "common methods" do
|
10
|
+
describe "server" do
|
11
|
+
it "should return the host" do
|
12
|
+
FakeHTTPService.server(:host => SPEC_CONF["host"]).should == SPEC_CONF["host"]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://asterisk:asterisk@127.0.0.1:8088/ari/applications?method=get
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- Asterisk/12.5.0
|
23
|
+
Date:
|
24
|
+
- Mon, 01 Sep 2014 13:36:13 GMT
|
25
|
+
Connection:
|
26
|
+
- close
|
27
|
+
Cache-Control:
|
28
|
+
- no-cache, no-store
|
29
|
+
Content-Type:
|
30
|
+
- application/json
|
31
|
+
Content-Length:
|
32
|
+
- '2'
|
33
|
+
body:
|
34
|
+
encoding: UTF-8
|
35
|
+
string: "[]"
|
36
|
+
http_version:
|
37
|
+
recorded_at: Mon, 01 Sep 2014 13:36:13 GMT
|
38
|
+
recorded_with: VCR 2.9.2
|
@@ -0,0 +1,39 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://asterisk:asterisk@127.0.0.1:8088/ari/asterisk/info?method=get
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- Asterisk/12.5.0
|
23
|
+
Date:
|
24
|
+
- Mon, 01 Sep 2014 11:11:42 GMT
|
25
|
+
Connection:
|
26
|
+
- close
|
27
|
+
Cache-Control:
|
28
|
+
- no-cache, no-store
|
29
|
+
Content-Type:
|
30
|
+
- application/json
|
31
|
+
Content-Length:
|
32
|
+
- '419'
|
33
|
+
body:
|
34
|
+
encoding: UTF-8
|
35
|
+
string: '{"config":{"default_language":"en","name":"","setid":{"group":"","user":""}},"build":{"os":"Linux","kernel":"3.13.0-34-generic","machine":"x86_64","user":"tk","options":"LOADABLE_MODULES,
|
36
|
+
BUILD_NATIVE, OPTIONAL_API","date":"2014-09-01 10:40:07 UTC"},"system":{"entity_id":"08:00:27:51:53:a7","version":"12.5.0"},"status":{"startup_time":"2014-09-01T20:10:30.620+0900","last_reload_time":"2014-09-01T20:10:30.620+0900"}}'
|
37
|
+
http_version:
|
38
|
+
recorded_at: Mon, 01 Sep 2014 11:11:42 GMT
|
39
|
+
recorded_with: VCR 2.9.2
|