nuntium_api 0.13 → 0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/nuntium/exception.rb +10 -0
  2. data/lib/nuntium.rb +243 -58
  3. metadata +6 -5
@@ -0,0 +1,10 @@
1
+ class Nuntium
2
+ class Exception < ::StandardError
3
+ attr_accessor :properties
4
+
5
+ def initialize(msg, properties = {})
6
+ super msg
7
+ @properties = properties
8
+ end
9
+ end
10
+ end
data/lib/nuntium.rb CHANGED
@@ -6,150 +6,256 @@
6
6
  #
7
7
  # === Example
8
8
  #
9
- # api = Nuntium.new 'service_url', 'account_name', 'application_name', 'application_password'
9
+ # require 'rubygems'
10
+ # require 'nuntium'
11
+ #
12
+ # api = Nuntium.new "service_url", "account_name", "application_name", "application_password"
13
+ #
14
+ # # Get all countries
15
+ # countries = api.countries
16
+ #
17
+ # # Get all carriers that belong to a specific country
18
+ # carriers = api.carriers 'ar'
19
+ #
20
+ # # Get all channels
21
+ # channels = api.channels
22
+ #
23
+ # # Create a channel
24
+ # api.create_channel {
25
+ # :name => "my_channel",
26
+ # :kind => "clickatell",
27
+ # :protocol => "sms",
28
+ # :direction =>"bidirectional",
29
+ # :enabled => true,
30
+ # :priority => 10,
31
+ # :configuration => {:password => "secret"}
32
+ # }
33
+ #
34
+ # message = {
35
+ # :from => "sms://1234",
36
+ # :to => "sms://5678",
37
+ # :subject => "Hi",
38
+ # :body => "Hello Nuntium!",
39
+ # }
40
+ #
41
+ # # Send an Application Originated message.
42
+ # # The response is of type HTTParty::Response
43
+ # response = api.send_ao message
44
+ #
45
+ # # Can also send many messages at once
46
+ # messages = [{:to => "sms://1", :body => 'One'}, {:to => "sms://2", :body => 'Two'}]
47
+ # response = api.send_ao messages
48
+ #
49
+ # # Simulate sending and get a list of candidate channels
50
+ # api.get_candidate_channels_for_ao message
51
+
10
52
  require 'rubygems'
11
- require 'httparty'
53
+ require 'net/http'
12
54
  require 'json'
55
+ require 'rest_client'
56
+ require 'cgi'
57
+ require File.expand_path('../nuntium/exception', __FILE__)
13
58
 
14
59
  # Provides access to the Nuntium Public API.
15
60
  class Nuntium
16
- include HTTParty
17
-
18
61
  # Creates an application-authenticated Nuntium api access.
19
62
  def initialize(url, account, application, password)
20
63
  @url = url
21
64
  @account = account
22
65
  @application = application
23
- @auth = {:username => "#{account}/#{application}", :password => password}
66
+ @options = {
67
+ :user => "#{account}/#{application}",
68
+ :password => password,
69
+ :headers => {:content_type => 'application/json'},
70
+ }
24
71
  end
25
72
 
26
- # Gets the list of countries known to Nuntium.
73
+ # Gets the list of countries known to Nuntium as an array of hashes.
74
+ #
75
+ # Raises Nuntium::Exception if something goes wrong.
27
76
  def countries
28
- self.class.get "#{@url}/api/countries.json"
77
+ get_json "/api/countries.json"
29
78
  end
30
79
 
31
- # Gets a country given its iso2 or iso3 code, or nil if a country with that iso does not exist.
80
+ # Gets a country as a hash given its iso2 or iso3 code, or nil if a country with that iso does not exist.
81
+ #
82
+ # Raises Nuntium::Exception if something goes wrong.
32
83
  def country(iso)
33
- c = self.class.get "#{@url}/api/countries/#{iso}.json"
34
- return nil if c.class <= String
35
- c
84
+ get_json "/api/countries/#{iso}.json"
36
85
  end
37
86
 
38
- # Gets the list of carriers known to Nuntium that belong to a country, given its
39
- # iso2 or iso3 code. Gets all carriers if no country is specified.
87
+ # Gets the list of carriers known to Nuntium that belong to a country as an array of hashes, given its
88
+ # iso2 or iso3 code. Gets all carriers as an array of hashes if no country is specified.
89
+ #
90
+ # Raises Nuntium::Exception if something goes wrong.
40
91
  def carriers(country_id = nil)
