sms-pilot-api-v1 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c7152ee4bb497bc839d159e8cdc7bb9b9b5735179a8c5ced0176924acd53727
4
- data.tar.gz: 9dfa498a10e6b68c6115ed42ff4a6b678a18b4b31ad2532f1092095d9efe9a60
3
+ metadata.gz: ef5f991fb1af59f48bbc7ccab3e1ab3b417c76fc22a584922fa5bca8879e294c
4
+ data.tar.gz: 83031cf779a24ed4b1d44de6d08f33ef611a0b9fdc63742c14ec792080c54fa5
5
5
  SHA512:
6
- metadata.gz: fb942ccb1bfab86c399c1c0567885d8ca0b43ca54f3e832d6316d6ad2838beb7d1ade363f537247aff90aa8090886a78f2ac0187c9e82c077ade0944bb4e5497
7
- data.tar.gz: 6ca91958e3d50371b7a48c7679b6a6285f6ff9d8389e2e2a0605e02f6eea85359e2b873366351d762fe48bad1bf288c3f9d94244fa8c0ac5a09a1c85230ae5de
6
+ metadata.gz: 84a60a7e124256682fd89d4d411c7402feb6597b0541493c2bd08b88b95a515cdf4ae9c0fb435939d7b6f98a56b2d9dd513cd344023bb2f446fbcffc8507eac0
7
+ data.tar.gz: d0a91bb376ef6090356040cc8eddca2272ce1917e044a7a7cea43f6fe812d265ea1c548eb63e95b5c163a1baed78758bb35a5a0075dea096674bbd4649f0a4ab
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
+ .DS_Storage
2
+ .rspec_status
1
3
  /.bundle/
2
4
  /.yardoc
3
5
  /_yardoc/
@@ -6,6 +8,3 @@
6
8
  /pkg/
7
9
  /spec/reports/
8
10
  /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ --private
2
+ --protected
3
+ -m markdown
4
+ -M redcarpet
5
+ -
6
+ lib/**/*.rb
7
+ CHANGELOG.md
8
+ README.md
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
- ## [Unreleased]
1
+ # Changelog
2
2
 
3
- ## [0.1.0] - 2021-05-06
3
+ ## [0.0.6] - 9 May 2021
4
+
5
+ - Corrects cost type
6
+ - Switches to PRY in console
7
+
8
+ ## [0.0.5] - 9 May 2021
9
+
10
+ - Adds locale support (RU / EN)
11
+
12
+ ## [0.0.4] - 9 May 2021
13
+
14
+ - Drop dependence on HTTP.rb gem
15
+ - Corrects what `#send_sms` returns (could return String errors instead of Booleans)
16
+ - Adds extensive [documentation](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot/Client) via YARD & RubyDoc
17
+
18
+ ## [0.0.3] - 6 May 2021
4
19
 
5
20
  - Initial release
data/Gemfile CHANGED
@@ -5,5 +5,6 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in gemspec
6
6
  gemspec
7
7
 
8
+ gem "pry"
8
9
  gem "rake", "~> 13.0"
9
10
  gem "rspec", "~> 3.0"
data/Gemfile.lock CHANGED
@@ -1,32 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sms-pilot-api-v1 (0.1.0)
5
- http (>= 4.4)
4
+ sms-pilot-api-v1 (0.0.5)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
10
- addressable (2.7.0)
11
- public_suffix (>= 2.0.2, < 5.0)
9
+ coderay (1.1.3)
12
10
  diff-lcs (1.4.4)
13
- domain_name (0.5.20190701)
14
- unf (>= 0.0.5, < 1.0.0)
15
- ffi (1.15.0)
16
- ffi-compiler (1.0.1)
17
- ffi (>= 1.0.0)
18
- rake
19
- http (4.4.1)
20
- addressable (~> 2.3)
21
- http-cookie (~> 1.0)
22
- http-form_data (~> 2.2)
23
- http-parser (~> 1.2.0)
24
- http-cookie (1.0.3)
25
- domain_name (~> 0.5)
26
- http-form_data (2.3.0)
27
- http-parser (1.2.3)
28
- ffi-compiler (>= 1.0, < 2.0)
29
- public_suffix (4.0.6)
11
+ method_source (1.0.0)
12
+ pry (0.14.1)
13
+ coderay (~> 1.1)
14
+ method_source (~> 1.0)
30
15
  rake (13.0.3)
