ballou_sms_gateway 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +5 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/Readme.md +80 -0
- data/ballou_sms_gateway.gemspec +25 -0
- data/lib/ballou_sms_gateway/request.rb +24 -0
- data/lib/ballou_sms_gateway.rb +153 -0
- data/spec/ballou_sms_gateway_spec.rb +213 -0
- data/spec/fixtures/vcr_cassettes/invalid-request.yml +32 -0
- data/spec/fixtures/vcr_cassettes/valid-request.yml +218 -0
- data/spec/spec_helper.rb +25 -0
- metadata +145 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Ballou SMS Gateway
|
2
|
+
|
3
|
+
Ruby bindings for [Ballou's SMS Gateway](http://www.ballou.se/tj%C3%A4nster/sms-verktyg).
|
4
|
+
|
5
|
+
Follow me on [Twitter](http://twitter.com/linusoleander) or [Github](https://github.com/oleander/) for more info and updates.
|
6
|
+
|
7
|
+
## How to use
|
8
|
+
|
9
|
+
### Send a message
|
10
|
+
|
11
|
+
``` ruby
|
12
|
+
BallouSmsGateway.new.username("u").password("p").from("Github").to("070XXXXXXX").message("Hello world!").send!
|
13
|
+
```
|
14
|
+
|
15
|
+
### Send a message to multiply receivers
|
16
|
+
|
17
|
+
``` ruby
|
18
|
+
BallouSmsGateway.new.username("u").password("p").from("Github").to("070XXXXXXX", "070YYYYYYY").message("Hello world!").send!
|
19
|
+
```
|
20
|
+
|
21
|
+
### Send a very long message
|
22
|
+
|
23
|
+
Add the `long` method to the chain to send up to *918* characters.
|
24
|
+
|
25
|
+
``` ruby
|
26
|
+
BallouSmsGateway.new.username("u").password("p").from("Github").to("070XXXXXXX").message("A very long message ...").long.send!
|
27
|
+
```
|
28
|
+
|
29
|
+
### Options
|
30
|
+
|
31
|
+
The list below is a set of methods that can be chained, like above. **Order doesn't matter.**
|
32
|
+
|
33
|
+
- **id** (String) (CR) (Optimal) A unique ID for the text message. Used for statics. Default is a [UUID string](http://en.wikipedia.org/wiki/Universally_unique_identifier).
|
34
|
+
- **username** (String) (UN) Ballou username.
|
35
|
+
- **password** (String) (PW) Ballou password.
|
36
|
+
- **from** (String) (O) Who is the SMS from? Up to 10 character using text or up to 15 character using only numbers.
|
37
|
+
- **to** (String or Array< String >) (D) SMS receiver(s). May begin with a plus sign, otherwise just integers.
|
38
|
+
- **message** (String) (M) Message to be send. Max 160 character, if the `long` flag isn't set.
|
39
|
+
- **long** (No argument) (LONGSMS) Makes it possible to send a long message, up to *918* character.
|
40
|
+
- **request_id** (String) (RI) (Optimal) Default is a [UUID string](http://en.wikipedia.org/wiki/Universally_unique_identifier).
|
41
|
+
|
42
|
+
Take a look at the [official (swedish) site](http://www.ballou.se/exempel/) for more information.
|
43
|
+
|
44
|
+
### The send! method
|
45
|
+
|
46
|
+
When you're done buildning your query the final thing todo is to apply the `send!` method.
|
47
|
+
It'll fire the request or raise an error if something was wrong.
|
48
|
+
|
49
|
+
The `send!` method returns a request object with the following methods.
|
50
|
+
|
51
|
+
- **id** (String) A unique ID generated Ballou.
|
52
|
+
- **request_id** (String) Request ID defined by you using the `request_id` method, or an auto-generated UUID string.
|
53
|
+
- **sms_id** (String) ID defined by you using the `id` method, or an auto-generated UUID string.
|
54
|
+
- **to** (String) Receiver specified by you using the `to` method.
|
55
|
+
- **send?** (Boolean) Was the SMS send?
|
56
|
+
- **valid?** (Boolean) Alias for `send?`.
|
57
|
+
- **error** (Fixnum) Error code. `0` if everything went okay.
|
58
|
+
- **status** (Fixnum) Status code. `-1` means that the SMS was added to Ballou's queue.
|
59
|
+
- **message** (String) A message from Ballou. This is set when a request goes wrong.
|
60
|
+
|
61
|
+
Here are some custom states that might be useful to know about.
|
62
|
+
|
63
|
+
When a request goes wrong, like `404`, `500` and so on, the `status` method is set to `-2`.
|
64
|
+
This, in most cases, means that you should take a look at the `error` status code for more information.
|
65
|
+
Error `7` means that the request resulted in a non `2xx` response. This should not happend unless Ballou goes down or in someway changes the API.
|
66
|
+
Take a look at the `message` method for more information.
|
67
|
+
|
68
|
+
For *even* more information and status codes, visit the [official site](http://www.ballou.se/exempel/).
|
69
|
+
|
70
|
+
## How to install
|
71
|
+
|
72
|
+
[sudo] gem install ballou_sms_gateway
|
73
|
+
|
74
|
+
## Requirements
|
75
|
+
|
76
|
+
*Ballou SMS gateway* is tested in *OS X 10.7.2* using Ruby *1.9.2*.
|
77
|
+
|
78
|
+
## License
|
79
|
+
|
80
|
+
*Ballou SMS gateway* is released under the *MIT license*.
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.authors = ["Linus Oleander"]
|
3
|
+
gem.email = ["linus@oleander.nu"]
|
4
|
+
gem.description = %q{Ruby bindings for Ballou's (ballou.se) SMS Gateway.}
|
5
|
+
gem.summary = %q{Ruby bindings for Ballou's (ballou.se) SMS Gateway.}
|
6
|
+
gem.homepage = "https://github.com/oleander/ballou-sms-gateway"
|
7
|
+
|
8
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
9
|
+
gem.files = `git ls-files`.split("\n")
|
10
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
11
|
+
gem.name = "ballou_sms_gateway"
|
12
|
+
gem.require_paths = ["lib"]
|
13
|
+
gem.version = "1.0.0"
|
14
|
+
|
15
|
+
gem.add_dependency("rest-client", "~> 1.6.7")
|
16
|
+
gem.add_dependency("uuid", "~> 2.3.4")
|
17
|
+
gem.add_dependency("nokogiri", "~> 1.5.0")
|
18
|
+
gem.add_dependency("acts_as_chain", "~> 1.0.1")
|
19
|
+
|
20
|
+
gem.add_development_dependency("vcr")
|
21
|
+
gem.add_development_dependency("rspec")
|
22
|
+
gem.add_development_dependency("webmock")
|
23
|
+
|
24
|
+
gem.required_ruby_version = "~> 1.9.0"
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module BallouSmsGatewayModule
|
2
|
+
class Request
|
3
|
+
attr_reader :id, :to, :sms_id, :request_id, :message
|
4
|
+
def initialize(args)
|
5
|
+
args.keys.each { |name| instance_variable_set "@" + name.to_s, args[name] }
|
6
|
+
end
|
7
|
+
#
|
8
|
+
# @return Boolean Did everything went okay?
|
9
|
+
#
|
10
|
+
def send?
|
11
|
+
error == 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def status
|
15
|
+
@status ? @status.to_i : -2
|
16
|
+
end
|
17
|
+
|
18
|
+
def error
|
19
|
+
@error.to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :valid?, :send?
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require "uuid"
|
2
|
+
require "rest-client"
|
3
|
+
require "uri"
|
4
|
+
require "cgi"
|
5
|
+
require "acts_as_chain"
|
6
|
+
require "nokogiri"
|
7
|
+
require "iconv"
|
8
|
+
require "ballou_sms_gateway/request"
|
9
|
+
|
10
|
+
class BallouSmsGateway
|
11
|
+
acts_as_chain :username, :password, :id, :request_id, :message
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
#
|
15
|
+
# @UN Username
|
16
|
+
# @PW Password
|
17
|
+
# @O Sender
|
18
|
+
# @RI Request id
|
19
|
+
# @CR SMS id
|
20
|
+
# @D Receiver
|
21
|
+
# @LONGSMS Is this a long sms?
|
22
|
+
# @M Message
|
23
|
+
#
|
24
|
+
@url = %w{
|
25
|
+
http://sms2.ballou.se/http/get/SendSms.php?
|
26
|
+
UN=%s&
|
27
|
+
PW=%s&
|
28
|
+
CR=%s&
|
29
|
+
RI=%s&
|
30
|
+
O=%s&
|
31
|
+
D=%s&
|
32
|
+
LONGSMS=%s&
|
33
|
+
M=%s
|
34
|
+
}.join
|
35
|
+
|
36
|
+
@id = UUID.new.generate
|
37
|
+
@long = false
|
38
|
+
@request_id = UUID.new.generate
|
39
|
+
@error_message = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def long
|
43
|
+
tap { @long = true }
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Sends the message. Raises error if message is to long or if @send and @from isn't set.
|
48
|
+
#
|
49
|
+
def send!
|
50
|
+
if @message.length > 160 and not @long
|
51
|
+
raise "Message is to long, #{@message.length} characters."
|
52
|
+
end
|
53
|
+
|
54
|
+
[:from, :to, :password, :username].each do |method|
|
55
|
+
var = instance_variable_get("@#{method}")
|
56
|
+
unless var
|
57
|
+
raise "You need to specify #{method}, using the ##{method} method."
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
defaults = {
|
62
|
+
sms_id: @id,
|
63
|
+
request_id: @request_id
|
64
|
+
}
|
65
|
+
|
66
|
+
doc = Nokogiri::XML(do_request!)
|
67
|
+
if response = doc.at_css("response message")
|
68
|
+
BallouSmsGatewayModule::Request.new({
|
69
|
+
id: response.attr("id"),
|
70
|
+
message: response.text,
|
71
|
+
to: response.attr("to_msisdn"),
|
72
|
+
status: response.attr("status"),
|
73
|
+
error: response.attr("error")
|
74
|
+
}.merge(defaults))
|
75
|
+
elsif response = doc.at_css("ballou_sms_response error")
|
76
|
+
BallouSmsGatewayModule::Request.new({
|
77
|
+
to: @to,
|
78
|
+
status: -2,
|
79
|
+
error: response.attr("code"),
|
80
|
+
message: response.text,
|
81
|
+
}.merge(defaults))
|
82
|
+
else
|
83
|
+
BallouSmsGatewayModule::Request.new({
|
84
|
+
to: @to,
|
85
|
+
status: -2,
|
86
|
+
error: 7,
|
87
|
+
message: @error_message
|
88
|
+
}.merge(defaults))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# @to A list of phonenumbers. Can contain 0-9 and the "+" sign.
|
94
|
+
# @return BallouSmsGateway
|
95
|
+
def to(*to)
|
96
|
+
to.flatten.each do |number|
|
97
|
+
unless number.to_s.match(/^\+?[0-9]{4,}$/)
|
98
|
+
raise "Invalid receiver."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
@to = to.flatten.map { |number| number }.join(",")
|
103
|
+
return self
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# @from String Sender. Max length when only numbers are submitet; 15, otherwise; 10
|
108
|
+
# @return BallouSmsGateway
|
109
|
+
#
|
110
|
+
def from(from)
|
111
|
+
if from.to_s.length.zero?
|
112
|
+
raise "Sender is invalid, to short."
|
113
|
+
end
|
114
|
+
|
115
|
+
# Max length 15 for integers and 10 for chars
|
116
|
+
if from.match(/^[0-9]+$/)
|
117
|
+
if from.length > 15
|
118
|
+
raise "Sender is invalid, to long."
|
119
|
+
end
|
120
|
+
elsif from.length > 10
|
121
|
+
raise "Sender is invalid, to long."
|
122
|
+
end
|
123
|
+
|
124
|
+
@from = from
|
125
|
+
return self
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
def url
|
130
|
+
@url % [
|
131
|
+
@username,
|
132
|
+
@password,
|
133
|
+
@id,
|
134
|
+
@request_id,
|
135
|
+
@from,
|
136
|
+
@to,
|
137
|
+
@long,
|
138
|
+
@message
|
139
|
+
].map{|v| URI::escape(to_latin_1(v))}
|
140
|
+
end
|
141
|
+
|
142
|
+
def do_request!
|
143
|
+
data = RestClient.get(url)
|
144
|
+
rescue RestClient::Exception
|
145
|
+
@error_message = $!.message
|
146
|
+
ensure
|
147
|
+
data || ""
|
148
|
+
end
|
149
|
+
|
150
|
+
def to_latin_1(string)
|
151
|
+
Iconv.conv("ISO-8859-1", "UTF-8", string.to_s)
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
describe BallouSmsGateway do
|
2
|
+
let(:long_message) { "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut a" }
|
3
|
+
let(:message) { "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostr" }
|
4
|
+
let(:gateway) { BallouSmsGateway.new }
|
5
|
+
let(:from) { "Person A" }
|
6
|
+
let(:to) { "0702211444" }
|
7
|
+
let(:id) { "858426d0-e17c-012e-9cc9-58b035fcfcff" }
|
8
|
+
let(:request_id) { "345b9360-e17c-012e-9c99-58b035fcfcff" }
|
9
|
+
|
10
|
+
describe "#message" do
|
11
|
+
before(:each) do
|
12
|
+
RestClient.should_receive(:get).any_number_of_times
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should raise an error if message is to long" do
|
16
|
+
lambda {
|
17
|
+
gateway.message(long_message).send!
|
18
|
+
}.should raise_error("Message is to long, 201 characters.")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not raise error if message is to long, if #long is used" do
|
22
|
+
lambda {
|
23
|
+
gateway.long.message(long_message).send!
|
24
|
+
}.should_not raise_error("Message is to long, 201 characters.")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#send!" do
|
29
|
+
before(:each) do
|
30
|
+
RestClient.should_receive(:get).any_number_of_times
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should raise error if we're trying to send a non valid message" do
|
34
|
+
lambda {
|
35
|
+
gateway.message(message).send!
|
36
|
+
}.should raise_error("You need to specify from, using the #from method.")
|
37
|
+
|
38
|
+
lambda {
|
39
|
+
gateway.from(from).message(message).send!
|
40
|
+
}.should raise_error("You need to specify to, using the #to method.")
|
41
|
+
|
42
|
+
lambda {
|
43
|
+
gateway.from(from).to(to).message(message).send!
|
44
|
+
}.should raise_error("You need to specify password, using the #password method.")
|
45
|
+
|
46
|
+
lambda {
|
47
|
+
gateway.from(from).to(to).message(message).send!
|
48
|
+
}.should raise_error("You need to specify password, using the #password method.")
|
49
|
+
|
50
|
+
lambda {
|
51
|
+
gateway.from(from).to(to).password("password").message(message).send!
|
52
|
+
}.should raise_error("You need to specify username, using the #username method.")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#to" do
|
57
|
+
before(:each) do
|
58
|
+
RestClient.should_receive(:get).any_number_of_times
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should fail duo to invalid phonenumber" do
|
62
|
+
["invalid", "070-123-123", "070invalid", ["invalid"], "070+220022"].each do |number|
|
63
|
+
lambda {
|
64
|
+
gateway.to(number)
|
65
|
+
}.should raise_error("Invalid receiver.")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not fail" do
|
70
|
+
["070123123", ["070229393", "+070203993"], "8372928384"].each do |number|
|
71
|
+
lambda {
|
72
|
+
gateway.to(*number)
|
73
|
+
}.should_not raise_error
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#from" do
|
79
|
+
it "should fail, it's to long - or short" do
|
80
|
+
["aaaaaaaaaaaa", "12345678910111213141516", ""].each do |number|
|
81
|
+
lambda {
|
82
|
+
gateway.from(number)
|
83
|
+
}.should raise_error(RuntimeError)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should not fail" do
|
88
|
+
["aaaaaaaaaa", "123456789123456", "a", "1"].each do |number|
|
89
|
+
lambda {
|
90
|
+
gateway.from(number)
|
91
|
+
}.should_not raise_error
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#request_id and #id" do
|
98
|
+
it "should be possible to pass id" do
|
99
|
+
stub_request(:get, /.*/).to_return(status: 200)
|
100
|
+
request = gateway.
|
101
|
+
password(USER["password"]).
|
102
|
+
username(USER["username"]).
|
103
|
+
from("BallouSms").
|
104
|
+
to(USER["phone"]).
|
105
|
+
id("my_custom_id").
|
106
|
+
request_id(request_id).
|
107
|
+
message("This is an example").
|
108
|
+
send!
|
109
|
+
a_request(:get, /CR=my_custom_id/).should have_been_made.once
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should be possible to pass request_id" do
|
113
|
+
stub_request(:get, /.*/).to_return(status: 200)
|
114
|
+
request = gateway.
|
115
|
+
password(USER["password"]).
|
116
|
+
username(USER["username"]).
|
117
|
+
from("BallouSms").
|
118
|
+
to(USER["phone"]).
|
119
|
+
id(id).
|
120
|
+
request_id("my_custom_request_id").
|
121
|
+
message("This is an example").
|
122
|
+
send!
|
123
|
+
a_request(:get, /RI=my_custom_request_id/).should have_been_made.once
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "request" do
|
128
|
+
use_vcr_cassette "valid-request"
|
129
|
+
|
130
|
+
it "should be possible to send a message" do
|
131
|
+
request = gateway.
|
132
|
+
password(USER["password"]).
|
133
|
+
username(USER["username"]).
|
134
|
+
from("BallouSms").
|
135
|
+
to(USER["phone"]).
|
136
|
+
id(id).
|
137
|
+
request_id(request_id).
|
138
|
+
message("This is an example").
|
139
|
+
send!
|
140
|
+
|
141
|
+
request.id.should eq("219578214912")
|
142
|
+
request.sms_id.should eq(id)
|
143
|
+
request.request_id.should eq(request_id)
|
144
|
+
request.to.should eq(USER["phone"])
|
145
|
+
request.status.should eq(-1)
|
146
|
+
request.error.should eq(0)
|
147
|
+
request.message.should be_empty
|
148
|
+
request.should be_send
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should send message to invalid receiver" do
|
152
|
+
request = gateway.
|
153
|
+
password(USER["password"]).
|
154
|
+
username(USER["username"]).
|
155
|
+
from("BallouSms").
|
156
|
+
to("07011").
|
157
|
+
id(id).
|
158
|
+
request_id(request_id).
|
159
|
+
message("This is an example").
|
160
|
+
send!
|
161
|
+
|
162
|
+
request.to.should eq("07011")
|
163
|
+
request.status.should eq(-2)
|
164
|
+
request.sms_id.should eq(id)
|
165
|
+
request.request_id.should eq(request_id)
|
166
|
+
request.error.should eq(3)
|
167
|
+
request.should_not be_send
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should be able to handle request errors" do
|
171
|
+
stub_request(:get, /.*/).to_return(status: 404)
|
172
|
+
request = gateway.
|
173
|
+
password(USER["password"]).
|
174
|
+
username(USER["username"]).
|
175
|
+
from("BallouSms").
|
176
|
+
to(USER["phone"]).
|
177
|
+
id(id).
|
178
|
+
request_id(request_id).
|
179
|
+
message("This is an example").
|
180
|
+
send!
|
181
|
+
|
182
|
+
request.to.should eq(USER["phone"])
|
183
|
+
request.status.should eq(-2)
|
184
|
+
request.sms_id.should eq(id)
|
185
|
+
request.request_id.should eq(request_id)
|
186
|
+
request.error.should eq(7)
|
187
|
+
request.should_not be_send
|
188
|
+
request.message.should eq("404 Resource Not Found")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "invalid request" do
|
193
|
+
use_vcr_cassette "invalid-request"
|
194
|
+
|
195
|
+
it "should be able to handle error messages" do
|
196
|
+
request = gateway.
|
197
|
+
password("invalid").
|
198
|
+
username("invalid").
|
199
|
+
from("BallouSms").
|
200
|
+
to(USER["phone"]).
|
201
|
+
id(id).
|
202
|
+
request_id(request_id).
|
203
|
+
message("This is an example").
|
204
|
+
send!
|
205
|
+
|
206
|
+
request.should_not be_valid
|
207
|
+
request.should_not be_send
|
208
|
+
request.error.should eq(2)
|
209
|
+
request.status.should eq(-2)
|
210
|
+
request.message.should eq("Authentication failed or IP rejected")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=858426d0-e17c-012e-9cc9-58b035fcfcff&D=<phone>&LONGSMS=false&M=This%20is%20an%20example&O=BallouSms&PW=invalid&RI=345b9360-e17c-012e-9c99-58b035fcfcff&UN=invalid
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
accept:
|
9
|
+
- "*/*; q=0.5, application/xml"
|
10
|
+
accept-encoding:
|
11
|
+
- gzip, deflate
|
12
|
+
response: !ruby/struct:VCR::Response
|
13
|
+
status: !ruby/struct:VCR::ResponseStatus
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Wed, 26 Oct 2011 11:08:23 GMT
|
19
|
+
server:
|
20
|
+
- Apache
|
21
|
+
content-length:
|
22
|
+
- "277"
|
23
|
+
content-type:
|
24
|
+
- text/xml
|
25
|
+
body: |
|
26
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
27
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
28
|
+
<ballou_sms_response>
|
29
|
+
<error code="2">Authentication failed or IP rejected</error>
|
30
|
+
</ballou_sms_response>
|
31
|
+
|
32
|
+
http_version: "1.1"
|
@@ -0,0 +1,218 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=345b9360-e17c-012e-9c99-58b035fcfcff&D=<phone>&LONGSMS=false&M=This%20is%20an%20example&O=BallouSms&PW=<password>&RI=345b9840-e17c-012e-9c9a-58b035fcfcff&UN=<username>
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
accept:
|
9
|
+
- "*/*; q=0.5, application/xml"
|
10
|
+
accept-encoding:
|
11
|
+
- gzip, deflate
|
12
|
+
response: !ruby/struct:VCR::Response
|
13
|
+
status: !ruby/struct:VCR::ResponseStatus
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Tue, 25 Oct 2011 21:14:08 GMT
|
19
|
+
server:
|
20
|
+
- Apache
|
21
|
+
content-length:
|
22
|
+
- "326"
|
23
|
+
content-type:
|
24
|
+
- text/xml
|
25
|
+
body: |
|
26
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
27
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
28
|
+
<ballou_sms_response>
|
29
|
+
<response type="status"><message id="219577248823" to_msisdn="<phone>" status="-1" error="0"/></response>
|
30
|
+
</ballou_sms_response>
|
31
|
+
|
32
|
+
http_version: "1.1"
|
33
|
+
- !ruby/struct:VCR::HTTPInteraction
|
34
|
+
request: !ruby/struct:VCR::Request
|
35
|
+
method: :get
|
36
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=377ff250-e17c-012e-9ca9-58b035fcfcff&D=<phone>&LONGSMS=false&M=This%20is%20an%20example&O=BallouSms&PW=<password>&RI=377ff770-e17c-012e-9caa-58b035fcfcff&UN=<username>
|
37
|
+
body:
|
38
|
+
headers:
|
39
|
+
accept:
|
40
|
+
- "*/*; q=0.5, application/xml"
|
41
|
+
accept-encoding:
|
42
|
+
- gzip, deflate
|
43
|
+
response: !ruby/struct:VCR::Response
|
44
|
+
status: !ruby/struct:VCR::ResponseStatus
|
45
|
+
code: 200
|
46
|
+
message: OK
|
47
|
+
headers:
|
48
|
+
date:
|
49
|
+
- Tue, 25 Oct 2011 21:14:13 GMT
|
50
|
+
server:
|
51
|
+
- Apache
|
52
|
+
content-length:
|
53
|
+
- "326"
|
54
|
+
content-type:
|
55
|
+
- text/xml
|
56
|
+
body: |
|
57
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
58
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
59
|
+
<ballou_sms_response>
|
60
|
+
<response type="status"><message id="219577253825" to_msisdn="<phone>" status="-1" error="0"/></response>
|
61
|
+
</ballou_sms_response>
|
62
|
+
|
63
|
+
http_version: "1.1"
|
64
|
+
- !ruby/struct:VCR::HTTPInteraction
|
65
|
+
request: !ruby/struct:VCR::Request
|
66
|
+
method: :get
|
67
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=4460ef30-e17c-012e-9cb9-58b035fcfcff&D=<phone>&LONGSMS=false&M=This%20is%20an%20example&O=BallouSms&PW=<password>&RI=4460f640-e17c-012e-9cba-58b035fcfcff&UN=<username>
|
68
|
+
body:
|
69
|
+
headers:
|
70
|
+
accept:
|
71
|
+
- "*/*; q=0.5, application/xml"
|
72
|
+
accept-encoding:
|
73
|
+
- gzip, deflate
|
74
|
+
response: !ruby/struct:VCR::Response
|
75
|
+
status: !ruby/struct:VCR::ResponseStatus
|
76
|
+
code: 200
|
77
|
+
message: OK
|
78
|
+
headers:
|
79
|
+
date:
|
80
|
+
- Tue, 25 Oct 2011 21:14:35 GMT
|
81
|
+
server:
|
82
|
+
- Apache
|
83
|
+
content-length:
|
84
|
+
- "326"
|
85
|
+
content-type:
|
86
|
+
- text/xml
|
87
|
+
body: |
|
88
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
89
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
90
|
+
<ballou_sms_response>
|
91
|
+
<response type="status"><message id="219577275827" to_msisdn="<phone>" status="-1" error="0"/></response>
|
92
|
+
</ballou_sms_response>
|
93
|
+
|
94
|
+
http_version: "1.1"
|
95
|
+
- !ruby/struct:VCR::HTTPInteraction
|
96
|
+
request: !ruby/struct:VCR::Request
|
97
|
+
method: :get
|
98
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=858426d0-e17c-012e-9cc9-58b035fcfcff&D=<phone>&LONGSMS=false&M=This%20is%20an%20example&O=BallouSms&PW=<password>&RI=85842bf0-e17c-012e-9cca-58b035fcfcff&UN=<username>
|
99
|
+
body:
|
100
|
+
headers:
|
101
|
+
accept:
|
102
|
+
- "*/*; q=0.5, application/xml"
|
103
|
+
accept-encoding:
|
104
|
+
- gzip, deflate
|
105
|
+
response: !ruby/struct:VCR::Response
|
106
|
+
status: !ruby/struct:VCR::ResponseStatus
|
107
|
+
code: 200
|
108
|
+
message: OK
|
109
|
+
headers:
|
110
|
+
date:
|
111
|
+
- Tue, 25 Oct 2011 21:16:24 GMT
|
112
|
+
server:
|
113
|
+
- Apache
|
114
|
+
content-length:
|
115
|
+
- "326"
|
116
|
+
content-type:
|
117
|
+
- text/xml
|
118
|
+
body: |
|
119
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
120
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
121
|
+
<ballou_sms_response>
|
122
|
+
<response type="status"><message id="219577384846" to_msisdn="<phone>" status="-1" error="0"/></response>
|
123
|
+
</ballou_sms_response>
|
124
|
+
|
125
|
+
http_version: "1.1"
|
126
|
+
- !ruby/struct:VCR::HTTPInteraction
|
127
|
+
request: !ruby/struct:VCR::Request
|
128
|
+
method: :get
|
129
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=858426d0-e17c-012e-9cc9-58b035fcfcff&D=<phone>&LONGSMS=false&M=This%20is%20an%20example&O=BallouSms&PW=<password>&RI=345b9360-e17c-012e-9c99-58b035fcfcff&UN=<username>
|
130
|
+
body:
|
131
|
+
headers:
|
132
|
+
accept:
|
133
|
+
- "*/*; q=0.5, application/xml"
|
134
|
+
accept-encoding:
|
135
|
+
- gzip, deflate
|
136
|
+
response: !ruby/struct:VCR::Response
|
137
|
+
status: !ruby/struct:VCR::ResponseStatus
|
138
|
+
code: 200
|
139
|
+
message: OK
|
140
|
+
headers:
|
141
|
+
date:
|
142
|
+
- Tue, 25 Oct 2011 21:30:14 GMT
|
143
|
+
server:
|
144
|
+
- Apache
|
145
|
+
content-length:
|
146
|
+
- "326"
|
147
|
+
content-type:
|
148
|
+
- text/xml
|
149
|
+
body: |
|
150
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
151
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
152
|
+
<ballou_sms_response>
|
153
|
+
<response type="status"><message id="219578214912" to_msisdn="<phone>" status="-1" error="0"/></response>
|
154
|
+
</ballou_sms_response>
|
155
|
+
|
156
|
+
http_version: "1.1"
|
157
|
+
- !ruby/struct:VCR::HTTPInteraction
|
158
|
+
request: !ruby/struct:VCR::Request
|
159
|
+
method: :get
|
160
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=858426d0-e17c-012e-9cc9-58b035fcfcff&D=07011&LONGSMS=false&M=This%20is%20an%20example&O=BallouSms&PW=<password>&RI=345b9360-e17c-012e-9c99-58b035fcfcff&UN=<username>
|
161
|
+
body:
|
162
|
+
headers:
|
163
|
+
accept:
|
164
|
+
- "*/*; q=0.5, application/xml"
|
165
|
+
accept-encoding:
|
166
|
+
- gzip, deflate
|
167
|
+
response: !ruby/struct:VCR::Response
|
168
|
+
status: !ruby/struct:VCR::ResponseStatus
|
169
|
+
code: 200
|
170
|
+
message: OK
|
171
|
+
headers:
|
172
|
+
date:
|
173
|
+
- Tue, 25 Oct 2011 21:47:08 GMT
|
174
|
+
server:
|
175
|
+
- Apache
|
176
|
+
content-length:
|
177
|
+
- "291"
|
178
|
+
content-type:
|
179
|
+
- text/xml
|
180
|
+
body: |
|
181
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
182
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
183
|
+
<ballou_sms_response>
|
184
|
+
<response type="status"><message to_msisdn="07011" error="3"/></response>
|
185
|
+
</ballou_sms_response>
|
186
|
+
|
187
|
+
http_version: "1.1"
|
188
|
+
- !ruby/struct:VCR::HTTPInteraction
|
189
|
+
request: !ruby/struct:VCR::Request
|
190
|
+
method: :get
|
191
|
+
uri: http://sms2.ballou.se:80/http/get/SendSms.php?CR=URI::escape(@id)&D=@to&LONGSMS=@long&M=CGI::escape(@message)&O=@from&PW=URI::escape(@password)&RI=URI::escape(@request_id)&UN=URI::escape(@username)
|
192
|
+
body:
|
193
|
+
headers:
|
194
|
+
accept:
|
195
|
+
- "*/*; q=0.5, application/xml"
|
196
|
+
accept-encoding:
|
197
|
+
- gzip, deflate
|
198
|
+
response: !ruby/struct:VCR::Response
|
199
|
+
status: !ruby/struct:VCR::ResponseStatus
|
200
|
+
code: 200
|
201
|
+
message: OK
|
202
|
+
headers:
|
203
|
+
date:
|
204
|
+
- Tue, 25 Oct 2011 22:11:30 GMT
|
205
|
+
server:
|
206
|
+
- Apache
|
207
|
+
content-length:
|
208
|
+
- "277"
|
209
|
+
content-type:
|
210
|
+
- text/xml
|
211
|
+
body: |
|
212
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
213
|
+
<!DOCTYPE ballou_sms_response PUBLIC "-//ballou//SMS Response DTD//EN" "http://sms2.ballou.se/dtd/ballou_sms_response.dtd">
|
214
|
+
<ballou_sms_response>
|
215
|
+
<error code="2">Authentication failed or IP rejected</error>
|
216
|
+
</ballou_sms_response>
|
217
|
+
|
218
|
+
http_version: "1.1"
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "rspec"
|
2
|
+
require "webmock/rspec"
|
3
|
+
require "movies"
|
4
|
+
require "vcr"
|
5
|
+
require "ballou_sms_gateway"
|
6
|
+
|
7
|
+
USER = YAML.load_file "./spec/fixtures/user_details.yml"
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.mock_with :rspec
|
11
|
+
config.extend VCR::RSpec::Macros
|
12
|
+
end
|
13
|
+
|
14
|
+
VCR.config do |c|
|
15
|
+
c.cassette_library_dir = "spec/fixtures/vcr_cassettes"
|
16
|
+
c.stub_with :webmock
|
17
|
+
c.default_cassette_options = {
|
18
|
+
record: :new_episodes
|
19
|
+
}
|
20
|
+
c.allow_http_connections_when_no_cassette = false
|
21
|
+
|
22
|
+
USER.keys.each do |key|
|
23
|
+
c.filter_sensitive_data("<#{key}>") { USER[key].to_s }
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ballou_sms_gateway
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Linus Oleander
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-10-26 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rest-client
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.6.7
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: uuid
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.3.4
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: nokogiri
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.5.0
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: acts_as_chain
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.0.1
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id004
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: vcr
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id005
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id006
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: webmock
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
type: :development
|
91
|
+
version_requirements: *id007
|
92
|
+
description: Ruby bindings for Ballou's (ballou.se) SMS Gateway.
|
93
|
+
email:
|
94
|
+
- linus@oleander.nu
|
95
|
+
executables: []
|
96
|
+
|
97
|
+
extensions: []
|
98
|
+
|
99
|
+
extra_rdoc_files: []
|
100
|
+
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- .rspec
|
104
|
+
- Gemfile
|
105
|
+
- Rakefile
|
106
|
+
- Readme.md
|
107
|
+
- ballou_sms_gateway.gemspec
|
108
|
+
- lib/ballou_sms_gateway.rb
|
109
|
+
- lib/ballou_sms_gateway/request.rb
|
110
|
+
- spec/ballou_sms_gateway_spec.rb
|
111
|
+
- spec/fixtures/vcr_cassettes/invalid-request.yml
|
112
|
+
- spec/fixtures/vcr_cassettes/valid-request.yml
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
homepage: https://github.com/oleander/ballou-sms-gateway
|
115
|
+
licenses: []
|
116
|
+
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ~>
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: 1.9.0
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: "0"
|
134
|
+
requirements: []
|
135
|
+
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 1.8.8
|
138
|
+
signing_key:
|
139
|
+
specification_version: 3
|
140
|
+
summary: Ruby bindings for Ballou's (ballou.se) SMS Gateway.
|
141
|
+
test_files:
|
142
|
+
- spec/ballou_sms_gateway_spec.rb
|
143
|
+
- spec/fixtures/vcr_cassettes/invalid-request.yml
|
144
|
+
- spec/fixtures/vcr_cassettes/valid-request.yml
|
145
|
+
- spec/spec_helper.rb
|