sms_aero 0.0.11 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -6
  3. data/CHANGELOG.md +15 -10
  4. data/README.md +25 -30
  5. data/lib/sms_aero.rb +119 -34
  6. data/lib/sms_aero/birthday.rb +12 -0
  7. data/lib/sms_aero/callable.rb +6 -0
  8. data/lib/sms_aero/channel.rb +15 -0
  9. data/lib/sms_aero/digital.rb +7 -0
  10. data/lib/sms_aero/filled_string.rb +11 -0
  11. data/lib/sms_aero/future.rb +16 -0
  12. data/lib/sms_aero/group.rb +11 -0
  13. data/lib/sms_aero/optional.rb +15 -0
  14. data/lib/sms_aero/phone.rb +11 -0
  15. data/lib/sms_aero/response.rb +30 -0
  16. data/lib/sms_aero/response/with_balance.rb +5 -0
  17. data/lib/sms_aero/response/with_groups.rb +5 -0
  18. data/lib/sms_aero/response/with_id.rb +9 -0
  19. data/lib/sms_aero/response/with_senders.rb +5 -0
  20. data/lib/sms_aero/response/with_statuses.rb +5 -0
  21. data/lib/sms_aero/response/with_tariff.rb +5 -0
  22. data/lib/sms_aero/tariff.rb +8 -0
  23. data/sms_aero.gemspec +2 -4
  24. data/spec/{sms_aero/types → models}/birthday_spec.rb +2 -2
  25. data/spec/{sms_aero/types → models}/channel_spec.rb +2 -2
  26. data/spec/{sms_aero/types → models}/digital_spec.rb +1 -1
  27. data/spec/{sms_aero/types → models}/future_spec.rb +5 -5
  28. data/spec/{sms_aero/types → models}/phone_spec.rb +1 -1
  29. data/spec/{sms_aero/operations → operations}/add_blacklist_spec.rb +19 -3
  30. data/spec/{sms_aero/operations → operations}/add_group_spec.rb +4 -4
  31. data/spec/{sms_aero/operations → operations}/add_phone_spec.rb +39 -76
  32. data/spec/{sms_aero/operations → operations}/check_balance_spec.rb +2 -4
  33. data/spec/{sms_aero/operations → operations}/check_groups_spec.rb +0 -0
  34. data/spec/{sms_aero/operations → operations}/check_senders_spec.rb +5 -5
  35. data/spec/{sms_aero/operations → operations}/check_sending_spec.rb +3 -3
  36. data/spec/{sms_aero/operations → operations}/check_sign_spec.rb +2 -2
  37. data/spec/{sms_aero/operations → operations}/check_status_spec.rb +3 -3
  38. data/spec/{sms_aero/operations → operations}/check_tariff_spec.rb +1 -1
  39. data/spec/{sms_aero/operations → operations}/delete_group_spec.rb +3 -3
  40. data/spec/{sms_aero/operations → operations}/delete_phone_spec.rb +4 -4
  41. data/spec/{sms_aero/operations → operations}/send_sms_spec.rb +49 -11
  42. data/spec/spec_helper.rb +4 -1
  43. data/spec/support/en.yml +8 -0
  44. metadata +61 -101
  45. data/lib/sms_aero/models/answer.rb +0 -8
  46. data/lib/sms_aero/models/sms.rb +0 -16
  47. data/lib/sms_aero/models/tariff.rb +0 -8
  48. data/lib/sms_aero/operations/add_blacklist.rb +0 -11
  49. data/lib/sms_aero/operations/add_group.rb +0 -11
  50. data/lib/sms_aero/operations/add_phone.rb +0 -17
  51. data/lib/sms_aero/operations/check_balance.rb +0 -11
  52. data/lib/sms_aero/operations/check_groups.rb +0 -12
  53. data/lib/sms_aero/operations/check_senders.rb +0 -15
  54. data/lib/sms_aero/operations/check_sending.rb +0 -11
  55. data/lib/sms_aero/operations/check_sign.rb +0 -15
  56. data/lib/sms_aero/operations/check_status.rb +0 -11
  57. data/lib/sms_aero/operations/check_tariff.rb +0 -12
  58. data/lib/sms_aero/operations/delete_group.rb +0 -11
  59. data/lib/sms_aero/operations/delete_phone.rb +0 -12
  60. data/lib/sms_aero/operations/hlr.rb +0 -36
  61. data/lib/sms_aero/operations/send_sms.rb +0 -22
  62. data/lib/sms_aero/operations/send_to_group.rb +0 -15
  63. data/lib/sms_aero/types/birthday.rb +0 -20
  64. data/lib/sms_aero/types/channel.rb +0 -4
  65. data/lib/sms_aero/types/digital.rb +0 -8
  66. data/lib/sms_aero/types/filled_string.rb +0 -3
  67. data/lib/sms_aero/types/future.rb +0 -16
  68. data/lib/sms_aero/types/password.rb +0 -6
  69. data/lib/sms_aero/types/phone.rb +0 -12
  70. data/lib/sms_aero/types/sign_status.rb +0 -9
  71. data/spec/sms_aero/operations/hlr_spec.rb +0 -96
  72. data/spec/sms_aero/operations/send_to_group_spec.rb +0 -185
  73. data/spec/sms_aero/types/sign_status_spec.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b52fc948890d3313610388be5e1757e77212476
