joker-dmapi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
19
+ .DS_Store
20
+ dev
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in epp-client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Yuriy Kolodovskyy
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,79 @@
1
+ # Joker DMAPI client library
2
+
3
+ https://joker.com/faq/category/33/22-dmapi.html
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'joker-dmapi'
10
+
11
+ or this line:
12
+
13
+ gem 'joker-dmapi', git: 'https://github.com/kolodovskyy/joker-dmapi.git'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install joker-dmapi
22
+
23
+ ## Usage (example)
24
+
25
+ require "joker-dmapi"
26
+
27
+ ENV['JOKER_DMAPI_DEBUG'] = 'yes'
28
+
29
+ JokerDMAPI::Client.with_connection('LOGIN', 'PASSWORD') do |j|
30
+ j.contact_info 'CCOM-000000'
31
+ j.domain_info 'joker.com'
32
+
33
+ j.contact_create {
34
+ tld: 'com',
35
+ name: 'Test name',
36
+ email: 'test@tes.com',
37
+ address: ['Test str.'],
38
+ city: 'Kiev',
39
+ postal_code: '00000',
40
+ country: 'UA',
41
+ phone: '+380.443063232',
42
+ }
43
+
44
+ # handle returted
45
+ j.contact_create_result '51930786'
46
+
47
+ j.contact_delete 'CCOM-000000'
48
+ j.complete? '51930793'
49
+
50
+ j.domain_registrant_update 'ukrtoday.com', {
51
+ tld: 'com',
52
+ name: 'Test name',
53
+ organization: 'Test org',
54
+ address: [ 'Test str.' ],
55
+ city: 'Kiev',
56
+ postal_code: '00000',
57
+ country: 'UA',
58
+ phone: '+380.442063232',
59
+ fax: '+380.442063233',
60
+ email: 'test@test.com'
61
+ }
62
+
63
+ j.complete? '51931047'
64
+
65
+ j.domain_update 'ukrtoday.com', {
66
+ admin: 'CCOM-000000',
67
+ tech: 'CCOM-000000',
68
+ billing: 'CCOM-000000',
69
+ nservers: %w(ns1.test.com ns2.test.com)
70
+ }
71
+ end
72
+
73
+ ## Maintainers and Authors
74
+
75
+ Yuriy Kolodovskyy (https://github.com/kolodovskyy)
76
+
77
+ ## License
78
+
79
+ MIT License. Copyright 2012 [Yuriy Kolodovskyy](http://twitter.com/kolodovskyy)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'joker-dmapi'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "joker-dmapi"
8
+ gem.version = JokerDMAPI::VERSION
9
+ gem.authors = ["Yuriy Kolodovskyy"]
10
+ gem.email = %w{kolodovskyy@ukrindex.com}
11
+ gem.description = %q{Joker DMAPI client library}
12
+ gem.summary = %q{Joker DMAPI client library}
13
+ gem.homepage = "https://github.com/kolodovskyy/joker-dmapi"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = %w{lib}
19
+
20
+ gem.add_dependency "addressable"
21
+ gem.add_development_dependency "bundler"
22
+ end
@@ -0,0 +1,92 @@
1
+ require "net/http"
2
+ require "addressable/uri"
3
+ require "joker-dmapi/result"
4
+ require "joker-dmapi/contact"
5
+ require "joker-dmapi/domain"
6
+
7
+ module JokerDMAPI
8
+ VERSION = '0.0.1'
9
+
10
+ class Client
11
+ URI = 'https://dmapi.joker.com:443/request/'
12
+
13
+ include JokerDMAPI::Result
14
+ include JokerDMAPI::Contact
15
+ include JokerDMAPI::Domain
16
+
17
+ def initialize(username, password)
18
+ @username, @password = username, password
19
+ end
20
+
21
+ def self.with_connection(username, password, &block)
22
+ connection = self.new(username, password)
23
+ yield connection
24
+ connection.logout
25
+ end
26
+
27
+ def logout
28
+ unless @auth_sid.nil?
29
+ query :logout
30
+ @auth_sid = nil
31
+ end
32
+ end
33
+
34
+ def query(request, params = {})
35
+ params['auth-sid'] = auth_sid
36
+ response = request(request, params.inject({}) { |r, (key, value)| r[key.to_s.gsub('_', '-')] = value; r })
37
+ check_status response
38
+ response
39
+ end
40
+
41
+ private
42
+
43
+ def parse_line(line)
44
+ parts = line.split /\s*:\s*/, 2
45
+ if parts.length == 2
46
+ { parts[0].downcase.gsub('-', '_').gsub('.', '_').to_sym => parts[1] }
47
+ else
48
+ line
49
+ end
50
+ end
51
+
52
+ def parse_attributes(attributes)
53
+ attributes.split("\n").inject({}) do |h, line|
54
+ attribute = parse_line line
55
+ h.merge!(attribute) if attribute.is_a? Hash
56
+ h
57
+ end
58
+ end
59
+
60
+ def parse_response(response)
61
+ response.each_line { |line| puts "<< #{line}" } if ENV['JOKER_DMAPI_DEBUG']
62
+ parts = response.split "\n\n", 2
63
+ { headers: parse_attributes(parts[0]), body: parts[1] }
64
+ end
65
+
66
+ def request(request, params = {})
67
+ uri = Addressable::URI.parse(URI + request.to_s)
68
+ uri.query_values = params
69
+ http = Net::HTTP.new(uri.host, uri.port)
70
+ http.use_ssl = true
71
+ #http.verify_mode = OpenSSL::SSL::VERIFY_NONE
72
+ puts ">> #{uri.request_uri}" if ENV['JOKER_DMAPI_DEBUG']
73
+ parse_response http.request(Net::HTTP::Get.new(uri.request_uri)).body
74
+ end
75
+
76
+ def check_status(response)
77
+ if response[:headers][:status_code] != '0'
78
+ raise "#{response[:headers][:status_code]}: #{response[:headers][:error]}\n"
79
+ end
80
+ end
81
+
82
+ def auth_sid
83
+ if @auth_sid.nil?
84
+ response = request(:login, username: @username, password: @password)
85
+ check_status response
86
+ @auth_sid = response[:headers][:auth_sid]
87
+ @tlds = response[:body].split "\n"
88
+ end
89
+ @auth_sid
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,147 @@
1
+ module JokerDMAPI
2
+ module Contact
3
+ CONTACT_REQUIRED = [ :tld, :name, :email, :address, :city, :postal_code, :country, :phone ]
4
+ CONTACT_ALLOWED = CONTACT_REQUIRED + [ :organization, :state, :fax ]
5
+ CONTACT_LENGTH_LIMIT = %w(biz cn eu)
6
+
7
+ # Returns the information about a contact
8
+ #
9
+ # Takes handler as string
10
+ #
11
+ # Returned is a hash:
12
+ # [<tt>:name</tt>] the contact's name
13
+ # [<tt>:organization</tt>] the contact's organization name
14
+ # [<tt>:address</tt>] an array containing from one to three elements with contact's address
15
+ # [<tt>:city</tt>] the contact's city
16
+ # [<tt>:state</tt>] the contact's state
17
+ # [<tt>:postal_code</tt>] the contact's postal code
18
+ # [<tt>:country</tt>] the contact's country code (UA)
19
+ # [<tt>:email</tt>] the contact's email address
20
+ # [<tt>:phone</tt>] the contact's voice phone number
21
+ # [<tt>:fax</tt>] the contact's fax number
22
+ # [<tt>:handle</tt>] the contact's handler from Joker
23
+ # [<tt>:created_date</tt>] the date and time of contact created
24
+ # [<tt>:modified_date</tt>] the date and time of contact modified
25
+ def contact_info(handle)
26
+ response = query 'query-whois', contact: handle
27
+ result = {}
28
+ response[:body].split("\n").each do |line|
29
+ line.slice! /^contact\./
30
+ line_parsed = parse_line(line)
31
+ next if line_parsed.is_a? String
32
+ key, value = line_parsed.first
33
+ case key
34
+ when :name then next if value == "- -"
35
+ when :address_1, :address_2, :address_3 then
36
+ result[:address] = [] unless result.has_key? :address
37
+ result[:address] << value
38
+ when :state then next if value == "--"
39
+ when :organization then next if value == "-" or value.empty?
40
+ when :created_date, :modified_date then
41
+ result[key] = DateTime.parse value
42
+ else
43
+ result.merge! line_parsed
44
+ end
45
+ end
46
+ result
47
+ end
48
+
49
+ # Create new contact
50
+ #
51
+ # Takes contact's fields as hash:
52
+ # [<tt>:tld</tt>] the TLD to use new contact
53
+ # [<tt>:name</tt>] the contact's name
54
+ # [<tt>:organization</tt>] the contact's organization name
55
+ # [<tt>:address</tt>] an array containing from one to three elements with contact's address
56
+ # [<tt>:city</tt>] the contact's city
57
+ # [<tt>:state</tt>] the contact's state
58
+ # [<tt>:postal_code</tt>] the contact's postal code
59
+ # [<tt>:country</tt>] the contact's country code (UA)
60
+ # [<tt>:email</tt>] the contact's email address
61
+ # [<tt>:phone</tt>] the contact's voice phone number
62
+ # [<tt>:fax</tt>] the contact's fax number
63
+ #
64
+ # Returned is a hash of response:
65
+ # [<tt>:headers</tt>]
66
+ # [<tt>:proc_id</tt>] process ID (used at check result)
67
+ # [<tt>:tracking_id</tt>] tracking ID
68
+ def contact_create(fields)
69
+ query 'contact-create', contact_prepare(fields)
70
+ end
71
+
72
+ # Check result of create contact
73
+ #
74
+ # Get <tt>proc_id</tt>
75
+ # Returned contact's handle name (and delete result) or <tt>nil</tt> if don't ready
76
+ def contact_create_result(proc_id)
77
+ result = parse_attributes(result_retrieve(proc_id)[:body].split("\n\n", 1)[0])
78
+ if result.has_key?(:completion_status) and result[:completion_status] == 'ack'
79
+ result_delete proc_id
80
+ result[:object_name]
81
+ else
82
+ nil
83
+ end
84
+ end
85
+
86
+ # Update contact
87
+ #
88
+ # Takes <tt>handle</tt> to select contact and contact's fields as hash:
89
+ # [<tt>:name</tt>] the contact's name
90
+ # [<tt>:organization</tt>] the contact's organization name
91
+ # [<tt>:address</tt>] an array containing from one to three elements with contact's address
92
+ # [<tt>:city</tt>] the contact's city
93
+ # [<tt>:state</tt>] the contact's state
94
+ # [<tt>:postal_code</tt>] the contact's postal code
95
+ # [<tt>:country</tt>] the contact's country code (UA)
96
+ # [<tt>:email</tt>] the contact's email address
97
+ # [<tt>:phone</tt>] the contact's voice phone number
98
+ # [<tt>:fax</tt>] the contact's fax number
99
+ #
100
+ # Returned is a hash of response:
101
+ # [<tt>:headers</tt>]
102
+ # [<tt>:proc_id</tt>] process ID (used at check result)
103
+ # [<tt>:tracking_id</tt>] tracking ID
104
+ def contact_update(handle, fields)
105
+ fields = contact_prepare(fields)
106
+ fields[:handle] = handle
107
+ query 'contact-modify', fields
108
+ end
109
+
110
+ # Delete contact
111
+ # Takes <tt>handle</tt>
112
+ def contact_delete(handle)
113
+ query 'contact-delete', { handle: handle }
114
+ end
115
+
116
+ private
117
+
118
+ def contact_prepare(fields)
119
+ raise ArgumentError, "Required fields not found" unless (CONTACT_REQUIRED - fields.keys).empty?
120
+ auth_sid
121
+ raise ArgumentError, "TLD must be one of accepted" unless @tlds.include? fields[:tld]
122
+ if CONTACT_LENGTH_LIMIT.include? fields[:tld]
123
+ [ :name, :organization, :city, :state ].each do |field|
124
+ next unless fields.has_key? field
125
+ fields[field] = fields[field][0...30] # only 30 allowed
126
+ end
127
+ if fields.has_key? :address
128
+ fields[:address].map! { |addr| addr[0...30] }
129
+ end
130
+ end
131
+ fields = fields.keep_if { |key, value| CONTACT_ALLOWED.include? key }
132
+ if fields.has_key? :organization and !fields[:organization].empty?
133
+ fields[:individual] = 'No'
134
+ else
135
+ fields[:individual] = 'Yes'
136
+ end
137
+ unless fields[:address].size > 0 and fields[:address].size <= 3
138
+ raise ArgumentError, "From one to three lines of address allowed"
139
+ end
140
+ (1..3).each do |index|
141
+ fields["address-" + index.to_s] = fields[:address][index-1].nil? ? '' : fields[:address][index-1]
142
+ end
143
+ fields.delete :address
144
+ fields
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,133 @@
1
+ module JokerDMAPI
2
+ module Domain
3
+ # Returns the information about a domain
4
+ #
5
+ # Takes FQDN as string
6
+ #
7
+ # Returned is a hash:
8
+ # [<tt>:fqdn</tt>] FQDN
9
+ # [<tt>:status</tt>] domain status
10
+ # [<tt>:registrant</tt>] registrant (owner) as hash keys:
11
+ # [<tt>:name</tt>] registrant's name
12
+ # [<tt>:organization</tt>] registrant's organization
13
+ # [<tt>:address</tt>] an array of registrant's address
14
+ # [<tt>:postal_code</tt>] registrant's postal code
15
+ # [<tt>:country</tt>] registrant's country code
16
+ # [<tt>:owner_c_email</tt>] owner's email address
17
+ # [<tt>:email</tt>] registrant's email address
18
+ # [<tt>:phone</tt>] registrant's voice phone number
19
+ # [<tt>:fax</tt>] registrant's fax number
20
+ # [<tt>:reseller_lines</tt>] an array of reseller data
21
+ # [<tt>:admin_c</tt>] registrant's admin-c handle
22
+ # [<tt>:tech_c</tt>] registrant's tech-c handle
23
+ # [<tt>:billing_c</tt>] registrant's billing-c handle
24
+ # [<tt>:nservers</tt>] an array of NS servers
25
+ # [<tt>:created_date</tt>] date and time of creation
26
+ # [<tt>:modified_date</tt>] date and time of modification
27
+ # [<tt>:expires</tt>] date and time of expiration
28
+ def domain_info(domain)
29
+ response = query 'query-whois', domain: domain
30
+ result = {}
31
+ response[:body].split("\n").each do |line|
32
+ line.slice! /^domain\./
33
+ line_parsed = parse_line(line)
34
+ next if line_parsed.is_a? String
35
+ key, value = line_parsed.first
36
+ case key
37
+ when :fqdn, :status then result.merge! line_parsed
38
+ when :name, :organization, :city, :postal_code, :country, :owner_c_email, :email, :phone, :fax then
39
+ result[:registrant] = {} unless result.has_key? :registrant
40
+ result[:registrant].merge! line_parsed
41
+ when :address_1, :address_2, :address_3 then
42
+ result[:registrant] = {} unless result.has_key? :registrant
43
+ result[:registrant][:address] = [] unless result[:registrant].has_key? :address
44
+ result[:registrant][:address] << value
45
+ when :reseller_line then
46
+ result[:reseller_lines] = [] unless result.has_key? :reseller_lines
47
+ result[:reseller_lines] << value
48
+ when :created_date, :modified_date, :expires then
49
+ result[key] = DateTime.parse value
50
+ when :admin_c, :tech_c, :billing_c then
51
+ result.merge! line_parsed
52
+ when :nservers_nserver_handle then
53
+ result[:nservers] = [] unless result.has_key? :nservers
54
+ result[:nservers] << value
55
+ else
56
+ next
57
+ end
58
+ end
59
+ result
60
+ end
61
+
62
+ # Register new domain
63
+ #
64
+ # Takes <tt>domain</tt> and domain's fields as hash:
65
+ # [<tt>:period</tt>] registration period (years!!!)
66
+ # [<tt>:registrant</tt>] registrant (owner) handle (registered)
67
+ # [<tt>:admin</tt>] admin handle (registered)
68
+ # [<tt>:tech</tt>] tech handle (registered)
69
+ # [<tt>:billing</tt>] billing handle (registered)
70
+ # [<tt>:nservers</tt>] an array of NS servers
71
+ #
72
+ # Returned is a hash of response:
73
+ # [<tt>:headers</tt>]
74
+ # [<tt>:proc_id</tt>] process ID (used at check result)
75
+ # [<tt>:tracking_id</tt>] tracking ID
76
+ def domain_create(domain, fields)
77
+ unless ([ :period, :registrant, :admin, :tech, :billing, :nservers ] - fields.keys).empty?
78
+ raise ArgumentError, "Required fields not found"
79
+ end
80
+ query 'domain-register', {
81
+ domain: domain,
82
+ period: (fields[:period] * 12),
83
+ owner_c: fields[:registrant],
84
+ admin_c: fields[:admin],
85
+ tech_c: fields[:tech],
86
+ billing_c: fields[:billing],
87
+ ns_list: fields[:nservers].join(':')
88
+ }
89
+ end
90
+
91
+ # Update domain
92
+ #
93
+ # Takes <tt>domain</tt> and domain's fields as hash:
94
+ # [<tt>:admin</tt>] admin handle (registered)
95
+ # [<tt>:tech</tt>] tech handle (registered)
96
+ # [<tt>:billing</tt>] billing handle (registered)
97
+ # [<tt>:nservers</tt>] an array of NS servers
98
+ #
99
+ # Returned is a hash of response:
100
+ # [<tt>:headers</tt>]
101
+ # [<tt>:proc_id</tt>] process ID (used at check result)
102
+ # [<tt>:tracking_id</tt>] tracking ID
103
+ def domain_update(domain, fields)
104
+ unless ([ :admin, :tech, :billing, :nservers ] - fields.keys).empty?
105
+ raise ArgumentError, "Required fields not found"
106
+ end
107
+ query 'domain-modify', {
108
+ domain: domain,
109
+ admin_c: fields[:admin],
110
+ tech_c: fields[:tech],
111
+ billing_c: fields[:billing],
112
+ ns_list: fields[:nservers].join(':')
113
+ }
114
+ end
115
+
116
+ # Renew domain
117
+ #
118
+ # Takes <tt>domain</tt> and <tt>period</tt>
119
+ # WARNING!!! <tt>period</tt> in YEARS
120
+ def domain_renew(domain, period)
121
+ query 'domain-renew', { domain: domain, period: (12 * period) }
122
+ end
123
+
124
+ # Update registrant's info
125
+ #
126
+ # Takes <tt>domain</tt> and fields (see contact_update)
127
+ def domain_registrant_update(domain, fields)
128
+ fields = contact_prepare(fields)
129
+ fields[:domain] = domain
130
+ query 'domain-owner-change', fields
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,25 @@
1
+ module JokerDMAPI
2
+ module Result
3
+ # Check result
4
+ #
5
+ # Get <tt>proc_id</tt>
6
+ # Returned <tt>true</tt> if done (result deleted)
7
+ def complete?(proc_id)
8
+ result = parse_attributes(result_retrieve(proc_id)[:body].split("\n\n", 1)[0])
9
+ if result.has_key?(:completion_status) and result[:completion_status] == 'ack'
10
+ result_delete proc_id
11
+ true
12
+ else
13
+ false
14
+ end
15
+ end
16
+
17
+ def result_retrieve(proc_id)
18
+ query 'result-retrieve', { proc_id: proc_id }
19
+ end
20
+
21
+ def result_delete(proc_id)
22
+ query 'result-delete', { proc_id: proc_id }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1 @@
1
+ require "joker-dmapi/client"
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: joker-dmapi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Yuriy Kolodovskyy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: addressable
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: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
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
+ description: Joker DMAPI client library
47
+ email:
48
+ - kolodovskyy@ukrindex.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - joker-dmapi.gemspec
59
+ - lib/joker-dmapi.rb
60
+ - lib/joker-dmapi/client.rb
61
+ - lib/joker-dmapi/contact.rb
62
+ - lib/joker-dmapi/domain.rb
63
+ - lib/joker-dmapi/result.rb
64
+ homepage: https://github.com/kolodovskyy/joker-dmapi
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 1.8.24
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Joker DMAPI client library
88
+ test_files: []