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,38 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module ListsGet
5
+
6
+ def get_lists(offset=0, limit=50)
7
+ response = post_to_api(get_lists_body(offset, limit))
8
+ Response.parse(response.body)
9
+ end
10
+
11
+ def get_lists_body(offset, limit)
12
+ build_request("contact-lists.get", :offset => offset,
13
+ :limit => limit )
14
+ end
15
+
16
+ class Lists
17
+ include HappyMapper
18
+
19
+ element :id, String
20
+ element :name, String
21
+ element :recipient_count, Integer
22
+
23
+ end
24
+
25
+ class Response
26
+ include HappyMapper
27
+ tag 'xml'
28
+
29
+ element :total, String
30
+ element :time, Time
31
+ element :timestamp, String
32
+ element :error, String
33
+
34
+ has_many :lists, Lists, :tag => 'data'
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,42 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module ListsGetRecipients
5
+
6
+ def get_list_recipients(id, offset=0, limit=50)
7
+ response = post_to_api(get_list_recipients_body(id, offset, limit))
8
+ Response.parse(response.body)
9
+ end
10
+
11
+ def get_list_recipients_body(id, offset, limit)
12
+ build_request("contact-lists.get-recipients", :id => id,
13
+ :offset => offset,
14
+ :limit => limit )
15
+ end
16
+
17
+ class Recipients
18
+ include HappyMapper
19
+
20
+ element :mobile, String
21
+ element :firstname, String
22
+ element :lastname, String
23
+ element :datetime_entry, String
24
+ element :dest_country, String
25
+ element :bounce_count, Integer
26
+
27
+ end
28
+
29
+ class Response
30
+ include HappyMapper
31
+ tag 'xml'
32
+
33
+ element :total, String
34
+ element :time, Time
35
+ element :timestamp, String
36
+ element :error, String
37
+
38
+ has_many :recipients, Recipients, :tag => 'data'
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module ListsGetUnsubscribed
5
+
6
+ def get_list_unsubscribed(id, offset=0, limit=50)
7
+ response = post_to_api(get_list_unsubscribed_body(id, offset, limit))
8
+ Response.parse(response.body)
9
+ end
10
+
11
+ def get_list_unsubscribed_body(id, offset, limit)
12
+ build_request("contact-lists.get-unsubscribed", :id => id,
13
+ :offset => offset,
14
+ :limit => limit )
15
+ end
16
+
17
+ class Recipients
18
+ include HappyMapper
19
+
20
+ element :mobile, String
21
+ element :firstname, String
22
+ element :lastname, String
23
+ element :datetime_entry, String
24
+ element :dest_country, String
25
+ element :bounce_count, Integer
26
+
27
+ end
28
+
29
+ class Response
30
+ include HappyMapper
31
+ tag 'xml'
32
+
33
+ element :total, String
34
+ element :time, Time
35
+ element :timestamp, String
36
+ element :error, String
37
+
38
+ has_many :recipients, Recipients, :tag => 'data'
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module MessageResponses
5
+
6
+ def message_responses(message_id, offset=0, limit=50)
7
+ response = post_to_api(message_responses_body(message_id, offset, limit))
8
+ Response.parse(response.body)
9
+ end
10
+
11
+ def message_responses_body(message_id, offset, limit)
12
+ build_request("messages.responses", :message_id => message_id,
13
+ :offset => offset,
14
+ :limit => limit )
15
+ end
16
+
17
+ class Replies
18
+ include HappyMapper
19
+
20
+ element :firstname, String
21
+ element :lastname, String
22
+ element :mobile, String
23
+ element :datetime_entry_orig, String
24
+ element :message, String
25
+
26
+ end
27
+
28
+ class Response
29
+ include HappyMapper
30
+ tag 'xml'
31
+
32
+ element :total, String
33
+ element :time, Time
34
+ element :timestamp, String
35
+ element :error, String
36
+
37
+ has_many :replies, Replies, :tag => 'data'
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module MessagesAdd
5
+
6
+ def add_message(from, list_id, message, options={})
7
+ @response = post_to_api(add_message_body(from, list_id, message, options))
8
+ Response.parse(@response.body)
9
+ end
10
+
11
+ def add_message_body(from, list_id, message, options={})
12
+ build_request("messages.add", :caller_id => check_valid_sender(from),
13
+ :list_id => list_id,
14
+ :message => encode_msg(message),
15
+ :sendtime => (options.has_key?(:sendtime) ? options[:sendtime] : nil),
16
+ :contact_list => (options.has_key?(:contact_list) ? options[:contact_list] : nil))
17
+ end
18
+
19
+ class Response
20
+ include HappyMapper
21
+ tag 'xml'
22
+
23
+ element :error, String
24
+ element :total, String
25
+ element :time, String
26
+ element :timestamp, String
27
+
28
+ element :result, String, :xpath => "data/result"
29
+ element :message_id, String, :xpath => "data/message_id"
30
+ element :list_id, String, :xpath => "data/list_id"
31
+ element :message, String, :xpath => "data/message"
32
+ element :cost, String, :xpath => "data/cost"
33
+ element :balance, String, :xpath => "data/balance"
34
+ element :charge_error, String, :xpath => "data/charge_error"
35
+
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,44 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module MessagesGet
5
+
6
+ def get_messages(offset=0, limit=50)
7
+ response = post_to_api(get_messages_body(offset, limit))
8
+ Response.parse(response.body)
9
+ end
10
+
11
+ def get_messages_body(offset, limit)
12
+ build_request("messages.get", :offset => offset,
13
+ :limit => limit )
14
+ end
15
+
16
+ class Messages
17
+ include HappyMapper
18
+
19
+ element :id, String
20
+ element :list_id, String
21
+ element :mobile_from, String
22
+ element :message, String
23
+ element :datetime_send, Time
24
+ element :datetime_actioned, Time
25
+ element :recipient_count, Integer
26
+ element :status, String
27
+ element :schedule, String
28
+
29
+ end
30
+
31
+ class Response
32
+ include HappyMapper
33
+ tag 'xml'
34
+
35
+ element :total, String
36
+ element :time, Time
37
+ element :timestamp, String
38
+ element :error, String
39
+
40
+ has_many :messages, Messages, :tag => 'data'
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ require 'happymapper'
2
+
3
+ module BurstSms
4
+ module MessagesMultiple
5
+
6
+ def send_message(from, recipients, message, options={})
7
+ @response = post_to_api(send_message_body(from, recipients, message, options))
8
+ Response.parse(@response.body)
9
+ end
10
+
11
+ def send_message_body(from, recipients, message, options={})
12
+ build_request("messages.multiple", :caller_id => check_valid_sender(from),
13
+ :mobile => sanitize_numbers(recipients),
14
+ :message => encode_msg(message),
15
+ :sendtime => (options.has_key?(:sendtime) ? options[:sendtime] : nil),
16
+ :contact_list => (options.has_key?(:contact_list) ? options[:contact_list] : nil))
17
+ end
18
+
19
+ class Response
20
+ include HappyMapper
21
+ tag 'xml'
22
+
23
+ element :result, String, :xpath => "data/result"
24
+ element :total_recipients, String, :xpath => "data/total_recipients"
25
+ element :total_recipients_queued, String, :xpath => "data/total_recipients_queued"
26
+ element :message_id, String, :xpath => "data/message_id"
27
+ element :contact_list_addition, String, :xpath => "data/contact_list_addition"
28
+ element :error, String
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ module BurstSms
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,171 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe BurstSms do
5
+
6
+ before(:all) do
7
+ @burst = BurstSms::API.new("79798797897", "x")
8
+ end
9
+
10
+ context "Burst API credentials" do
11
+
12
+ it "Populates the API credentials in XML requests" do
13
+ @request_body = @burst.get_messages_body(0,50)
14
+ @nok_parsed = Nokogiri::XML(@request_body)
15
+ @nok_parsed.should have_xml('//request/key', '79798797897')
16
+ @nok_parsed.should have_xml('//request/secret', 'x')
17
+ end
18
+
19
+ end
20
+
21
+ context "'messages.multiple' - http://burstsms.com/api-documentation/messages.multiple" do
22
+
23
+ before(:all) do
24
+ #numbers cocktail has numbers which are valid(5 out of 10 in array) + too short, too long, landlines, duplicates, non-numerical. tests gsub formula
25
+ @numbers_cocktail = ['61490900900', '61490900910', '+61 414 899 766', '0403 855 445', '0403-855-445', '0487-000-777', '0987 788 665', '0455 777 3334', '0455 678 87', '09AB 009 456']
26
+ @request_body = @burst.send_message_body('6147779990', @numbers_cocktail, "sms txt\n of words and such:/" )
27
+ @nok_parsed = Nokogiri::XML(@request_body)
28
+ end
29
+
30
+ it "Builds correct XML structure" do
31
+ nodes = ['//request/method', '//request/params/mobile', '//request/params/message', '//request/params/caller_id']
32
+ nodes.each { |n| @nok_parsed.should have_xml(n)}
33
+ end
34
+
35
+ it "Add sendtime and contact_list if present" do
36
+ time = Time.now
37
+ @request_body = @burst.send_message_body('6147779990', @numbers_cocktail, "sms txt\n of words and such:/", :sendtime => time, :contact_list => "123456")
38
+ nok_request = Nokogiri::XML(@request_body)
39
+ nok_request.should have_xml("//request/params/sendtime")
40
+ nok_request.should have_xml("//request/params/contact_list")
41
+ end
42
+
43
+ it "Processes Recipient Numbers: Sanitises format, deletes invalid and duplicates" do
44
+ @nok_parsed.should have_xml('//params/mobile', "61490900900,61490900910,61414899766,61403855445,61487000777")
45
+ end
46
+
47
+ it "Handles single recipient number" do
48
+ @single_num = @burst.send_message_body('6147779990', '0404 678 876', "sms" )
49
+ Nokogiri::XML(@single_num).should have_xml('//params/mobile', '61404678876')
50
+ end
51
+
52
+ it "Encodes message body to URI format" do
53
+ @nok_parsed.should have_xml('//params/message', 'sms%20txt%0A%20of%20words%20and%20such%3A%2F')
54
+ end
55
+
56
+ it "Checks sender ID Length" do
57
+ expect {@burst.send_message_body('61477799900a', @numbers_cocktail, "sms" ) }.to raise_error("Sender ID is too Long")
58
+ expect {@burst.send_message_body('6147779990012345', @numbers_cocktail, "sms" ) }.to raise_error("Sender Number is too Long")
59
+
60
+ end
61
+
62
+ it "Sends correct API request and parses XML response to ruby object" do
63
+ # This has the potential to fail in ruby-1.8 due to Hash ordering... or lack of it.
64
+ stub_request(:post, BurstSms::API_URL).with(:body => File.read('spec/fixtures/api_requests/messages_multiple.txt')).to_return(:status => 200, :body => File.read('spec/fixtures/api_responses/send_message_success.txt'))
65
+ @response = @burst.send_message('6147779990', @numbers_cocktail, "sms txt\n of words and such:/" )
66
+ @response.result.should == 'queued'
67
+ @response.error.should == nil
68
+ end
69
+
70
+ it "Create error from failed response" do
71
+ stub_request(:post, BurstSms::API_URL).to_return(:status => 200, :body => File.read("spec/fixtures/api_responses/generic_failure.txt"))
72
+ @response = @burst.send_message('6147779990', @numbers_cocktail, "sms txt\n of words and such:/" )
73
+ @response.result.should == nil
74
+ @response.error.should == 'Authentication failed - key: 797987, secret: x'
75
+ end
76
+ end
77
+
78
+ context "'messages.get' - http://burstsms.com/api-documentation/messages.get" do
79
+
80
+ it "Builds correct XML structure" do
81
+ @request_body = @burst.get_messages_body(0,50)
82
+ @nok_parsed = Nokogiri::XML(@request_body)
83
+ nodes = ['//request/key', '//request/secret', '//request/version', '//request/method', '//request/params/offset', '//request/params/limit']
84
+ nodes.each { |n| @nok_parsed.should have_xml(n)}
85
+ end
86
+
87
+ it "Sends correct API request and parses XML response to ruby object" do
88
+ # This has the potential to fail in ruby-1.8 due to Hash ordering... or lack of it.
89
+ stub_request(:post, BurstSms::API_URL).with(:body => File.read('spec/fixtures/api_requests/messages_get.txt')).to_return(:status => 200, :body => File.read('spec/fixtures/api_responses/messages_get_success.txt'))
90
+ @response = @burst.get_messages()
91
+ @response.total.should == '67'
92
+ @response.messages.size.should == 4
93
+ @response.messages.first.id.should == "28153"
94
+ @response.error.should == nil
95
+ end
96
+
97
+ it "Create error from failed response" do
98
+ stub_request(:post, BurstSms::API_URL).to_return(:status => 200, :body => File.read("spec/fixtures/api_responses/generic_failure.txt"))
99
+ @response = @burst.get_messages()
100
+ @response.total.should == nil
101
+ @response.error.should == 'Authentication failed - key: 797987, secret: x'
102
+ end
103
+ end
104
+
105
+ context "'messages.add' - http://burstsms.com/api-documentation/messages.add" do
106
+
107
+ it "Builds correct XML structure" do
108
+ @request_body = @burst.add_message_body('6147779990', 123 , "sms txt\n of words and such:/")
109
+ @nok_parsed = Nokogiri::XML(@request_body)
110
+ nodes = ['//request/method', '//request/params/list_id', '//request/params/caller_id', '//request/params/message']
111
+ nodes.each { |n| @nok_parsed.should have_xml(n)}
112
+ end
113
+
114
+ it "Sends correct API request and parses XML response to ruby object" do
115
+ # This has the potential to fail in ruby-1.8 due to Hash ordering... or lack of it.
116
+ stub_request(:post, BurstSms::API_URL).with(:body => File.read('spec/fixtures/api_requests/messages_add.txt')).to_return(:status => 200, :body => File.read('spec/fixtures/api_responses/messages_add_success.txt'))
117
+ @response = @burst.add_message('6147779990', 1075 , "sms txt\n of words and such:/")
118
+ @response.total.should == '1'
119
+ @response.result.should == 'queued'
120
+ @response.list_id.should == "1075"
121
+ @response.error.should == nil
122
+ end
123
+
124
+ it "Create error from failed response" do
125
+ stub_request(:post, BurstSms::API_URL).to_return(:status => 200, :body => File.read("spec/fixtures/api_responses/generic_failure.txt"))
126
+ @response = @burst.add_message('6147779990', 1075 , "sms txt\n of words and such:/")
127
+ @response.total.should == nil
128
+ @response.error.should == 'Authentication failed - key: 797987, secret: x'
129
+ end
130
+
131
+ it "Encodes message body to URI format" do
132
+ @request_body = @burst.add_message_body('6147779990', 123 , "sms txt\n of words and such:/")
133
+ @nok_parsed = Nokogiri::XML(@request_body)
134
+ @nok_parsed.should have_xml('//params/message', 'sms%20txt%0A%20of%20words%20and%20such%3A%2F')
135
+ end
136
+
137
+ it "Checks sender ID Length" do
138
+ expect {@burst.add_message_body('61477799900a', 1075, "sms" ) }.to raise_error("Sender ID is too Long")
139
+ expect {@burst.add_message_body('6147779990012345', 1075, "sms" ) }.to raise_error("Sender Number is too Long")
140
+
141
+ end
142
+ end
143
+
144
+ context "'messages.responses' - http://burstsms.com/api-documentation/messages.responses" do
145
+
146
+ it "Builds correct XML structure" do
147
+ @request_body = @burst.message_responses_body('123', 0 , 50)
148
+ @nok_parsed = Nokogiri::XML(@request_body)
149
+ nodes = ['//request/method', '//request/params/message_id', '//request/params/offset', '//request/params/limit']
150
+ nodes.each { |n| @nok_parsed.should have_xml(n)}
151
+ end
152
+
153
+ it "Sends correct API request and parses XML response to ruby object" do
154
+ # This has the potential to fail in ruby-1.8 due to Hash ordering... or lack of it.
155
+ stub_request(:post, BurstSms::API_URL).with(:body => File.read('spec/fixtures/api_requests/message_responses.txt')).to_return(:status => 200, :body => File.read('spec/fixtures/api_responses/message_responses_success.txt'))
156
+ @response = @burst.message_responses('123')
157
+ @response.total.should == '4'
158
+ @response.replies.size.should == 1
159
+ @response.replies.first.firstname.should == "Bob"
160
+ @response.error.should == nil
161
+ end
162
+
163
+ it "Create error from failed response" do
164
+ stub_request(:post, BurstSms::API_URL).to_return(:status => 200, :body => File.read("spec/fixtures/api_responses/generic_failure.txt"))
165
+ @response = @burst.message_responses('123')
166
+ @response.total.should == nil
167
+ @response.error.should == 'Authentication failed - key: 797987, secret: x'
168
+ end
169
+ end
170
+
171
+ end