4
- data.tar.gz: 26936444af10df3a81997e8b78acbb18a8c480a7
3
+ metadata.gz: fdf410ad50fc28f563f44d7749d96e6a1d0c55a3
4
+ data.tar.gz: cdbbbb1536558b11a8d58f070785e0a67802bc75
5
5
  SHA512:
6
- metadata.gz: 69ee02b04df901f37a568abf8debc38ca4ac3ad0fc3587a255866d85bd328a75e9e4b359445c209809084447cacfe3dedbbed39fd1421eec84af880b901c778d
7
- data.tar.gz: d90ab49c4c46fc3e8e40a2f8d9b0ed90be2017a21fe7bf30b5d7dcf03c171a5ba0437012fedbf5371874420cd6e1f8522124fd0ee58027746a643bb510114706
6
+ metadata.gz: 1cb59cd8f2900d1f72ca3ceeedfc41bcd75dce2f265f2d6316f4ba312d0204c21e2b36ad90463d111c2f4ef3261dc7119c8ea32b34f66653a496e9ebb3a51fb3
7
+ data.tar.gz: 71563a2b0af8242313d0f38b6b2e6eb684869d162e0cd1aa68c412fc798f52d076c472d61aa023c4dcc7e171407326c8fb3395bbfc9ae5f2ab268e6752b24adb
@@ -12,9 +12,6 @@ Metrics/LineLength:
12
12
  - http
13
13
  - https
14
14
 
15
- Layout/SpaceInLambdaLiteral:
16
- Enabled: false
17
-
18
15
  Style/Lambda:
19
16
  Enabled: false
20
17
 
@@ -24,14 +21,14 @@ Style/StringLiterals:
24
21
  Style/FrozenStringLiteralComment:
25
22
  Enabled: false
26
23
 
27
- Style/DateTime:
28
- Enabled: false
29
-
30
24
  Style/Documentation:
31
25
  Enabled: false
32
26
 
33
27
  Style/ClassAndModuleChildren:
34
28
  Enabled: false
35
29
 
30
+ Style/SpaceInLambdaLiteral:
31
+ Enabled: false
32
+
36
33
  Style/PercentLiteralDelimiters:
37
34
  Enabled: false
@@ -1,18 +1,25 @@
1
1
  # Change Log
2
+
2
3
  All notable changes to this project will be documented in this file.
3
4
 
4
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
7
 
7
- ## [0.0.11] - [2017-12-19]
8
+ ## [0.1.0] - [2017-08-11]
8
9
 
