burstsms 0.1.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 (48) hide show
  1. data/.gitignore +5 -0
  2. data/.travis.yml +4 -0
  3. data/Gemfile +4 -0
  4. data/LICENCE +20 -0
  5. data/README.md +128 -0
  6. data/Rakefile +6 -0
  7. data/burstsms.gemspec +27 -0
  8. data/lib/burstsms.rb +37 -0
  9. data/lib/burstsms/api.rb +78 -0
  10. data/lib/burstsms/lists_add.rb +30 -0
  11. data/lib/burstsms/lists_add_recipient.rb +34 -0
  12. data/lib/burstsms/lists_delete.rb +28 -0
  13. data/lib/burstsms/lists_delete_recipient.rb +29 -0
  14. data/lib/burstsms/lists_get.rb +38 -0
  15. data/lib/burstsms/lists_get_recipients.rb +42 -0
  16. data/lib/burstsms/lists_get_unsubscribed.rb +42 -0
  17. data/lib/burstsms/message_responses.rb +41 -0
  18. data/lib/burstsms/messages_add.rb +39 -0
  19. data/lib/burstsms/messages_get.rb +44 -0
  20. data/lib/burstsms/messages_multiple.rb +32 -0
  21. data/lib/burstsms/version.rb +3 -0
  22. data/spec/burst_sms_spec.rb +171 -0
  23. data/spec/contact_lists_spec.rb +188 -0
  24. data/spec/fixtures/api_requests/lists_add.txt +10 -0
  25. data/spec/fixtures/api_requests/lists_add_recipient.txt +13 -0
  26. data/spec/fixtures/api_requests/lists_delete.txt +10 -0
  27. data/spec/fixtures/api_requests/lists_delete_recipient.txt +11 -0
  28. data/spec/fixtures/api_requests/lists_get.txt +11 -0
  29. data/spec/fixtures/api_requests/lists_get_recipients.txt +12 -0
  30. data/spec/fixtures/api_requests/lists_get_unsubscribed.txt +12 -0
  31. data/spec/fixtures/api_requests/message_responses.txt +12 -0
  32. data/spec/fixtures/api_requests/messages_add.txt +12 -0
  33. data/spec/fixtures/api_requests/messages_get.txt +11 -0
  34. data/spec/fixtures/api_requests/messages_multiple.txt +12 -0
  35. data/spec/fixtures/api_responses/generic_failure.txt +7 -0
  36. data/spec/fixtures/api_responses/lists_add_recipient_success.txt +11 -0
  37. data/spec/fixtures/api_responses/lists_add_success.txt +12 -0
  38. data/spec/fixtures/api_responses/lists_delete_recipient_success.txt +8 -0
  39. data/spec/fixtures/api_responses/lists_delete_success.txt +8 -0
  40. data/spec/fixtures/api_responses/lists_get_recipients_success.txt +33 -0
  41. data/spec/fixtures/api_responses/lists_get_success.txt +19 -0
  42. data/spec/fixtures/api_responses/lists_get_unsubscribed_success.txt +33 -0
  43. data/spec/fixtures/api_responses/message_responses_success.txt +16 -0
  44. data/spec/fixtures/api_responses/messages_add_success.txt +17 -0
  45. data/spec/fixtures/api_responses/messages_get_success.txt +53 -0
  46. data/spec/fixtures/api_responses/send_message_success.txt +14 -0
  47. data/spec/spec_helper.rb +36 -0
  48. metadata +173 -0
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in burst_sms.gemspec
4
+ gemspec
data/LICENCE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Made in Data Pty Ltd and David Barlow
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ Software), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,128 @@
1
+ # Burst Sms [![Build Status](https://secure.travis-ci.org/madeindata/Burst-Sms.png?branch=master)](http://travis-ci.org/madeindata/Burst-Sms)
2
+
3
+ Rubygem for the Burst SMS API. Sends SMS to Australian mobiles
4
+ For use with a [burstsms.com.au](http://burstsms.com.au) account.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ gem install 'burstsms'
10
+
11
+ or add the following line to Gemfile:
12
+
13
+ gem 'burstsms'
14
+
15
+ and run `bundle` from your shell.
16
+
17
+ Usage
18
+ -----
19
+ **Create an authenticated instance**
20
+
21
+ @burstsms = BurstSms::API.new('api_key', 'secret')
22
+
23
+ **Responses**
24
+ Responses from the API are converted into ruby objects with attributes you can access.
25
+
26
+ Available attributes for each method are listed in their description below.
27
+
28
+ Every method will return a `error` attribute if something goes wrong
29
+
30
+
31
+ **Send a SMS** - [messages.multiple](http://burstsms.com/api-documentation/messages.multiple)
32
+
33
+ @burstsms.send_message('caller_id', 'recipients', 'message')
34
+
35
+ Response attributes :result :total_recipients :total_recipients_queued :message_id :contact_list_addition
36
+
37
+ `caller_id` Can be a Number upto 15 digits or a alpha-numeric string upto 11 characters.
38
+ `recipient/s` A single mobile number or an array of mobile numbers for multiple recipients.
39
+ `message` String containing sms message to send.
40
+ optional:
41
+ `sendtime` Set specific time to send message.
42
+ `contact_list` Add recipients to an existing contact list in your account.
43
+
44
+ *__NOTE:__The gem handles conversion of mobile numbers to the format required by the API. Also duplicate and invalid numbers will be deleted from the array.*
45
+ __example__: you can pass in an array of numbers like `['+61 414 899 766', '0403 855 555', '0403-855-445']` and it will be converted to `['61414899766', '61403855555', '61403855445']`
46
+
47
+ ------
48
+
49
+ Additional Methods
50
+ ------------------
51
+
52
+ **Send a SMS to an existing list** - [messages.add](http://burstsms.com/api-documentation/messages.add)
53
+
54
+ @burstsms.add_message('caller_id', 'list_id', 'message')
55
+
56
+ #returns :total :time :result :message_id :list_id :message :cost :balance :charge_error
57
+
58
+ **Retrieve history of sent messages** - [messages.get](http://burstsms.com/api-documentation/messages.get)
59
+
60
+ @burstsms.get_messages() #takes optional arguments offset and limit(default is 50)
61
+
62
+ #returns :total :time :messages
63
+ #messages return :id :list_id :mobile_from :message :datetime_send :datetime_actioned :recipient_count :status :schedule
64
+
65
+ **Retrieve responses from a message** - [messages.responses](http://burstsms.com/api-documentation/messages.responses)
66
+
67
+ @burstsms.message_responses('message_id') #takes optional arguments offset and limit(default is 50)
68
+
69
+ #returns :total :time :replies
70
+ #replies return :firstname :lastname :mobile :message :datetime_entry_orig
71
+
72
+ **Retrieve Contact Lists** - [contact-lists.get](http://burstsms.com/api-documentation/contact-lists.get)
73
+
74
+ @burstsms.get_lists() #takes optional arguments offset and limit(default is 50)
75
+
76
+ #returns :total :time :lists
77
+ #lists return :id :name :recipient_count
78
+
79
+ **Add Contact List** - [contact-lists.add](http://burstsms.com/api-documentation/contact-lists.add)
80
+
81
+ @burstsms.add_list('name of new list')
82
+
83
+ #returns :total :time :name :list_id :recipient_count
84
+
85
+ **Delete Contact List** - [contact-lists.delete](http://burstsms.com/api-documentation/contact-lists.delete)
86
+
87
+ @burstsms.delete_list('list_id')
88
+
89
+ #returns :total :time :response
90
+
91
+ **Retrieve Contact List Recipients** - [contact-lists.get-recipients](http://burstsms.com/api-documentation/contact-lists.get-recipients)
92
+
93
+ @burstsms.get_list_recipients('list_id') #takes optional arguments offset and limit(default is 50)
94
+
95
+ #returns :total :time :recipients
96
+ #recipients return :firstname :lastname :mobile :datetime_entry :dest_country :bounce_count
97
+
98
+ **Retrieve Contact List Unsubscribed** - [contact-lists.get-unsubscribed](http://burstsms.com/api-documentation/contact-lists.get-unsubscribed)
99
+
100
+ @burstsms.get_list_unsubscribed('list_id') #takes optional arguments offset and limit(default is 50)
101
+
102
+ #returns :total :time :recipients
103
+ #recipients return :firstname :lastname :mobile :datetime_entry :dest_country :bounce_count
104
+
105
+ **Add Contact List Recipient** - [contact-lists.add-recipient](http://burstsms.com/api-documentation/contact-lists.add-recipient)
106
+
107
+ @burstsms.add_list_recipient("list_id", "mobile_number", :firstname => 'Bob', :lastname => 'Smith') #name fields optional
108
+
109
+ #returns :total :time :result :list_id
110
+ #refer to Burst Sms docs for possible result values
111
+
112
+ **Delete Contact List Recipient** - [contact-lists.delete-recipient](http://burstsms.com/api-documentation/contact-lists.delete-recipient)
113
+
114
+ @burstsms.delete_list_recipient("list_id", "mobile_number")
115
+
116
+ #returns :total :time :result
117
+ #refer to Burst Sms docs for possible result values
118
+
119
+ ------
120
+ **TODO**
121
+
122
+ - Complete 'contact-lists.add-multiple-recipients'
123
+ - Add reseller API functions.
124
+
125
+ Licence
126
+ -------
127
+
128
+ Copyright © 2012 *Made in Data Pty Ltd* and *David Barlow* [@madeindata](http://twitter.com/madeindata). Refer to terms in LICENCE file.
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => :spec
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "burstsms/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "burstsms"
7
+ s.version = BurstSms::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["David Barlow"]
10
+ s.email = ["david@madeindata.com"]
11
+ s.homepage = "https://github.com/madeindata/Burst-Sms"
12
+ s.summary = %q{Ruby Interface for the Burst SMS gateway}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+
20
+ s.add_dependency "unhappymapper"
21
+ s.add_dependency "httparty"
22
+
23
+ s.add_development_dependency "rspec", "~> 2.6"
24
+ s.add_development_dependency "webmock", "~> 1.7.10"
25
+ s.add_development_dependency 'rake'
26
+
27
+ end
@@ -0,0 +1,37 @@
1
+ require 'uri'
2
+ require 'happymapper'
3
+ require 'httparty'
4
+
5
+
6
+ module BurstSms
7
+
8
+ class ParamBuilder
9
+ include HappyMapper
10
+ tag 'params'
11
+ def initialize(parameters={})
12
+ parameters.each do |property,value|
13
+ self.class.element property, String unless respond_to?("#{property}=")
14
+ send("#{property}=",value) if respond_to?("#{property}=")
15
+ end
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+
22
+ require 'burstsms/messages_multiple'
23
+ require 'burstsms/messages_get'
24
+ require 'burstsms/messages_add'
25
+ require 'burstsms/message_responses'
26
+ require 'burstsms/lists_get'
27
+ require 'burstsms/lists_add'
28
+ require 'burstsms/lists_delete'
29
+ require 'burstsms/lists_get_recipients'
30
+ require 'burstsms/lists_get_unsubscribed'
31
+ require 'burstsms/lists_add_recipient'
32
+ require 'burstsms/lists_delete_recipient'
33
+
34
+
35
+ require 'burstsms/api'
36
+
37
+
@@ -0,0 +1,78 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ API_URL = "https://burstsms.com/api"
5
+ API_VERSION = 0.3
6
+
7
+ class API
8
+ include HappyMapper
9
+
10
+ include MessagesMultiple
11
+ include MessagesGet
12
+ include MessagesAdd
13
+ include MessageResponses
14
+
15
+ include ListsGet
16
+ include ListsAdd
17
+ include ListsDelete
18
+ include ListsGetRecipients
19
+ include ListsGetUnsubscribed
20
+ include ListsAddRecipient
21
+ include ListsDeleteRecipient
22
+
23
+ tag 'request'
24
+
25
+ element :version, Float
26
+ element :key, String
27
+ element :secret, String
28
+ element :api_method, String, :tag => 'method_'
29
+
30
+ has_one :params, String
31
+
32
+
33
+
34
+ def initialize(api_key, api_secret)
35
+ self.key = api_key
36
+ self.secret = api_secret
37
+ self.version = BurstSms::API_VERSION
38
+ end
39
+
40
+
41
+
42
+ private
43
+
44
+ def sanitize_numbers(recipients)
45
+ Array(recipients).map{|n| n.gsub(/[^0-9]/i, '').gsub(/\A(04)|\A(4)/, '614')}.delete_if{|n| n.length != 11 || !n.start_with?('614')}.uniq.join(',')
46
+ end
47
+
48
+ def encode_msg(message)
49
+ URI.escape( message, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
50
+ end
51
+
52
+ def check_valid_sender(from)
53
+ sender = from.gsub(/[^0-9a-z_\s]/i, '')
54
+ if sender =~ /\D/
55
+ raise "Sender ID is too Long" if sender.length > 11
56
+ else
57
+ raise "Sender Number is too Long" if sender.length > 15
58
+ end
59
+ return sender
60
+ end
61
+
62
+ def build_request(api_call, parameters={})
63
+ self.params = ParamBuilder.new(parameters)
64
+ self.api_method = api_call
65
+ self.to_xml()
66
+ end
67
+
68
+ def post_to_api(request_xml)
69
+ #XML request has to be wrapped as a 'request' param in body
70
+ response = HTTParty.post( BurstSms::API_URL, :body => "request=#{request_xml}" )
71
+ end
72
+
73
+ end
74
+
75
+
76
+
77
+
78
+ end
@@ -0,0 +1,30 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module ListsAdd
5
+
6
+ def add_list(name)
7
+ response = post_to_api(add_list_body(name))
8
+ Response.parse(response.body)
9
+ end
10
+
11
+ def add_list_body(name)
12
+ build_request("contact-lists.add", :name => name)
13
+ end
14
+
15
+ class Response
16
+ include HappyMapper
17
+ tag 'xml'
18
+
19
+ element :total, String
20
+ element :time, Time
21
+ element :timestamp, String
22
+ element :error, String
23
+
24
+ element :name, String, :xpath => "data/name"
25
+ element :recipient_count, String, :xpath => "data/recipient_count"
26
+ element :list_id, String, :xpath => "data/id"
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module ListsAddRecipient
5
+
6
+ def add_list_recipient(list_id, mobile, options={})
7
+ response = post_to_api(add_list_recipient_body(list_id, mobile, options))
8
+ Response.parse(response.body)
9
+ end
10
+
11
+ def add_list_recipient_body(list_id, mobile, options={})
12
+ build_request("contact-lists.add-recipient", :list_id => list_id,
13
+ :mobile => mobile,
14
+ :firstname => (options.has_key?(:firstname) ? options[:firstname] : nil),
15
+ :lastname => (options.has_key?(:lastname) ? options[:lastname] : nil),
16
+ :mobile_dest_country => (options.has_key?(:mobile_dest_country) ? options[:mobile_dest_country] : nil)
17
+ )
18
+ end
19
+
20
+ class Response
21
+ include HappyMapper
22
+ tag 'xml'
23
+
24
+ element :total, String
25
+ element :time, Time
26
+ element :timestamp, String
27
+ element :error, String
28
+
29
+ element :result, String, :xpath => "data/result"
30
+ element :list_id, String, :xpath => "data/list_id"
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module ListsDelete
5
+
6
+ def delete_list(id)
7
+ @response = post_to_api(delete_list_body(id))
8
+ Response.parse(@response.body)
9
+ end
10
+
11
+ def delete_list_body(id)
12
+ build_request("contact-lists.delete", :id => id)
13
+ end
14
+
15
+ class Response
16
+ include HappyMapper
17
+ tag 'xml'
18
+
19
+ element :error, String
20
+ element :total, String
21
+ element :time, String
22
+ element :timestamp, String
23
+ element :response, String
24
+
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module ListsDeleteRecipient
5
+
6
+ def delete_list_recipient(list_id, mobile)
7
+ @response = post_to_api(delete_list_recipient_body(list_id, mobile))
8
+ Response.parse(@response.body)
9
+ end
10
+
11
+ def delete_list_recipient_body(list_id, mobile)
12
+ build_request("contact-lists.delete-recipient", :list_id => list_id,
13
+ :mobile => mobile)
14
+ end
15
+
16
+ class Response
17
+ include HappyMapper
18
+ tag 'xml'
19
+
20
+ element :error, String
21
+ element :total, String
22
+ element :time, String
23
+ element :timestamp, String
24
+ element :result, String
25
+
26
+
27
+ end
28
+ end
29
+ end