41
92
  if country_id
42
- self.class.get "#{@url}/api/carriers.json", :query => {:country_id => country_id}
93
+ get_json "/api/carriers.json?country_id=#{country_id}"
43
94
  else
44
- self.class.get "#{@url}/api/carriers.json"
95
+ get_json "/api/carriers.json"
45
96
  end
46
97
  end
47
98
 
48
- # Gets a carrier given its guid, or nil if a carrier with that guid does not exist.
99
+ # Gets a carrier as a hash given its guid, or nil if a carrier with that guid does not exist.
100
+ #
101
+ # Raises Nuntium::Exception if something goes wrong.
49
102
  def carrier(guid)
50
- c = self.class.get "#{@url}/api/carriers/#{guid}.json"
51
- return nil if c.class <= String
52
- c
103
+ get_json "/api/carriers/#{guid}.json"
53
104
  end
54
105
 
55
106
  # Returns the list of channels belonging to the application or that don't
56
- # belong to any application.
107
+ # belong to any application, as an array of hashes.
108
+ #
109
+ # Raises Nuntium::Exception if something goes wrong.
57
110
  def channels
58
- chans = self.class.get "#{@url}/api/channels.json", :basic_auth => @auth
59
- return nil if chans.class <= String
60
- chans.each do |channel|
61
- read_configuration channel
111
+ get "/api/channels.json" do |response, error|
112
+ raise Nuntium::Exception.new error.message if error
113
+
114
+ channels = JSON.parse response.body
115
+ channels.each { |channel| read_configuration channel }
116
+ channels
62
117
  end
63
118
  end
64
119
 
65
- # Returns a chnanel given its name, or nil if the channel doesn't exist
120
+ # Returns a channel given its name. Raises when the channel does not exist.
121
+ #
122
+ # Raises Nuntium::Exception if something goes wrong.
66
123
  def channel(name)
67
- response = self.class.get "#{@url}/api/channels/#{name}.json", :basic_auth => @auth
68
- return_channel response
124
+ get_channels "/api/channels/#{name}.json"
69
125
  end
70
126
 
71
127
  # Creates a channel.
128
+ #
72
129
  # create_channel :name => 'foo', :kind => 'qst_server', :protocol => 'sms', :configuration => {:password => 'bar'}
130
+ #
131
+ # Raises Nuntium::Exception if something goes wrong. You can access specific errors on properties via the properties
132
+ # accessor of the exception.
73
133
  def create_channel(channel)
74
134
  write_configuration channel
75
- response = self.class.post "#{@url}/api/channels.json", :basic_auth => @auth, :body => channel.to_json
76
- return_channel response
135
+ post "/api/channels.json", channel.to_json do |response, error|
136
+ handle_channel_error error if error
137
+
138
+ channel = JSON.parse response
139
+ read_configuration channel
140
+ channel
141
+ end
77
142
  end
78
143
 
79
144
  # Updates a channel.
145
+ #
80
146
  # update_channel :name => 'foo', :kind => 'qst_server', :protocol => 'sms', :configuration => {:password => 'bar'}
147
+ #
148
+ # Raises Nuntium::Exception if something goes wrong. You can access specific errors on properties via the properties
149
+ # accessor of the exception.
81
150
  def update_channel(channel)
82
151
  write_configuration channel
83
- response = self.class.put "#{@url}/api/channels/#{channel['name'] || channel[:name]}.json", :basic_auth => @auth, :body => channel.to_json
84
- return_channel response
152
+ channel_name = channel['name'] || channel[:name]
153
+
154
+ put "/api/channels/#{channel_name}.json", channel.to_json do |response, error|
155
+ handle_channel_error error if error
156
+
157
+ channel = JSON.parse response.body
158
+ read_configuration channel
159
+ channel
160
+ end
85
161
  end
86
162
 
87
163
  # Deletes a chnanel given its name.
164
+ #
165
+ # Raises Nuntium::Exception if something goes wrong.
88
166
  def delete_channel(name)
89
- self.class.delete "#{@url}/api/channels/#{name}", :basic_auth => @auth
167
+ delete "/api/channels/#{name}" do |response, error|
168
+ raise Nuntium::Exception.new error.message if error
169
+
170
+ response
171
+ end
90
172
  end
91
173
 
