smsru-ruby 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '055631208861d034be5c8318a3a8e52a04462d08e89816077cfbc3bb4cca0be7'
4
- data.tar.gz: 3961c10a7e11a77bc886b848b37cf6b31b8da93eb13a14b8370db25d43a10f20
3
+ metadata.gz: 9fa32fb7428f230423bda4d5a4b8e776c719df31daebe9ffb30e488e8bc7c620
4
+ data.tar.gz: 8dd26fbc54609529e34df51e2ff374e64d3657be1187e2ff76a9d33dbbcbb7ed
5
5
  SHA512:
6
- metadata.gz: 54785ce27189179b91c1126107bda2ed46afc27160152fa1304a4a5d71e4700b04fa32fd55d6786226cba091e1b7188f644d4393bd7de31807a865a500152117
7
- data.tar.gz: 5aeb1ac3e4990df7dc1d54a23c1ed961336b7efea9a505eb20e85219f95307ee4e188cbdb09e4d7578af4e4fb4277763ac649d2137c271a29a635470b3a85b31
6
+ metadata.gz: a4fb447fbe3057aaab9b6e92ee90645bb2294ef0b7a75fc697c4befd820e77f9115f485b1f4c12ac05c624a0b5224ab82b8b5f375fa7ee958b7eeb39b793f7d9
7
+ data.tar.gz: 235d9ca8fba5a74229ee3416a2fc58bc704aabb2f1b93d8bf18daff8916f948d10d2f56ef7aaa6a5ee3522e059515832dce806fe3fe755adbcdba09c82bea509
data/.yardopts CHANGED
@@ -3,4 +3,4 @@
3
3
  lib/**/*.rb
4
4
  -
5
5
  CHANGELOG.md
6
- LICENSE.txt
6
+ LICENSE
data/CHANGELOG.md CHANGED
@@ -5,16 +5,51 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ The public API that Semantic Versioning covers is every constant and method
9
+ under `SmsRu` that YARD documents as public: the `SmsRu` client and its `auth`,
10
+ `callbacks`, `call_check`, `my`, and `stoplist` sub-resources, the result and
11
+ event `Data` classes, the `SmsRu::Statuses` constants and predicates, the error
12
+ hierarchy under `SmsRu::Error`, and `SmsRu::Webhook.parse`. Anything marked
13
+ `@api private`, including `SmsRu::Coerce` and the sub-resource constructors, may
14
+ change in any release. The minimum supported Ruby version is part of the public
15
+ API: raising it takes a MAJOR release.
16
+
8
17
  ## [Unreleased]
9
18
 
19
+ ## [3.0.0] - 2026-09-07
20
+
21
+ ### Removed
22
+
23
+ - Ruby 3.2 support. The minimum supported Ruby is now 3.3.
24
+
25
+ ### Added
26
+
27
+ - This changelog now declares which constants and methods Semantic Versioning
28
+ covers, so a version range says something checkable about what may change.
29
+
30
+ ## [2.0.1] - 2026-07-31
31
+
32
+ ### Added
33
+
34
+ - Releases are now built and published by GitHub Actions over OIDC, and every
35
+ published gem carries a Sigstore provenance attestation. Verify one with
36
+ `https://rubygems.org/api/v1/attestations/smsru-ruby-VERSION.json`.
37
+
38
+ ### Changed
39
+
40
+ - Renamed `LICENSE.txt` to `LICENSE`. The license text is untouched and the gem
41
+ is still MIT.
42
+ - Rewrote the README and widened the gemspec summary and description to describe
43
+ the full API surface.
44
+
10
45
  ## [2.0.0] - 2026-07-13
11
46
 
12
47
  ### Changed
13
48
 
14
- - **BREAKING:** Renamed the gem from `smsru_ruby` to `smsru-ruby` for
49
+ - **Breaking:** Renamed the gem from `smsru_ruby` to `smsru-ruby` for
15
50
  consistency with the `-ruby` suffix convention. Update your `Gemfile`
16
51
  (`gem "smsru-ruby"`) and requires (`require "smsru-ruby"`). The Ruby API is
17
- unchanged — the top-level class is still `SmsRu`.
52
+ unchanged. The top-level class is still `SmsRu`.
18
53
 
19
54
  ## [1.0.0] - 2026-06-26
20
55
 
