cellular 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Guardfile +6 -0
- data/README.md +39 -3
- data/Rakefile +8 -0
- data/cellular.gemspec +10 -1
- data/lib/cellular/backends.rb +1 -0
- data/lib/cellular/backends/cool_sms.rb +33 -0
- data/lib/cellular/backends/sendega.rb +19 -9
- data/lib/cellular/models/sms.rb +2 -2
- data/lib/cellular/version.rb +1 -1
- data/spec/cellular/backends/cool_sms_spec.rb +67 -0
- data/spec/cellular/backends/sendega_spec.rb +101 -0
- data/spec/cellular/configuration_spec.rb +14 -0
- data/spec/cellular/models/sms_spec.rb +68 -0
- data/spec/cellular_spec.rb +28 -0
- data/spec/fixtures/backends/cool_sms/failure.xml +6 -0
- data/spec/fixtures/backends/cool_sms/success.xml +11 -0
- data/spec/fixtures/backends/sendega/failure.xml +13 -0
- data/spec/fixtures/backends/sendega/service.wsdl +491 -0
- data/spec/fixtures/backends/sendega/success.xml +13 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/fixture.rb +4 -0
- metadata +139 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d69945358dbd5a90eda81aee664adfffe7a971a
|
4
|
+
data.tar.gz: d0cccde1eb19cc6d1eb8b54d2414ee21815f02f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e752bde39f9752f58f4e5c09aa2eb73a431c19066324aeb69a45930b83393aa59e042e5afe8549c5c23c749bdf5d390880273b977cee25a8f0c959080cb255f
|
7
|
+
data.tar.gz: 87d001976dbefd1fc8b7bc76f6e01007ebe23e17f28ec74f0a2ac37c6d8b9fdab0de2cd5b7c623935bfb7487c11e928b4b17fe6e4c35a6d506e1f254201821b2
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
# Cellular
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/cellular.png)](https://rubygems.org/gems/cellular)
|
4
|
+
[![Build Status](https://secure.travis-ci.org/hyperoslo/cellular.png?branch=master)](https://travis-ci.org/hyperoslo/cellular)
|
5
|
+
[![Dependency Status](https://gemnasium.com/hyperoslo/cellular.png)](https://gemnasium.com/hyperoslo/cellular)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/hyperoslo/cellular.png)](https://codeclimate.com/github/hyperoslo/cellular)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/hyperoslo/cellular/badge.png?branch=master)](https://coveralls.io/r/hyperoslo/cellular)
|
8
|
+
|
3
9
|
Sending and receiving SMSs with Ruby through pluggable backends.
|
4
10
|
|
5
|
-
**Supported Ruby versions: 1.9 or higher**
|
11
|
+
**Supported Ruby versions: 1.9.3 or higher**
|
6
12
|
|
7
13
|
Licensed under the **MIT** license, see LICENSE for more information.
|
8
14
|
|
@@ -24,7 +30,37 @@ Or install it yourself as:
|
|
24
30
|
|
25
31
|
## Usage
|
26
32
|
|
27
|
-
|
33
|
+
### Configuration
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
Cellular.configure do |config|
|
37
|
+
config.username = 'username'
|
38
|
+
config.password = 'password'
|
39
|
+
config.backend = Cellular::Backends::Sendega
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
|
44
|
+
### Available Backends
|
45
|
+
|
46
|
+
* CoolSMS (http://coolsms.com/)
|
47
|
+
* Sendega (http://sendega.com/)
|
48
|
+
|
49
|
+
|
50
|
+
### Sending SMSs
|
51
|
+
|
52
|
+
The options supported may differ between backends.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
sms = Cellular::SMS.new(
|
56
|
+
recipient: '47xxxxxxxx',
|
57
|
+
sender: 'Custom sender',
|
58
|
+
country: 'NO',
|
59
|
+
message: 'This is an SMS message'
|
60
|
+
)
|
61
|
+
|
62
|
+
sms.deliver
|
63
|
+
```
|
28
64
|
|
29
65
|
|
30
66
|
## Contributing
|
@@ -33,4 +69,4 @@ Usage instructions to follow shortly.
|
|
33
69
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
34
70
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
35
71
|
4. Push to the branch (`git push origin my-new-feature`)
|
36
|
-
5. Create pull
|
72
|
+
5. Create pull request
|
data/Rakefile
CHANGED
data/cellular.gemspec
CHANGED
@@ -19,7 +19,16 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
20
|
gem.require_paths = ['lib']
|
21
21
|
|
22
|
-
gem.add_dependency '
|
22
|
+
gem.add_dependency 'httparty', '~> 0.13.0'
|
23
|
+
gem.add_dependency 'savon', '~> 2.0'
|
23
24
|
|
24
25
|
gem.add_development_dependency 'pry'
|
26
|
+
|
27
|
+
gem.add_development_dependency 'guard'
|
28
|
+
gem.add_development_dependency 'guard-rspec'
|
29
|
+
gem.add_development_dependency 'rake'
|
30
|
+
gem.add_development_dependency 'webmock'
|
31
|
+
|
32
|
+
gem.add_development_dependency 'coveralls'
|
33
|
+
gem.add_development_dependency 'simplecov'
|
25
34
|
end
|
data/lib/cellular/backends.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Cellular
|
4
|
+
module Backends
|
5
|
+
class CoolSMS
|
6
|
+
|
7
|
+
# Documentation: http://www.coolsms.com/support/dokumentation/http-gateway.sms
|
8
|
+
GATEWAY_URL = 'https://sms.coolsmsc.dk/'
|
9
|
+
|
10
|
+
def self.deliver(options = {})
|
11
|
+
query = {
|
12
|
+
username: Cellular.config.username,
|
13
|
+
password: Cellular.config.password,
|
14
|
+
from: options[:sender],
|
15
|
+
to: options[:recipient],
|
16
|
+
message: options[:message],
|
17
|
+
charset: 'utf-8',
|
18
|
+
resulttype: 'xml',
|
19
|
+
lang: 'en'
|
20
|
+
}
|
21
|
+
|
22
|
+
result = HTTParty.get(GATEWAY_URL, query: query)
|
23
|
+
response = result.parsed_response['smsc']
|
24
|
+
|
25
|
+
[
|
26
|
+
response['status'],
|
27
|
+
response['result'] || response['message']['result']
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -6,7 +6,7 @@ module Cellular
|
|
6
6
|
|
7
7
|
GATEWAY_URL = 'https://smsc.sendega.com/Content.asmx?WSDL'
|
8
8
|
|
9
|
-
def self.deliver(options = {})
|
9
|
+
def self.deliver(options = {}, savon_options = {})
|
10
10
|
# Send an SMS and return its initial delivery status code.
|
11
11
|
#
|
12
12
|
# Delivery status codes:
|
@@ -34,7 +34,9 @@ module Cellular
|
|
34
34
|
# See Gate API Documentation:
|
35
35
|
# http://www.sendega.no/downloads/Sendega%20API%20documentation%20v2.0.pdf
|
36
36
|
|
37
|
-
|
37
|
+
savon_options[:wsdl] = GATEWAY_URL
|
38
|
+
|
39
|
+
client = Savon.client savon_options
|
38
40
|
|
39
41
|
result = client.call(:send, message: {
|
40
42
|
username: Cellular.config.username,
|
@@ -43,13 +45,13 @@ module Cellular
|
|
43
45
|
destination: options[:recipient],
|
44
46
|
pricegroup: options[:price] || 0, # default price to 0
|
45
47
|
contentTypeID: 1,
|
46
|
-
contentHeader:
|
48
|
+
contentHeader: '',
|
47
49
|
content: options[:message],
|
48
50
|
dlrUrl: Cellular.config.delivery_url,
|
49
51
|
ageLimit: 0,
|
50
|
-
extID:
|
51
|
-
sendDate:
|
52
|
-
refID:
|
52
|
+
extID: '',
|
53
|
+
sendDate: '',
|
54
|
+
refID: '',
|
53
55
|
priority: 0,
|
54
56
|
gwID: 0,
|
55
57
|
pid: 0,
|
@@ -57,10 +59,18 @@ module Cellular
|
|
57
59
|
}
|
58
60
|
)
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
+
body = result.body[:send_response][:send_result]
|
63
|
+
|
64
|
+
if body[:success]
|
65
|
+
[
|
66
|
+
body[:error_number].to_i,
|
67
|
+
'Message is received and is being processed.'
|
68
|
+
]
|
62
69
|
else
|
63
|
-
[
|
70
|
+
[
|
71
|
+
body[:error_number].to_i,
|
72
|
+
body[:error_message]
|
73
|
+
]
|
64
74
|
end
|
65
75
|
end
|
66
76
|
|
data/lib/cellular/models/sms.rb
CHANGED
data/lib/cellular/version.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cellular::Backends::CoolSMS do
|
4
|
+
|
5
|
+
let(:recipient) { '47xxxxxxxx' }
|
6
|
+
let(:sender) { 'Custom sender' }
|
7
|
+
let(:message) { 'This is an SMS message' }
|
8
|
+
|
9
|
+
let(:options) {
|
10
|
+
{
|
11
|
+
recipient: recipient,
|
12
|
+
sender: sender,
|
13
|
+
message: message
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
before do
|
18
|
+
Cellular.config.username = 'username'
|
19
|
+
Cellular.config.password = 'password'
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '::deliver' do
|
23
|
+
before do
|
24
|
+
stub_request(:get, 'https://sms.coolsmsc.dk/?charset=utf-8&from=Custom%20sender&lang=en&message=This%20is%20an%20SMS%20message&password=password&resulttype=xml&to=47xxxxxxxx&username=username').
|
25
|
+
to_return headers: { 'Content-Type' => 'text/xml' }, body: fixture('backends/cool_sms/success.xml')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'uses HTTParty to deliver an SMS' do
|
29
|
+
expect(HTTParty).to receive(:get).with(described_class::GATEWAY_URL, query: {
|
30
|
+
username: 'username',
|
31
|
+
password: 'password',
|
32
|
+
from: sender,
|
33
|
+
to: recipient,
|
34
|
+
message: message,
|
35
|
+
charset: 'utf-8',
|
36
|
+
resulttype: 'xml',
|
37
|
+
lang: 'en'
|
38
|
+
}).and_call_original
|
39
|
+
|
40
|
+
described_class.deliver(options)
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when successful' do
|
44
|
+
it 'returns success and a message' do
|
45
|
+
expect(described_class.deliver(options)).to eq [
|
46
|
+
'success',
|
47
|
+
'The message was sent correctly.'
|
48
|
+
]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when not successful' do
|
53
|
+
before do
|
54
|
+
stub_request(:get, 'https://sms.coolsmsc.dk/?charset=utf-8&from=Custom%20sender&lang=en&message=This%20is%20an%20SMS%20message&password=password&resulttype=xml&to=47xxxxxxxx&username=username').
|
55
|
+
to_return headers: { 'Content-Type' => 'text/xml' }, body: fixture('backends/cool_sms/failure.xml')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns failure and a message' do
|
59
|
+
expect(described_class.deliver(options)).to eq [
|
60
|
+
'failure',
|
61
|
+
'Access denied.'
|
62
|
+
]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cellular::Backends::Sendega do
|
4
|
+
|
5
|
+
let(:recipient) { '47xxxxxxxx' }
|
6
|
+
let(:sender) { 'Custom sender' }
|
7
|
+
let(:message) { 'This is an SMS message' }
|
8
|
+
let(:price) { 100 }
|
9
|
+
let(:country) { 'NO '}
|
10
|
+
|
11
|
+
let(:options) {
|
12
|
+
{
|
13
|
+
recipient: recipient,
|
14
|
+
sender: sender,
|
15
|
+
message: message,
|
16
|
+
price: price
|
17
|
+
}
|
18
|
+
}
|
19
|
+
let(:savon_options) {
|
20
|
+
{
|
21
|
+
log: false
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
before do
|
26
|
+
stub_request(:get, described_class::GATEWAY_URL).
|
27
|
+
to_return body: fixture('backends/sendega/service.wsdl')
|
28
|
+
|
29
|
+
Cellular.config.username = 'username'
|
30
|
+
Cellular.config.password = 'password'
|
31
|
+
Cellular.config.delivery_url = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '::deliver' do
|
35
|
+
it 'uses Savon to deliver an SMS' do
|
36
|
+
client = double()
|
37
|
+
Savon.stub(:client).and_return client
|
38
|
+
|
39
|
+
result = double(body: {send_response: {send_result: {}}})
|
40
|
+
|
41
|
+
expect(client).to receive(:call).with(:send, message: {
|
42
|
+
username: Cellular.config.username,
|
43
|
+
password: Cellular.config.password,
|
44
|
+
sender: sender,
|
45
|
+
destination: recipient,
|
46
|
+
pricegroup: price,
|
47
|
+
contentTypeID: 1,
|
48
|
+
contentHeader: '',
|
49
|
+
content: message,
|
50
|
+
dlrUrl: nil,
|
51
|
+
ageLimit: 0,
|
52
|
+
extID: '',
|
53
|
+
sendDate: '',
|
54
|
+
refID: '',
|
55
|
+
priority: 0,
|
56
|
+
gwID: 0,
|
57
|
+
pid: 0,
|
58
|
+
dcs: 0
|
59
|
+
}).and_return result
|
60
|
+
|
61
|
+
described_class.deliver(options, savon_options)
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when successful' do
|
65
|
+
before do
|
66
|
+
stub_request(:post, 'https://smsc.sendega.com/Content.asmx').
|
67
|
+
to_return body: fixture('backends/sendega/success.xml')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns a success code and a message' do
|
71
|
+
expect(described_class.deliver(options, savon_options)).to eq [
|
72
|
+
0,
|
73
|
+
'Message is received and is being processed.'
|
74
|
+
]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when not successful' do
|
79
|
+
before do
|
80
|
+
stub_request(:post, 'https://smsc.sendega.com/Content.asmx').
|
81
|
+
to_return body: fixture('backends/sendega/failure.xml')
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'returns an error code and a message' do
|
85
|
+
expect(described_class.deliver(options, savon_options)).to eq [
|
86
|
+
9001,
|
87
|
+
'Not validated - Username and password does not match (e)'
|
88
|
+
]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '::receive' do
|
94
|
+
it 'has not been implemented yet' do
|
95
|
+
expect do
|
96
|
+
described_class.receive ''
|
97
|
+
end.to raise_error NotImplementedError
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cellular::Configuration do
|
4
|
+
|
5
|
+
it { should respond_to :username= }
|
6
|
+
it { should respond_to :username }
|
7
|
+
it { should respond_to :password= }
|
8
|
+
it { should respond_to :password }
|
9
|
+
it { should respond_to :delivery_url= }
|
10
|
+
it { should respond_to :delivery_url }
|
11
|
+
it { should respond_to :backend= }
|
12
|
+
it { should respond_to :backend }
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cellular::SMS do
|
4
|
+
|
5
|
+
let(:recipient) { '47xxxxxxxx' }
|
6
|
+
let(:sender) { 'Custom sender' }
|
7
|
+
let(:message) { 'This is an SMS message' }
|
8
|
+
let(:price) { 100 }
|
9
|
+
let(:country) { 'NO '}
|
10
|
+
|
11
|
+
subject do
|
12
|
+
described_class.new(
|
13
|
+
recipient: recipient,
|
14
|
+
sender: sender,
|
15
|
+
message: message,
|
16
|
+
price: price,
|
17
|
+
country: country
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
before do
|
22
|
+
Cellular.config.backend = Cellular::Backends::Sendega
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#initialize' do
|
26
|
+
its(:recipient) { should eq recipient }
|
27
|
+
its(:sender) { should eq sender }
|
28
|
+
its(:message) { should eq message }
|
29
|
+
its(:price) { should eq price }
|
30
|
+
its(:country) { should eq country }
|
31
|
+
|
32
|
+
it { should_not be_delivered }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#deliver' do
|
36
|
+
before do
|
37
|
+
expect(Cellular::Backends::Sendega).to receive(:deliver).with(
|
38
|
+
recipient: recipient,
|
39
|
+
sender: sender,
|
40
|
+
price: price,
|
41
|
+
country: country,
|
42
|
+
message: message
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'uses configured backend and marks SMS as delivered' do
|
47
|
+
subject.deliver
|
48
|
+
expect(subject).to be_delivered
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#save' do
|
53
|
+
it 'has not been implemented yet' do
|
54
|
+
expect do
|
55
|
+
subject.save
|
56
|
+
end.to raise_error NotImplementedError
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#receive' do
|
61
|
+
it 'has not been implemented yet' do
|
62
|
+
expect do
|
63
|
+
subject.receive
|
64
|
+
end.to raise_error NotImplementedError
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|