africastalking-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Ian Juma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Africastalking::Ruby
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/africastalking/ruby`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'africastalking-ruby'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install africastalking-ruby
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/africastalking-ruby.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
42
+
43
+ # africastalking-ruby
44
+ Official AfricasTalking Ruby API wrapper
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'africastalking/ruby/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "africastalking-ruby"
8
+ spec.version = Africastalking::Ruby::VERSION
9
+ spec.authors = ["Ian Juma"]
10
+ spec.email = ["ijuma@africastalking.com"]
11
+
12
+ spec.summary = %q{Official AfricasTalking Ruby API wrapper}
13
+ spec.description = %q{A Ruby library for communicating with the AfricasTalking REST API}
14
+ spec.homepage = "https://github.com/AfricasTalkingLtd/africastalking-ruby"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ #spec.add_dependency "rubygems"
23
+ #spec.add_dependency "net/http"
24
+ #spec.add_dependency "uri"
25
+ #spec.add_dependency "json"
26
+
27
+ # spec.add_development_dependency "bundler", "~> 1.11"
28
+ # spec.add_development_dependency "rake", "~> 10.0"
29
+ # spec.add_development_dependency "rspec", "~> 3.0"
30
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "africastalking/ruby"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,332 @@
1
+ module AfricasTalkingGateway
2
+
3
+ require 'rubygems'
4
+ require 'net/http'
5
+ require 'uri'
6
+ require 'json'
7
+
8
+ class AfricasTalkingGatewayException < Exception
9
+ end
10
+
11
+ class SMSMessages
12
+ attr_accessor :id, :text, :from, :to, :linkId, :date
13
+
14
+ def initialize(id_, text_, from_, to_, linkId_, date_)
15
+ @id = id_
16
+ @text = text_
17
+ @from = from_
18
+ @to = to_
19
+ @linkId = linkId_
20
+ @date = date_
21
+ end
22
+ end
23
+
24
+ class StatusReport
25
+ attr_accessor :number, :status, :cost, :messageId
26
+
27
+ def initialize(number_, status_, cost_,messageId_)
28
+ @number = number_
29
+ @status = status_
30
+ @cost = cost_
31
+ @messageId = messageId_
32
+ end
33
+ end
34
+
35
+ class PremiumSubscriptionNumbers
36
+ attr_accessor :phoneNumber, :id
37
+
38
+ def initialize(number_, id_)
39
+ @phoneNumber = number_
40
+ @id = id_
41
+ end
42
+ end
43
+
44
+ class AirtimeResult
45
+ attr_accessor :amount, :phoneNumber, :requestId, :status, :errorMessage, :discount
46
+
47
+ def initialize(status_, number_, amount_, requestId_, errorMessage_, discount_)
48
+ @status = status_
49
+ @phoneNumber = number_
50
+ @amount = amount_
51
+ @requestId = requestId_
52
+ @errorMessage = errorMessage_
53
+ @discount = discount_
54
+ end
55
+ end
56
+
57
+ class CallResponse
58
+ attr_accessor :phoneNumber, :status
59
+
60
+ def initialize(status_, number_)
61
+ @status = status_
62
+ @phoneNumber = number_
63
+ end
64
+ end
65
+
66
+ class QueuedCalls
67
+ attr_accessor :numCalls, :phoneNumber, :queueName
68
+
69
+ def initialize(number_, numCalls_, queueName_)
70
+ @phoneNumber = number_
71
+ @numCalls = numCalls_
72
+ @queueName = queueName_
73
+ end
74
+ end
75
+
76
+ class AfricasTalkingGateway
77
+
78
+ SMS_URL = 'https://api.africastalking.com/version1/messaging'
79
+ VOICE_URL = 'https://voice.africastalking.com'
80
+ SUBSCRIPTION_URL = 'https://api.africastalking.com/version1/subscription'
81
+ USERDATA_URL = 'https://api.africastalking.com/version1/user'
82
+ AIRTIME_URL = 'https://api.africastalking.com/version1/airtime'
83
+
84
+ HTTP_CREATED = 201
85
+ HTTP_OK = 200
86
+
87
+ #Set debug flag to to true to view response body
88
+ DEBUG = false
89
+
90
+
91
+ def initialize(user_name,api_key)
92
+ @user_name = user_name
93
+ @api_key = api_key
94
+
95
+ @response_code = nil
96
+ end
97
+
98
+ def sendMessage(recipients_, message_, from_ = nil, bulkSMSMode_ = 1, enqueue_ = 0, keyword_ = nil, linkId_ = nil, retryDurationInHours_ = nil)
99
+ post_body = {
100
+ 'username' => @user_name,
101
+ 'message' => message_,
102
+ 'to' => recipients_,
103
+ 'bulkSMSMode' => bulkSMSMode_
104
+ }
105
+ if (from_ != nil)
106
+ post_body['from'] = from_
107
+ end
108
+
109
+ if (enqueue_ > 0)
110
+ post_body['enqueue'] = enqueue_
111
+ end
112
+
113
+ if (keyword_ != nil)
114
+ post_body['keyword'] = keyword_
115
+ end
116
+
117
+ if (linkId_ != nil)
118
+ post_body['linkId'] = linkId_
119
+ end
120
+
121
+ if (retryDurationInHours_ != nil)
122
+ post_body['retryDurationInHours'] = retryDurationInHours_
123
+ end
124
+
125
+ response = executePost(SMS_URL, post_body)
126
+ if @response_code == HTTP_CREATED
127
+ reports = JSON.parse(response,:quirks_mode=>true)["SMSMessageData"]["Recipients"].collect { |entry|
128
+ StatusReport.new entry["number"], entry["status"], entry["cost"], entry["messageId"]
129
+ }
130
+ return reports
131
+ else
132
+ raise AfricasTalkingGatewayAfricasTalkingGatewayException, response
133
+ end
134
+ end
135
+
136
+ def fetchMessages(last_received_id_)
137
+ url = "#{SMS_URL}?username=#{@user_name}&lastReceivedId=#{last_received_id_}"
138
+ response = executePost(url)
139
+ if @response_code == HTTP_OK
140
+ messages = JSON.parse(response, :quirky_mode => true)["SMSMessageData"]["Messages"].collect { |msg|
141
+ SMSMessages.new msg["id"], msg["text"], msg["from"], msg["to"], msg["linkId"], msg["date"]
142
+ }
143
+ return messages
144
+ else
145
+ raise AfricasTalkingGatewayException, response
146
+ end
147
+ end
148
+
149
+ def createSubcription(phone_number_, short_code_, keyword_)
150
+ if(phone_number_.length == 0 || short_code.length == 0 || keyword_.length == 0)
151
+ raise AfricasTalkingGatewayException, "Please supply phone number, short code and keyword"
152
+ end
153
+
154
+ post_body = {
155
+ 'username' => @user_name,
156
+ 'phoneNumber' => phone_number_,
157
+ 'shortCode' => short_code_,
158
+ 'keyword' => keyword_
159
+ }
160
+ url = "#{SUBSCRIPTION_URL}/create"
161
+ response = executePost(url, post_body)
162
+ if(@response_code == HTTP_CREATED)
163
+ return JSON.parse(response, :quirky_mode => true)
164
+ else
165
+ raise AfricasTalkingGatewayException, response
166
+ end
167
+ end
168
+
169
+ def deleteSubcription(phone_number_, short_code_, keyword_)
170
+ if(phone_number_.length == 0 || short_code.length == 0 || keyword_.length == 0)
171
+ raise AfricasTalkingGatewayException, "Please supply phone number, short code and keyword"
172
+ end
173
+
174
+ post_body = {
175
+ 'username' => @user_name,
176
+ 'phoneNumber' => phone_number_,
177
+ 'shortCode' => short_code_,
178
+ 'keyword' => keyword_
179
+ }
180
+ url = "#{SUBSCRIPTION_URL}/delete"
181
+
182
+ response = executePost(url, post_body)
183
+
184
+ if(@response_code == HTTP_CREATED)
185
+ return JSON.parse(response, :quirky_mode => true)
186
+ else
187
+ raise AfricasTalkingGatewayException, response
188
+ end
189
+ end
190
+
191
+ def fetchPremiumSubscriptions(short_code_, keyword_, last_received_id_ = 0)
192
+ if(short_code_.length == 0 || keyword_.length == 0)
193
+ raise AfricasTalkingGatewayException, "Please supply the short code and keyword"
194
+ end
195
+
196
+ url = "#{SUBSCRIPTION_URL}?username=#{@user_name}&shortCode=#{short_code_}&keyword=#{keyword_}&lastReceivedId=#{last_received_id_}"
197
+
198
+ response = executePost(url)
199
+
200
+ if(@response_code == HTTP_OK)
201
+ subscriptions = JSON.parse(response)['responses'].collect{ |subscriber|
202
+ PremiumSubscriptionNumbers.new subscriber['phoneNumber'], subscriber['id']
203
+ }
204
+ return subscriptions
205
+ else
206
+ raise AfricasTalkingGatewayException, response
207
+ end
208
+ end
209
+
210
+ def call(from_, to_)
211
+ post_body = {
212
+ 'username' => @user_name,
213
+ 'from' => from_,
214
+ 'to' => to_
215
+ }
216
+ response = executePost("#{VOICE_URL}/call", post_body)
217
+ if(@response_code == HTTP_OK || @response_code == HTTP_CREATED)
218
+ jObject = JSON.parse(response, :quirky_mode => true)
219
+
220
+ if (jObject['errorMessage'] == "None")
221
+ results = jObject['entries'].collect{|result|
222
+ CallResponse.new result['status'], result['phoneNumber']
223
+ }
224
+ return results
225
+ end
226
+
227
+ raise AfricasTalkingGatewayException, jObject['errorMessage']
228
+ end
229
+
230
+ raise AfricasTalkingGatewayException, response
231
+ end
232
+
233
+ def getNumQueuedCalls(phone_number_, queue_name_ = nil)
234
+ post_body = {
235
+ 'username' => @user_name,
236
+ 'phoneNumbers' => phone_number_,
237
+ }
238
+ if (queue_name_ != nil)
239
+ post_body['queueName'] = queue_name_
240
+ end
241
+ url = "#{VOICE_URL}/queueStatus"
242
+ response = executePost(url, post_body)
243
+
244
+ jsObject = JSON.parse(response, :quirky_mode => true)
245
+
246
+ if(@response_code == HTTP_OK || @response_code == HTTP_CREATED)
247
+ if (jsObject['errorMessage'] == "None")
248
+ results = jsObject['entries'].collect{|result|
249
+ QueuedCalls.new result['phoneNumber'], result['numCalls'], result['queueName']
250
+ }
251
+ return results
252
+ end
253
+
254
+ raise AfricasTalkingGatewayException, jsObject['errorMessage']
255
+ end
256
+
257
+ raise AfricasTalkingGatewayException, response
258
+ end
259
+
260
+ def uploadMediaFile(url_string_)
261
+ post_body = {
262
+ 'username' => @user_name,
263
+ 'url' => url_string_
264
+ }
265
+ url = "#{VOICE_URL}/mediaUpload"
266
+ response = executePost(url, post_body)
267
+
268
+ jsObject = JSON.parse(response, :quirky_mode => true)
269
+
270
+ raise AfricasTalkingGatewayException, jsObject['errorMessage'] if jsObject['errorMessage'] != "None"
271
+ end
272
+
273
+ def sendAirtime(recipients_)
274
+ recipients = recipients_.to_json
275
+ post_body = {
276
+ 'username' => @user_name,
277
+ 'recipients' => recipients
278
+ }
279
+ url = "#{AIRTIME_URL}/send"
280
+ response = executePost(url, post_body)
281
+ if (@response_code == HTTP_CREATED)
282
+ responses = JSON.parse(response)['responses']
283
+ if (responses.length > 0)
284
+ results = responses.collect{ |result|
285
+ AirtimeResult.new result['status'], result['phoneNumber'],result['amount'],result['requestId'], result['errorMessage'], result['discount']
286
+ }
287
+ return results
288
+ else
289
+ raise AfricasTalkingGatewayException, response['errorMessage']
290
+ end
291
+ else
292
+ raise AfricasTalkingGatewayException, response
293
+ end
294
+
295
+ end
296
+
297
+ def getUserData()
298
+ url = "#{USERDATA_URL}?username=#{@user_name}"
299
+ response = executePost(url)
300
+ if (@response_code == HTTP_OK)
301
+ result = JSON.parse(response, :quirky_mode =>true)['UserData']
302
+ return result
303
+ else
304
+ raise AfricasTalkingGatewayException, response
305
+ end
306
+ end
307
+
308
+ def executePost(url_, data_ = nil)
309
+ uri = URI.parse(url_)
310
+ http = Net::HTTP.new(uri.host, uri.port)
311
+ http.use_ssl = true
312
+
313
+ if(data_ != nil)
314
+ request = Net::HTTP::Post.new(uri.request_uri)
315
+ request.set_form_data(data_)
316
+ else
317
+ request = Net::HTTP::Get.new(uri.request_uri)
318
+ end
319
+ request["apikey"] = @api_key
320
+ request["Accept"] = "application/json"
321
+
322
+ response = http.request(request)
323
+
324
+ if (DEBUG)
325
+ puts "Full response #{response.body}"
326
+ end
327
+
328
+ @response_code = response.code.to_i
329
+ return response.body
330
+ end
331
+ end
332
+ end