locasms 0.1.7 → 0.5.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 +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +6 -0
- data/.rubocop_todo.yml +30 -0
- data/.travis.yml +13 -5
- data/Gemfile +2 -0
- data/Guardfile +4 -2
- data/README.md +18 -4
- data/Rakefile +3 -1
- data/bin/console +9 -0
- data/lib/locasms.rb +11 -9
- data/lib/locasms/client.rb +49 -33
- data/lib/locasms/exception.rb +7 -7
- data/lib/locasms/helpers/date_time_helper.rb +38 -69
- data/lib/locasms/numbers.rb +14 -12
- data/lib/locasms/rest_client.rb +28 -15
- data/lib/locasms/version.rb +3 -1
- data/locasms.gemspec +28 -26
- data/spec/lib/locasms/client_spec.rb +114 -108
- data/spec/lib/locasms/helpers/date_time_helper_spec.rb +11 -35
- data/spec/lib/locasms/numbers_spec.rb +54 -68
- data/spec/lib/locasms/rest_client_spec.rb +55 -23
- data/spec/spec.opts +1 -2
- data/spec/spec_helper.rb +5 -4
- metadata +55 -80
- data/.hound.yml +0 -2
- data/.ruby-style.yml +0 -1063
data/lib/locasms/numbers.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module LocaSMS
|
3
4
|
# Class that sanitizes and validates a list of mobile's numbers
|
4
5
|
class Numbers
|
5
6
|
attr_reader :good, :bad
|
@@ -9,15 +10,16 @@ module LocaSMS
|
|
9
10
|
# @see #normalize
|
10
11
|
# @see #evaluate
|
11
12
|
def initialize(*numbers)
|
12
|
-
evaluated
|
13
|
-
@good
|
13
|
+
evaluated = evaluate(numbers)
|
14
|
+
@good = evaluated[:good]
|
15
|
+
@bad = evaluated[:bad]
|
14
16
|
end
|
15
17
|
|
16
18
|
# Checks if there are bad numbers
|
17
19
|
# @return [TrueClass, FalseClass] true if there are bad numbers
|
18
20
|
# @see #valid_number?
|
19
21
|
def bad?
|
20
|
-
|
22
|
+
!bad.empty?
|
21
23
|
end
|
22
24
|
|
23
25
|
# Clears all non digits from a mobile's number and converts into a normalized array
|
@@ -34,17 +36,19 @@ module LocaSMS
|
|
34
36
|
# numbers.normalize '8888-9999', ['AA', '6666-9999', '7777-0000'], '3333-4444,555-9999'
|
35
37
|
# # => ['88889999','AA','66669999','77770000','33334444','5559999']
|
36
38
|
def normalize(*numbers)
|
37
|
-
numbers
|
39
|
+
numbers
|
40
|
+
.join(',')
|
38
41
|
.split(',')
|
39
|
-
.map{|number| number.gsub(/[^0-9a-zA-Z]/, '') }
|
40
|
-
.delete_if
|
42
|
+
.map { |number| number.gsub(/[^0-9a-zA-Z]/, '') }
|
43
|
+
.delete_if(&:empty?)
|
41
44
|
end
|
42
45
|
|
43
46
|
# Validates if a mobile's number has only digits
|
44
47
|
# @param [String] number given number to be validated
|
45
48
|
# @return [TrueClass, FalseClass] true if the number is valid
|
46
49
|
def valid_number?(number)
|
47
|
-
return false if number.nil?
|
50
|
+
return false if number.nil? || number =~ (/[^0-9a-zA-Z]/)
|
51
|
+
|
48
52
|
[10, 11].include? number.size
|
49
53
|
end
|
50
54
|
|
@@ -63,10 +67,9 @@ module LocaSMS
|
|
63
67
|
# Numbers.new.evaluate('4199998888','11777770000','5551212')
|
64
68
|
# #=> {good: ['4199998888','11777770000'], bad: ['5551212']}
|
65
69
|
def evaluate(*numbers)
|
66
|
-
normalize(numbers).
|
70
|
+
normalize(numbers).each_with_object({ good: [], bad: [] }) do |number, hash|
|
67
71
|
bucket = valid_number?(number) ? :good : :bad
|
68
72
|
hash[bucket] << number
|
69
|
-
hash
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
@@ -76,5 +79,4 @@ module LocaSMS
|
|
76
79
|
(good || []).join(',')
|
77
80
|
end
|
78
81
|
end
|
79
|
-
|
80
|
-
end
|
82
|
+
end
|
data/lib/locasms/rest_client.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
4
|
+
require 'net/http'
|
2
5
|
|
3
6
|
module LocaSMS
|
4
|
-
|
5
7
|
# Class that handle http calls to LocaSMS api
|
6
|
-
# @see https://github.com/mcorp/locasms/wiki/A-API-de-envio
|
8
|
+
# @see https://github.com/mcorp/locasms/wiki/A-API-de-envio
|
9
|
+
# List of avaiable services
|
7
10
|
class RestClient
|
8
11
|
attr_accessor :base_url, :base_params
|
9
12
|
|
10
13
|
# Creates a new instance of the RestClient class
|
11
14
|
# @param [String] base_url a well formed url
|
12
15
|
# @param [Hash] base_params base params to send on every call
|
13
|
-
def initialize(base_url, base_params={})
|
16
|
+
def initialize(base_url, base_params = {})
|
14
17
|
@base_url = base_url
|
15
18
|
@base_params = base_params
|
16
19
|
end
|
@@ -34,12 +37,17 @@ module LocaSMS
|
|
34
37
|
# client.get :holdsms, id: 345678
|
35
38
|
# # => {"status"=>1,"data"=>nil,"msg"=>"SUCESSO"}
|
36
39
|
#
|
37
|
-
# @see https://github.com/mcorp/locasms/wiki/A-API-de-envio#lista-das-a%C3%A7%C3%B5es-dispon%C3%ADveis
|
40
|
+
# @see https://github.com/mcorp/locasms/wiki/A-API-de-envio#lista-das-a%C3%A7%C3%B5es-dispon%C3%ADveis
|
41
|
+
# List of avaiable actions
|
38
42
|
# @raise [LocaSMS::InvalidOperation] when asked for an invalid operation
|
39
43
|
# @raise [LocaSMS::InvalidLogin] when the given credentials are invalid
|
40
|
-
def get(action, params={})
|
41
|
-
params
|
42
|
-
|
44
|
+
def get(action, params = {})
|
45
|
+
params = params_for action, params
|
46
|
+
|
47
|
+
uri = URI.parse(base_url)
|
48
|
+
uri.query = URI.encode_www_form(params)
|
49
|
+
response = Net::HTTP.get_response(uri).body
|
50
|
+
|
43
51
|
parse_response(action, response)
|
44
52
|
end
|
45
53
|
|
@@ -54,9 +62,10 @@ module LocaSMS
|
|
54
62
|
# client.params_for :ACTION, a: 1, b: 2
|
55
63
|
# # => { action: :ACTION, lgn: 'LOGIN', pwd: 'PASSWORD', a: 1, b: 2 }
|
56
64
|
#
|
57
|
-
# @see https://github.com/mcorp/locasms/wiki/A-API-de-envio#lista-das-a%C3%A7%C3%B5es-dispon%C3%ADveis
|
58
|
-
|
59
|
-
|
65
|
+
# @see https://github.com/mcorp/locasms/wiki/A-API-de-envio#lista-das-a%C3%A7%C3%B5es-dispon%C3%ADveis
|
66
|
+
# List of avaiable actions
|
67
|
+
def params_for(action, params = {})
|
68
|
+
{ action: action }.merge(base_params).merge(params).select { |_k, v| v }
|
60
69
|
end
|
61
70
|
|
62
71
|
# Parses a result trying to get it in json
|
@@ -68,13 +77,17 @@ module LocaSMS
|
|
68
77
|
def parse_response(action, response)
|
69
78
|
raise InvalidOperation.new(action: action) if response =~ /^0:OPERACAO INVALIDA$/i
|
70
79
|
|
71
|
-
j =
|
80
|
+
j = begin
|
81
|
+
MultiJson.load(response)
|
82
|
+
rescue StandardError
|
83
|
+
{ 'status' => 1, 'data' => response, 'msg' => nil }
|
84
|
+
end
|
72
85
|
|
73
|
-
return j if j['status'] == 1
|
86
|
+
return j if (j['status'] == 1) || (action == :getstatus)
|
74
87
|
|
75
88
|
raise InvalidLogin.new(action: action) if j['msg'] =~ /^falha ao realizar login$/i
|
76
|
-
|
89
|
+
|
90
|
+
raise LocaSMS::Exception.new(message: j['msg'], raw: response, action: action)
|
77
91
|
end
|
78
92
|
end
|
79
|
-
|
80
|
-
end
|
93
|
+
end
|
data/lib/locasms/version.rb
CHANGED
data/locasms.gemspec
CHANGED
@@ -1,42 +1,44 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'locasms/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'locasms'
|
8
9
|
spec.version = LocaSMS::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
|
13
|
-
spec.
|
14
|
-
spec.
|
15
|
-
|
16
|
-
|
10
|
+
spec.authors = ['Adilson Carvalho', 'Leonardo Saraiva', 'Marco Carvalho']
|
11
|
+
spec.email = ['lc.adilson@gmail.com', 'vyper@maneh.org', 'marco.carvalho.swasthya@gmail.com']
|
12
|
+
spec.description = 'Cliente para o serviço de disparo de SMS da LocaSMS e de sua
|
13
|
+
versão para Short Code SMS (SMS Plataforma)'
|
14
|
+
spec.summary = 'Cliente para disparo de SMS, regular e Short Code, através da LocaSMS/SMS Plataforma'
|
15
|
+
spec.homepage = 'https://github.com/mcorp/locasms'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
21
|
+
spec.require_paths = ['lib']
|
20
22
|
|
21
|
-
spec.
|
22
|
-
spec.add_development_dependency 'rake', '~> 10.4.2'
|
23
|
+
spec.required_ruby_version = '~> 2.4'
|
23
24
|
|
24
|
-
|
25
|
-
spec.add_development_dependency 'rspec', '~> 3.2'
|
26
|
-
spec.add_development_dependency 'fuubar', '~> 2.0.0'
|
27
|
-
spec.add_development_dependency 'timecop', '~> 0.7.3'
|
25
|
+
spec.add_dependency 'multi_json', '~> 1.13'
|
28
26
|
|
29
|
-
|
30
|
-
spec.add_development_dependency '
|
31
|
-
|
32
|
-
|
27
|
+
spec.add_development_dependency 'bundler'
|
28
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
29
|
+
|
30
|
+
# test stuff
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.9'
|
32
|
+
spec.add_development_dependency 'timecop', '~> 0.9'
|
33
33
|
|
34
34
|
# for documentation
|
35
|
-
spec.add_development_dependency '
|
36
|
-
spec.add_development_dependency '
|
35
|
+
spec.add_development_dependency 'redcarpet', '~> 3.5'
|
36
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
37
37
|
|
38
38
|
# for code coverage
|
39
|
-
spec.add_development_dependency 'simplecov'
|
39
|
+
spec.add_development_dependency 'simplecov', '~> 0.18'
|
40
40
|
|
41
|
-
|
41
|
+
# for code quality
|
42
|
+
spec.add_development_dependency 'rubocop', '~> 0.93'
|
43
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.43'
|
42
44
|
end
|
@@ -1,140 +1,148 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
|
-
describe LocaSMS::Client do
|
4
|
-
|
5
|
-
subject { LocaSMS::Client.new :login, :password, rest_client: rest_client }
|
5
|
+
describe LocaSMS::Client do # rubocop:disable RSpec/FilePath
|
6
|
+
subject(:client) { described_class.new :login, :password, rest_client: rest_client, callback: nil }
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
load 'lib/locasms/client.rb'
|
12
|
-
yield
|
13
|
-
end
|
14
|
-
end
|
8
|
+
let(:rest_client) { instance_double 'RestClient' }
|
9
|
+
let(:base_args) { { msg: 'given message', numbers: '11988889991,11988889992,11988889993' } }
|
10
|
+
let(:default_callback_args) { base_args.merge(url_callback: 'default') }
|
11
|
+
let(:some_callback_args) { base_args.merge(url_callback: 'something') }
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
describe '::ENDPOINT' do
|
14
|
+
let(:domain) { described_class::DOMAIN }
|
15
|
+
|
16
|
+
context 'when default' do
|
17
|
+
it 'returns the default URL' do
|
18
|
+
endpoint = described_class::ENDPOINT[client.type]
|
19
|
+
expect(endpoint).to eq("http://#{domain}/painel/api.ashx")
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
context 'when shortcode' do
|
24
|
+
subject(:client) { described_class.new :login, :password, type: :shortcode }
|
25
|
+
|
26
|
+
it 'returns the short code URL' do
|
27
|
+
endpoint = described_class::ENDPOINT[client.type]
|
28
|
+
expect(endpoint).to eq("http://#{domain}/shortcode/api.ashx")
|
29
29
|
end
|
30
30
|
end
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
describe '.initialize' do
|
34
|
+
it { expect(client.login).to be(:login) }
|
35
|
+
it { expect(client.password).to be(:password) }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#deliver' do
|
39
|
+
it 'sends SMS' do
|
40
|
+
allow(rest_client).to receive(:get).and_return({})
|
41
|
+
|
42
|
+
client.deliver 'given message', '11988889991', '11988889992', '11988889993'
|
43
|
+
|
44
|
+
expect(rest_client).to have_received(:get).once.with(:sendsms, base_args.merge(url_callback: nil))
|
38
45
|
end
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
47
|
+
context 'when receive an error' do
|
48
|
+
let(:wrong_deliver) { -> { client.deliver('given message', '1', '2', '3') } }
|
49
|
+
|
50
|
+
it { expect(wrong_deliver).to raise_error(LocaSMS::Exception) }
|
51
|
+
|
52
|
+
it 'does not send SMS' do
|
53
|
+
allow(rest_client).to receive(:get)
|
54
|
+
|
55
|
+
wrong_deliver
|
56
|
+
|
57
|
+
expect(rest_client).not_to have_received(:get)
|
45
58
|
end
|
46
59
|
end
|
47
60
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
61
|
+
context 'when callback given as arg to #deliver' do
|
62
|
+
it 'uses specific callback' do
|
63
|
+
allow(rest_client).to receive(:get).and_return({})
|
64
|
+
|
65
|
+
client.deliver 'given message', '11988889991', '11988889992', '11988889993', url_callback: 'something'
|
66
|
+
|
67
|
+
expect(rest_client).to have_received(:get).once.with(:sendsms, some_callback_args)
|
53
68
|
end
|
54
69
|
end
|
55
|
-
end
|
56
70
|
|
57
|
-
|
58
|
-
|
59
|
-
|
71
|
+
it 'uses default callback' do
|
72
|
+
client = described_class.new :login, :password, rest_client: rest_client, url_callback: 'default'
|
73
|
+
|
74
|
+
allow(rest_client).to receive(:get).and_return({})
|
75
|
+
|
76
|
+
client.deliver 'given message', '11988889991', '11988889992', '11988889993'
|
77
|
+
|
78
|
+
expect(rest_client).to have_received(:get).once.with(:sendsms, default_callback_args)
|
79
|
+
end
|
60
80
|
end
|
61
81
|
|
62
|
-
describe '#
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
.once
|
71
|
-
.with(:sendsms, msg: 'given message', numbers:'XXX')
|
72
|
-
.and_return({})
|
73
|
-
|
74
|
-
subject.deliver 'given message', :a, :b, :c
|
82
|
+
describe '#deliver_at' do
|
83
|
+
let(:base_args) do
|
84
|
+
{
|
85
|
+
msg: 'given message',
|
86
|
+
numbers: '11988889991,11988889992,11988889993',
|
87
|
+
jobdate: '10/10/2020',
|
88
|
+
jobtime: '10:10'
|
89
|
+
}
|
75
90
|
end
|
76
91
|
|
77
|
-
it '
|
78
|
-
|
79
|
-
.once
|
80
|
-
.with([:a, :b, :c])
|
81
|
-
.and_raise(LocaSMS::Exception)
|
92
|
+
it 'sends SMS' do
|
93
|
+
allow(rest_client).to receive(:get).and_return({})
|
82
94
|
|
83
|
-
|
95
|
+
client.deliver_at 'given message', '2020-10-10 10:10', '11988889991', '11988889992', '11988889993'
|
84
96
|
|
85
|
-
expect
|
97
|
+
expect(rest_client).to have_received(:get).once.with(:sendsms, base_args.merge(url_callback: nil))
|
86
98
|
end
|
87
|
-
end
|
88
99
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
.
|
100
|
-
|
101
|
-
expect(rest_client).to receive(:get)
|
102
|
-
.once
|
103
|
-
.with(:sendsms, msg: 'given message', numbers:'XXX', jobdate: 'date', jobtime: 'time')
|
104
|
-
.and_return({})
|
105
|
-
|
106
|
-
subject.deliver_at 'given message', :datetime, :a, :b, :c
|
100
|
+
context 'when receive an error' do
|
101
|
+
let(:wrong_deliver_at) { -> { client.deliver_at('given message', '2020-10-10 10:10', '1', '2', '3') } }
|
102
|
+
|
103
|
+
it { expect(wrong_deliver_at).to raise_error(LocaSMS::Exception) }
|
104
|
+
|
105
|
+
it 'does not send SMS' do
|
106
|
+
allow(rest_client).to receive(:get)
|
107
|
+
|
108
|
+
wrong_deliver_at
|
109
|
+
|
110
|
+
expect(rest_client).not_to have_received(:get)
|
111
|
+
end
|
107
112
|
end
|
108
113
|
|
109
|
-
|
110
|
-
|
111
|
-
.
|
112
|
-
|
113
|
-
.
|
114
|
+
context 'with callback option' do
|
115
|
+
it 'when callback given as arg to #deliver' do
|
116
|
+
allow(rest_client).to receive(:get).and_return({})
|
117
|
+
|
118
|
+
client.deliver_at 'given message', '2020-10-10 10:10', '11988889991', '11988889992', '11988889993', url_callback: 'something'
|
119
|
+
|
120
|
+
expect(rest_client).to have_received(:get).once.with(:sendsms, some_callback_args)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'uses default callback' do
|
124
|
+
client = described_class.new :login, :password, rest_client: rest_client, url_callback: 'default'
|
114
125
|
|
115
|
-
|
116
|
-
.once
|
117
|
-
.with(:datetime)
|
118
|
-
.and_return(%w[date time])
|
126
|
+
allow(rest_client).to receive(:get).and_return({})
|
119
127
|
|
120
|
-
|
128
|
+
client.deliver_at 'given message', '2020-10-10 10:10', '11988889991', '11988889992', '11988889993'
|
121
129
|
|
122
|
-
|
130
|
+
expect(rest_client).to have_received(:get).once.with(:sendsms, default_callback_args)
|
131
|
+
end
|
123
132
|
end
|
124
133
|
end
|
125
134
|
|
126
135
|
describe '#balance' do
|
127
|
-
it '
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
.and_return({})
|
136
|
+
it 'checks param assignment' do
|
137
|
+
allow(rest_client).to receive(:get).and_return({})
|
138
|
+
|
139
|
+
client.balance
|
132
140
|
|
133
|
-
|
141
|
+
expect(rest_client).to have_received(:get).once.with(:getbalance)
|
134
142
|
end
|
135
143
|
end
|
136
144
|
|
137
|
-
context '
|
145
|
+
context 'when receive all campaign based methods' do
|
138
146
|
def check_for(method)
|
139
147
|
rest_method = {
|
140
148
|
campaign_status: :getstatus,
|
@@ -142,19 +150,17 @@ describe LocaSMS::Client do
|
|
142
150
|
campaign_release: :releasesms
|
143
151
|
}[method]
|
144
152
|
|
145
|
-
|
146
|
-
.once
|
147
|
-
.with(rest_method, id: '12345')
|
148
|
-
.and_return({})
|
153
|
+
allow(rest_client).to receive(:get).and_return({})
|
149
154
|
|
150
|
-
|
155
|
+
client.send method, '12345'
|
156
|
+
|
157
|
+
expect(rest_client).to have_received(:get).once.with(rest_method, id: '12345')
|
151
158
|
end
|
152
159
|
|
153
|
-
it{ check_for :campaign_status }
|
154
|
-
it{ check_for :campaign_hold }
|
155
|
-
it{ check_for :campaign_release }
|
160
|
+
it { check_for :campaign_status }
|
161
|
+
it { check_for :campaign_hold }
|
162
|
+
it { check_for :campaign_release }
|
156
163
|
|
157
|
-
it '
|
164
|
+
it 'has tests to cover campaign_status csv result'
|
158
165
|
end
|
159
|
-
|
160
166
|
end
|