92
- # Returns the list of candidate channels when simulating routing the given
93
- # AO message.
174
+ # Returns the list of candidate channels when simulating routing the given AO message.
175
+ #
94
176
  # candidate_channels_for_ao :from => 'sms://1', :to => 'sms://2', :subject => 'hello', :body => 'hi!'
177
+ #
178
+ # Raises Nuntium::Exception if something goes wrong.
95
179
  def candidate_channels_for_ao(message)
96
- chans = self.class.get "#{@url}/api/candidate/channels.json", :basic_auth => @auth, :body => message
97
- return nil if chans.class <= String
98
- chans.each do |channel|
99
- read_configuration channel
100
- end
180
+ get_channels "/api/candidate/channels.json?#{to_query message}"
101
181
  end
102
182
 
103
183
  # Sends one or many AO messages.
104
184
  # Returns an enhanced HTTParty::Response instance with id, guid and token readers that matches those x-headers
105
185
  # returned by Nuntium.
186
+ #
106
187
  # To send a token, just include it in the message as :token => 'my_token'
188
+ #
107
189
  # send_ao :from => 'sms://1', :to => 'sms://2', :subject => 'hello', :body => 'hi!'
108
190
  # send_ao [{:from => 'sms://1', :to => 'sms://2', :subject => 'hello', :body => 'hi!'}, {...}]
191
+ #
192
+ # Returns a hash with :id, :guid and :token keys if a single message was sent, otherwise
193
+ # returns a hash with a :token key.
194
+ #
195
+ # Raises Nuntium::Exception if something goes wrong.
109
196
  def send_ao(messages)
110
- response = if messages.is_a? Array
111
- self.class.post "#{@url}/#{@account}/#{@application}/send_ao.json", :basic_auth => @auth, :body => messages.to_json
197
+ if messages.is_a? Array
198
+ post "/#{@account}/#{@application}/send_ao.json", messages.to_json do |response, error|
199
+ raise Nuntium::Exception.new error.message if error
200
+
201
+ {:token => response.headers[:x_nuntium_token]}
202
+ end
112
203
  else
113
- self.class.post "#{@url}/#{@account}/#{@application}/send_ao", :basic_auth => @auth, :body => messages
204
+ get "/#{@account}/#{@application}/send_ao?#{to_query messages}" do |response, error|
205
+ raise Nuntium::Exception.new error.message if error
206
+
207
+ {
208
+ :id => response.headers[:x_nuntium_id],
209
+ :guid => response.headers[:x_nuntium_guid],
210
+ :token => response.headers[:x_nuntium_token],
211
+ }
212
+ end
114
213
  end
115
- def response.id; headers['x-nuntium-id']; end
116
- def response.token; headers['x-nuntium-token']; end
117
- def response.guid; headers['x-nuntium-guid']; end
118
- response
119
214
  end
120
215
 
121
216
  # Gets AO messages that have the given token. The response is an array of hashes with the messages' attributes.
217
+ #
218
+ # Raises Nuntium::Exception if something goes wrong.
122
219
  def get_ao(token)
123
- self.class.get "#{@url}/#{@account}/#{@application}/get_ao.json?token=#{token}", :basic_auth => @auth
220
+ get_json "/#{@account}/#{@application}/get_ao.json?token=#{token}"
124
221
  end
125
222
 
126
223
  # Gets the custom attributes specified for a given address. Returns a hash with the attributes
224
+ #
225
+ # Raises Nuntium::Exception if something goes wrong.
127
226
  def get_custom_attributes(address)
128
- attrs = self.class.get "#{@url}/api/custom_attributes?address=#{address}", :basic_auth => @auth
129
- return nil unless attrs.is_a? Hash
130
- attrs
227
+ get_json "/api/custom_attributes?address=#{address}"
131
228
  end
132
229
 
230
+ # Sets custom attributes of a given address.
231
+ #
232
+ # Raises Nuntium::Exception if something goes wrong.
133
233
  def set_custom_attributes(address, attributes)
134
- self.class.post "#{@url}/api/custom_attributes?address=#{address}", :basic_auth => @auth, :body => attributes
234
+ post "/api/custom_attributes?address=#{address}", attributes.to_json do |response, error|
235
+ raise Nuntium::Exception.new error.message if error
236
+
237
+ nil
238
+ end
135
239
  end
136
240
 
137
241
  private
138
242
 
139
243
  def write_configuration(channel)
244
+ return unless channel[:configuration] || channel['configuration']
245
+
140
246
  configuration = []