31
16
  rspec (3.10.0)
32
17
  rspec-core (~> 3.10.0)
@@ -41,14 +26,12 @@ GEM
41
26
  diff-lcs (>= 1.2.0, < 2.0)
42
27
  rspec-support (~> 3.10.0)
43
28
  rspec-support (3.10.2)
44
- unf (0.1.4)
45
- unf_ext
46
- unf_ext (0.0.7.7)
47
29
 
48
30
  PLATFORMS
49
31
  x86_64-darwin-17
50
32
 
51
33
  DEPENDENCIES
34
+ pry
52
35
  rake (~> 13.0)
53
36
  rspec (~> 3.0)
54
37
  sms-pilot-api-v1!
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # SmsPilot API v1 client
2
2
 
3
- Обёртка отправки GET-запроса на API endpoint сервиса SMS Pilot (API v1) для удобства доступа к ошибкам, статусам, цене SMS и т. п.
3
+ [![Gem Version](https://badge.fury.io/rb/sms-pilot-api-v1.svg)](https://badge.fury.io/rb/sms-pilot-api-v1)
4
+
5
+ Simple wrapper around SMS pilot API v1. Version 1 because it returns more data within its standard response.
4
6
 
5
7
  ## Installation
6
8
 
@@ -16,7 +18,7 @@ from GitHub:
16
18
  gem "sms-pilot-api-v1", git: "https://github.com/sergeypedan/sms-pilot-api-v1.git"
17
19
  ```
18
20
 
19
- ## Usage
21
+ ## Playground
20
22
 
21
23
  Test sending SMS from console with a test API key (find it at the end of this page):
22
24
 
@@ -25,11 +27,18 @@ cd $(bundle info sms-pilot-api-v1 --path)
25
27
  bin/console
26
28
  ```
27
29
 
30
+
31
+ ## Usage
32
+
28
33
  ### Initialize
29
34
 
30
35
  ```ruby
31
- client = SmsPilot::Client.new(api_key: "XXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZXXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZ")
32
- #<SmsPilot::Client:0x00007fb1c602d490 @api_key="XXXXX...", @error=nil, @response_status=nil, @response_headers=nil, @response_body=nil, @response_data={}, @url=nil>
36
+ require "sms_pilot"
37
+
38
+ key = "XXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZXXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZ"
39
+
40
+ client = SmsPilot::Client.new(api_key: key)
41
+ client = SmsPilot::Client.new(api_key: key, locale: :en) # Available locales are [:en, :ru]
33
42
  ```
34
43
 
35
44
  ### Before sending
@@ -42,7 +51,7 @@ client.phone # => nil
42
51
  client.rejected? # => false
43
52
  client.response_body # => nil
44
53
  client.response_data # => {}
45
- client.response_headers # => nil
54
+ client.response_headers # => {}
46
55
  client.response_status # => nil
47
56
  client.sender_blocked? # => false
48
57
  client.sms_cost # => nil
@@ -54,7 +63,8 @@ client.url # => nil
54
63
  ### Sending SMS
55
64
 
56
65
  ```ruby
57
- client.send_sms("+7 (902) 123-45-67", "Привет, мир!") # => true
66
+ client.send_sms("+7 (902) 123-45-67", "Привет, мир!")
67
+ # => true
58
68
  ```
59
69
 
60
70
  Returns result of `sms_sent?`, so it’s either `true` or `false`.
@@ -140,10 +150,11 @@ SMS sent:
140
150
 
141
151
  ```json
142
152
  {
153
+ "balance": "11908.50",
154
+ "cost": "1.68",
143
155
  "send": [
144
156
  { "server_id": "10000", "phone": "79021234567", "price": "1.68", "status": "0" }
145
- ],
146
- "balance": "11908.50", "cost": "1.68"
157
+ ]
147
158
  }
148
159
  ```
149
160
 
data/bin/console CHANGED
@@ -8,8 +8,5 @@ require "sms_pilot"
8
8
  # with your gem easier. You can also use a different console, if you like.
9
9
 
10
10
  # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require "irb"
15
- IRB.start(__FILE__)
11
+ require "pry"
12
+ Pry.start
data/lib/sms_pilot.rb CHANGED
@@ -3,4 +3,3 @@
3
3
  require_relative "sms_pilot/version"
4
4
  require_relative "sms_pilot/errors"
5
5
  require_relative "sms_pilot/client"
6
-
@@ -1,16 +1,97 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "http"
3
+ require "json"
4
+ require "net/https"
4
5
  require "uri"
5
6
 
6
7
  module SmsPilot
7
8
 
8
- API_ENDPOINT = "https://smspilot.ru/api.php".freeze
9
-
9
+ # @!attribute [r] api_key
10
+ # @return [String] Your API key
11
+ #
12
+ # @!attribute [r] error
13
+ # Error message returned from the API, combined with the error code
14
+ # @example
15
+ # client.error #=> "Пользователь временно блокирован (спорная ситуация) (error code: 122)"
16
+ # @return [nil, String]
17
+ # @see #error_code
18
+ # @see #error_description
19
+ #
20
+ # @!attribute [r] locale
21
+ # @return [Symbol] Chosen locale (affects only the language of errors)
22
+ #
23
+ # @!attribute [r] phone
24
+ # @return [nil, String] phone after normalization
25
+ #
26
+ # @!attribute [r] response_body
27
+ # Response format is JSON (because we request it that way in {#build_uri}.
28
+ # @example
29
+ # "{\"send\":[{\"server_id\":\"10000\",\"phone\":\"79021234567\",\"price\":\"1.68\",\"status\":\"0\"}],\"balance\":\"20006.97\",\"cost\":\"1.68\"}"
30
+ # @return [nil, String] Unmodified HTTP resonse body that API returned
31
+ # @see #response_data
32
+ # @see #response_headers
33
+ # @see #response_status
34
+ #
35
+ # @!attribute [r] response_data
36
+ # Parsed <tt>@response_body</tt>. May be an empty <tt>Hash</tt> if parsing fails.
37
+ # @example
38
+ # {
39
+ # "balance" => "20006.97",
40
+ # "cost" => "1.68",
41
+ # "send" => [
42
+ # {
43
+ # "phone" => "79021234567",
44
+ # "price" => "1.68",
45
+ # "server_id" => "10000",
46
+ # "status" => "0"
47
+ # }
48
+ # ]
49
+ # }
50
+ # @return [Hash]
51
+ # @see #response_body
52
+ # @see #response_headers
53
+ # @see #response_status
54
+ #
55
+ # @!attribute [r] response_headers
56
+ # @example
57
+ # {
58
+ # "Access-Control-Allow-Origin" => "*",
59
+ # "Connection" => "close",
60
+ # "Content-Length" => "179",
61
+ # "Content-Type" => "application/json; charset=utf-8",
62
+ # "Date" => "Thu, 06 May 2021 04:52:58 GMT",
63
+ # "Server" => "nginx"
64
+ # }
65
+ # @return [nil, String] Unmodified HTTP resonse headers that API returned.
66
+ # @see #response_body
67
+ # @see #response_data
68
+ # @see #response_status
69
+ #
70
+ # @!attribute [r] response_status
71
+ # HTTP status of the request to the API. 200 in case of success.
72
+ # @example
73
+ # client.response_status #=> 200
74
+ #
75
+ # @return [nil, Integer]
76
+ # @see #response_body
77
+ # @see #response_data
78
+ # @see #response_headers
79
+ #
80
+ # @!attribute [r] url
81
+ # @example
82
+ # client.url #=> "https://smspilot.ru/api.php?api_key=XXX&format=json&send=TEXT&to=79021234567"
83
+ # @return [String] URL generated by combining <tt>API_ENDPOINT</tt>, your API key, SMS text & phone
84
+ #
10
85
  class Client
11
86
 
87
+ # Check current API endpoint URL at {https://smspilot.ru/apikey.php#api1}
88
+ #
89
+ API_ENDPOINT = "https://smspilot.ru/api.php".freeze
90
+ AVAILABLE_LOCALES = [:ru, :en].freeze
91
+
12
92
  attr_reader :api_key
13
93
  attr_reader :error
94
+ attr_reader :locale
14
95
  attr_reader :phone
15
96
  attr_reader :response_body
16
97
  attr_reader :response_data
@@ -19,128 +100,312 @@ module SmsPilot
19
100
  attr_reader :url
20
101
 
21
102
 
22
- def initialize(api_key:)
23
- fail TypeError, "API key must be a String, you pass a #{api_key.class} (#{api_key})" unless api_key.is_a? String
24
- fail TypeError, "API key cannot be empty" if api_key == ""
25
-
26
- @api_key = api_key
103
+ # @param api_key [String]
104
+ # @param locale [Symbol]
105
+ #
106
+ # @return [SmsPilot::Client]
107
+ # @raise [SmsPilot::InvalidAPIkeyError] if you pass anything but a non-empty String
108
+ # @raise [SmsPilot::InvalidLocaleError] if you pass anything but <tt>:ru</tt> or <tt>:en</tt>
109
+ #
110
+ # @see https://smspilot.ru/my-settings.php Get your production API key here
111
+ # @see https://smspilot.ru/apikey.php Get your development API key here
112
+ # @note Current development API key is <tt>"XXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZXXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZ"</tt>
113
+ #
114
+ # @example
115
+ # client = SmsPilot::Client.new(api_key: ENV["SMS_PILOT_API_KEY"])
116
+ # client = SmsPilot::Client.new(api_key: ENV["SMS_PILOT_API_KEY"], locale: :en)
117
+ #
118
+ def initialize(api_key:, locale: AVAILABLE_LOCALES[0])
119
+ @api_key = validate_api_key!(api_key)
27
120
  @error = nil
121
+ @locale = validate_locale!(locale)
28
122
  @response_status = nil
29
- @response_headers = nil
123
+ @response_headers = {}
30
124
  @response_body = nil
31
125
  @response_data = {}
32
126
  @url = nil
33
127
  end
34
128
 
35
- def send_sms(phone, text)
36
- fail TypeError, "`phone` must be a String, you pass a #{phone.class} (#{phone})" unless phone.is_a? String
37
- fail TypeError, "`text` must be a String, you pass a #{ text.class} (#{ text})" unless text.is_a? String
38
- fail ArgumentError, "`phone` cannot be empty" if phone == ""
39
- fail ArgumentError, "`text` cannot be empty" if text == ""
40
- fail ArgumentError, "`phone` must contain digits" if phone.scan(/\d/).none?
129
+
130
+ # @!group Main
131
+
132
+ # Send HTTP request to the API to ask them to transmit your SMS
133
+ #
134
+ # @return [Boolean] <tt>true</tt> if the SMS has been sent, <tt>false</tt> otherwise
135
+ #
136
+ # @param [String] phone The phone to send the SMS to. In free-form, will be sanitized.
137
+ # @param [String] message The text of your message.
138
+ #
139
+ # @raise [SmsPilot::InvalidPhoneError] if you pass anythig but a String with the <tt>phone</tt> argument
140
+ # @raise [SmsPilot::InvalidMessageError] if you pass anythig but a String with the <tt>message</tt> argument
141
+ # @raise [SmsPilot::InvalidMessageError] if your message is empty
142
+ # @raise [SmsPilot::InvalidPhoneError] if your phone is empty
143
+ # @raise [SmsPilot::InvalidPhoneError] if your phone has no digits
144
+ #
145
+ # @example
146
+ # client.send_sms("+7 (902) 123-45-67", "Привет, мир!") # => true
147
+ #
148
+ def send_sms(phone, message)
149
+ validate_phone! phone
150
+ validate_message! message
41
151
 
42
152
  @phone = normalize_phone(phone)
43
- @url = build_url(@phone, text)
153
+ uri = build_uri(@phone, message)
154
+ @url = uri.to_s
155
+
156
+ response = Net::HTTP.get_response(uri)
44
157
 
45
- response = HTTP.timeout(connect: 15, read: 30).accept(:json).get(@url)
46
- @response_status = response.status.code
47
- @response_headers = response.headers.to_h
48
- @response_body = response.body.to_s
158
+ @response_body = response.body
159
+ @response_status = response.code.to_i
160
+ @response_headers = response.each_capitalized.to_h
49
161
 
50
- unless response.status.success?
51
- @error = "HTTP request failed with code #{response.status.code}"
162
+ unless response.is_a?(Net::HTTPSuccess)
163
+ @error = "HTTP request failed with code #{response.code}"
52
164
  return false
53
165
  end
54
166
 
55
167
  @response_data = JSON.parse @response_body
56
168
 
57
- return @error = "#{error_description} (код ошибки: #{error_code})" if rejected?
169
+ if rejected?
170
+ @error = "#{error_description} (error code: #{error_code})"
171
+ return false
172
+ end
173
+
58
174
  return true
59
175
 
60
176
  rescue JSON::ParserError => error
61
177
  @error = "API returned invalid JSON. #{error.message}"
178
+ return false
62
179
 
63
- rescue HTTP::Error => error
64
- @error = error.message
65
-
66
- rescue => error
180
+ rescue SocketError, EOFError, IOError, SystemCallError,
181
+ Timeout::Error, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
182
+ Net::ProtocolError, OpenSSL::SSL::SSLError => error
67
183
  @error = error.message
184
+ return false
68
185
  end
69
186
 
187
+ # @!endgroup
188
+
189
+
190
+ # @!group State accessors
70
191
 
192
+ # Your current balance, remaining after sending that latest SMS.
193
+ #
194
+ # @return [nil, Float] Always <tt>nil</tt> before you send SMS and if the SMS was not sent, always Float after successfull SMS transmission.
195
+ # @example
196
+ # client.balance #=> 20215.25
197
+ #
71
198
  def balance
72
199
  @response_data["balance"]&.to_f if sms_sent?
73
200
  end
74
201
 
75
202
 
76
- # Коды ошибок: https://smspilot.ru/apikey.php#err
77
- # Расшифровка ошибки пишется в @error
203
+ # Numerical code of the error that occured when sending the SMS. In the range from 0 to 715 (which may change).
204
+ #
205
+ # @return [nil, Integer] <tt>nil</tt> is returned before sending SMS. Otherwise <tt>Integer</tt>
206
+ # @example
207
+ # client.error_code #=> 122
208
+ # @see #error
209
+ # @see #error_description
210
+ # @see https://smspilot.ru/apikey.php#err Error codes at the API documentation website
78
211
  #
79
212
  def error_code
80
213
  @response_data.dig("error", "code")&.to_i if rejected?
81
214
  end
82
215
 
83
216
 
84
- # Коды ошибок: https://smspilot.ru/apikey.php#err
85
- # Расшифровка ошибки пишется в @error
217
+ # Description of the error that occured when sending the SMS
218
+ #
219
+ # @return [nil, String] <tt>nil</tt> is returned before sending SMS. Otherwise <tt>String</tt>
220
+ # @example
221
+ # client.error_description #=> "Пользователь временно блокирован (спорная ситуация)"
222
+ # @see #error
223
+ # @see #error_code
224
+ # @see https://smspilot.ru/apikey.php#err Error codes at the API documentation website
86
225
  #
87
226
  def error_description
88
- @response_data.dig("error", "description_ru") if rejected?
227
+ method_name = (@locale == :ru) ? "description_ru" : "description"
228
+ @response_data.dig("error", method_name) if rejected?
89
229
  end
90
230
 
91
231
 
92
- # HTTP запрос удался, но API отказался отправлять SMS
232
+ # Did the API reject your request to send that SMS
233
+ #
234
+ # @return [Boolean] <tt>false</tt> is returned before sending SMS. Otherwise the <tt>Boolean</tt> corresponds to whether your request to send an SMS was rejected.
235
+ # @example
236
+ # client.rejected? #=> false
237
+ #
93
238
  def rejected?
94
239
  return false if sms_sent?
95
240
  @response_data["error"].is_a? Hash
96
241
  end
97
242
 
98
243
 
99
- # API сообщает, что мы заблокированы
244
+ # Did the API block you
100
245
  #
101
- # 105 из-за низкого баланса
102
- # 106 за спам/ошибки
103
- # 107 за недостоверные учетные данные / недоступна эл. почта / проблемы с телефоном
104
- # 122 спорная ситуация
246
+ # Error code | Description
247
+ # :---|:------------------
248
+ # 105 | из-за низкого баланса
249
+ # 106 | за спам/ошибки
250
+ # 107 | за недостоверные учетные данные / недоступна эл. почта / проблемы с телефоном
251
+ # 122 | спорная ситуация
105
252
  #
106
- # Расшифровка ошибки пишется в @error
253
+ # @return [Boolean] <tt>nil</tt> is returned before sending SMS. Otherwise the <tt>Boolean</tt> corresponds to whether the API has blocked you.
254
+ # @example
255
+ # client.sender_blocked? #=> false
256
+ # @see #error
257
+ # @see https://smspilot.ru/apikey.php#err Error codes at the API documentation website
107
258
  #
108
259
  def sender_blocked?
109
260
  [105, 106, 107, 122].include? error_code
110
261
  end
111
262
 
112
263
 
113
- # Цена отправленной только что SMS
264
+ # The cost of the SMS that has just been sent, in RUB
265
+ #
266
+ # @return [nil, Float]
267
+ # @example
268
+ # client.sms_cost #=> 2.63
269
+ #
114
270
  def sms_cost
115
- @response_data["cost"] if sms_sent?
271
+ @response_data["cost"]&.to_f if sms_sent?
116
272
  end
117
273
 
118
274
 
119
- # API успешно отправил SMS
275
+ # Has the SMS transmission been a success.
276
+ #
277
+ # @return [Boolean] <tt>nil</tt> is returned before sending SMS. Otherwise the <tt>Boolean</tt> corresponds to the result of SMS transmission.
278
+ # @see #sms_status
279
+ # @see #rejected?
280
+ # @see #error
281
+ #
282
+ # @example
283
+ # client.sms_sent? #=> true
284
+ #
120
285
  def sms_sent?
121
286
  @response_data["send"] != nil
122
287
  end
123
288
 
124
289
 
125
- # Статус доставки SMS
126
- # https://smspilot.ru/apikey.php#status
290
+ # SMS delivery status, as returned by the API
291
+ #
292
+ # @return [nil, Integer] <tt>nil</tt> is returned before sending SMS or if the request was rejected. Otherwise an <tt>Integer</tt> in the range of [-2..3] is returned.
293
+ # @see https://smspilot.ru/apikey.php#status List of available statuses at API documentation website
294
+ #
295
+ # Code | Name | Final? | Description
296
+ # ----:|:--------------|:-------|:-------------
297
+ # -2 | Ошибка | Да | Ошибка, неправильные параметры запроса
298
+ # -1 | Не доставлено | Да | Сообщение не доставлено (не в сети, заблокирован, не взял трубку), PING — не в сети, HLR — не обслуживается (заблокирован)
299
+ # 0 | Новое | Нет | Новое сообщение/запрос, ожидает обработки у нас на сервере
300
+ # 1 | В очереди | Нет | Сообщение или запрос ожидают отправки на сервере оператора
301
+ # 2 | Доставлено | Да | Доставлено, звонок совершен, PING — в сети, HLR — обслуживается
302
+ # 3 | Отложено | Нет | Отложенная отправка, отправка сообщения/запроса запланирована на другое время
303
+ #
304
+ # @example
305
+ # client.sms_status #=> 2
127
306
  #
128
307
  def sms_status
129
308
  @response_data.dig("send", 0, "status")&.to_i if sms_sent?
130
309
  end
131
310
 
311
+ # @!endgroup
132
312
 
133
- private
134
313
 
135
- def build_url(phone, text)
136
- URI.parse(API_ENDPOINT).tap do |url|
137
- url.query = URI.encode_www_form({ apikey: @api_key, format: :json, send: text, to: phone })
138
- end.to_s
314
+ # The URI we will send an HTTP request to
315
+ #
316
+ # @private
317
+ # @return [URI]
318
+ # @raise [URI::InvalidURIError] but is very unlikely because we provide the URL ourselves
319
+ #
320
+ # @example
321
+ # build_uri("79021234567", "Hello, World!")
322
+ # #=> #<URI::HTTPS https://smspilot.ru/api.php?apikey=XXX…&format=json&send=Hello%2C+World%21&to=79021234567>
323
+ #
324
+ private def build_uri(phone, text)
325
+ URI.parse(API_ENDPOINT).tap do |uri|
326
+ uri.query = URI.encode_www_form({ apikey: @api_key, format: :json, send: text, to: phone })
327
+ end
139
328
  end
140
329
 
141
- def normalize_phone(phone)
330
+
331
+ # Cleans up your phone from anything but digits. Also replaces 8 to 7 if it is the first digit.
332
+ #
333
+ # @private
334
+ # @return [String]
335
+ #
336
+ # @example
337
+ # normalize_phone("8 (902) 123-45-67") #=> 79021234567
338
+ # normalize_phone("+7-902-123-45-67") #=> 79021234567
339
+ #
340
+ private def normalize_phone(phone)
142
341
  phone.gsub(/[^0-9]/, '').sub(/^8/, '7').gsub('+7', '8')
143
342
  end
144
343
 
344
+
345
+ # @!group Validations
346
+
347
+ # Validates api_key
348
+ #
349
+ # @private
350
+ # @return [String] the original value passed into the method, only if it was valid
351
+ # @param [String] api_key
352
+
353
+ # @raise [SmsPilot::InvalidError] if api_key is not a String
354
+ # @raise [SmsPilot::InvalidError] if api_key is an empty String
355
+ #
356
+ private def validate_api_key!(api_key)
357
+ fail SmsPilot::InvalidAPIkeyError, "API key must be a String, you pass a #{api_key.class} (#{api_key})" unless api_key.is_a? String
358
+ fail SmsPilot::InvalidAPIkeyError, "API key cannot be empty" if api_key == ""
359
+ return api_key
360
+ end
361
+
362
+
363
+ # Validates locale
364
+ #
365
+ # @private
366
+ # @return [Symbol] the original value passed into the method, only if it was valid
367
+ # @param [Symbol] locale
368
+
369
+ # @raise [SmsPilot::InvalidError] if locale is not a Symbol
370
+ # @raise [SmsPilot::InvalidError] if locale is unrecognized
371
+ #
372
+ private def validate_locale!(locale)
373
+ fail SmsPilot::InvalidLocaleError, "locale must be a Symbol" unless locale.is_a? Symbol
374
+ fail SmsPilot::InvalidLocaleError, "API does not support locale :#{locale}; choose one of #{AVAILABLE_LOCALES.inspect}" unless AVAILABLE_LOCALES.include? locale
375
+ return locale
376
+ end
377
+
378
+
379
+ # Validates message
380
+ #
381
+ # @private
382
+ # @return [nil]
383
+ #
384
+ # @raise [SmsPilot::InvalidMessageError] if you pass anythig but a String with the <tt>message</tt> argument
385
+ # @raise [SmsPilot::InvalidMessageError] if your message is empty
386
+ #
387
+ private def validate_message!(message)
388
+ fail SmsPilot::InvalidMessageError, "SMS message must be a String, you pass a #{ message.class} (#{ message})" unless message.is_a? String
389
+ fail SmsPilot::InvalidMessageError, "SMS message cannot be empty" if message == ""
390
+ end
391
+
392
+
393
+ # Validates phone
394
+ #
395
+ # @private
396
+ # @return [nil]
397
+ #
398
+ # @raise [SmsPilot::InvalidPhoneError] if you pass anythig but a String with the <tt>phone</tt> argument
399
+ # @raise [SmsPilot::InvalidPhoneError] if your phone is empty
400
+ # @raise [SmsPilot::InvalidPhoneError] if your phone has no digits
401
+ #
402
+ private def validate_phone!(phone)
403
+ fail SmsPilot::InvalidPhoneError, "phone must be a String, you pass a #{phone.class} (#{phone})" unless phone.is_a? String
404
+ fail SmsPilot::InvalidPhoneError, "phone cannot be empty" if phone == ""
405
+ fail SmsPilot::InvalidPhoneError, "phone must contain digits" if phone.scan(/\d/).none?
406
+ end
407
+
408
+ # @!endgroup
409
+
145
410
  end
146
411
  end
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SmsPilot
4
- class Error < StandardError; end
4
+
5
+ class InvalidAPIkeyError < ArgumentError; end
6
+ class InvalidMessageError < ArgumentError; end
7
+ class InvalidPhoneError < ArgumentError; end
8
+ class InvalidLocaleError < ArgumentError; end
9
+
5
10
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SmsPilot
4
- VERSION = "0.0.3"
4
+
5
+ # Gem version
6
+ VERSION = "0.0.6"
7
+
5
8
  end
@@ -3,20 +3,20 @@
3
3
  require_relative "lib/sms_pilot/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
+ spec.name = "sms-pilot-api-v1"
6
7
  spec.authors = ["Sergey Pedan"]
7
8
  spec.summary = "Simple wrapper around SMS pilot API v1"
8
9
  spec.description = "#{spec.summary}. Version 1 because it returns more data within its standard response"
9
10
  spec.email = ["sergey.pedan@gmail.com"]
10
- spec.homepage = "https://github.com/sergeypedan/sms-pilot-api-v1"
11
+ spec.homepage = "https://github.com/sergeypedan/#{spec.name}"
11
12
  spec.license = "MIT"
12
- spec.name = "sms-pilot-api-v1"
13
13
  spec.version = SmsPilot::VERSION
14
14
 
15
15
  spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
16
16
 
17
17
  spec.metadata = {
18
- "changelog_uri" => "#{spec.homepage}/blob/master/Changelog.md",
19
- "documentation_uri" => "#{spec.homepage}#usage",
18
+ "changelog_uri" => "#{spec.homepage}/blob/master/CHANGELOG.md",
19
+ "documentation_uri" => "https://rubydoc.info/github/sergeypedan/#{spec.name}/master/",
20
20
  "homepage_uri" => spec.homepage,
21
21
  "source_code_uri" => spec.homepage
22
22
  }
@@ -24,12 +24,10 @@ Gem::Specification.new do |spec|
24
24
  # Specify which files should be added to the gem when it is released.
25
25
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
26
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
27
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features|pkg|doc)/}) }
28
28
  end
