iqsms 0.2.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 +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +157 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/iqsms.gemspec +34 -0
- data/lib/iqsms.rb +28 -0
- data/lib/iqsms/client.rb +177 -0
- data/lib/iqsms/errors.rb +4 -0
- data/lib/iqsms/message.rb +57 -0
- data/lib/iqsms/message_status.rb +38 -0
- data/lib/iqsms/request_status.rb +24 -0
- data/lib/iqsms/response.rb +17 -0
- data/lib/iqsms/response/balance.rb +23 -0
- data/lib/iqsms/response/send_sms.rb +19 -0
- data/lib/iqsms/response/senders.rb +9 -0
- data/lib/iqsms/response/status.rb +6 -0
- data/lib/iqsms/response/status_queue.rb +6 -0
- data/lib/iqsms/utils.rb +24 -0
- data/lib/iqsms/version.rb +3 -0
- metadata +150 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 65a3e6a22bce872c365b68647b72723f430b3515
|
4
|
+
data.tar.gz: 1acb7d5f92a1e041cf1c8229146474b12c471814
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d92d17a96b7094d7183535e8ecbe936802906c128096f39a6677484c33e03c7fb8a8f43a742d5a60b3948bfe6adf70ddbb64d45a0f8a318712f4d986a4aefb93
|
7
|
+
data.tar.gz: e1596a1cf04b5e097cf749dfe044a1f060d0d232c9140e7df556adaca724a4583ad45e80454269b204012f79929c0e194557f89ba4c19f6ce273bfe945a3d020
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 pineapplethief
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
# Iqsms
|
2
|
+
|
3
|
+
This is Ruby gem to consume https://iqsms.ru JSON API for sending sms messages.
|
4
|
+
|
5
|
+
Some features:
|
6
|
+
|
7
|
+
* Clean, simple code.
|
8
|
+
* Uses fast and cool [http.rb](https://github.com/httprb/http) gem under the hood to do requests.
|
9
|
+
* Leverages persistent HTTP connections and connection_pool for maximum performance.
|
10
|
+
* Wraps results in PORO's instead of just spitting out hashes and arrays.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'iqsms'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install iqsms
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
First you need to instantiate instance of API client:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
client = IqSMS::Client.new(login: your_login, password: your_password)
|
34
|
+
```
|
35
|
+
|
36
|
+
You then call API endpoints by invoking client instance methods `send_sms`, `balance`, `status`, `status_queue`, `senders`. Raw HTTP response is then wrapped into endpoint-specific respones object with convenient getters and predicates.
|
37
|
+
|
38
|
+
### Response class
|
39
|
+
|
40
|
+
All API response objects have some common methods:
|
41
|
+
|
42
|
+
* `original_response` - returns http.rb response object. See [http.rb](https://github.com/httprb/http) for more info.
|
43
|
+
* `hash` - response body parsed into JSON for you.
|
44
|
+
* `status` - instance of `IqSMS::RequestStatus` class.
|
45
|
+
|
46
|
+
### RequestStatus class
|
47
|
+
|
48
|
+
You have one in each response. Instances have some useful predicate methods to query if request was successful or not.
|
49
|
+
|
50
|
+
* `status` - status string as returned from service, see [API reference](https://iqsms.ru/api/api_json/) for more info.
|
51
|
+
* `description` - extra info about error
|
52
|
+
* `auth_failed?` - wrong login/password
|
53
|
+
* `accepted?` - all ok
|
54
|
+
* `rejected?` - some error happened
|
55
|
+
|
56
|
+
### Message class
|
57
|
+
|
58
|
+
Represents SMS message either to be sent to service or returned from it(as result of original `send_sms` action or querying for message status later).
|
59
|
+
|
60
|
+
List of methods is pretty self-explanatory, see API reference:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
:client_id,
|
64
|
+
:smsc_id,
|
65
|
+
:phone,
|
66
|
+
:text,
|
67
|
+
:wap_url,
|
68
|
+
:sender,
|
69
|
+
:flash,
|
70
|
+
:status
|
71
|
+
```
|
72
|
+
|
73
|
+
You may want to store messages you send in relational database or almost-persistent storage like Redis if you want to check for message statuses, since knowledge of client_id (your database PK or UUID or whatever) or smsc_id(assigned to each message by service) is required.
|
74
|
+
|
75
|
+
|
76
|
+
### MessageStatus class
|
77
|
+
|
78
|
+
Represents status for an sms message. `delivered?` is pretty self-explanatory, `status_text` returns useful message about state of sms delivery in russian.
|
79
|
+
|
80
|
+
## Examples
|
81
|
+
|
82
|
+
### Send SMS
|
83
|
+
|
84
|
+
This endpoint uses duck-typing for messages, object(s) passed in just have to respond to specific methods, so you can use your ActiveRecord models directly.
|
85
|
+
`phone`, `text`, `client_id` and `sender` are mandatory, others are optional.
|
86
|
+
Phones are sent as-is, so any phone number normalization must be done in your app before-hand (see f.e. [phony-rails gem](https://github.com/joost/phony_rails))
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
message = YourSMSModel.create(phone: '+11234567899', text: 'hey there', sender: 'one of your senders', client_id: '1')
|
90
|
+
send_sms_response = client.send_sms(message)
|
91
|
+
if send_sms_response.accepted?
|
92
|
+
# do your logic to update message smsc_id and status, which are in send_sms_response.statuses
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
### Check SMS status
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
messages = YourSMSModel.where(phone: 'bla')
|
100
|
+
status_response = client.status(messages)
|
101
|
+
if status_response.accepted?
|
102
|
+
status_response.statuses # Same as send_sms endpoint
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
### Check SMS status via named queue
|
107
|
+
|
108
|
+
Either instantiate client with status_queue_name option,
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
client = IqSMS::Client.new(login: your_login, password: your_password, status_queue_name: 'myQueue')
|
112
|
+
```
|
113
|
+
|
114
|
+
Or just set one on instance you already have by using writer:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
client.status_queue_name = 'myQueue'
|
118
|
+
```
|
119
|
+
|
120
|
+
Then call endpoint as usual:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
status_queue_limit = 10 # default is 5
|
124
|
+
status_queue_response = client.status_queue(status_queue_limit)
|
125
|
+
if status_queue_response.accepted?
|
126
|
+
status_queue_response.statuses # same as send_sms and status end-points
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
### Get your senders
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
senders_response = client.senders
|
134
|
+
|
135
|
+
senders_response.senders # returns array of strings - names of the senders
|
136
|
+
```
|
137
|
+
|
138
|
+
### Check Balance
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
balance_response = client.balance
|
142
|
+
|
143
|
+
balance_response.balance # => 2.5
|
144
|
+
balance_response.currency # => 'RUB'
|
145
|
+
balance_response.credit # have no idea what the heck is that
|
146
|
+
```
|
147
|
+
|
148
|
+
## Development
|
149
|
+
|
150
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
151
|
+
|
152
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
153
|
+
|
154
|
+
## Contributing
|
155
|
+
|
156
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/iqsms_ruby.
|
157
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "iqsms"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/iqsms.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'iqsms/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'iqsms'
|
8
|
+
spec.version = IqSMS::VERSION
|
9
|
+
spec.authors = ['Aleksey Glukhov']
|
10
|
+
spec.email = ['gluhov1985@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'Ruby gem for iqsms JSON API'
|
13
|
+
spec.description = 'Ruby gem for iqsms JSON API'
|
14
|
+
spec.homepage = 'https://github.com/pineapplethief'
|
15
|
+
|
16
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(%r{^(test|spec|features)/})
|
20
|
+
end
|
21
|
+
spec.bindir = 'exe'
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.required_ruby_version = '>= 2.2.0'
|
26
|
+
|
27
|
+
spec.add_runtime_dependency 'addressable', '~> 2.3'
|
28
|
+
spec.add_runtime_dependency 'activesupport', '>= 4.2'
|
29
|
+
spec.add_runtime_dependency 'connection_pool', '~> 2.2'
|
30
|
+
spec.add_runtime_dependency 'http', '~> 2.2'
|
31
|
+
|
32
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
33
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
34
|
+
end
|
data/lib/iqsms.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'iqsms/version'
|
2
|
+
|
3
|
+
require 'bigdecimal'
|
4
|
+
require 'bigdecimal/util'
|
5
|
+
|
6
|
+
require 'active_support/core_ext/object/blank'
|
7
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
8
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
9
|
+
require 'active_support/hash_with_indifferent_access'
|
10
|
+
require 'addressable/uri'
|
11
|
+
require 'connection_pool'
|
12
|
+
require 'http'
|
13
|
+
require 'json'
|
14
|
+
|
15
|
+
require 'iqsms/utils'
|
16
|
+
|
17
|
+
require 'iqsms/client'
|
18
|
+
require 'iqsms/errors'
|
19
|
+
require 'iqsms/message'
|
20
|
+
require 'iqsms/message_status'
|
21
|
+
require 'iqsms/request_status'
|
22
|
+
|
23
|
+
require 'iqsms/response'
|
24
|
+
require 'iqsms/response/balance'
|
25
|
+
require 'iqsms/response/send_sms'
|
26
|
+
require 'iqsms/response/senders'
|
27
|
+
require 'iqsms/response/status'
|
28
|
+
require 'iqsms/response/status_queue'
|
data/lib/iqsms/client.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
module IqSMS
|
2
|
+
class Client
|
3
|
+
@mutex = Mutex.new
|
4
|
+
|
5
|
+
def self.connection_pool_for(url)
|
6
|
+
@mutex.synchronize do
|
7
|
+
@connection_pool ||= {}
|
8
|
+
if @connection_pool[url].blank?
|
9
|
+
@connection_pool[url] = ConnectionPool.new(size: 5, timeout: 5) do
|
10
|
+
HTTP.persistent(url)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
@connection_pool[url]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :connection
|
18
|
+
attr_writer :status_queue_name
|
19
|
+
|
20
|
+
def initialize(login:, password:, **options)
|
21
|
+
with_value_must_be_present!(login) { @login = login }
|
22
|
+
with_value_must_be_present!(password) { @password = password }
|
23
|
+
|
24
|
+
@options = options.reverse_merge(default_options)
|
25
|
+
|
26
|
+
check_status_queue_name!
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_sms(messages)
|
30
|
+
messages = Array(messages)
|
31
|
+
check_messages_size!(messages)
|
32
|
+
|
33
|
+
options = {
|
34
|
+
statusQueueName: status_queue_name,
|
35
|
+
messages: messages.map { |message| Message.message_to_hash(message) }
|
36
|
+
}
|
37
|
+
|
38
|
+
request(:post, 'send'.freeze, options) do |response|
|
39
|
+
Response::SendSms.new(response)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def status(messages)
|
44
|
+
messages = Array(messages)
|
45
|
+
check_messages_size!(messages)
|
46
|
+
|
47
|
+
options = {
|
48
|
+
statusQueueName: status_queue_name,
|
49
|
+
messages: messages.map { |message| Message.message_to_hash_for_status(message) }
|
50
|
+
}
|
51
|
+
|
52
|
+
request(:post, 'status'.freeze, options) do |response|
|
53
|
+
Response::Status.new(response)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def status_queue(status_queue_limit = 5)
|
58
|
+
if status_queue_name.blank?
|
59
|
+
raise ArgumentError, 'status_queue_name must be set to use status_queue endpoint'
|
60
|
+
end
|
61
|
+
|
62
|
+
options = {
|
63
|
+
statusQueueName: status_queue_name,
|
64
|
+
statusQueueLimit: status_queue_limit
|
65
|
+
}
|
66
|
+
|
67
|
+
request(:post, 'statusQueue'.freeze, options) do |response|
|
68
|
+
Response::StatusQueue.new(response)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def balance
|
73
|
+
request(:post, 'messages/v2/balance'.freeze) do |response|
|
74
|
+
Response::Balance.new(response)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def senders
|
79
|
+
request(:post, 'senders'.freeze) do |response|
|
80
|
+
Response::Senders.new(response)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def ping?
|
85
|
+
request(:post, 'messages/v2/balance'.freeze) do |response|
|
86
|
+
response.status.success?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def status_queue_name
|
91
|
+
@status_queue_name ||= @options[:status_queue_name]
|
92
|
+
end
|
93
|
+
|
94
|
+
def status_queue_name=(value)
|
95
|
+
@status_queue_name = value
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def request(method, path, **params)
|
101
|
+
params = params.nil? ? {} : params.dup
|
102
|
+
|
103
|
+
params = params.reverse_merge!(authentication_params)
|
104
|
+
|
105
|
+
self.class.connection_pool_for(base_url).with do |connection|
|
106
|
+
begin
|
107
|
+
retries ||= 0
|
108
|
+
|
109
|
+
response = connection.headers(accept: 'application/json'.freeze)
|
110
|
+
.send(method, full_url(path), json: params)
|
111
|
+
|
112
|
+
block_given? ? yield(response) : response
|
113
|
+
rescue HTTP::StateError => error
|
114
|
+
retries += 1
|
115
|
+
retries < 3 ? retry : raise(error)
|
116
|
+
ensure
|
117
|
+
response.flush if response.present?
|
118
|
+
connection.close if connection.present?
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def with_value_must_be_present!(value)
|
124
|
+
raise ArgumentError, "can't be blank".freeze if value.blank?
|
125
|
+
yield
|
126
|
+
end
|
127
|
+
|
128
|
+
def check_status_queue_name!
|
129
|
+
queue_name = @options[:status_queue_name]
|
130
|
+
return unless queue_name.present?
|
131
|
+
|
132
|
+
unless queue_name.is_a?(String)
|
133
|
+
raise ArgumentError, 'status_queue_name must be a string'.freeze
|
134
|
+
end
|
135
|
+
if queue_name.size < 3 || queue_name.size > 16
|
136
|
+
raise ArgumentError, 'status_queue_name length must be in between 3 and 16 chars'.freeze
|
137
|
+
end
|
138
|
+
unless queue_name =~ /[a-zA-Z0-9]+/
|
139
|
+
raise ArgumentError, 'status_queue_name must be alphanumeric only'.freeze
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def check_messages_size!(messages)
|
144
|
+
return if messages.size <= 200
|
145
|
+
|
146
|
+
raise MaximumMessagesLimitExceededError, 'API has cap of 200 messages per one request'
|
147
|
+
end
|
148
|
+
|
149
|
+
def default_options
|
150
|
+
{
|
151
|
+
base_url: 'http://json.gate.iqsms.ru'.freeze
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
def authentication_params
|
156
|
+
{
|
157
|
+
login: @login,
|
158
|
+
password: @password
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
def base_url
|
163
|
+
@options[:base_url] || self.class.default_base_url
|
164
|
+
end
|
165
|
+
|
166
|
+
def base_uri
|
167
|
+
@base_uri ||= Addressable::URI.parse(base_url)
|
168
|
+
@base_uri
|
169
|
+
end
|
170
|
+
|
171
|
+
def full_url(path)
|
172
|
+
uri = base_uri
|
173
|
+
uri.path = path
|
174
|
+
uri.to_s
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/lib/iqsms/errors.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module IqSMS
|
2
|
+
class Message
|
3
|
+
def self.message_to_hash(message)
|
4
|
+
hash = {
|
5
|
+
clientId: message.client_id,
|
6
|
+
phone: message.phone,
|
7
|
+
text: message.text
|
8
|
+
}
|
9
|
+
hash[:wap_url] = message.wap_url if message.respond_to?(:wap_url) && message.wap_url.present?
|
10
|
+
hash[:sender] = message.sender if message.sender.present?
|
11
|
+
hash[:flash] = '1' if message.respond_to?(:flash) && message.flash.present?
|
12
|
+
hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.message_to_hash_for_status(message)
|
16
|
+
{
|
17
|
+
clientId: message.client_id,
|
18
|
+
smscId: message.smsc_id
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :client_id,
|
23
|
+
:smsc_id,
|
24
|
+
:phone,
|
25
|
+
:text,
|
26
|
+
:wap_url,
|
27
|
+
:sender,
|
28
|
+
:flash,
|
29
|
+
:status
|
30
|
+
|
31
|
+
def initialize(client_id:,
|
32
|
+
phone:,
|
33
|
+
text:,
|
34
|
+
wap_url: nil,
|
35
|
+
sender: nil,
|
36
|
+
smsc_id: nil,
|
37
|
+
status: nil,
|
38
|
+
flash: false)
|
39
|
+
@client_id = client_id
|
40
|
+
@phone = phone
|
41
|
+
@text = text
|
42
|
+
@wap_url = wap_url
|
43
|
+
@sender = sender
|
44
|
+
@smsc_id = smsc_id
|
45
|
+
@status = MessageStatus.new(status: status, client_id: client_id, smsc_id: smsc_id)
|
46
|
+
@flash = flash
|
47
|
+
end
|
48
|
+
|
49
|
+
def flash?
|
50
|
+
@flash
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_hash
|
54
|
+
self.class.message_to_hash(self)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module IqSMS
|
2
|
+
class MessageStatus
|
3
|
+
attr_reader :status, :client_id, :smsc_id
|
4
|
+
|
5
|
+
def initialize(status:, client_id: nil, smsc_id: nil)
|
6
|
+
@status = status
|
7
|
+
@client_id = client_id
|
8
|
+
@smsc_id = smsc_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def queued?
|
12
|
+
@status == 'queued'
|
13
|
+
end
|
14
|
+
|
15
|
+
def delivered?
|
16
|
+
@status == 'delivered'
|
17
|
+
end
|
18
|
+
|
19
|
+
def status_text
|
20
|
+
case @status
|
21
|
+
when 'accepted'.freeze
|
22
|
+
'Сообщение принято на обработку'.freeze
|
23
|
+
when 'queued'.freeze
|
24
|
+
'Сообщение находится в очереди'.freeze
|
25
|
+
when 'delivered'.freeze
|
26
|
+
'Сообщение доставлено'.freeze
|
27
|
+
when 'delivery error'.freeze
|
28
|
+
'Ошибка доставки SMS (абонент в течение времени доставки находился вне зоны действия сети или номер абонента заблокирован)'.freeze
|
29
|
+
when 'smsc submit'.freeze
|
30
|
+
'Сообщение доставлено в SMSC'.freeze
|
31
|
+
when 'smsc reject'.freeze
|
32
|
+
'Сообщение отвергнуто SMSC (номер заблокирован или не существует)'.freeze
|
33
|
+
when 'incorrect id'.freeze
|
34
|
+
'Неверный идентификатор сообщения'.freeze
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module IqSMS
|
2
|
+
class RequestStatus
|
3
|
+
def initialize(status, description)
|
4
|
+
@status = status
|
5
|
+
@description = description
|
6
|
+
end
|
7
|
+
|
8
|
+
def accepted?
|
9
|
+
@status == 'ok'.freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def rejected?
|
13
|
+
@status == 'error'.freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def auth_failed?
|
17
|
+
rejected? && @description == 'error authorization'.freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
def status_queue_empty?
|
21
|
+
@description == 'queue is empty'.freeze
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module IqSMS
|
2
|
+
class Response
|
3
|
+
attr_reader :original_response, :hash, :status
|
4
|
+
|
5
|
+
def initialize(original_response)
|
6
|
+
@original_response = original_response
|
7
|
+
@hash = if @original_response.body.present?
|
8
|
+
JSON.parse(@original_response.body)
|
9
|
+
else
|
10
|
+
{}
|
11
|
+
end
|
12
|
+
@hash = IqSMS::Utils.deeply_with_indifferent_access(@hash)
|
13
|
+
|
14
|
+
@status = RequestStatus.new(@hash[:status], @hash[:description])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module IqSMS
|
2
|
+
class Response
|
3
|
+
class Balance < Response
|
4
|
+
def balance_hash
|
5
|
+
@hash[:balance].first
|
6
|
+
end
|
7
|
+
|
8
|
+
def balance
|
9
|
+
@balance ||= balance_hash[:balance].to_s.to_d
|
10
|
+
@balance
|
11
|
+
end
|
12
|
+
|
13
|
+
def currency
|
14
|
+
balance_hash[:type]
|
15
|
+
end
|
16
|
+
|
17
|
+
def credit
|
18
|
+
@credit ||= balance_hash[:credit].to_s.to_d
|
19
|
+
@credit
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module IqSMS
|
2
|
+
class Response
|
3
|
+
class SendSms < Response
|
4
|
+
attr_reader :statuses
|
5
|
+
|
6
|
+
def initialize(original_response)
|
7
|
+
super
|
8
|
+
|
9
|
+
@statuses = Array(@hash[:messages]).map do |hash_message|
|
10
|
+
MessageStatus.new(
|
11
|
+
status: hash_message[:status],
|
12
|
+
client_id: hash_message[:client_id],
|
13
|
+
smsc_id: hash_message[:smsc_id]
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/iqsms/utils.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module IqSMS
|
2
|
+
module Utils
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def deeply_with_indifferent_access(hash)
|
6
|
+
hash = ActiveSupport::HashWithIndifferentAccess.new(hash)
|
7
|
+
hash.each do |key, value|
|
8
|
+
if value.is_a?(Hash)
|
9
|
+
hash[key] = deeply_with_indifferent_access(value)
|
10
|
+
elsif value.is_a?(Array)
|
11
|
+
hash[key] = value.map do |element|
|
12
|
+
if element.is_a?(Hash)
|
13
|
+
deeply_with_indifferent_access(element)
|
14
|
+
else
|
15
|
+
element
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: iqsms
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aleksey Glukhov
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: addressable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: connection_pool
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: http
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.13'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.13'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
description: Ruby gem for iqsms JSON API
|
98
|
+
email:
|
99
|
+
- gluhov1985@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- bin/console
|
110
|
+
- bin/setup
|
111
|
+
- iqsms.gemspec
|
112
|
+
- lib/iqsms.rb
|
113
|
+
- lib/iqsms/client.rb
|
114
|
+
- lib/iqsms/errors.rb
|
115
|
+
- lib/iqsms/message.rb
|
116
|
+
- lib/iqsms/message_status.rb
|
117
|
+
- lib/iqsms/request_status.rb
|
118
|
+
- lib/iqsms/response.rb
|
119
|
+
- lib/iqsms/response/balance.rb
|
120
|
+
- lib/iqsms/response/send_sms.rb
|
121
|
+
- lib/iqsms/response/senders.rb
|
122
|
+
- lib/iqsms/response/status.rb
|
123
|
+
- lib/iqsms/response/status_queue.rb
|
124
|
+
- lib/iqsms/utils.rb
|
125
|
+
- lib/iqsms/version.rb
|
126
|
+
homepage: https://github.com/pineapplethief
|
127
|
+
licenses: []
|
128
|
+
metadata:
|
129
|
+
allowed_push_host: https://rubygems.org
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 2.2.0
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
requirements: []
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 2.6.8
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: Ruby gem for iqsms JSON API
|
150
|
+
test_files: []
|