asterisk-ari 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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