@@ -34,8 +69,8 @@ same API, reworked to be idiomatic Ruby. How it differs from the original:
34
69
  and `Cost`; plus `#confirmed?` and `#available_today`. No raw decoded JSON or
35
70
  magic numbers.
36
71
  - **Typed error hierarchy** under `SmsRu::Error` (`AuthError`,
37
- `InsufficientFundsError`, `ResponseError`, `ConnectionError`) — errors are
38
- raised, not returned as status codes you have to inspect.
72
+ `InsufficientFundsError`, `ResponseError`, `ConnectionError`). Errors are
73
+ raised rather than returned as status codes you have to inspect.
39
74
  - **First-class inbound webhooks**: `SmsRu::Webhook.parse` decodes the callback
40
75
  POST into typed events (`SmsRu::Events::SmsStatus`, `CallcheckStatus`, `Test`,
41
76
  `Unknown`), and `SmsRu::Webhook.valid?` verifies the signature.
@@ -47,6 +82,8 @@ same API, reworked to be idiomatic Ruby. How it differs from the original:
47
82
  SMS.ru's loosely-typed JSON is normalized to the declared types at the parse
48
83
  boundary, so result objects never surface raw wire values.
49
84
 
50
- [Unreleased]: https://github.com/svyatov/smsru-ruby/compare/v2.0.0...HEAD
85
+ [Unreleased]: https://github.com/svyatov/smsru-ruby/compare/v3.0.0...HEAD
86
+ [3.0.0]: https://github.com/svyatov/smsru-ruby/compare/v2.0.1...v3.0.0
87
+ [2.0.1]: https://github.com/svyatov/smsru-ruby/compare/v2.0.0...v2.0.1
51
88
  [2.0.0]: https://github.com/svyatov/smsru-ruby/compare/v1.0.0...v2.0.0
52
89
  [1.0.0]: https://github.com/svyatov/smsru-ruby/releases/tag/v1.0.0
