cellular 1.0.0 → 1.1.0
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.
- 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
|
+
[](https://rubygems.org/gems/cellular)
|
4
|
+
[](https://travis-ci.org/hyperoslo/cellular)
|
5
|
+
[](https://gemnasium.com/hyperoslo/cellular)
|
6
|
+
[](https://codeclimate.com/github/hyperoslo/cellular)
|
7
|
+
[](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
|