asterisk-ari 0.0.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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +20 -0
  4. data/Gemfile +13 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +38 -0
  7. data/Rakefile +8 -0
  8. data/asterisk-ari.gemspec +28 -0
  9. data/lib/ari.rb +2 -0
  10. data/lib/ari/client.rb +1441 -0
  11. data/lib/ari/errors.rb +38 -0
  12. data/lib/ari/http_services.rb +87 -0
  13. data/lib/ari/json.rb +23 -0
  14. data/lib/ari/response.rb +18 -0
  15. data/lib/ari/version.rb +3 -0
  16. data/spec/ari/client_spec.rb +158 -0
  17. data/spec/ari/errors_spec.rb +25 -0
  18. data/spec/ari/http_service_spec.rb +18 -0
  19. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_applications_list_returns_data.yml +38 -0
  20. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_asterisk_get_info_returns_data.yml +39 -0
  21. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_bridges_create_returns_data.yml +147 -0
  22. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_bridges_list_returns_data.yml +38 -0
  23. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_channels_list_returns_data.yml +38 -0
  24. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_device_states_list_returns_data.yml +38 -0
  25. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_endpoints_list_by_tech_returns_data.yml +38 -0
  26. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_endpoints_list_returns_data.yml +38 -0
  27. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_endpoints_send_message_returns_data.yml +38 -0
  28. 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
  29. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_recordings_list_stored_returns_data.yml +38 -0
  30. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_sounds_get_returns_data.yml +38 -0
  31. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_sounds_list_with_params_returns_data.yml +395 -0
  32. data/spec/fixtures/vcr_cassettes/ARI_Client/api_request_sounds_list_without_params_returns_data.yml +395 -0
  33. data/spec/spec_helper.rb +22 -0
  34. data/spec/support/config.yml +4 -0
  35. data/spec/support/config_loader.rb +2 -0
  36. data/spec/support/vcr.rb +14 -0
  37. metadata +164 -0
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module ARI
2
+ VERSION = "0.0.1"
3
+ end
@@ -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