29
29
 
30
30
  spec.bindir = "bin"
31
31
  spec.require_paths = ["lib"]
32
32
 
33
- spec.add_runtime_dependency "http", "~> 4"
34
-
35
33
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sms-pilot-api-v1
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Pedan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-06 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: http
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '4'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '4'
11
+ date: 2021-05-08 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description: Simple wrapper around SMS pilot API v1. Version 1 because it returns
28
14
  more data within its standard response
29
15
  email:
@@ -34,6 +20,7 @@ extra_rdoc_files: []
34
20
  files:
35
21
  - ".gitignore"
36
22
  - ".rspec"
23
+ - ".yardopts"
37
24
  - CHANGELOG.md
38
25
  - Gemfile
39
26
  - Gemfile.lock
@@ -45,14 +32,13 @@ files:
45
32
  - lib/sms_pilot/client.rb
46
33
  - lib/sms_pilot/errors.rb
47
34
  - lib/sms_pilot/version.rb
48
- - sms-pilot-api-v1-0.0.2.gem
49
35
  - sms-pilot-api-v1.gemspec
50
36
  homepage: https://github.com/sergeypedan/sms-pilot-api-v1
51
37
  licenses:
52
38
  - MIT
53
39
  metadata:
54
- changelog_uri: https://github.com/sergeypedan/sms-pilot-api-v1/blob/master/Changelog.md
55
- documentation_uri: https://github.com/sergeypedan/sms-pilot-api-v1#usage
40
+ changelog_uri: https://github.com/sergeypedan/sms-pilot-api-v1/blob/master/CHANGELOG.md
41
+ documentation_uri: https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/
56
42
  homepage_uri: https://github.com/sergeypedan/sms-pilot-api-v1
57
43
  source_code_uri: https://github.com/sergeypedan/sms-pilot-api-v1
58
44
  post_install_message:
@@ -70,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
56
  - !ruby/object:Gem::Version
71
57
  version: '0'
72
58
  requirements: []
73
- rubygems_version: 3.2.5
59
+ rubygems_version: 3.2.8
74
60
  signing_key:
75
61
  specification_version: 4
76
62
  summary: Simple wrapper around SMS pilot API v1
Binary file