9
- ### Added
10
- - Always add #success to response from #hlr (@Earendil95)
10
+ The gem is re-written on top of newer version of [evil-client]
11
+ Some changes in the interface has been made as well.
11
12
 
12
- ## [0.0.10] - [2017-12-03]
13
+ ### Changed
13
14
 
14
- ### Added
15
- - checking existance & availability of phone number using methods `#hlr` and `#hlr_status id` (@Earendil95)
15
+ - The root option `:test` renamed to `:testsend` for internal reasons of [evil-client][evil-client] implementation (nepalez)
16
+ - Version of [evil-client][evil-client] used under the hood: 0.3.3 -> 1.1.0 (nepalez)
17
+
18
+ ### Deleted
19
+
20
+ - Method `send_to_group` removed in favor or `group:` option of `send_sms` (nepalez)
21
+ - Validation of responses returned by a remote server (nepalez)
22
+ - Dependency from [dry-types][dry-types] (nepalez)
16
23
 
17
24
  ## [0.0.9] - [2017-06-23]
18
25
 
@@ -24,10 +31,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
24
31
  ### Added
25
32
  - Weakened dependency from [dry-types], allowing v0.0.9 (@nepalez)
26
33
 
27
- Between v0.9.0 and v0.9.1 an `optional` property has been broken.
28
-
34
+ [evil-client]: https://github.com/evilmartians/evil-client
29
35
  [dry-types]: https://github.com/dry-rb/dry-types
30
36
  [0.0.8]: https://github.com/nepalez/sms_aero/compare/v0.0.7...v0.0.8
31
37
  [0.0.9]: https://github.com/nepalez/sms_aero/compare/v0.0.8...v0.0.9
32
- [0.0.10]: https://github.com/nepalez/sms_aero/compare/v0.0.9...v0.0.10
33
- [0.0.11]: https://github.com/nepalez/sms_aero/compare/v0.0.10...v0.0.11
38
+ [0.1.0]: https://github.com/nepalez/sms_aero/compare/v0.0.9...v0.1.0
data/README.md CHANGED
@@ -5,17 +5,11 @@
5
5
  [![Dependency Status][gemnasium-badger]][gemnasium]
6
6
  [![Code Climate][codeclimate-badger]][codeclimate]
7
7
 
8
- HTTP(s) client to [SMS Aero service API][sms-aero].
8
+ HTTP(s) client to [SMS Aero service API][sms-aero]
9
+ written on top of [evil-client][evil-client] "framework".
9
10
 
10
- [sms-aero]: https://smsaero.ru/api/description/
11
- [codeclimate-badger]: https://img.shields.io/codeclimate/github/nepalez/sms_aero.svg?style=flat
12
- [codeclimate]: https://codeclimate.com/github/nepalez/sms_aero
13
- [gem-badger]: https://img.shields.io/gem/v/sms_aero.svg?style=flat
14
- [gem]: https://rubygems.org/gems/sms_aero
15
- [gemnasium-badger]: https://img.shields.io/gemnasium/nepalez/sms_aero.svg?style=flat
16
- [gemnasium]: https://gemnasium.com/nepalez/sms_aero
17
- [travis-badger]: https://img.shields.io/travis/nepalez/sms_aero/master.svg?style=flat
18
- [travis]: https://travis-ci.org/nepalez/sms_aero
11
+ <a href="https://evilmartians.com/">
12
+ <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
19
13
 
20
14
  ## Synopsis
21
15
 
@@ -28,7 +22,7 @@ Initialize a client with user and password:
28
22
  ```ruby
29
23
  client = SmsAero.new user: "joe", # required
30
24
  password: "foobar", # required
31
- test: true # optional - to send test SMS by default
25
+ testsend: true # optional - to send test SMS
32
26
  ```
33
27
 
34
28
  Then send requests:
@@ -39,9 +33,9 @@ answer = client.send_sms text: "Hello!",
39
33
  date: "2100/01/12", # Date, Time, DateTime are accepted as well