141
- channel[:configuration].each do |name, value|
247
+ (channel[:configuration] || channel['configuration']).each do |name, value|
142
248
  configuration << {:name => name, :value => value}
143
249
  end
144
- channel[:configuration] = configuration
250
+ if channel[:configuration]
251
+ channel[:configuration] = configuration
252
+ else
253
+ channel['configuration'] = configuration
254
+ end
145
255
  end
146
256
 
147
257
  def read_configuration(channel)
148
- configuration = {}
149
- (channel['configuration'] || channel[:configuration]).each do |hash|
150
- configuration[hash['name'] || hash[:name]] = hash['value'] || hash[:value]
151
- end
152
- channel['configuration'] = configuration
258
+ channel['configuration'] = Hash[channel['configuration'].map { |e| [e['name'], e['value']] }]
153
259
  end
154
260
 
155
261
  def return_channel(response)
@@ -164,4 +270,83 @@ class Nuntium
164
270
  end
165
271
  end
166
272
 
273
+ def get(path)
274
+ resource = RestClient::Resource.new @url, @options
275
+ resource = resource[path].get
276
+ yield resource, nil
277
+ rescue RestClient::Exception => ex
278
+ yield nil, ex
279
+ rescue Errno::ECONNREFUSED => ex
280
+ yield nil, ex
281
+ end
282
+
283
+ def get_json(path)
284
+ get(path) do |response, error|
285
+ raise Nuntium::Exception.new error.message if error
286
+
287
+ JSON.parse response.body
288
+ end
289
+ end
290
+
291
+ def get_channels(path)
292
+ get(path) do |response, error|
293
+ raise Nuntium::Exception.new error.message if error
294
+
295
+ channels = JSON.parse response.body
296
+ channels.each { |channel| read_configuration channel }
297
+ channels
298
+ end
299
+ end
300
+
301
+ def post(path, data)
302
+ resource = RestClient::Resource.new @url, @options
303
+ resource = resource[path].post(data)
304
+ yield resource, nil
305
+ rescue RestClient::Exception => ex
306
+ yield nil, ex
307
+ rescue Errno::ECONNREFUSED => ex
308
+ yield nil, ex
309
+ end
310
+
311
+ def put(path, data)
312
+ resource = RestClient::Resource.new @url, @options
313
+ resource = resource[path].put(data)
314
+ yield resource, nil
315
+ rescue RestClient::Exception => ex
316
+ yield nil, ex
317
+ rescue Errno::ECONNREFUSED => ex
318
+ yield nil, ex
319
+ end
320
+
321
+ def delete(path, data)
322
+ resource = RestClient::Resource.new @url, @options
323
+ resource = resource[path].delete
324
+ yield resource, nil
325
+ rescue RestClient::Exception => ex
326
+ yield nil, ex
327
+ rescue Errno::ECONNREFUSED => ex
328
+ yield nil, ex
329
+ end
330
+
331
+ def handle_channel_error(error)
332
+ if error.is_a? RestClient::BadRequest
333
+ response = JSON.parse error.response.body
334
+ raise Nuntium::Exception.new response['summary'], Hash[response['properties'].map {|e| [e.keys[0], e.values[0]]}]
335
+ else
336
+ raise Nuntium::Exception.new error.message
337
+ end
338
+ end
339
+
340
+ def to_query(hash)
341
+ query = ''
342
+ first = true
343
+ hash.each do |key, value|
344
+ query << '&' unless first
345
+ query << key.to_s
346
+ query << '='
347
+ query << CGI.escape(value.to_s)
348
+ first = false
349
+ end
350
+ query
351
+ end
167
352
  end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nuntium_api
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 13
9
- version: "0.13"
8
+ - 14
9
+ version: "0.14"
10
10
  platform: ruby
11
11
  authors:
12
12
  - InsTEDD
@@ -14,10 +14,10 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-09-02 00:00:00 Z
17
+ date: 2011-09-22 00:00:00 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
- name: httparty
20
+ name: rest-client
21
21
  prerelease: false
22
22
  requirement: &id001 !ruby/object:Gem::Requirement
23
23
  none: false
@@ -55,6 +55,7 @@ extra_rdoc_files: []
55
55
  files:
56
56
  - lib/nuntium_api.rb
57
57
  - lib/nuntium.rb
58
+ - lib/nuntium/exception.rb
58
59
  homepage: http://code.google.com/p/nuntium-api-ruby
59
60
  licenses: []
60
61