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.
@@ -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: []