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 +4 -4
- data/.gitignore +2 -3
- data/.yardopts +8 -0
- data/CHANGELOG.md +17 -2
- data/Gemfile +1 -0
- data/Gemfile.lock +7 -24
- data/README.md +19 -8
- data/bin/console +2 -5
- data/lib/sms_pilot.rb +0 -1
- data/lib/sms_pilot/client.rb +315 -50
- data/lib/sms_pilot/errors.rb +6 -1
- data/lib/sms_pilot/version.rb +4 -1
- data/sms-pilot-api-v1.gemspec +5 -7
- metadata +7 -21
- data/sms-pilot-api-v1-0.0.2.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef5f991fb1af59f48bbc7ccab3e1ab3b417c76fc22a584922fa5bca8879e294c
|
4
|
+
data.tar.gz: 83031cf779a24ed4b1d44de6d08f33ef611a0b9fdc63742c14ec792080c54fa5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84a60a7e124256682fd89d4d411c7402feb6597b0541493c2bd08b88b95a515cdf4ae9c0fb435939d7b6f98a56b2d9dd513cd344023bb2f446fbcffc8507eac0
|
7
|
+
data.tar.gz: d0a91bb376ef6090356040cc8eddca2272ce1917e044a7a7cea43f6fe812d265ea1c548eb63e95b5c163a1baed78758bb35a5a0075dea096674bbd4649f0a4ab
|
data/.gitignore
CHANGED
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
|
-
|
1
|
+
# Changelog
|
2
2
|
|
3
|
-
## [0.
|
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
data/Gemfile.lock
CHANGED
@@ -1,32 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sms-pilot-api-v1 (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
|
-
|
11
|
-
public_suffix (>= 2.0.2, < 5.0)
|
9
|
+
coderay (1.1.3)
|
12
10
|
diff-lcs (1.4.4)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
-
##
|
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
|
-
|
32
|
-
|
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 # =>
|
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", "Привет, мир!")
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
require "irb"
|
15
|
-
IRB.start(__FILE__)
|
11
|
+
require "pry"
|
12
|
+
Pry.start
|
data/lib/sms_pilot.rb
CHANGED
data/lib/sms_pilot/client.rb
CHANGED
@@ -1,16 +1,97 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "json"
|
4
|
+
require "net/https"
|
4
5
|
require "uri"
|
5
6
|
|
6
7
|
module SmsPilot
|
7
8
|
|
8
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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 =
|
123
|
+
@response_headers = {}
|
30
124
|
@response_body = nil
|
31
125
|
@response_data = {}
|
32
126
|
@url = nil
|
33
127
|
end
|
34
128
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
153
|
+
uri = build_uri(@phone, message)
|
154
|
+
@url = uri.to_s
|
155
|
+
|
156
|
+
response = Net::HTTP.get_response(uri)
|
44
157
|
|
45
|
-
|
46
|
-
@response_status = response.
|
47
|
-
@response_headers = response.
|
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.
|
51
|
-
@error = "HTTP request failed with code #{response.
|
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
|
-
|
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
|
64
|
-
|
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
|
-
#
|
77
|
-
#
|
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
|
-
#
|
85
|
-
#
|
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
|
-
@
|
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
|
-
#
|
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
|
-
#
|
244
|
+
# Did the API block you
|
100
245
|
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
246
|
+
# Error code | Description
|
247
|
+
# :---|:------------------
|
248
|
+
# 105 | из-за низкого баланса
|
249
|
+
# 106 | за спам/ошибки
|
250
|
+
# 107 | за недостоверные учетные данные / недоступна эл. почта / проблемы с телефоном
|
251
|
+
# 122 | спорная ситуация
|
105
252
|
#
|
106
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
126
|
-
#
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
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
|
-
|
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
|
data/lib/sms_pilot/errors.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module SmsPilot
|
4
|
-
|
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
|
data/lib/sms_pilot/version.rb
CHANGED
data/sms-pilot-api-v1.gemspec
CHANGED
@@ -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
|
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/
|
19
|
-
"documentation_uri" => "
|
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.
|
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-
|
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/
|
55
|
-
documentation_uri: https://
|
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.
|
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
|
data/sms-pilot-api-v1-0.0.2.gem
DELETED
Binary file
|