data/README.md CHANGED
@@ -1,104 +1,71 @@
1
1
  # smsru-ruby
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/smsru-ruby.svg)](https://rubygems.org/gems/smsru-ruby)
4
- [![CI](https://github.com/svyatov/smsru-ruby/actions/workflows/main.yml/badge.svg)](https://github.com/svyatov/smsru-ruby/actions/workflows/main.yml)
5
- [![codecov](https://codecov.io/gh/svyatov/smsru-ruby/branch/main/graph/badge.svg)](https://codecov.io/gh/svyatov/smsru-ruby)
6
- [![Documentation](https://img.shields.io/badge/docs-rubydoc.info-blue.svg)](https://rubydoc.info/gems/smsru-ruby)
7
- [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.2-CC342D.svg)](https://www.ruby-lang.org)
8
- [![Types: RBS](https://img.shields.io/badge/types-RBS-8A2BE2.svg)](https://github.com/svyatov/smsru-ruby/tree/main/sig)
9
-
10
- A modern, **dependency-free**, **fully typed** Ruby client for the [SMS.ru](https://sms.ru) HTTP API —
11
- typed results, typed errors, shipped RBS signatures, and first-class webhooks.
12
-
13
- It is a clean, idiomatic Ruby port of the official [SMS.ru PHP library](https://sms.ru/php):
14
- send single or bulk SMS, schedule delivery, check cost and delivery status, verify
15
- users by phone call, inspect your balance/limits/senders, manage the stoplist, and
16
- register delivery callbacks — all returning typed, immutable result objects and
17
- raising typed errors.
18
-
19
- ## Why smsru-ruby?
20
-
21
- - **Zero runtime dependencies** — only Ruby's standard library (`net/http`, `json`, `openssl`).
22
- - **Fully typed** — immutable `Data` result objects, not raw hashes, plus a typed error hierarchy: `rescue SmsRu::Error` catches everything.
23
- - **RBS signatures shipped** (`sig/`) and Steep-checked — type-check your integration out of the box.
24
- - **First-class webhooks** — parse signed delivery and call-authorization callbacks into typed events; the signature is verified in **constant time** (timing-attack safe).
25
- - **Secret-safe by default** — TLS verified; the optional logger never logs your `api_id`, phone numbers, or message text. Configurable timeout and transport retries.
26
- - **Outcome vs. delivery state** — two distinct ideas, each with its own predicates (`ok?` vs. `delivered?`/`pending?`/`failed?`), never conflated.
27
- - **100% test & documentation coverage, enforced in CI** across Ruby 3.2–4.0.
28
-
29
- ## What's covered
30
-
31
- The full SMS.ru API, mapped to an idiomatic Ruby surface:
32
-
33
- | Capability | Method |
34
- | --- | --- |
35
- | Send — single, bulk, or per-number text | `client.deliver` |
36
- | Price a message before sending | `client.cost` |
37
- | Delivery status, with state predicates | `client.status` |
38
- | Verify by flash call (outbound) | `client.call` |
39
- | Verify by callcheck (inbound) | `client.callcheck` |
40
- | Balance, limits, free limit, senders | `client.my` |
41
- | Validate credentials | `client.auth.ok?` |
42
- | Stoplist — add, remove, list | `client.stoplist` |
43
- | Webhook URLs — add, remove, list | `client.callbacks` |
44
- | Parse & verify incoming webhooks | `SmsRu::Webhook` |
45
-
46
- ## Table of contents
47
-
48
- - [Why smsru-ruby?](#why-smsru-ruby)
49
- - [What's covered](#whats-covered)
50
- - [Supported Ruby versions](#supported-ruby-versions)
51
- - [Installation](#installation)
52
- - [Quick start](#quick-start)
53
- - [Configuration](#configuration)
54
- - [Sending messages](#sending-messages)
55
- - [Cost and status](#cost-and-status)
56
- - [Verify by phone call](#verify-by-phone-call)
57
- - [Account information](#account-information)
58
- - [Stoplist](#stoplist)
59
- - [Callbacks (webhooks)](#callbacks-webhooks)
60
- - [Error handling](#error-handling)
61
- - [Development](#development)
62
- - [Recording test cassettes](#recording-test-cassettes)
63
- - [License](#license)
64
-
65
- ## Supported Ruby versions
66
-
67
- Ruby **3.2+** (the result objects use [`Data`](https://docs.ruby-lang.org/en/3.2/Data.html)).
68
- CI runs against `ruby-head`, `4.0`, `3.4`, `3.3`, and `3.2`.
3
+ smsru-ruby is a Ruby client for the [SMS.ru](https://sms.ru) HTTP API, for applications that send SMS,
4
+ check delivery, and verify users by phone call.
5
+
6
+ [![Gem version](https://img.shields.io/gem/v/smsru-ruby)](https://rubygems.org/gems/smsru-ruby)
7
+ [![CI](https://github.com/svyatov/smsru-ruby/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/svyatov/smsru-ruby/actions/workflows/main.yml)
8
+ [![Coverage](https://codecov.io/gh/svyatov/smsru-ruby/branch/main/graph/badge.svg)](https://app.codecov.io/gh/svyatov/smsru-ruby)
9
+
10
+ - **Covers the whole SMS.ru HTTP API.** Sending, cost, delivery status, flash call and callcheck
11
+ verification, balance and limits, stoplist, callback registration, and inbound webhook parsing.
12
+ - **11 typed result objects and 12 named status constants.** Every response arrives as a frozen `Data`
13
+ object rather than a decoded Hash.
14
+ - **No runtime dependencies.** The gem loads `net/http`, `json`, and `openssl` from the standard
15
+ library and nothing else.
16
+ - **A Ruby port of the official [SMS.ru PHP library](https://sms.ru/php).** Same API coverage, with
17
+ keyword arguments, namespaced sub-resources, and raised errors in place of flat `get_*` methods and
18
+ returned status codes.
19
+ - **100% line coverage and 100% documented public API.** Both gates run in CI on every push.
69
20
 
70
21
  ## Installation
71
22
 
23
+ Add the gem to your Gemfile.
24
+
72
25
  ```ruby
73
- # Gemfile
74
26
  gem "smsru-ruby"
75
27
  ```
76
28
 
77
- ```sh
78
- bundle install
79
- # or
80
- gem install smsru-ruby
81
- ```
82
-
83
- ```ruby
84
- require "smsru-ruby"
85
- ```
29
+ Then run `bundle install`. Without Bundler, run `gem install smsru-ruby`.
86
30
 
87
31
  ## Quick start
88
32
 
33
+ Create a client with your API id, then send a message.
34
+
89
35
  ```ruby
90
- client = SmsRu.new("YOUR_API_ID")
36
+ require "smsru-ruby"
91
37
 
38
+ client = SmsRu.new("YOUR_API_ID")
92
39
  result = client.deliver("79991234567", "Hello from Ruby!")
93
- result.messages.first.sms_id # => "000000-10000000"
94
- client.my.balance # => 4762.58
40
+
41
+ result.messages.first.sms_id # => "000000-10000000"
42
+ client.my.balance # => 4762.58
95
43
  ```
96
44
 
97
45
  Get your `api_id` in the SMS.ru dashboard under
98
- [Settings → API](https://sms.ru/?panel=api).
46
+ [Settings, API](https://sms.ru/?panel=api).
47
+
48
+ ## API coverage
49
+
50
+ The full SMS.ru API, mapped to an idiomatic Ruby surface:
51
+
52
+ | Capability | Method |
53
+ | --- | --- |
54
+ | Send a single, bulk, or per-number text | `client.deliver` |
55
+ | Price a message before sending | `client.cost` |
56
+ | Delivery status, with state predicates | `client.status` |
57
+ | Verify by flash call (outbound) | `client.call` |
58
+ | Verify by callcheck (inbound) | `client.callcheck` |
59
+ | Balance, limits, free limit, senders | `client.my` |
60
+ | Validate credentials | `client.auth.ok?` |
61
+ | Stoplist: add, remove, list | `client.stoplist` |
62
+ | Webhook URLs: add, remove, list | `client.callbacks` |
63
+ | Parse and verify incoming webhooks | `SmsRu::Webhook` |
99
64
 
100
65
  ## Configuration
101
66
 
67
+ Every client option is a keyword argument on `SmsRu.new`:
68
+
102
69
  ```ruby
103
70
  SmsRu.new(
104
71
  "YOUR_API_ID",
@@ -111,11 +78,11 @@ SmsRu.new(
111
78
  ```
112
79
 
113
80
  Retries apply only to transport-level problems (timeouts, refused connections).
114
- API errors are never retried — they are raised immediately.
81
+ API errors are never retried. They are raised immediately.
115
82
 
116
83
  `from` is a per-client default so you don't repeat your sender name on every call;
117
84
  a per-call `from:` always wins. The `logger` logs only the request path and
118
- transport failures — never your `api_id`, phone numbers, or message text.
85
+ transport failures, never your `api_id`, phone numbers, or message text.
119
86
 
120
87
  ## Sending messages
121
88
 
@@ -128,7 +95,7 @@ client.deliver("79991234567", "Hi there")
128
95
  # 2. Same text to many numbers (Array)
129
96
  client.deliver(["79991234567", "79991234568"], "Hi everyone")
130
97
 
131
- # 3. A different text per number (Hash — do not pass a separate text).
98
+ # 3. A different text per number (Hash, with no separate text argument).
132
99
  # Use braces so Ruby treats it as a positional Hash, not keyword arguments.
133
100
  client.deliver({
134
101
  "79991234567" => "Hi Alice",
@@ -143,7 +110,7 @@ client.deliver(
143
110
  "79991234567", "Hi",
144
111
  from: "MyCompany", # approved sender name
145
112
  time: Time.now.to_i + 3600, # scheduled send (UNIX time, up to 2 months ahead)
146
- ttl: 60, # message lifetime in minutes (1–1440)
113
+ ttl: 60, # message lifetime in minutes (1 to 1440)
147
114
  daytime: true, # defer night-time sends to the recipient's daytime
148
115
  translit: true, # transliterate Cyrillic to Latin
149
116
  test: true, # test mode for this call (overrides the client default)
@@ -174,6 +141,8 @@ result.failed # => [SmsRu::Sms, ...] rejected recipients
174
141
 
175
142
  ## Cost and status
176
143
 
144
+ Price a message before sending, and read the delivery state afterwards:
145
+
177
146
  ```ruby
178
147
  # Price a message before sending (text is optional; omit it for the price of 1 SMS)
179
148
  cost = client.cost("79991234567", "How much?")
@@ -185,15 +154,15 @@ cost.ok? # => true only if every recipient was priced
185
154
  cost.failed # => [SmsRu::CostItem, ...] recipients that errored
186
155
  cost.failed.first.error_code # => 207
187
156
 
188
- # Delivery status — one id or an Array of ids
157
+ # Delivery status takes one id or an Array of ids
189
158
  status = client.status("000000-10000000")
190
159
  status.status_code # => 103 (the delivery state code)
191
160
  status.status_text # => "Сообщение доставлено"
192
161
 
193
162
  # State predicates instead of memorizing codes:
194
163
  status.delivered? # => true (code 103)
195
- status.pending? # => false (codes 100–102, still in transit)
196
- status.failed? # => false (codes 104–108, 150)
164
+ status.pending? # => false (codes 100 to 102, still in transit)
165
+ status.failed? # => false (codes 104 to 108, 150)
197
166
  status.found? # => true (false only when the id is unknown, code -1)
198
167
 
199
168
  statuses = client.status(["000000-10000000", "000000-10000001"]) # => [SmsRu::Status, ...]
@@ -204,15 +173,15 @@ Every code has a named constant under `SmsRu::Statuses` (e.g.
204
173
  predicates don't cover. The same predicates are available on
205
174
  `SmsRu::Events::SmsStatus` from webhook payloads.
206
175
 
207
- > **Outcome vs. delivery state — two ideas, two names.** `ok?` (with
176
+ > **Outcome and delivery state are two ideas with two names.** `ok?` (with
208
177
  > `error_code`/`error_text` on a rejected `Sms`/`CostItem`) answers *did the
209
178
  > request succeed for this recipient*. `status_code` (with
210
- > `delivered?`/`pending?`/`failed?`) answers *where the message is in delivery* —
179
+ > `delivered?`/`pending?`/`failed?`) answers *where the message is in delivery*,
211
180
  > and only `Status` and webhook events carry it.
212
181
 
213
182
  ## Verify by phone call
214
183
 
215
- Two ways to verify a user by phone call — no SMS required.
184
+ Two ways to verify a user by phone call, with no SMS required.
216
185
 
217
186
  **Outbound (flash call).** SMS.ru calls the user; the last 4 digits of the
218
187
  calling number are the code. You receive the expected `code` to compare against
@@ -220,7 +189,7 @@ what the user enters:
220
189
 
221
190
  ```ruby
222
191
  call = client.call("79991234567")
223
- call.code # => "1435" — the last 4 digits the user will see
192
+ call.code # => "1435", the last 4 digits the user will see
224
193
  call.call_id # => "000000-10000000"
225
194
  ```
226
195
 
@@ -229,7 +198,7 @@ call (free for the caller) and marks the check confirmed:
229
198
 
230
199
  ```ruby
231
200
  check = client.callcheck.add("79991234567")
232
- check.call_phone_pretty # => "+7 (800) 500-8275" — show this to the user
201
+ check.call_phone_pretty # => "+7 (800) 500-8275", show this to the user
233
202
 
234
203
  # Poll until the user has called (or receive it via a callback/webhook):
235
204
  client.callcheck.status(check.check_id).confirmed? # => true
@@ -286,9 +255,9 @@ In your webhook handler, verify the signature, parse the payload, and
286
255
  acknowledge it by replying with the string `"100"`:
287
256
 
288
257
  ```ruby
289
- # In Rails, params[:data] is ActionController::Parameters, not a Hash — convert
290
- # it with .to_unsafe_h first, or the numeric-key ordering the signature depends
291
- # on is skipped and the check below rejects the payload. The payload is
258
+ # In Rails, params[:data] is ActionController::Parameters rather than a Hash.
259
+ # Convert it with .to_unsafe_h first, or the numeric-key ordering the signature
260
+ # depends on is skipped and the check below rejects the payload. The payload is
292
261
  # signature-verified, so to_unsafe_h is safe here (.to_h would drop keys).
293
262
  # In bare Rack params["data"] is already a Hash; pass it as-is.
294
263
  data = params[:data].to_unsafe_h
@@ -328,6 +297,8 @@ SmsRu::Error # base class
328
297
  └─ SmsRu::InsufficientFundsError # not enough money (code 201)
329
298
  ```
330
299
 
300
+ Rescue whichever level of that hierarchy your code needs, around any call.
301
+
331
302
  ```ruby
332
303
  begin
333
304
  client.deliver("79991234567", "Hi")
@@ -342,11 +313,14 @@ rescue SmsRu::ConnectionError => e
342
313
  end
343
314
  ```
344
315
 
345
- Note that per-recipient failures in a bulk `deliver` are **not** raised — they are
316
+ Note that per-recipient failures in a bulk `deliver` are **not** raised. They are
346
317
  reported on each `SmsRu::Sms` in `result.messages` (see above).
347
318
 
348
319
  ## Development
349
320
 
321
+ Ruby 3.3 or newer is required. CI runs against `ruby-head`, `4.0`, `3.4`, and
322
+ `3.3`.
323
+
350
324
  ```sh
351
325
  bin/setup # install dependencies
352
326
  bundle exec rake # run RuboCop, validate RBS signatures, and the test suite
@@ -361,12 +335,12 @@ diagnostics (no implicit `untyped`, no unannotated collections) at **100% type
361
335
  coverage**, gated in CI. Loosely-typed JSON from SMS.ru (which returns, say,
362
336
  `total_limit` as the string `"10"`) is normalized into the declared types at the
363
337
  parse boundary, and `rbs:test` checks that the values flowing through the suite
364
- actually match `sig/` at runtime — so the types can't drift from the code.
338
+ actually match `sig/` at runtime, so the types cannot drift from the code.
365
339
 
366
340
  ## Recording test cassettes
367
341
 
368
342
  End-to-end tests replay real SMS.ru responses recorded with [VCR](https://github.com/vcr/vcr).
369
- The cassettes are not committed with secrets — your `api_id` is filtered out. To
343
+ The cassettes are not committed with secrets: your `api_id` is filtered out. To
370
344
  record them once against your own account (message sends use `test=1`, so they are
371
345
  free):
372
346
 
@@ -378,6 +352,27 @@ This writes `test/cassettes/*.yml`. Commit them, then `COVERAGE=true bundle exec
378
352
  runs fully offline at 100% coverage. Before cassettes are recorded, the end-to-end
379
353
  tests are skipped (the unit and transport tests still run).
380
354
 
381
- ## License
382
-
383
- Released under the [MIT License](LICENSE.txt).
355
+ ## Help and project status
356
+
357
+ Ask a question or report a defect in the
358
+ [issue tracker](https://github.com/svyatov/smsru-ruby/issues). Both go to the same
359
+ place. For a security vulnerability, follow
360
+ [SECURITY.md](https://github.com/svyatov/smsru-ruby/blob/main/SECURITY.md) instead
361
+ of opening an issue.
362
+
363
+ Leonid Svyatov maintains this gem alone. He reads every issue, fixes defects in the
364
+ SMS.ru API coverage, and keeps the gem running on supported Ruby versions. Feature
365
+ work depends on the time he has.
366
+ [CONTRIBUTING.md](https://github.com/svyatov/smsru-ruby/blob/main/CONTRIBUTING.md#maintenance)
367
+ records who merges and releases.
368
+
369
+ ## Links
370
+
371
+ - [CHANGELOG.md](https://github.com/svyatov/smsru-ruby/blob/main/CHANGELOG.md) records every released
372
+ change.
373
+ - [CONTRIBUTING.md](https://github.com/svyatov/smsru-ruby/blob/main/CONTRIBUTING.md) covers setup,
374
+ tests, and the pull request process.
375
+ - [SECURITY.md](https://github.com/svyatov/smsru-ruby/blob/main/SECURITY.md) explains how to report a
376
+ vulnerability privately.
377
+ - [API documentation](https://rubydoc.info/gems/smsru-ruby) is generated from the source with YARD.
378
+ - [LICENSE](https://github.com/svyatov/smsru-ruby/blob/main/LICENSE) is the MIT License.
data/lib/sms_ru/client.rb CHANGED
@@ -20,7 +20,7 @@ class SmsRu
20
20
  # @param retries [Integer] retry attempts on transport failure (0 disables; PHP default is 5)
21
21
  # @param from [String, nil] default sender name for #deliver (overridable per call)
22
22
  # @param logger [Logger, nil] optional logger; logs the request path and transport
23
- # failures only — never the api_id, phone numbers, or message text
23
+ # failures only, never the api_id, phone numbers, or message text
24
24
  def initialize(api_id, timeout: 30, test: false, retries: 5, from: nil, logger: nil)
25
25
  @api_id = api_id
26
26
  @timeout = timeout
@@ -39,7 +39,7 @@ class SmsRu
39
39
  # forms, must be omitted for the Hash form
40
40
  # @param from [String, nil] an approved sender name
41
41
  # @param time [Integer, nil] schedule the send at this UNIX timestamp
42
- # @param ttl [Integer, nil] message lifetime in minutes (1–1440); undelivered
42
+ # @param ttl [Integer, nil] message lifetime in minutes (1 to 1440); undelivered
43
43
  # messages are discarded after this period
44
44
  # @param daytime [Boolean] when true, defer night-time sends to the recipient's daytime
45
45
  # @param translit [Boolean] transliterate Cyrillic to Latin
data/lib/sms_ru/coerce.rb CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  class SmsRu
4
4
  # Normalizes loosely-typed SMS.ru JSON values into the types the result
5
- # objects declare. SMS.ru is inconsistent on the wire — `/my/limit` returns
5
+ # objects declare. SMS.ru is inconsistent on the wire: `/my/limit` returns
6
6
  # `total_limit` as the string `"10"` but `used_today` as the number `0`, and
7
- # some counters arrive as `null` — so each field is coerced here rather than
7
+ # some counters arrive as `null`. Each field is coerced here rather than
8
8
  # trusted as-is.
9
9
  #
10
10
  # Each type has two helpers: the `?` variant returns nil for a
11
11
  # missing/blank/unparseable value (for the nullable fields), while the plain
12
12
  # variant falls back to a default (`""`/`0`/`0.0`, overridable) for the fields
13
- # the API always populates — so call sites declare their nullability by name.
13
+ # the API always populates, so call sites declare their nullability by name.
14
14
  #
15
15
  # @api private
16
16
  module Coerce
data/lib/sms_ru/data.rb CHANGED
@@ -155,7 +155,7 @@ class SmsRu
155
155
  end
156
156
 
157
157
  # Result of SmsRu#call (flash call). `code` is the last 4 digits of the number
158
- # that calls the user — what they read off the incoming call and enter.
158
+ # that calls the user, which is what they read off the incoming call and enter.
159
159
  #
160
160
  # @!attribute [r] code
161
161
  # @return [String] the 4-digit code (the calling number's last 4 digits)
@@ -212,7 +212,7 @@ class SmsRu
212
212
  def available_today = total_free - used_today
213
213
  end
214
214
 
215
- # Result of SmsRu::CallCheck#add — the number the user must call to authorize.
215
+ # Result of SmsRu::CallCheck#add: the number the user must call to authorize.
216
216
  #
217
217
  # @!attribute [r] check_id
218
218
  # @return [String] the check id to poll with SmsRu::CallCheck#status
@@ -235,7 +235,7 @@ class SmsRu
235
235
  end
236
236
  end
237
237
 
238
- # Result of SmsRu::CallCheck#status — whether the authorizing call has arrived.
238
+ # Result of SmsRu::CallCheck#status: whether the authorizing call has arrived.
239
239
  #
240
240
  # @!attribute [r] status_code
241
241
  # @return [Integer] the check status code (401 once confirmed)
@@ -41,10 +41,10 @@ class SmsRu
41
41
  # @return [Boolean] true once the message reached the handset (code 103)
42
42
  def delivered? = status_code == Statuses::DELIVERED
43
43
 
44
- # @return [Boolean] true while the message is still in transit (codes 100–102)
44
+ # @return [Boolean] true while the message is still in transit (codes 100 to 102)
45
45
  def pending? = !status_code.nil? && Statuses::PENDING.include?(status_code)
46
46
 
47
- # @return [Boolean] true when the message will not be delivered (codes 104–108, 150)
47
+ # @return [Boolean] true when the message will not be delivered (codes 104 to 108, and 150)
48
48
  def failed? = !status_code.nil? && Statuses::FAILED.include?(status_code)
49
49
  end
50
50
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  class SmsRu
4
4
  # The gem version.
5
- VERSION = "2.0.0"
5
+ VERSION = "3.0.0"
6
6
  end
@@ -8,14 +8,14 @@ class SmsRu
8
8
  #
9
9
  # The `data` param arrives as a Hash in bare Rack and an Array in PHP-style
10
10
  # clients. In Rails it is an `ActionController::Parameters`, which is **not** a
11
- # Hash — convert it with `.to_unsafe_h` first, or the numeric-key ordering the
11
+ # Hash. Convert it with `.to_unsafe_h` first, or the numeric-key ordering the
12
12
  # signature depends on is skipped and {valid?} rejects the payload. The
13
13
  # payload is signature-verified, so `to_unsafe_h` is safe here (`.to_h` would
14
14
  # drop unpermitted keys).
15
15
  #
16
- # {parse} returns one typed event per record — a {SmsRu::Events::SmsStatus},
16
+ # {parse} returns one typed event per record: a {SmsRu::Events::SmsStatus},
17
17
  # {SmsRu::Events::CallcheckStatus}, {SmsRu::Events::Test}, or
18
- # {SmsRu::Events::Unknown} — best handled with a case match:
18
+ # {SmsRu::Events::Unknown}. A case match handles them best:
19
19
  #
20
20
  # data = params[:data].to_unsafe_h # Rails; pass params["data"] as-is in bare Rack
21
21
  # return head(:forbidden) unless SmsRu::Webhook.valid?(data, params[:hash], api_id)
data/smsru-ruby.gemspec CHANGED
@@ -8,18 +8,18 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Leonid Svyatov"]
9
9
  spec.email = ["leonid@svyatov.com"]
10
10
 
11
- spec.summary = "Modern, dependency-free Ruby client for the SMS.ru API."
12
- spec.description = "A modern, dependency-free Ruby client for the SMS.ru HTTP API. Send single or bulk SMS, " \
11
+ spec.summary = "Ruby client for the SMS.ru HTTP API: send SMS, check delivery, verify users by phone call."
12
+ spec.description = "A Ruby client for the SMS.ru HTTP API. Send single or bulk SMS, " \
13
13
  "schedule delivery, check cost and delivery status, verify users by phone call, inspect " \
14
14
  "balance/limits/senders, manage the stoplist, and register delivery callbacks."
15
15
  spec.homepage = "https://github.com/svyatov/smsru-ruby"
16
16
  spec.license = "MIT"
17
17
 
18
- spec.required_ruby_version = ">= 3.2.0"
18
+ spec.required_ruby_version = ">= 3.3.0"
19
19
 
20
20
  spec.require_paths = ["lib"]
21
21
  spec.files = Dir["lib/**/*.rb"] + Dir["sig/**/*"] +
22
- %w[.yardopts CHANGELOG.md LICENSE.txt README.md smsru-ruby.gemspec]
22
+ %w[.yardopts CHANGELOG.md LICENSE README.md smsru-ruby.gemspec]
23
23
 
24
24
  spec.metadata["rubygems_mfa_required"] = "true"
25
25
  spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/smsru-ruby"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smsru-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leonid Svyatov
@@ -9,10 +9,9 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
- description: A modern, dependency-free Ruby client for the SMS.ru HTTP API. Send single
13
- or bulk SMS, schedule delivery, check cost and delivery status, verify users by
14
- phone call, inspect balance/limits/senders, manage the stoplist, and register delivery
15
- callbacks.
12
+ description: A Ruby client for the SMS.ru HTTP API. Send single or bulk SMS, schedule
13
+ delivery, check cost and delivery status, verify users by phone call, inspect balance/limits/senders,
14
+ manage the stoplist, and register delivery callbacks.
16
15
  email:
17
16
  - leonid@svyatov.com
18
17
  executables: []
@@ -21,7 +20,7 @@ extra_rdoc_files: []
21
20
  files:
22
21
  - ".yardopts"
23
22
  - CHANGELOG.md
24
- - LICENSE.txt
23
+ - LICENSE
25
24
  - README.md
26
25
  - lib/sms_ru/auth.rb
27
26
  - lib/sms_ru/call_check.rb
@@ -68,14 +67,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
68
67
  requirements:
69
68
  - - ">="
70
69
  - !ruby/object:Gem::Version
71
- version: 3.2.0
70
+ version: 3.3.0
72
71
  required_rubygems_version: !ruby/object:Gem::Requirement
73
72
  requirements:
74
73
  - - ">="
75
74
  - !ruby/object:Gem::Version
76
75
  version: '0'
77
76
  requirements: []
78
- rubygems_version: 4.0.16
77
+ rubygems_version: 3.6.9
79
78
  specification_version: 4
80
- summary: Modern, dependency-free Ruby client for the SMS.ru API.
79
+ summary: 'Ruby client for the SMS.ru HTTP API: send SMS, check delivery, verify users
80
+ by phone call.'
81
81
  test_files: []
File without changes