nexmos 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +67 -0
- data/Rakefile +6 -0
- data/lib/api.yml +113 -0
- data/lib/nexmos.rb +47 -0
- data/lib/nexmos/account.rb +5 -0
- data/lib/nexmos/base.rb +103 -0
- data/lib/nexmos/message.rb +5 -0
- data/lib/nexmos/number.rb +5 -0
- data/lib/nexmos/railties.rb +7 -0
- data/lib/nexmos/search.rb +5 -0
- data/lib/nexmos/version.rb +3 -0
- data/nexmos.gemspec +24 -0
- data/spec/nexmos/account_spec.rb +188 -0
- data/spec/nexmos/base_spec.rb +203 -0
- data/spec/nexmos/number_spec.rb +113 -0
- data/spec/nexmos_spec.rb +63 -0
- data/spec/spec_helper.rb +21 -0
- metadata +169 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3@nexmos --create
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Alexander Simonov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Nexmos [![Build Status](https://travis-ci.org/phenomena/nexmos.png)](https://travis-ci.org/phenomena/nexmos)[![Code Climate](https://codeclimate.com/github/phenomena/nexmos.png)](https://codeclimate.com/github/phenomena/nexmos)
|
2
|
+
|
3
|
+
Nexmo API wrapper
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'nexmos'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install nexmos
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Send text message
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# Nexmos specific client
|
25
|
+
client = ::Nexmos::Message.new('api-key', 'api-secret')
|
26
|
+
# get result from Nexmo
|
27
|
+
res = client.send_text(from: 'your number', to: '+1234567890', text: 'Hello world!')
|
28
|
+
# check if send is success
|
29
|
+
if res.success?
|
30
|
+
puts "ok"
|
31
|
+
else
|
32
|
+
puts "fail"
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
### Get balance
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
client = ::Nexmos::Account.new('api-key', 'api-secret')
|
40
|
+
res = client.get_balance
|
41
|
+
my_balance = res.value
|
42
|
+
```
|
43
|
+
|
44
|
+
## Rails integration
|
45
|
+
|
46
|
+
You can create `config/initializer/nexmos.rb` file with next content:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
Nexmos.setup do |n|
|
50
|
+
n.api_key = 'api_key'
|
51
|
+
n.api_secret = 'api_secret'
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
And then you can call all clients without providing key and secret.
|
56
|
+
|
57
|
+
## More details about api calls
|
58
|
+
|
59
|
+
More details about api calls you can found in the lib/api.yml file.
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/api.yml
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
:message:
|
2
|
+
:send_text:
|
3
|
+
:method: :get
|
4
|
+
:url: /sms/json
|
5
|
+
:required:
|
6
|
+
- from
|
7
|
+
- to
|
8
|
+
- text
|
9
|
+
:send_binary:
|
10
|
+
:method: :get
|
11
|
+
:url: /sms/json
|
12
|
+
:required:
|
13
|
+
- body
|
14
|
+
- udh
|
15
|
+
:params:
|
16
|
+
type: binary
|
17
|
+
:wap_push:
|
18
|
+
:method: :get
|
19
|
+
:url: /sms/json
|
20
|
+
:required:
|
21
|
+
- title
|
22
|
+
- url
|
23
|
+
:optional:
|
24
|
+
- validity
|
25
|
+
:params:
|
26
|
+
type: wappush
|
27
|
+
:search:
|
28
|
+
:message:
|
29
|
+
:method: :get
|
30
|
+
:url: /search/message
|
31
|
+
:required:
|
32
|
+
- id
|
33
|
+
:messages:
|
34
|
+
:method: :get
|
35
|
+
:url: /search/messages
|
36
|
+
:optional:
|
37
|
+
- ids
|
38
|
+
- date
|
39
|
+
- to
|
40
|
+
:rejections:
|
41
|
+
:method: :get
|
42
|
+
:url: /search/rejections
|
43
|
+
:required:
|
44
|
+
- date
|
45
|
+
:optional:
|
46
|
+
- to
|
47
|
+
:account:
|
48
|
+
:get_balance:
|
49
|
+
:method: :get
|
50
|
+
:url: /account/get-balance
|
51
|
+
:return: value
|
52
|
+
:get_pricing:
|
53
|
+
:method: :get
|
54
|
+
:url: /account/get-pricing/outbound
|
55
|
+
:required:
|
56
|
+
- country
|
57
|
+
:get_prefix_pricing:
|
58
|
+
:method: :get
|
59
|
+
:url: /account/get-prefix-pricing/outbound
|
60
|
+
:required:
|
61
|
+
- prefix
|
62
|
+
:settings:
|
63
|
+
:method: :post
|
64
|
+
:url: /account/settings
|
65
|
+
:optional:
|
66
|
+
- new_secret
|
67
|
+
- mo_call_back_url
|
68
|
+
- dr_call_back_url
|
69
|
+
:camelize: true
|
70
|
+
:get_numbers:
|
71
|
+
:method: :get
|
72
|
+
:url: /account/numbers
|
73
|
+
:optional:
|
74
|
+
- index
|
75
|
+
- size
|
76
|
+
- pattern
|
77
|
+
:top_up:
|
78
|
+
:method: :get
|
79
|
+
:url: /account/top-up
|
80
|
+
:required:
|
81
|
+
- trx
|
82
|
+
:number:
|
83
|
+
:search:
|
84
|
+
:method: :get
|
85
|
+
:url: /number/search
|
86
|
+
:required:
|
87
|
+
- country
|
88
|
+
:optional:
|
89
|
+
- pattern
|
90
|
+
- index
|
91
|
+
- size
|
92
|
+
:buy:
|
93
|
+
:method: :post
|
94
|
+
:url: /number/buy
|
95
|
+
:required:
|
96
|
+
- country
|
97
|
+
- msisdn
|
98
|
+
:cancel:
|
99
|
+
:method: :post
|
100
|
+
:url: /number/cancel
|
101
|
+
:required:
|
102
|
+
- country
|
103
|
+
- msisdn
|
104
|
+
:update:
|
105
|
+
:method: :post
|
106
|
+
:url: /number/update
|
107
|
+
:required:
|
108
|
+
- country
|
109
|
+
- msisdn
|
110
|
+
:optional:
|
111
|
+
- mo_http_url
|
112
|
+
- mo_smpp_sys_type
|
113
|
+
:camelize: true
|
data/lib/nexmos.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
require 'nexmos/version'
|
6
|
+
require 'nexmos/base'
|
7
|
+
module Nexmos
|
8
|
+
extend self
|
9
|
+
attr_accessor :api_key, :api_secret, :debug
|
10
|
+
attr_writer :user_agent, :logger
|
11
|
+
|
12
|
+
# ensures the setup only gets run once
|
13
|
+
@_ran_once = false
|
14
|
+
|
15
|
+
def reset!
|
16
|
+
@logger = nil
|
17
|
+
@_ran_once = false
|
18
|
+
@user_agent = nil
|
19
|
+
@api_key = nil
|
20
|
+
@api_secret = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def user_agent
|
24
|
+
@user_agent ||= "Nexmos v#{::Nexmos::VERSION}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup
|
28
|
+
yield self unless @_ran_once
|
29
|
+
@_ran_once = true
|
30
|
+
end
|
31
|
+
|
32
|
+
def logger
|
33
|
+
@logger ||= Logger.new(STDOUT)
|
34
|
+
end
|
35
|
+
|
36
|
+
def apis
|
37
|
+
@apis ||= YAML.load_file(File.expand_path('api.yml', File.dirname(__FILE__)))
|
38
|
+
end
|
39
|
+
|
40
|
+
reset!
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'nexmos/railties' if defined?(::Rails)
|
44
|
+
require 'nexmos/account'
|
45
|
+
require 'nexmos/message'
|
46
|
+
require 'nexmos/number'
|
47
|
+
require 'nexmos/search'
|
data/lib/nexmos/base.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module Nexmos
|
2
|
+
class Base
|
3
|
+
|
4
|
+
def initialize(key = ::Nexmos.api_key, secret = ::Nexmos.api_secret)
|
5
|
+
raise 'api_key should be set' if !key.present?
|
6
|
+
raise 'api_secret should be set' if !secret.present?
|
7
|
+
@default_params = {
|
8
|
+
'api_key' => key,
|
9
|
+
'api_secret' => secret
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def connection
|
14
|
+
self.class.connection.dup
|
15
|
+
end
|
16
|
+
|
17
|
+
def make_api_call(args, params = {})
|
18
|
+
normalize_params(params)
|
19
|
+
check_required_params(args, params)
|
20
|
+
camelize_params(params) if args[:camelize]
|
21
|
+
params.merge!(@default_params)
|
22
|
+
get_response(args, params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_response(args, params)
|
26
|
+
method = args[:method]
|
27
|
+
url = args[:url]
|
28
|
+
raise 'url or method params missing' if !method.present? || !url.present?
|
29
|
+
res = connection.__send__(method, url, params)
|
30
|
+
if res.success?
|
31
|
+
data = if res.body.is_a?(::Hash)
|
32
|
+
res.body.merge(:success? => true)
|
33
|
+
else
|
34
|
+
::Hashie::Mash.new({:success? => true})
|
35
|
+
end
|
36
|
+
return data
|
37
|
+
end
|
38
|
+
failed_res = ::Hashie::Mash.new({:success? => false, :not_authorized? => false, :failed? => false})
|
39
|
+
case res.status
|
40
|
+
when 401
|
41
|
+
failed_res.merge! :not_authorized? => true
|
42
|
+
when 420
|
43
|
+
failed_res.merge! :failed? => true
|
44
|
+
end
|
45
|
+
failed_res
|
46
|
+
end
|
47
|
+
|
48
|
+
def normalize_params(params)
|
49
|
+
params.stringify_keys!
|
50
|
+
end
|
51
|
+
|
52
|
+
def camelize_params(params)
|
53
|
+
if params.respond_to?(:transform_keys!)
|
54
|
+
params.transform_keys!{|key| key.camelize(:lower)}
|
55
|
+
else
|
56
|
+
params.keys.each do |key|
|
57
|
+
params[key.camelize(:lower)] = params.delete(key)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_required_params(args, params)
|
63
|
+
if args[:required]
|
64
|
+
required = params.slice(*args[:required])
|
65
|
+
unless required.keys.sort == args[:required].sort
|
66
|
+
missed = (args[:required] - required.keys).join(',')
|
67
|
+
raise ArgumentError, "#{missed} params required"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class << self
|
73
|
+
|
74
|
+
def define_api_calls(key)
|
75
|
+
::Nexmos.apis[key].each do |k,v|
|
76
|
+
define_method(k) do |*args|
|
77
|
+
params = args[0] || {}
|
78
|
+
make_api_call(v, params)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def faraday_options
|
84
|
+
{
|
85
|
+
:url => 'https://rest.nexmo.com',
|
86
|
+
:headers => {
|
87
|
+
:accept => 'application/json',
|
88
|
+
:user_agent => ::Nexmos.user_agent
|
89
|
+
}
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def connection
|
94
|
+
@connection ||= Faraday::Connection.new(faraday_options) do |conn|
|
95
|
+
conn.request :url_encoded
|
96
|
+
conn.response :rashify
|
97
|
+
conn.response :json, :content_type => /\bjson$/
|
98
|
+
conn.adapter Faraday.default_adapter
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end # self
|
102
|
+
end # Base
|
103
|
+
end # Nexmos
|
data/nexmos.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nexmos/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "nexmos"
|
8
|
+
gem.version = Nexmos::VERSION
|
9
|
+
gem.authors = ["Alexander Simonov"]
|
10
|
+
gem.email = ["alex@simonov.me"]
|
11
|
+
gem.description = %q{Nexmo API client}
|
12
|
+
gem.summary = %q{Nexmo API client}
|
13
|
+
gem.homepage = "https://github.com/simonoff/nexmos"
|
14
|
+
gem.files = `git ls-files`.split($/)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.add_dependency('rash')
|
19
|
+
gem.add_dependency('faraday')
|
20
|
+
gem.add_dependency('faraday_middleware')
|
21
|
+
gem.add_dependency('activesupport', '>= 3.0.0')
|
22
|
+
gem.add_development_dependency('rspec')
|
23
|
+
gem.add_development_dependency('webmock')
|
24
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos::Account do
|
3
|
+
let(:webmock_default_headers) do
|
4
|
+
{
|
5
|
+
:headers => {
|
6
|
+
'Accept' => 'application/json',
|
7
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
8
|
+
'User-Agent' => ::Nexmos.user_agent
|
9
|
+
}
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:finland_prices) do
|
14
|
+
{
|
15
|
+
"mt" => "0.02500000",
|
16
|
+
"country" => "FI",
|
17
|
+
"prefix" => "358",
|
18
|
+
"networks" =>
|
19
|
+
[{"code" => "24491",
|
20
|
+
"network" => "sonera, TeleFinland",
|
21
|
+
"ranges" => ["35840", "35842", "358450"],
|
22
|
+
"mtPrice" => "0.04500000"},
|
23
|
+
{"code" => "24414",
|
24
|
+
"network" => "GSM Aland",
|
25
|
+
"ranges" => ["3584570", "3584573", "3584575"],
|
26
|
+
"mtPrice" => "0.00850000"},
|
27
|
+
{"code" => "24421",
|
28
|
+
"network" => "SAUNALAHTI, EUnet Finland",
|
29
|
+
"ranges" => ["358451", "358452", "358453", "358456", "358458"],
|
30
|
+
"mtPrice" => "0.05000000"},
|
31
|
+
{"code" => "24412",
|
32
|
+
"network" => "dna",
|
33
|
+
"ranges" =>
|
34
|
+
["35841",
|
35
|
+
"35844",
|
36
|
+
"3584574",
|
37
|
+
"3584576",
|
38
|
+
"3584577",
|
39
|
+
"3584578",
|
40
|
+
"3584579",
|
41
|
+
"3584944"],
|
42
|
+
"mtPrice" => "0.00850000"},
|
43
|
+
{"code" => "24405",
|
44
|
+
"network" => "elisa",
|
45
|
+
"ranges" => ["35846", "35850"],
|
46
|
+
"mtPrice" => "0.05000000"}],
|
47
|
+
"name" => "Finland"
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:prefix_prices) do
|
52
|
+
{"count" => 1,
|
53
|
+
"prices" =>
|
54
|
+
[{"mt" => "0.02500000",
|
55
|
+
"country" => "FI",
|
56
|
+
"prefix" => "358",
|
57
|
+
"networks" =>
|
58
|
+
[{"code" => "24491",
|
59
|
+
"network" => "sonera, TeleFinland",
|
60
|
+
"ranges" => nil,
|
61
|
+
"mt_price" => "0.04500000"},
|
62
|
+
{"code" => "24414",
|
63
|
+
"network" => "GSM Aland",
|
64
|
+
"ranges" => nil,
|
65
|
+
"mtPrice" => "0.00850000"},
|
66
|
+
{"code" => "24400",
|
67
|
+
"network" => "Unknown Finland",
|
68
|
+
"ranges" => nil,
|
69
|
+
"mtPrice" => "0.02500000"},
|
70
|
+
{"code" => "24421",
|
71
|
+
"network" => "SAUNALAHTI, EUnet Finland",
|
72
|
+
"ranges" => nil,
|
73
|
+
"mtPrice" => "0.05000000"},
|
74
|
+
{"code" => "24412",
|
75
|
+
"network" => "dna",
|
76
|
+
"ranges" => nil,
|
77
|
+
"mtPrice" => "0.00850000"},
|
78
|
+
{"code" => "24405",
|
79
|
+
"network" => "elisa",
|
80
|
+
"ranges" => nil,
|
81
|
+
"mtPrice" => "0.05000000"}],
|
82
|
+
"name" => "Finland"}],
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
before(:each) do
|
87
|
+
::Nexmos.reset!
|
88
|
+
::Nexmos.setup do |c|
|
89
|
+
c.api_key = 'default_key'
|
90
|
+
c.api_secret = 'default_secret'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
subject { ::Nexmos::Account.new }
|
95
|
+
|
96
|
+
context '#get_balance' do
|
97
|
+
|
98
|
+
it 'should return value' do
|
99
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/get-balance?api_key=default_key&api_secret=default_secret").
|
100
|
+
with(webmock_default_headers).to_return(:status => 200, :body => {"value" => 4.107}, :headers => {})
|
101
|
+
res = subject.get_balance
|
102
|
+
res.should be_kind_of(::Hash)
|
103
|
+
res.value.should == 4.107
|
104
|
+
request.should have_been_made.once
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context '#get_pricing' do
|
109
|
+
it 'should return error on missed param' do
|
110
|
+
expect { subject.get_pricing }.to raise_error('country params required')
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should be success' do
|
114
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/get-pricing/outbound?api_key=default_key&api_secret=default_secret&country=FI").
|
115
|
+
with(webmock_default_headers).to_return(:status => 200, :body => finland_prices, :headers => {})
|
116
|
+
res = subject.get_pricing(:country => 'FI')
|
117
|
+
res.should be_kind_of(::Hash)
|
118
|
+
res.success?.should be_true
|
119
|
+
res.country.should == 'FI'
|
120
|
+
res.keys.sort.should == %w(country name prefix mt networks success?).sort
|
121
|
+
res.networks.should be_kind_of(::Array)
|
122
|
+
res.networks[0].keys.sort.should == %w(code network mt_price ranges).sort
|
123
|
+
request.should have_been_made.once
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context '#get_prefix_pricing' do
|
128
|
+
it 'should return error on missed param' do
|
129
|
+
expect { subject.get_prefix_pricing }.to raise_error('prefix params required')
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should be success' do
|
133
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/get-prefix-pricing/outbound?api_key=default_key&api_secret=default_secret&prefix=358").
|
134
|
+
with(webmock_default_headers).to_return(:status => 200, :body => prefix_prices, :headers => {})
|
135
|
+
res = subject.get_prefix_pricing(:prefix => '358')
|
136
|
+
res.should be_kind_of(::Hash)
|
137
|
+
res.success?.should be_true
|
138
|
+
res.keys.sort.should == %w(count prices success?).sort
|
139
|
+
res.prices.should be_kind_of(::Array)
|
140
|
+
res.prices[0].keys.sort.should == %w(country name prefix mt networks).sort
|
141
|
+
res.prices[0].networks.should be_kind_of(::Array)
|
142
|
+
res.prices[0].networks[0].keys.sort.should == %w(code network mt_price ranges).sort
|
143
|
+
request.should have_been_made.once
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context '#get_numbers' do
|
148
|
+
it 'should return only count on empty numbers' do
|
149
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/numbers?api_key=default_key&api_secret=default_secret").
|
150
|
+
with(webmock_default_headers).to_return(:status => 200, :body => {:count => 0}, :headers => {})
|
151
|
+
res = subject.get_numbers
|
152
|
+
res.should be_kind_of(::Hash)
|
153
|
+
res.success?.should be_true
|
154
|
+
res['count'].should == 0
|
155
|
+
request.should have_been_made.once
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should return numbers array' do
|
159
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/numbers?api_key=default_key&api_secret=default_secret").
|
160
|
+
with(webmock_default_headers).to_return(:status => 200, :body => { "count" => 1,"numbers" => [{"country" => "ES","msisdn" => "34911067000","type" => "landline"}]}, :headers => {})
|
161
|
+
res = subject.get_numbers
|
162
|
+
res.should be_kind_of(::Hash)
|
163
|
+
res.success?.should be_true
|
164
|
+
res['count'].should == 1
|
165
|
+
res['numbers'].should be_kind_of(::Array)
|
166
|
+
res['numbers'].first.should be_kind_of(::Hash)
|
167
|
+
res['numbers'].first.should == {"country" => "ES","msisdn" => "34911067000","type" => "landline"}
|
168
|
+
request.should have_been_made.once
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context '#top_up' do
|
173
|
+
it 'should return error on missed param' do
|
174
|
+
expect { subject.top_up }.to raise_error('trx params required')
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should success top up' do
|
178
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/top-up?api_key=default_key&api_secret=default_secret&trx=test_trx").
|
179
|
+
with(webmock_default_headers).to_return(:status => 200, :body => '', :headers => {})
|
180
|
+
res = subject.top_up :trx => 'test_trx'
|
181
|
+
res.should be_kind_of(::Hash)
|
182
|
+
res.success?.should be_true
|
183
|
+
request.should have_been_made.once
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos::Base do
|
3
|
+
|
4
|
+
let(:webmock_default_headers) do
|
5
|
+
{
|
6
|
+
:headers => {
|
7
|
+
'Accept'=>'application/json',
|
8
|
+
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
9
|
+
'User-Agent'=> ::Nexmos.user_agent
|
10
|
+
}
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
::Nexmos.reset!
|
16
|
+
end
|
17
|
+
context 'class' do
|
18
|
+
subject { ::Nexmos::Base }
|
19
|
+
let(:default_faraday_options) do
|
20
|
+
{
|
21
|
+
:url => 'https://rest.nexmo.com',
|
22
|
+
:headers => {
|
23
|
+
:accept => 'application/json',
|
24
|
+
:user_agent => ::Nexmos.user_agent
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
its(:faraday_options) { should == default_faraday_options }
|
30
|
+
its(:connection) { should be_kind_of(::Faraday::Connection) }
|
31
|
+
|
32
|
+
context 'faraday_options' do
|
33
|
+
it 'should have custom user agent' do
|
34
|
+
::Nexmos.setup do |c|
|
35
|
+
c.user_agent = 'test user agent'
|
36
|
+
end
|
37
|
+
default_faraday_options[:headers][:user_agent] = 'test user agent'
|
38
|
+
subject.faraday_options.should == default_faraday_options
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'define_api_calls' do
|
43
|
+
it 'should call define_method' do
|
44
|
+
::Nexmos.apis[:account].keys.each do |k|
|
45
|
+
subject.should_receive(:define_method).with(k)
|
46
|
+
end
|
47
|
+
subject.define_api_calls(:account)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should define dynamic method and call make_api_call inside' do
|
51
|
+
subject.define_api_calls(:account)
|
52
|
+
instance = subject.new('test_key', 'test_secret')
|
53
|
+
instance.should_receive(:make_api_call).with(::Nexmos.apis[:account][:get_balance], {})
|
54
|
+
instance.get_balance
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'instance' do
|
61
|
+
subject { ::Nexmos::Base.new('test_api', 'test_secret') }
|
62
|
+
context 'new' do
|
63
|
+
it 'should raise on empty api_key' do
|
64
|
+
expect {::Nexmos::Base.new('', 'test_secret')}.to raise_error('api_key should be set')
|
65
|
+
end
|
66
|
+
it 'should raise on empty api_secret' do
|
67
|
+
expect {::Nexmos::Base.new('test_key', '')}.to raise_error('api_secret should be set')
|
68
|
+
end
|
69
|
+
it 'should set default_params with values from ::Nexmos module' do
|
70
|
+
::Nexmos.setup do |c|
|
71
|
+
c.api_key = 'default_key'
|
72
|
+
c.api_secret = 'default_secret'
|
73
|
+
end
|
74
|
+
instance = ::Nexmos::Base.new
|
75
|
+
instance.instance_variable_get('@default_params').should == {'api_key' => 'default_key', 'api_secret' => 'default_secret'}
|
76
|
+
end
|
77
|
+
it 'should set default_params with custom api key and secret' do
|
78
|
+
instance = ::Nexmos::Base.new('test_key', 'test_secret')
|
79
|
+
instance.instance_variable_get('@default_params').should == {'api_key' => 'test_key', 'api_secret' => 'test_secret'}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
its(:connection) { should be_kind_of(::Faraday::Connection) }
|
84
|
+
|
85
|
+
context 'make_api_call' do
|
86
|
+
|
87
|
+
before(:each) do
|
88
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret").
|
89
|
+
with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=> ::Nexmos.user_agent}).
|
90
|
+
to_return(:status => 200, :body => {'key' => 'value'}, :headers => {})
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:api_params_without_required) do
|
94
|
+
{
|
95
|
+
:method => :get,
|
96
|
+
:url => '/test/url'
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
let(:api_params_with_required) do
|
101
|
+
{
|
102
|
+
:method => :get,
|
103
|
+
:url => '/test/url',
|
104
|
+
:required => %w(key1 key2)
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should call check_required_params' do
|
109
|
+
subject.should_receive(:check_required_params)
|
110
|
+
subject.make_api_call(api_params_with_required)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should raise if all required params missing' do
|
114
|
+
expect{subject.make_api_call(api_params_with_required)}.to raise_error('key1,key2 params required')
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should raise if some required params missing' do
|
118
|
+
expect{subject.make_api_call(api_params_with_required,{:key1 => 'val'})}.to raise_error('key2 params required')
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should call normalize_params' do
|
122
|
+
subject.should_receive(:normalize_params).and_call_original
|
123
|
+
subject.make_api_call(api_params_without_required)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should not call camelize_params' do
|
127
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&test_call=value").
|
128
|
+
with(webmock_default_headers).
|
129
|
+
to_return(:status => 200, :body => {}, :headers => {})
|
130
|
+
subject.should_not_receive(:camelize_params)
|
131
|
+
subject.make_api_call(api_params_without_required, {'test_call' => 'value'})
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should call camelize_params' do
|
135
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
136
|
+
with(webmock_default_headers).
|
137
|
+
to_return(:status => 200, :body => {}, :headers => {})
|
138
|
+
subject.should_receive(:camelize_params).and_call_original
|
139
|
+
subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should call get_response' do
|
143
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret").
|
144
|
+
with(webmock_default_headers).
|
145
|
+
to_return(:status => 200, :body => {}, :headers => {})
|
146
|
+
subject.should_receive(:get_response).and_call_original
|
147
|
+
subject.make_api_call(api_params_without_required)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should return hash' do
|
151
|
+
subject.make_api_call(api_params_without_required).should be_a_kind_of(::Hash)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should return Hashie::Mash' do
|
155
|
+
subject.make_api_call(api_params_without_required).should be_a_kind_of(::Hashie::Mash)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should respond to success? method in result' do
|
159
|
+
subject.make_api_call(api_params_without_required).should respond_to(:success?)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should have success? key in hash' do
|
163
|
+
subject.make_api_call(api_params_without_required)[:success?].should be
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should have success? == true' do
|
167
|
+
subject.make_api_call(api_params_without_required)[:success?].should be_true
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should have success? == false on response with status != 200' do
|
171
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
172
|
+
with(webmock_default_headers).
|
173
|
+
to_return(:status => 410, :body => {}, :headers => {})
|
174
|
+
res = subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
175
|
+
res[:success?].should be_false
|
176
|
+
res[:failed?].should be_false
|
177
|
+
res[:not_authorized?].should be_false
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should have not_authorized? == true' do
|
181
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
182
|
+
with(webmock_default_headers).
|
183
|
+
to_return(:status => 401, :body => {}, :headers => {})
|
184
|
+
res = subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
185
|
+
res[:success?].should be_false
|
186
|
+
res[:not_authorized?].should be_true
|
187
|
+
res[:failed?].should be_false
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should have failed? == true' do
|
191
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
192
|
+
with(webmock_default_headers).
|
193
|
+
to_return(:status => 420, :body => {}, :headers => {})
|
194
|
+
res = subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
195
|
+
res[:success?].should be_false
|
196
|
+
res[:not_authorized?].should be_false
|
197
|
+
res[:failed?].should be_true
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos::Number do
|
3
|
+
let(:webmock_default_headers) do
|
4
|
+
{
|
5
|
+
:headers => {
|
6
|
+
'Accept' => 'application/json',
|
7
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
8
|
+
'User-Agent' => ::Nexmos.user_agent
|
9
|
+
}
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:finland_numbers_search) do
|
14
|
+
{"numbers" => [
|
15
|
+
{"type" => "mobile-lvn",
|
16
|
+
"msisdn" => "3584573950816",
|
17
|
+
"country" => "FI",
|
18
|
+
"cost" => "3.00"},
|
19
|
+
{"type" => "mobile-lvn",
|
20
|
+
"msisdn" => "3584573950815",
|
21
|
+
"country" => "FI",
|
22
|
+
"cost" => "3.00"},
|
23
|
+
{"type" => "mobile-lvn",
|
24
|
+
"msisdn" => "3584573950814",
|
25
|
+
"country" => "FI",
|
26
|
+
"cost" => "3.00"},
|
27
|
+
{"type" => "mobile-lvn",
|
28
|
+
"msisdn" => "3584573950813",
|
29
|
+
"country" => "FI",
|
30
|
+
"cost" => "3.00"},
|
31
|
+
{"type" => "mobile-lvn",
|
32
|
+
"msisdn" => "3584573950812",
|
33
|
+
"country" => "FI",
|
34
|
+
"cost" => "3.00"},
|
35
|
+
{"type" => "mobile-lvn",
|
36
|
+
"msisdn" => "3584573950806",
|
37
|
+
"country" => "FI",
|
38
|
+
"cost" => "3.00"},
|
39
|
+
{"type" => "mobile-lvn",
|
40
|
+
"msisdn" => "3584573950805",
|
41
|
+
"country" => "FI",
|
42
|
+
"cost" => "3.00"},
|
43
|
+
{"type" => "mobile-lvn",
|
44
|
+
"msisdn" => "3584573950804",
|
45
|
+
"country" => "FI",
|
46
|
+
"cost" => "3.00"},
|
47
|
+
{"type" => "mobile-lvn",
|
48
|
+
"msisdn" => "3584573950798",
|
49
|
+
"country" => "FI",
|
50
|
+
"cost" => "3.00"},
|
51
|
+
{"type" => "mobile-lvn",
|
52
|
+
"msisdn" => "3584573950796",
|
53
|
+
"country" => "FI",
|
54
|
+
"cost" => "3.00"}],
|
55
|
+
"count" => 22}
|
56
|
+
end
|
57
|
+
|
58
|
+
before(:each) do
|
59
|
+
::Nexmos.reset!
|
60
|
+
::Nexmos.setup do |c|
|
61
|
+
c.api_key = 'default_key'
|
62
|
+
c.api_secret = 'default_secret'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
subject { ::Nexmos::Number.new }
|
67
|
+
|
68
|
+
context '#search' do
|
69
|
+
it 'should return error on missed param' do
|
70
|
+
expect { subject.search }.to raise_error('country params required')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should return list of numbers' do
|
74
|
+
request = stub_request(:get, "https://rest.nexmo.com/number/search?api_key=default_key&api_secret=default_secret&country=FI").
|
75
|
+
with(webmock_default_headers).to_return(:status => 200, :body => finland_numbers_search, :headers => {})
|
76
|
+
res = subject.search(:country => 'FI')
|
77
|
+
res.should be_kind_of(::Hash)
|
78
|
+
res.success?.should be_true
|
79
|
+
res['count'].should == 22
|
80
|
+
res['numbers'].should be_kind_of(::Array)
|
81
|
+
res['numbers'].size.should == 10
|
82
|
+
res['numbers'].first.keys.sort.should == ["cost", "country", "msisdn", "type"]
|
83
|
+
request.should have_been_made.once
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context '#buy' do
|
88
|
+
it 'should return error on missed params' do
|
89
|
+
expect { subject.buy }.to raise_error('country,msisdn params required')
|
90
|
+
end
|
91
|
+
it 'should return error on missed params' do
|
92
|
+
expect { subject.buy :country => 'FI' }.to raise_error('msisdn params required')
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should buy number' do
|
96
|
+
request = stub_request(:post, "https://rest.nexmo.com/number/buy").
|
97
|
+
with(
|
98
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=> ::Nexmos.user_agent},
|
99
|
+
:body => {"api_key"=>"default_key", "api_secret"=>"default_secret", "country"=>"FI", "msisdn"=>"3584573950816"}
|
100
|
+
).to_return(:status => 200, :body => "", :headers => {})
|
101
|
+
res = subject.buy(:country => 'FI', :msisdn => '3584573950816' )
|
102
|
+
res.should be_kind_of(::Hash)
|
103
|
+
res.success?.should be_true
|
104
|
+
request.should have_been_made.once
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context '#cancel' do
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
data/spec/nexmos_spec.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos do
|
3
|
+
subject{ ::Nexmos }
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
subject.reset!
|
7
|
+
end
|
8
|
+
|
9
|
+
context '#reset!' do
|
10
|
+
its(:user_agent) { should == "Nexmos v#{::Nexmos::VERSION}" }
|
11
|
+
its(:api_key) { should be_nil }
|
12
|
+
its(:api_secret) { should be_nil }
|
13
|
+
its(:logger) { should be_kind_of(::Logger) }
|
14
|
+
end
|
15
|
+
|
16
|
+
context '#setup' do
|
17
|
+
|
18
|
+
context 'single call' do
|
19
|
+
it 'should set user_agent' do
|
20
|
+
subject.setup do |c|
|
21
|
+
c.user_agent = 'Test1245'
|
22
|
+
end
|
23
|
+
subject.user_agent.should == 'Test1245'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should set logger' do
|
27
|
+
newlogger = ::Logger.new(STDERR)
|
28
|
+
subject.setup do |c|
|
29
|
+
c.logger = newlogger
|
30
|
+
end
|
31
|
+
subject.logger.should == newlogger
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should set api_key' do
|
35
|
+
subject.setup do |c|
|
36
|
+
c.api_key = 'test-api-key'
|
37
|
+
end
|
38
|
+
subject.api_key.should == 'test-api-key'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should set api_secret' do
|
42
|
+
subject.setup do |c|
|
43
|
+
c.api_secret = 'test-api-secret'
|
44
|
+
end
|
45
|
+
subject.api_secret.should == 'test-api-secret'
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'double call' do
|
51
|
+
it 'should not accept running setup more then once' do
|
52
|
+
subject.setup do |c|
|
53
|
+
c.api_key = 'test-api-key'
|
54
|
+
end
|
55
|
+
subject.setup do |c|
|
56
|
+
c.api_key = 'test-api-key2'
|
57
|
+
end
|
58
|
+
subject.api_key.should == 'test-api-key'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
require 'webmock'
|
8
|
+
require 'webmock/rspec'
|
9
|
+
require 'nexmos'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
13
|
+
config.run_all_when_everything_filtered = true
|
14
|
+
config.filter_run :focus
|
15
|
+
|
16
|
+
# Run specs in random order to surface order dependencies. If you find an
|
17
|
+
# order dependency and want to debug it, you can fix the order by providing
|
18
|
+
# the seed, which is printed after each run.
|
19
|
+
# --seed 1234
|
20
|
+
config.order = 'random'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nexmos
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexander Simonov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rash
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: faraday
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: faraday_middleware
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: activesupport
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 3.0.0
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 3.0.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: webmock
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Nexmo API client
|
111
|
+
email:
|
112
|
+
- alex@simonov.me
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- .rspec
|
119
|
+
- .rvmrc
|
120
|
+
- .travis.yml
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- lib/api.yml
|
126
|
+
- lib/nexmos.rb
|
127
|
+
- lib/nexmos/account.rb
|
128
|
+
- lib/nexmos/base.rb
|
129
|
+
- lib/nexmos/message.rb
|
130
|
+
- lib/nexmos/number.rb
|
131
|
+
- lib/nexmos/railties.rb
|
132
|
+
- lib/nexmos/search.rb
|
133
|
+
- lib/nexmos/version.rb
|
134
|
+
- nexmos.gemspec
|
135
|
+
- spec/nexmos/account_spec.rb
|
136
|
+
- spec/nexmos/base_spec.rb
|
137
|
+
- spec/nexmos/number_spec.rb
|
138
|
+
- spec/nexmos_spec.rb
|
139
|
+
- spec/spec_helper.rb
|
140
|
+
homepage: https://github.com/simonoff/nexmos
|
141
|
+
licenses: []
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ! '>='
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
requirements: []
|
159
|
+
rubyforge_project:
|
160
|
+
rubygems_version: 1.8.24
|
161
|
+
signing_key:
|
162
|
+
specification_version: 3
|
163
|
+
summary: Nexmo API client
|
164
|
+
test_files:
|
165
|
+
- spec/nexmos/account_spec.rb
|
166
|
+
- spec/nexmos/base_spec.rb
|
167
|
+
- spec/nexmos/number_spec.rb
|
168
|
+
- spec/nexmos_spec.rb
|
169
|
+
- spec/spec_helper.rb
|