sms-pilot-api-v1 0.0.5 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +70 -3
- data/Gemfile +7 -2
- data/Gemfile.lock +22 -4
- data/README.md +44 -7
- data/bin/console +2 -5
- data/lib/sms_pilot.rb +5 -0
- data/lib/sms_pilot/client.rb +183 -82
- data/lib/sms_pilot/errors.rb +5 -4
- data/lib/sms_pilot/version.rb +1 -1
- data/sms-pilot-api-v1.gemspec +7 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e18ed848bce6fc14c2011704a417ebcd18b26a2364d6eded6f70c4bf8e0fd37a
|
4
|
+
data.tar.gz: 8c0fc16b26a26194ebd2543aa231f0b41b74181141de85f4530114c2045c55ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64fad357cc93e5b0901db4c15a6965881e205fbb45ef3637d196d280ef11e089595e8e402ad81030883f51472c33716f239381343a05b58d01a334879b46678a
|
7
|
+
data.tar.gz: 172f139edc7163d805edd08a891cbeb1e1789832693b706fe99f5fc76b41f4b40fdc6aada62977b1c84df7d69a0539dad76df465aee66371ca3d144a39ca7444
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,78 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## [0.0.
|
3
|
+
## [0.0.10] - 2021-05-11
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Accepts sender name in [`#initialize`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:initialize)
|
8
|
+
- Tests for `send_sms`
|
9
|
+
|
10
|
+
## [0.0.9] - 2021-05-10
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- Passes `charset` attribute to the API in [`#build_uri`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:build_uri)
|
15
|
+
- Passes `lang` attribute to the API in [`#build_uri`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:build_uri)
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- Stores constant request params in constants
|
20
|
+
|
21
|
+
### Deprecated
|
22
|
+
|
23
|
+
- Deprecates [`#sms_status`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:sms_status) in favor of [`#broadcast_status`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:broadcast_status)
|
24
|
+
|
25
|
+
## [0.0.8] - 2021-05-10
|
26
|
+
|
27
|
+
### Added
|
28
|
+
|
29
|
+
- [`#broadcast_id`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:broadcast_id) method
|
30
|
+
- [roadmap section](https://github.com/sergeypedan/sms-pilot-api-v1#roadmap) in the Readme
|
31
|
+
|
32
|
+
## [0.0.7] - 2021-05-09
|
33
|
+
|
34
|
+
### Changed
|
35
|
+
|
36
|
+
- Returns original values from validation methods
|
37
|
+
- Offloads parsing response body to a method
|
38
|
+
- Improves documentation
|
39
|
+
|
40
|
+
### Added
|
41
|
+
|
42
|
+
- Adds CodeClimate badges
|
43
|
+
- Writes tests for [`#initialize`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:initialize)
|
44
|
+
- Writes tests for [`#api_key`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:api_key)
|
45
|
+
|
46
|
+
## [0.0.6] - 2021-05-09
|
47
|
+
|
48
|
+
### Fixed
|
49
|
+
|
50
|
+
- Corrects cost type
|
51
|
+
|
52
|
+
### Changed
|
53
|
+
|
54
|
+
- Switches to PRY in console
|
55
|
+
|
56
|
+
## [0.0.5] - 2021-05-09
|
57
|
+
|
58
|
+
### Added
|
59
|
+
|
60
|
+
- Adds locale support (RU / EN)
|
61
|
+
|
62
|
+
## [0.0.4] - 2021-05-09
|
63
|
+
|
64
|
+
### Fixed
|
65
|
+
|
66
|
+
- Corrects what [`#send_sms`](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot%2FClient:send_sms) returns (could return String errors instead of Booleans)
|
67
|
+
|
68
|
+
### Changed
|
4
69
|
|
5
70
|
- Drop dependence on HTTP.rb gem
|
6
|
-
|
71
|
+
|
72
|
+
### Added
|
73
|
+
|
7
74
|
- Adds extensive [documentation](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot/Client) via YARD & RubyDoc
|
8
75
|
|
9
|
-
## [0.0.3] -
|
76
|
+
## [0.0.3] - 2021-05-06
|
10
77
|
|
11
78
|
- Initial release
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,25 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sms-pilot-api-v1 (0.0.
|
4
|
+
sms-pilot-api-v1 (0.0.9)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
addressable (2.7.0)
|
10
|
+
public_suffix (>= 2.0.2, < 5.0)
|
11
|
+
coderay (1.1.3)
|
12
|
+
crack (0.4.5)
|
13
|
+
rexml
|
9
14
|
diff-lcs (1.4.4)
|
15
|
+
hashdiff (1.0.1)
|
16
|
+
method_source (1.0.0)
|
17
|
+
pry (0.14.1)
|
18
|
+
coderay (~> 1.1)
|
19
|
+
method_source (~> 1.0)
|
20
|
+
public_suffix (4.0.6)
|
10
21
|
rake (13.0.3)
|
22
|
+
rexml (3.2.5)
|
11
23
|
rspec (3.10.0)
|
12
24
|
rspec-core (~> 3.10.0)
|
13
25
|
rspec-expectations (~> 3.10.0)
|
@@ -21,14 +33,20 @@ GEM
|
|
21
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
22
34
|
rspec-support (~> 3.10.0)
|
23
35
|
rspec-support (3.10.2)
|
36
|
+
webmock (3.12.2)
|
37
|
+
addressable (>= 2.3.6)
|
38
|
+
crack (>= 0.3.2)
|
39
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
24
40
|
|
25
41
|
PLATFORMS
|
26
42
|
x86_64-darwin-17
|
27
43
|
|
28
44
|
DEPENDENCIES
|
29
|
-
|
30
|
-
|
45
|
+
pry
|
46
|
+
rake
|
47
|
+
rspec
|
31
48
|
sms-pilot-api-v1!
|
49
|
+
webmock
|
32
50
|
|
33
51
|
BUNDLED WITH
|
34
|
-
2.2.
|
52
|
+
2.2.17
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# SmsPilot API v1 client
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/sms-pilot-api-v1)
|
4
|
+
[](https://codeclimate.com/github/sergeypedan/sms-pilot-api-v1/maintainability)
|
5
|
+
[](https://codeclimate.com/github/sergeypedan/sms-pilot-api-v1/test_coverage)
|
6
|
+
[](https://inch-ci.org/github/sergeypedan/sms-pilot-api-v1)
|
4
7
|
|
5
8
|
Simple wrapper around SMS pilot API v1. Version 1 because it returns more data within its standard response.
|
6
9
|
|
@@ -18,7 +21,7 @@ from GitHub:
|
|
18
21
|
gem "sms-pilot-api-v1", git: "https://github.com/sergeypedan/sms-pilot-api-v1.git"
|
19
22
|
```
|
20
23
|
|
21
|
-
##
|
24
|
+
## Playground
|
22
25
|
|
23
26
|
Test sending SMS from console with a test API key (find it at the end of this page):
|
24
27
|
|
@@ -27,21 +30,30 @@ cd $(bundle info sms-pilot-api-v1 --path)
|
|
27
30
|
bin/console
|
28
31
|
```
|
29
32
|
|
33
|
+
|
34
|
+
## Usage
|
35
|
+
|
30
36
|
### Initialize
|
31
37
|
|
32
38
|
```ruby
|
33
39
|
require "sms_pilot"
|
34
40
|
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
key = "XXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZXXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZ"
|
42
|
+
|
43
|
+
client = SmsPilot::Client.new(api_key: key)
|
44
|
+
client = SmsPilot::Client.new(api_key: key, locale: :en) # Available locales are [:en, :ru]
|
38
45
|
```
|
39
46
|
|
47
|
+
Method [documentation](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot/Client#initialize-instance_method) at RubyDoc.
|
48
|
+
|
40
49
|
### Before sending
|
41
50
|
|
51
|
+
There are a bunch of methods describing the state of affairs:
|
52
|
+
|
42
53
|
```ruby
|
43
54
|
client.api_key # => "YOUR API KEY"
|
44
55
|
client.balance # => nil
|
56
|
+
client.broadcast_id # => nil
|
45
57
|
client.error # => nil
|
46
58
|
client.phone # => nil
|
47
59
|
client.rejected? # => false
|
@@ -56,20 +68,28 @@ client.sms_status # => nil
|
|
56
68
|
client.url # => nil
|
57
69
|
```
|
58
70
|
|
71
|
+
before the request is sent they return obvious nils or empty structures; after the request they are populated with data.
|
72
|
+
|
73
|
+
See [structured documentation](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot/Client) for those methods at RubyDoc.
|
74
|
+
|
59
75
|
### Sending SMS
|
60
76
|
|
61
77
|
```ruby
|
62
|
-
client.send_sms("+7 (902) 123-45-67", "Привет, мир!")
|
78
|
+
client.send_sms("+7 (902) 123-45-67", "Привет, мир!")
|
79
|
+
client.send_sms("+7 (902) 123-45-67", "Привет, мир!", "ФССПРФ")
|
80
|
+
# => true
|
63
81
|
```
|
64
82
|
|
65
83
|
Returns result of `sms_sent?`, so it’s either `true` or `false`.
|
66
84
|
|
85
|
+
Method [documentation](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot/Client#send_sms-instance_method) at RubyDoc.
|
67
86
|
|
68
87
|
### Sending SMS succeeded
|
69
88
|
|
70
89
|
```ruby
|
71
90
|
client.api_key # => "YOUR API KEY"
|
72
91
|
client.balance # => 20006.97
|
92
|
+
client.broadcast_id # => 10000
|
73
93
|
client.error # => nil
|
74
94
|
client.phone # => "79021234567"
|
75
95
|
client.rejected? # => false
|
@@ -89,6 +109,7 @@ client.url # => "https://smspilot.ru/api.php?apikey=1234567890&form
|
|
89
109
|
```ruby
|
90
110
|
client.api_key # => "YOUR API KEY"
|
91
111
|
client.balance # => nil
|
112
|
+
client.broadcast_id # => nil
|
92
113
|
client.error # => "Неправильный API-ключ (см. настройки API в личном кабинете) (код ошибки: 101)"
|
93
114
|
client.phone # => "79021234567"
|
94
115
|
client.rejected? # => true
|
@@ -108,6 +129,7 @@ client.url # => "https://smspilot.ru/api.php?apikey=1234567890&form
|
|
108
129
|
```ruby
|
109
130
|
client.api_key # => "YOUR API KEY"
|
110
131
|
client.balance # => nil
|
132
|
+
client.broadcast_id # => nil
|
111
133
|
client.error # => "HTTP request failed with code 404"
|
112
134
|
client.phone # => "79021234567"
|
113
135
|
client.rejected? # => false
|
@@ -125,9 +147,9 @@ client.url # => "https://smspilot.ru/api.php?apikey=1234567890&form
|
|
125
147
|
|
126
148
|
## SMS pilot API docs
|
127
149
|
|
128
|
-
- [
|
150
|
+
- [Web version](https://smspilot.ru/apikey.php) — см. вкладку PHP, в остальных ничего нет
|
129
151
|
- [PDF version](https://smspilot.ru/download/SMSPilotRu-HTTP-v1.9.19.pdf) — тут намного подробнее
|
130
|
-
- [
|
152
|
+
- [API error code](https://smspilot.ru/apikey.php#err)
|
131
153
|
|
132
154
|
|
133
155
|
## Test API key
|
@@ -164,3 +186,18 @@ SMS rejected:
|
|
164
186
|
}
|
165
187
|
}
|
166
188
|
```
|
189
|
+
|
190
|
+
|
191
|
+
## Documentation
|
192
|
+
|
193
|
+
See [structured documentation](https://rubydoc.info/github/sergeypedan/sms-pilot-api-v1/master/SmsPilot/Client) at RubyDoc.
|
194
|
+
|
195
|
+
|
196
|
+
## Roadmap
|
197
|
+
|
198
|
+
1. Switch to POST to escape 1024 symbolos GET request limit
|
199
|
+
1. Support passing `sender` to the API
|
200
|
+
1. Switch to result object pattern
|
201
|
+
1. Проверка статусов SMS
|
202
|
+
1. Проверка баланса
|
203
|
+
1. Информация о пользователе
|
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
@@ -7,7 +7,9 @@ require "uri"
|
|
7
7
|
module SmsPilot
|
8
8
|
|
9
9
|
# @!attribute [r] api_key
|
10
|
-
# @return [String]
|
10
|
+
# @return [String] your API key
|
11
|
+
# @example
|
12
|
+
# client.api_key #=> "XXX..."
|
11
13
|
#
|
12
14
|
# @!attribute [r] error
|
13
15
|
# Error message returned from the API, combined with the error code
|
@@ -18,13 +20,19 @@ module SmsPilot
|
|
18
20
|
# @see #error_description
|
19
21
|
#
|
20
22
|
# @!attribute [r] locale
|
21
|
-
#
|
23
|
+
# Chosen locale (affects only the language of errors)
|
24
|
+
#
|
25
|
+
# @return [Symbol]
|
26
|
+
# @example
|
27
|
+
# client.locale #=> :ru
|
22
28
|
#
|
23
29
|
# @!attribute [r] phone
|
24
30
|
# @return [nil, String] phone after normalization
|
31
|
+
# @example
|
32
|
+
# client.phone #=> "79021234567"
|
25
33
|
#
|
26
34
|
# @!attribute [r] response_body
|
27
|
-
# Response format is JSON (because we request it that way in {#build_uri}.
|
35
|
+
# Response format is JSON (because we request it that way in {#build_uri}).
|
28
36
|
# @example
|
29
37
|
# "{\"send\":[{\"server_id\":\"10000\",\"phone\":\"79021234567\",\"price\":\"1.68\",\"status\":\"0\"}],\"balance\":\"20006.97\",\"cost\":\"1.68\"}"
|
30
38
|
# @return [nil, String] Unmodified HTTP resonse body that API returned
|
@@ -32,28 +40,9 @@ module SmsPilot
|
|
32
40
|
# @see #response_headers
|
33
41
|
# @see #response_status
|
34
42
|
#
|
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
43
|
# @!attribute [r] response_headers
|
56
44
|
# @example
|
45
|
+
# client.response_headers #=>
|
57
46
|
# {
|
58
47
|
# "Access-Control-Allow-Origin" => "*",
|
59
48
|
# "Connection" => "close",
|
@@ -77,38 +66,42 @@ module SmsPilot
|
|
77
66
|
# @see #response_data
|
78
67
|
# @see #response_headers
|
79
68
|
#
|
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
|
-
#
|
85
69
|
class Client
|
86
70
|
|
87
71
|
# Check current API endpoint URL at {https://smspilot.ru/apikey.php#api1}
|
88
72
|
#
|
89
73
|
API_ENDPOINT = "https://smspilot.ru/api.php".freeze
|
74
|
+
|
75
|
+
# Locale influences only the language of API errors
|
76
|
+
#
|
90
77
|
AVAILABLE_LOCALES = [:ru, :en].freeze
|
91
78
|
|
79
|
+
REQUEST_ACCEPT_FORMAT = "json".freeze
|
80
|
+
REQUEST_CHARSET = "utf-8".freeze
|
81
|
+
|
92
82
|
attr_reader :api_key
|
93
83
|
attr_reader :error
|
94
84
|
attr_reader :locale
|
95
85
|
attr_reader :phone
|
96
86
|
attr_reader :response_body
|
97
|
-
attr_reader :response_data
|
98
87
|
attr_reader :response_headers
|
99
88
|
attr_reader :response_status
|
100
|
-
attr_reader :url
|
101
89
|
|
102
90
|
|
103
91
|
# @param api_key [String]
|
92
|
+
# @param locale [Symbol]
|
93
|
+
#
|
104
94
|
# @return [SmsPilot::Client]
|
105
95
|
# @raise [SmsPilot::InvalidAPIkeyError] if you pass anything but a non-empty String
|
96
|
+
# @raise [SmsPilot::InvalidLocaleError] if you pass anything but <tt>:ru</tt> or <tt>:en</tt>
|
97
|
+
#
|
106
98
|
# @see https://smspilot.ru/my-settings.php Get your production API key here
|
107
99
|
# @see https://smspilot.ru/apikey.php Get your development API key here
|
108
100
|
# @note Current development API key is <tt>"XXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZXXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZ"</tt>
|
109
101
|
#
|
110
102
|
# @example
|
111
103
|
# client = SmsPilot::Client.new(api_key: ENV["SMS_PILOT_API_KEY"])
|
104
|
+
# client = SmsPilot::Client.new(api_key: ENV["SMS_PILOT_API_KEY"], locale: :en)
|
112
105
|
#
|
113
106
|
def initialize(api_key:, locale: AVAILABLE_LOCALES[0])
|
114
107
|
@api_key = validate_api_key!(api_key)
|
@@ -117,8 +110,6 @@ module SmsPilot
|
|
117
110
|
@response_status = nil
|
118
111
|
@response_headers = {}
|
119
112
|
@response_body = nil
|
120
|
-
@response_data = {}
|
121
|
-
@url = nil
|
122
113
|
end
|
123
114
|
|
124
115
|
|
@@ -136,37 +127,26 @@ module SmsPilot
|
|
136
127
|
# @raise [SmsPilot::InvalidMessageError] if your message is empty
|
137
128
|
# @raise [SmsPilot::InvalidPhoneError] if your phone is empty
|
138
129
|
# @raise [SmsPilot::InvalidPhoneError] if your phone has no digits
|
130
|
+
# @raise [URI::InvalidURIError] but is almost impossible, because we provide the URL ourselves
|
139
131
|
#
|
140
132
|
# @example
|
141
133
|
# client.send_sms("+7 (902) 123-45-67", "Привет, мир!") # => true
|
134
|
+
# client.send_sms("+7 (902) 123-45-67", "Привет, мир!", "ФССПРФ") # => true
|
142
135
|
#
|
143
|
-
def send_sms(phone, message)
|
136
|
+
def send_sms(phone, message, sender_name = nil)
|
144
137
|
validate_phone! phone
|
145
138
|
validate_message! message
|
139
|
+
validate_sender_name! sender_name
|
146
140
|
|
147
141
|
@phone = normalize_phone(phone)
|
148
|
-
uri
|
149
|
-
@url = uri.to_s
|
150
|
-
|
151
|
-
response = Net::HTTP.get_response(uri)
|
152
|
-
|
153
|
-
@response_body = response.body
|
154
|
-
@response_status = response.code.to_i
|
155
|
-
@response_headers = response.each_capitalized.to_h
|
156
|
-
|
157
|
-
unless response.is_a?(Net::HTTPSuccess)
|
158
|
-
@error = "HTTP request failed with code #{response.code}"
|
159
|
-
return false
|
160
|
-
end
|
142
|
+
@uri = build_uri(@phone, message, sender_name)
|
161
143
|
|
162
|
-
|
144
|
+
response = persist_response_details Net::HTTP.get_response(@uri)
|
163
145
|
|
164
|
-
|
165
|
-
|
166
|
-
return false
|
167
|
-
end
|
146
|
+
@error = "HTTP request failed with code #{response.code}" and return false unless response.is_a?(Net::HTTPSuccess)
|
147
|
+
@error = "#{error_description} (error code: #{error_code})" and return false if rejected?
|
168
148
|
|
169
|
-
|
149
|
+
true
|
170
150
|
|
171
151
|
rescue JSON::ParserError => error
|
172
152
|
@error = "API returned invalid JSON. #{error.message}"
|
@@ -191,7 +171,45 @@ module SmsPilot
|
|
191
171
|
# client.balance #=> 20215.25
|
192
172
|
#
|
193
173
|
def balance
|
194
|
-
|
174
|
+
response_data["balance"]&.to_f if sms_sent?
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
# SMS broadcast ID (API documentation calls it “server ID” but it makes no sense, as it is clearly the ID of the transmission, not of a server)
|
179
|
+
#
|
180
|
+
# @example
|
181
|
+
# client.broadcast_id #=> 10000
|
182
|
+
#
|
183
|
+
# @return [nil, Integer]
|
184
|
+
#
|
185
|
+
# @see #response_data
|
186
|
+
#
|
187
|
+
def broadcast_id
|
188
|
+
@response_data.dig("send", 0, "server_id")&.to_i if sms_sent?
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
# SMS delivery status, as returned by the API
|
193
|
+
#
|
194
|
+
# @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.
|
195
|
+
# @see https://smspilot.ru/apikey.php#status List of available statuses at API documentation website
|
196
|
+
#
|
197
|
+
# Code | Name | Final? | Description
|
198
|
+
# ----:|:--------------|:-------|:-------------
|
199
|
+
# -2 | Ошибка | Да | Ошибка, неправильные параметры запроса
|
200
|
+
# -1 | Не доставлено | Да | Сообщение не доставлено (не в сети, заблокирован, не взял трубку), PING — не в сети, HLR — не обслуживается (заблокирован)
|
201
|
+
# 0 | Новое | Нет | Новое сообщение/запрос, ожидает обработки у нас на сервере
|
202
|
+
# 1 | В очереди | Нет | Сообщение или запрос ожидают отправки на сервере оператора
|
203
|
+
# 2 | Доставлено | Да | Доставлено, звонок совершен, PING — в сети, HLR — обслуживается
|
204
|
+
# 3 | Отложено | Нет | Отложенная отправка, отправка сообщения/запроса запланирована на другое время
|
205
|
+
#
|
206
|
+
# @example
|
207
|
+
# client.broadcast_status #=> 2
|
208
|
+
#
|
209
|
+
# @see #sms_status
|
210
|
+
#
|
211
|
+
def broadcast_status
|
212
|
+
@response_data.dig("send", 0, "status")&.to_i if sms_sent?
|
195
213
|
end
|
196
214
|
|
197
215
|
|
@@ -232,7 +250,36 @@ module SmsPilot
|
|
232
250
|
#
|
233
251
|
def rejected?
|
234
252
|
return false if sms_sent?
|
235
|
-
|
253
|
+
response_data["error"].is_a? Hash
|
254
|
+
end
|
255
|
+
|
256
|
+
|
257
|
+
# Parses <tt>@response_body</tt> and memoizes result in <tt>@response_data</tt>
|
258
|
+
#
|
259
|
+
# @example
|
260
|
+
# {
|
261
|
+
# "balance" => "20006.97",
|
262
|
+
# "cost" => "1.68",
|
263
|
+
# "send" => [
|
264
|
+
# {
|
265
|
+
# "phone" => "79021234567",
|
266
|
+
# "price" => "1.68",
|
267
|
+
# "server_id" => "10000",
|
268
|
+
# "status" => "0"
|
269
|
+
# }
|
270
|
+
# ]
|
271
|
+
# }
|
272
|
+
#
|
273
|
+
# @return [Hash]
|
274
|
+
# @raise [JSON::ParserError] which is rescued in {#send_sms}
|
275
|
+
#
|
276
|
+
# @see #response_body
|
277
|
+
# @see #response_headers
|
278
|
+
# @see #response_status
|
279
|
+
#
|
280
|
+
def response_data
|
281
|
+
return {} unless @response_body
|
282
|
+
@response_data ||= JSON.parse @response_body
|
236
283
|
end
|
237
284
|
|
238
285
|
|
@@ -263,7 +310,7 @@ module SmsPilot
|
|
263
310
|
# client.sms_cost #=> 2.63
|
264
311
|
#
|
265
312
|
def sms_cost
|
266
|
-
|
313
|
+
response_data["cost"]&.to_f if sms_sent?
|
267
314
|
end
|
268
315
|
|
269
316
|
|
@@ -278,54 +325,74 @@ module SmsPilot
|
|
278
325
|
# client.sms_sent? #=> true
|
279
326
|
#
|
280
327
|
def sms_sent?
|
281
|
-
|
328
|
+
response_data["send"] != nil
|
282
329
|
end
|
283
330
|
|
284
331
|
|
285
|
-
#
|
286
|
-
#
|
287
|
-
# @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.
|
288
|
-
# @see https://smspilot.ru/apikey.php#status List of available statuses at API documentation website
|
332
|
+
# @deprecated (in favor of {#broadcast_status})
|
289
333
|
#
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
#
|
296
|
-
# 2 | Доставлено | Да | Доставлено, звонок совершен, PING — в сети, HLR — обслуживается
|
297
|
-
# 3 | Отложено | Нет | Отложенная отправка, отправка сообщения/запроса запланирована на другое время
|
334
|
+
def sms_status
|
335
|
+
broadcast_status
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
# URL generated by combining <tt>API_ENDPOINT</tt>, your API key, SMS text & phone
|
298
340
|
#
|
299
341
|
# @example
|
300
|
-
# client.
|
342
|
+
# client.url #=> "https://smspilot.ru/api.php?api_key=XXX&format=json&send=TEXT&to=79021234567"
|
301
343
|
#
|
302
|
-
|
303
|
-
|
344
|
+
# @return [nil, String]
|
345
|
+
#
|
346
|
+
def url
|
347
|
+
@uri&.to_s
|
304
348
|
end
|
305
349
|
|
306
350
|
# @!endgroup
|
307
351
|
|
308
352
|
|
309
353
|
# The URI we will send an HTTP request to
|
310
|
-
#
|
311
354
|
# @private
|
312
|
-
# @return [URI]
|
313
|
-
# @raise [URI::InvalidURIError] but is very unlikely because we provide the URL ourselves
|
314
355
|
#
|
315
356
|
# @example
|
316
357
|
# build_uri("79021234567", "Hello, World!")
|
317
358
|
# #=> #<URI::HTTPS https://smspilot.ru/api.php?apikey=XXX…&format=json&send=Hello%2C+World%21&to=79021234567>
|
318
359
|
#
|
319
|
-
|
360
|
+
# @return [URI]
|
361
|
+
# @raise [URI::InvalidURIError] but is almost impossible, because we provide the URL ourselves
|
362
|
+
#
|
363
|
+
# @param [String] phone
|
364
|
+
# @param [String] text
|
365
|
+
# @param [nil, String] sender_name
|
366
|
+
#
|
367
|
+
# @see #api_key
|
368
|
+
# @see #phone
|
369
|
+
# @see #validate_phone!
|
370
|
+
# @see #validate_message!
|
371
|
+
# @see #validate_sender_name!
|
372
|
+
#
|
373
|
+
private def build_uri(phone, text, sender_name)
|
374
|
+
attributes = {
|
375
|
+
apikey: @api_key,
|
376
|
+
charset: REQUEST_CHARSET,
|
377
|
+
format: REQUEST_ACCEPT_FORMAT,
|
378
|
+
lang: @locale,
|
379
|
+
send: text,
|
380
|
+
to: phone
|
381
|
+
}
|
382
|
+
attributes = attributes.merge({ sender: sender_name }) if sender_name
|
383
|
+
|
320
384
|
URI.parse(API_ENDPOINT).tap do |uri|
|
321
|
-
uri.query = URI.encode_www_form(
|
385
|
+
uri.query = URI.encode_www_form(attributes)
|
322
386
|
end
|
323
387
|
end
|
324
388
|
|
325
389
|
|
390
|
+
|
391
|
+
|
326
392
|
# Cleans up your phone from anything but digits. Also replaces 8 to 7 if it is the first digit.
|
327
393
|
#
|
328
394
|
# @private
|
395
|
+
# @param [String] phone
|
329
396
|
# @return [String]
|
330
397
|
#
|
331
398
|
# @example
|
@@ -337,6 +404,21 @@ module SmsPilot
|
|
337
404
|
end
|
338
405
|
|
339
406
|
|
407
|
+
# Saves response details into instance variables
|
408
|
+
# @private
|
409
|
+
#
|
410
|
+
# @return [response]
|
411
|
+
# @raise [TypeError] unless a Net::HTTPResponse passed
|
412
|
+
#
|
413
|
+
private def persist_response_details(response)
|
414
|
+
fail TypeError, "Net::HTTPResponse expected, you pass a #{response.class}" unless response.is_a? Net::HTTPResponse
|
415
|
+
@response_body = response.body
|
416
|
+
@response_status = response.code.to_i
|
417
|
+
@response_headers = response.each_capitalized.to_h
|
418
|
+
response
|
419
|
+
end
|
420
|
+
|
421
|
+
|
340
422
|
# @!group Validations
|
341
423
|
|
342
424
|
# Validates api_key
|
@@ -344,7 +426,7 @@ module SmsPilot
|
|
344
426
|
# @private
|
345
427
|
# @return [String] the original value passed into the method, only if it was valid
|
346
428
|
# @param [String] api_key
|
347
|
-
|
429
|
+
#
|
348
430
|
# @raise [SmsPilot::InvalidError] if api_key is not a String
|
349
431
|
# @raise [SmsPilot::InvalidError] if api_key is an empty String
|
350
432
|
#
|
@@ -360,7 +442,7 @@ module SmsPilot
|
|
360
442
|
# @private
|
361
443
|
# @return [Symbol] the original value passed into the method, only if it was valid
|
362
444
|
# @param [Symbol] locale
|
363
|
-
|
445
|
+
#
|
364
446
|
# @raise [SmsPilot::InvalidError] if locale is not a Symbol
|
365
447
|
# @raise [SmsPilot::InvalidError] if locale is unrecognized
|
366
448
|
#
|
@@ -372,9 +454,10 @@ module SmsPilot
|
|
372
454
|
|
373
455
|
|
374
456
|
# Validates message
|
375
|
-
#
|
376
457
|
# @private
|
377
|
-
#
|
458
|
+
#
|
459
|
+
# @param [String] message
|
460
|
+
# @return [String] the original value passed into the method, only if it was valid
|
378
461
|
#
|
379
462
|
# @raise [SmsPilot::InvalidMessageError] if you pass anythig but a String with the <tt>message</tt> argument
|
380
463
|
# @raise [SmsPilot::InvalidMessageError] if your message is empty
|
@@ -382,13 +465,15 @@ module SmsPilot
|
|
382
465
|
private def validate_message!(message)
|
383
466
|
fail SmsPilot::InvalidMessageError, "SMS message must be a String, you pass a #{ message.class} (#{ message})" unless message.is_a? String
|
384
467
|
fail SmsPilot::InvalidMessageError, "SMS message cannot be empty" if message == ""
|
468
|
+
message
|
385
469
|
end
|
386
470
|
|
387
471
|
|
388
472
|
# Validates phone
|
389
|
-
#
|
390
473
|
# @private
|
391
|
-
#
|
474
|
+
#
|
475
|
+
# @param [String] phone
|
476
|
+
# @return [String] the original value passed into the method, only if it was valid
|
392
477
|
#
|
393
478
|
# @raise [SmsPilot::InvalidPhoneError] if you pass anythig but a String with the <tt>phone</tt> argument
|
394
479
|
# @raise [SmsPilot::InvalidPhoneError] if your phone is empty
|
@@ -398,6 +483,22 @@ module SmsPilot
|
|
398
483
|
fail SmsPilot::InvalidPhoneError, "phone must be a String, you pass a #{phone.class} (#{phone})" unless phone.is_a? String
|
399
484
|
fail SmsPilot::InvalidPhoneError, "phone cannot be empty" if phone == ""
|
400
485
|
fail SmsPilot::InvalidPhoneError, "phone must contain digits" if phone.scan(/\d/).none?
|
486
|
+
phone
|
487
|
+
end
|
488
|
+
|
489
|
+
|
490
|
+
# Validates sender name
|
491
|
+
# @private
|
492
|
+
#
|
493
|
+
# @param [nil, String] sender_name
|
494
|
+
# @return [String] the original value passed into the method, only if it was valid
|
495
|
+
#
|
496
|
+
# @raise [SmsPilot::InvalidSenderNameError] if you pass anything but <tt>nil</tt> or non-empty <tt>String</tt>
|
497
|
+
#
|
498
|
+
private def validate_sender_name!(sender_name)
|
499
|
+
fail SmsPilot::InvalidSenderNameError, "sender name must be either nil or String" unless [NilClass, String].include? sender_name.class
|
500
|
+
fail SmsPilot::InvalidSenderNameError, "sender name cannot be empty" if sender_name == ""
|
501
|
+
sender_name
|
401
502
|
end
|
402
503
|
|
403
504
|
# @!endgroup
|
data/lib/sms_pilot/errors.rb
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
module SmsPilot
|
4
4
|
|
5
|
-
class InvalidAPIkeyError
|
6
|
-
class
|
7
|
-
class
|
8
|
-
class
|
5
|
+
class InvalidAPIkeyError < ArgumentError; end
|
6
|
+
class InvalidLocaleError < ArgumentError; end
|
7
|
+
class InvalidMessageError < ArgumentError; end
|
8
|
+
class InvalidPhoneError < ArgumentError; end
|
9
|
+
class InvalidSenderNameError < ArgumentError; end
|
9
10
|
|
10
11
|
end
|
data/lib/sms_pilot/version.rb
CHANGED
data/sms-pilot-api-v1.gemspec
CHANGED
@@ -15,10 +15,10 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
16
16
|
|
17
17
|
spec.metadata = {
|
18
|
-
|
18
|
+
"changelog_uri" => "#{spec.homepage}/blob/master/CHANGELOG.md",
|
19
19
|
"documentation_uri" => "https://rubydoc.info/github/sergeypedan/#{spec.name}/master/",
|
20
|
-
|
21
|
-
|
20
|
+
"homepage_uri" => spec.homepage,
|
21
|
+
"source_code_uri" => spec.homepage
|
22
22
|
}
|
23
23
|
|
24
24
|
# Specify which files should be added to the gem when it is released.
|
@@ -27,7 +27,10 @@ Gem::Specification.new do |spec|
|
|
27
27
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features|pkg|doc)/}) }
|
28
28
|
end
|
29
29
|
|
30
|
-
spec.bindir = "
|
30
|
+
spec.bindir = "exe"
|
31
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
32
|
spec.require_paths = ["lib"]
|
32
33
|
|
34
|
+
# spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
35
|
+
|
33
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Pedan
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Simple wrapper around SMS pilot API v1. Version 1 because it returns
|
14
14
|
more data within its standard response
|