iqsms 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in iqsms.gemspec
4
+ gemspec
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.
@@ -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
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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
@@ -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'
@@ -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
@@ -0,0 +1,4 @@
1
+ module IqSMS
2
+ class MaximumMessagesLimitExceededError < StandardError
3
+ end
4
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ module IqSMS
2
+ class Response
3
+ class Senders < Response
4
+ def senders
5
+ Array(@hash[:senders])
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ module IqSMS
2
+ class Response
3
+ class Status < SendSms
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module IqSMS
2
+ class Response
3
+ class StatusQueue < Status
4
+ end
5
+ end
6
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module IqSMS
2
+ VERSION = '0.2.0'
3
+ 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: []