40
34
  type: 3 # see API docs for details
41
35
 
42
- answer.result # => "accepted"
43
- answer.id # => "38293"
44
- answer.success # => true (checks whether id was returned)
36
+ answer.result # => "accepted"
37
+ answer.id # => "38293"
38
+ answer.success? # => true (checks whether an id has been returned)
45
39
  ```
46
40
 
47
41
  ```ruby
@@ -50,13 +44,14 @@ answer.result # => "pending"
50
44
  ```
51
45
 
52
46
  ```ruby
53
- answer = client.send_to_group text: "Hello!",
54
- group: "customers",
55
- date: "2100/01/12",
56
- type: 1
47
+ answer = client.send_sms text: "Hello!",
48
+ group: "customers",
49
+ date: Date.new("2100/01/12"),
50
+ type: 1
57
51
 
58
- answer.result # => "accepted"
59
- answer.id # => "894924"
52
+ answer.result # => "accepted"
53
+ answer.id # => "894924"
54
+ answer.success? # => true (checks whether an id has been returned)
60
55
  ```
61
56
 
62
57
  ```ruby
@@ -128,13 +123,13 @@ answer = client.delete_phone phone: "+7 (999) 123-4567",
128
123
  answer.result # => "accepted"
129
124
  ```
130
125
 
131
- ```ruby
132
- # checking existance & availability of phone number
133
- answer = client.hlr phone: "+7 (999) 123-4567"
134
- answer.result # => "accepted"
135
- id = answer.id # => "12345", id of request
136
-
137
- answer = client.hlr_status id
138
- answer.result # => "accepted"
139
- answer.status # => any of :available, :unavailable or :nonexistent
140
- ```
126
+ [sms-aero]: https://smsaero.ru/api/description/
127
+ [codeclimate-badger]: https://img.shields.io/codeclimate/github/nepalez/sms_aero.svg?style=flat
128
+ [codeclimate]: https://codeclimate.com/github/nepalez/sms_aero
129
+ [gem-badger]: https://img.shields.io/gem/v/sms_aero.svg?style=flat
130
+ [gem]: https://rubygems.org/gems/sms_aero
131
+ [gemnasium-badger]: https://img.shields.io/gemnasium/nepalez/sms_aero.svg?style=flat
132
+ [gemnasium]: https://gemnasium.com/nepalez/sms_aero
133
+ [travis-badger]: https://img.shields.io/travis/nepalez/sms_aero/master.svg?style=flat
134
+ [travis]: https://travis-ci.org/nepalez/sms_aero
135
+ [evil-client]: https://github.com/evilmartians/evil-client
@@ -1,56 +1,141 @@
1
1
  require "evil/client"
2
- require "dry-types"
3
2
 
4
3
  # HTTP(s) client to the "SMS Aero" online service
5
- class SmsAero
6
- extend Evil::Client::DSL
4
+ class SmsAero < Evil::Client
5
+ require_relative "sms_aero/callable"
6
+ require_relative "sms_aero/optional"
7
+ require_relative "sms_aero/filled_string"
8
+ require_relative "sms_aero/future"
9
+ require_relative "sms_aero/digital"
10
+ require_relative "sms_aero/phone"
11
+ require_relative "sms_aero/birthday"
12
+ require_relative "sms_aero/group"
13
+ require_relative "sms_aero/channel"
14
+ require_relative "sms_aero/tariff"
15
+ require_relative "sms_aero/response"
7
16
 
8
- # Collection of dry-types with gem-specific additions
9
- Types = Module.new { |types| types.include Dry::Types.module }
17
+ option :user, FilledString
18
+ option :password, optional: true
19
+ option :token, default: -> { OpenSSL::Digest::MD5.new.hexdigest(password) }
20
+ option :use_ssl, true.method(:&), default: proc { true }
21
+ option :use_post, true.method(:&), default: proc { true }
22
+ option :testsend, true.method(:&), default: proc { false }
10
23
 
11
- # Definitions for types, models, and API operations
12
- %w(types models operations).each do |folder|
13
- path = File.expand_path("../sms_aero/#{folder}/*.rb", __FILE__)
14
- Dir[path].each { |file| require(file) }
24
+ path { "http#{'s' if use_ssl}://gate.smsaero.ru/" }
25
+ http_method { use_post ? :post : :get }
26
+ query { { user: user, password: token, answer: "json" } }
27
+ response(200) { |*res| Response.build(*res) }
28
+ headers "X-Ruby-Client" => "https://github.com/nepalez/sms_aero",
29
+ "X-Ruby-Framework" => "https://github.com/evilmartians/evil-client"
30
+
31
+ operation :add_blacklist do
32
+ option :phone, Phone
33
+
34
+ path "addblacklist"
35
+ query { { phone: phone } }
15
36
  end
16
37
 
17
- settings do
18
- option :user, Types::FilledString
19
- option :password, Types::Password
20
- option :use_ssl, Types::Form::Bool, default: proc { true }
21
- option :use_post, Types::Form::Bool, default: proc { true }
22
- option :test, Types::Form::Bool, default: proc { false }
38
+ operation :add_group do
39
+ option :group, Group
40
+
41
+ path "addgroup"
42
+ query { { group: group } }
23
43
  end
24
44
 
25
- base_url do |settings|
26
- "http#{'s' if settings.use_ssl}://gate.smsaero.ru/"
45
+ operation :add_phone do
46
+ option :phone, Phone
47
+ option :group, optional: true, type: Group
48
+ option :bday, optional: true, type: Birthday
49
+ option :lname, optional: true
50
+ option :fname, optional: true
51
+ option :sname, optional: true
52
+ option :param, optional: true
53
+ option :param2, optional: true
54
+ option :param3, optional: true
55
+
56
+ path "addphone"
57
+ query { options.except :password, :token, :use_ssl, :use_post, :testsend }
27
58
  end
28
59
 
29
- operation do |settings|
30
- documentation "https://smsaero.ru/api/description/"
60
+ operation :check_balance do
61
+ path "balance"
62
+ response(200) { |*res| Response::WithBalance.build(*res) }
63
+ end
31
64
 
32
- http_method(settings.use_post ? :post : :get)
65
+ operation :check_groups do
66
+ path "checkgroup"
67
+ response(200) { |*res| Response::WithGroups.build(*res) }
68
+ end
33
69
 
34
- security do
35
- key_auth :user, settings.user, using: :query
36
- key_auth :password, settings.password, using: :query
37
- key_auth :answer, "json", using: :query
38
- end
70
+ operation :check_senders do
71
+ option :sign, FilledString
72
+
73
+ path "senders"
74
+ query { { sign: sign } }
75
+ response(200) { |*res| Response::WithSenders.build(*res) }
76
+ end
77
+
78
+ operation :check_sending do
79
+ option :id, FilledString
80
+
81
+ path "checksending"
82
+ query { { id: id } }
83
+ end
84
+
85
+ operation :check_sign do
86
+ option :sign, FilledString
39
87
 
40
- responses format: :json do
41
- response :success, 200, model: Answer
42
- response :failure, 200, model: Answer
88
+ path "sign"
89
+ query { { sign: sign } }
90
+
91
+ response(200) do |_, _, body|
92
+ data = JSON.parse(body.first)
93
+ Response::WithStatuses.new(data: data)
43
94
  end
44
95
  end
45
96
 
46
- private
97
+ operation :check_status do
98
+ option :id, FilledString
99
+
100
+ path "status"
101
+ query { { id: id } }
102
+ end
103
+
104
+ operation :check_tariff do
105
+ path "checktarif"
106
+
107
+ response(200) { |*res| Response::WithTariff.build(*res) }
108
+ end
109
+
110
+ operation :delete_group do
111
+ option :group, FilledString
47
112
 
48
- def method_missing(name, *args)
49
- op = operations[name.to_sym]
50
- op ? op.call(*args) : super
113
+ path "delgroup"
114
+ query { options.select { |key| key == :group } }
51
115
  end
52
116
 
53
- def respond_to_missing?(name, *)
54
- operations.key? name.to_sym
117
+ operation :delete_phone do
118
+ option :phone, Phone
119
+ option :group, FilledString, optional: true
120
+
121
+ path "delphone"
122
+ query { options.select { |key| %i[phone group].include? key } }
123
+ end
124
+
125
+ operation :send_sms do
126
+ option :to, Phone, optional: true
127
+ option :group, Group, optional: true
128
+ option :from, FilledString
129
+ option :text, FilledString
130
+ option :date, Future, optional: true
131
+ option :digital, Digital, optional: true
132
+ option :type, Channel, default: -> { 2 unless digital == 1 }
133
+
134
+ validate(:address_given) { !to ^ !group }
135
+
136
+ path { group && "sendtogroup" || testsend && "testsend" || "send" }
137
+ query { options.slice(:to, :group, :from, :text, :date, :digital, :type) }
138
+
139
+ response(200) { |*res| Response::WithId.build(*res) }
55
140
  end
56
141
  end
@@ -0,0 +1,12 @@
1
+ class SmsAero::Birthday < String
2
+ extend SmsAero::Callable
3
+
4
+ private
5
+
6
+ def initialize(value)
7
+ date = value.respond_to?(:to_date) ? value.to_date : Date.parse(value)
8
+ super date.strftime "%Y-%m-%d"
9
+ rescue
10
+ raise "#{value} is not a valid value for a birthday"
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ module SmsAero::Callable
2
+ def call(*args)
3
+ new(*args)
4
+ end
5
+ alias [] call
6
+ end
@@ -0,0 +1,15 @@
1
+ class SmsAero::Channel < String
2
+ extend SmsAero::Callable
3
+
4
+ def self.new(value)
5
+ value ? super(value) : Dry::Initializer::UNDEFINED
6
+ end
7
+
8
+ private
9
+
10
+ def initialize(value)
11
+ channel = value.to_s
12
+ return super(channel) if %w(1 2 3 4 6).include? channel
13
+ raise "Incorrect value #{channel} for channel"
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module SmsAero::Digital
2
+ extend SmsAero::Callable
3
+
4
+ def self.new(value)
5
+ value ? 1 : 0
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ class SmsAero::FilledString < String
2
+ extend SmsAero::Callable
3
+
4
+ private
5
+
6
+ def initialize(value)
7
+ string = value.to_s
8
+ raise "blank value" if string == ""
9
+ super string
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ # Coercible Unix time in future
2
+ class SmsAero::Future < String
3
+ extend SmsAero::Callable
4
+
5
+ private
6
+
7
+ def initialize(value)
8
+ time = value.to_time if value.respond_to? :to_time
9
+ time ||= ::Time.parse(value) unless value.is_a? Numeric
10
+ number = time.to_i
11
+ return super(number.to_s) if number > ::Time.now.to_i
12
+ raise "#{value} is a time in the past, not in the future"
13
+ rescue
14
+ raise "#{value} is not a valid time"
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ class SmsAero::Group < String
2
+ extend SmsAero::Callable
3
+
4
+ private
5
+
6
+ def initialize(value)
7
+ group = value.to_s
8
+ raise "'#{value}' is not a valid group name" unless group[/^\w{1,20}$/]
9
+ super group
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module SmsAero::Optional
2
+ private
3
+
4
+ def initialize(opts)
5
+ super opts.each_with_object({}) { |(key, val), obj| obj[key.to_sym] = val }
6
+ end
7
+
8
+ def respond_to_missing?(name, *)
9
+ @__options__.respond_to? name
10
+ end
11
+
12
+ def method_missing(*args, &block)
13
+ respond_to_missing?(*args) ? @__options__.send(*args, &block) : super
14
+ end
15
+ end