docheck 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.rdoc +38 -15
- data/data/rdap_dns.json +5354 -0
- data/exe/docheck +6 -0
- data/lib/docheck/application.rb +22 -63
- data/lib/docheck/bootstrap.rb +44 -0
- data/lib/docheck/checker.rb +53 -0
- data/lib/docheck/cli.rb +70 -0
- data/lib/docheck/errors.rb +12 -0
- data/lib/docheck/http_client.rb +77 -0
- data/lib/docheck/name.rb +20 -0
- data/lib/docheck/result.rb +23 -0
- data/lib/docheck/version.rb +3 -1
- data/lib/docheck.rb +17 -5
- metadata +27 -51
- data/.gitignore +0 -3
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -39
- data/Rakefile +0 -2
- data/bin/docheck +0 -3
- data/docheck.gemspec +0 -28
- data/lib/docheck/command.rb +0 -31
- data/test/docheck_test.rb +0 -66
- data/test/helper.rb +0 -7
data/exe/docheck
ADDED
data/lib/docheck/application.rb
CHANGED
|
@@ -1,76 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Docheck
|
|
4
|
+
# The 1.x API, kept for compatibility. New code should use Checker.
|
|
2
5
|
class Application
|
|
3
|
-
|
|
4
|
-
# DNS name of the generic top-level domain
|
|
5
|
-
# http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
|
|
6
|
-
TLD = %w[aero asia biz cat com coop edu gov info
|
|
7
|
-
int jobs mil mobi museum name net org pro tel travel]
|
|
8
|
-
|
|
9
6
|
attr_reader :available_domains, :registered_domains
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@base_name = base_name.to_s.downcase
|
|
8
|
+
def initialize(base_name, checker: Checker.new)
|
|
9
|
+
@base_name = base_name
|
|
10
|
+
@checker = checker
|
|
15
11
|
@available_domains = []
|
|
16
12
|
@registered_domains = []
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
result = fetch
|
|
22
|
-
|
|
23
|
-
puts "\nDocheck Result\n"
|
|
24
|
-
puts "--------------\n"
|
|
25
|
-
puts "Available Domains:"
|
|
26
|
-
result.first.map{|domain_name| puts "- #{domain_name}"}
|
|
27
|
-
puts "\n"
|
|
28
|
-
puts "Registered Domains:"
|
|
29
|
-
result.last.map{|domain_name| puts "- #{domain_name}"}
|
|
30
|
-
|
|
31
|
-
true
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Check domain name availability
|
|
35
|
-
# and return the result as array.
|
|
36
|
-
#
|
|
37
|
-
# The first element of array will return all
|
|
38
|
-
# available domains as array.
|
|
39
|
-
#
|
|
40
|
-
# The last element of array will return all
|
|
41
|
-
# registered domains as array.
|
|
15
|
+
# Returns [available_domains, registered_domains]. Each call replaces the
|
|
16
|
+
# previous result. Raises InvalidNameError for an invalid name.
|
|
42
17
|
def fetch
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if whois_domain.available?
|
|
50
|
-
@available_domains << domain_name
|
|
51
|
-
elsif whois_domain.registered?
|
|
52
|
-
@registered_domains << domain_name
|
|
53
|
-
end
|
|
54
|
-
rescue Timeout::Error
|
|
55
|
-
if attempts <= 3
|
|
56
|
-
attempts += 1
|
|
57
|
-
retry
|
|
58
|
-
else
|
|
59
|
-
attempts = 0
|
|
60
|
-
next
|
|
61
|
-
end
|
|
62
|
-
rescue
|
|
63
|
-
if attempts <= 3
|
|
64
|
-
attempts += 1
|
|
65
|
-
retry
|
|
66
|
-
else
|
|
67
|
-
attempts = 0
|
|
68
|
-
next
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
18
|
+
results = @checker.check(@base_name)
|
|
19
|
+
@available_domains = results.select(&:available?).map(&:domain)
|
|
20
|
+
@registered_domains = results.select(&:registered?).map(&:domain)
|
|
21
|
+
[@available_domains, @registered_domains]
|
|
22
|
+
end
|
|
72
23
|
|
|
73
|
-
|
|
24
|
+
# Prints the fetch result to +out+ and returns true.
|
|
25
|
+
def print(out = $stdout) # rubocop:disable Naming/PredicateMethod -- 1.x public API name
|
|
26
|
+
available, registered = fetch
|
|
27
|
+
out.puts "Available Domains:"
|
|
28
|
+
available.each { |domain| out.puts "- #{domain}" }
|
|
29
|
+
out.puts
|
|
30
|
+
out.puts "Registered Domains:"
|
|
31
|
+
registered.each { |domain| out.puts "- #{domain}" }
|
|
32
|
+
true
|
|
74
33
|
end
|
|
75
34
|
end
|
|
76
35
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Docheck
|
|
6
|
+
# Maps each TLD to its RDAP base URL, using the IANA bootstrap file format
|
|
7
|
+
# (RFC 9224). The gem bundles a snapshot in data/rdap_dns.json so that a
|
|
8
|
+
# lookup needs no extra network call. Refresh it with `rake rdap:update`.
|
|
9
|
+
class Bootstrap
|
|
10
|
+
DEFAULT_PATH = File.expand_path("../../data/rdap_dns.json", __dir__)
|
|
11
|
+
|
|
12
|
+
def self.default
|
|
13
|
+
@default ||= load_file(DEFAULT_PATH)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.load_file(path)
|
|
17
|
+
parse(File.read(path))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.parse(json)
|
|
21
|
+
services = JSON.parse(json).fetch("services")
|
|
22
|
+
new(services.each_with_object({}) do |(tlds, urls), map|
|
|
23
|
+
url = urls.find { |u| u.start_with?("https://") }
|
|
24
|
+
tlds.each { |tld| map[tld.downcase] = url } if url
|
|
25
|
+
end)
|
|
26
|
+
rescue JSON::ParserError, KeyError, TypeError, NoMethodError => e
|
|
27
|
+
raise BootstrapError, "invalid RDAP bootstrap data: #{e.message}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(base_urls)
|
|
31
|
+
@base_urls = base_urls.to_h do |tld, url|
|
|
32
|
+
raise BootstrapError, "RDAP base URL for #{tld} must use https: #{url}" unless url.start_with?("https://")
|
|
33
|
+
|
|
34
|
+
[tld.downcase.freeze, (url.end_with?("/") ? url : "#{url}/").freeze]
|
|
35
|
+
end.freeze
|
|
36
|
+
freeze
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns the RDAP base URL for +tld+ (ending in "/"), or nil.
|
|
40
|
+
def base_url(tld)
|
|
41
|
+
@base_urls[tld.to_s.downcase]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docheck
|
|
4
|
+
# Checks a name against a list of TLDs, one RDAP lookup per TLD in parallel.
|
|
5
|
+
class Checker
|
|
6
|
+
# Generic TLDs open to public registration.
|
|
7
|
+
DEFAULT_TLDS = %w[com net org info biz name pro mobi asia tel travel jobs aero cat coop museum].freeze
|
|
8
|
+
|
|
9
|
+
# Upper bound in seconds for a whole #check call.
|
|
10
|
+
DEADLINE = 10
|
|
11
|
+
|
|
12
|
+
attr_reader :tlds
|
|
13
|
+
|
|
14
|
+
def initialize(tlds: DEFAULT_TLDS, bootstrap: Bootstrap.default, http: HttpClient.new, deadline: DEADLINE)
|
|
15
|
+
@tlds = tlds.map { |tld| tld.to_s.downcase.delete_prefix(".").freeze }.freeze
|
|
16
|
+
@bootstrap = bootstrap
|
|
17
|
+
@http = http
|
|
18
|
+
@deadline = deadline
|
|
19
|
+
freeze
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns one Result per TLD, in TLD order. Raises InvalidNameError when
|
|
23
|
+
# +name+ is not a valid DNS label. Lookups still running at the deadline
|
|
24
|
+
# get +:unknown+.
|
|
25
|
+
def check(name)
|
|
26
|
+
label = Name.normalize(name)
|
|
27
|
+
threads = tlds.map { |tld| Thread.new { lookup("#{label}.#{tld}", tld) } }
|
|
28
|
+
collect(threads, tlds.map { |tld| "#{label}.#{tld}" })
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def lookup(domain, tld)
|
|
34
|
+
base_url = @bootstrap.base_url(tld)
|
|
35
|
+
return :unsupported unless base_url
|
|
36
|
+
|
|
37
|
+
@http.status("#{base_url}domain/#{domain}")
|
|
38
|
+
rescue StandardError
|
|
39
|
+
:unknown
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def collect(threads, domains)
|
|
43
|
+
ends_at = now + @deadline
|
|
44
|
+
threads.zip(domains).map do |thread, domain|
|
|
45
|
+
finished = thread.join([ends_at - now, 0].max)
|
|
46
|
+
thread.kill unless finished
|
|
47
|
+
Result.new(domain: domain, status: finished ? thread.value : :unknown)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/docheck/cli.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "optparse"
|
|
4
|
+
require_relative "../docheck"
|
|
5
|
+
|
|
6
|
+
module Docheck
|
|
7
|
+
# The docheck command. #run returns the process exit status.
|
|
8
|
+
class CLI
|
|
9
|
+
EX_OK = 0
|
|
10
|
+
EX_USAGE = 64
|
|
11
|
+
|
|
12
|
+
LABELS = {
|
|
13
|
+
available: "Available",
|
|
14
|
+
registered: "Registered",
|
|
15
|
+
unknown: "Unknown (lookup failed)",
|
|
16
|
+
unsupported: "Unsupported (no RDAP server)"
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
19
|
+
def initialize(argv, out: $stdout, err: $stderr, checker: nil)
|
|
20
|
+
@argv = argv.dup
|
|
21
|
+
@out = out
|
|
22
|
+
@err = err
|
|
23
|
+
@checker = checker
|
|
24
|
+
@done = false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def run
|
|
28
|
+
name = nil
|
|
29
|
+
parser = option_parser { |value| name = value }
|
|
30
|
+
parser.parse!(@argv)
|
|
31
|
+
return EX_OK if @done
|
|
32
|
+
return usage_error(parser, "missing --name") unless name
|
|
33
|
+
|
|
34
|
+
print_results((@checker || Checker.new).check(name))
|
|
35
|
+
EX_OK
|
|
36
|
+
rescue OptionParser::ParseError, InvalidNameError => e
|
|
37
|
+
usage_error(parser, e.message)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def option_parser(&on_name)
|
|
43
|
+
OptionParser.new do |opts|
|
|
44
|
+
opts.banner = "Usage: docheck -n NAME (example: docheck -n google)"
|
|
45
|
+
opts.on("-n", "--name NAME", "Check NAME against each TLD", &on_name)
|
|
46
|
+
opts.on("-v", "--version", "Show version") { finish("docheck #{VERSION}") }
|
|
47
|
+
opts.on("-h", "--help", "Show help") { finish(opts.help) }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def finish(text)
|
|
52
|
+
@out.puts text
|
|
53
|
+
@done = true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def usage_error(parser, message)
|
|
57
|
+
@err.puts "docheck: #{message}"
|
|
58
|
+
@err.puts parser.help
|
|
59
|
+
EX_USAGE
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def print_results(results)
|
|
63
|
+
results.group_by(&:status).sort_by { |status, _| LABELS.keys.index(status) }.each do |status, group|
|
|
64
|
+
@out.puts "#{LABELS.fetch(status)}:"
|
|
65
|
+
group.each { |result| @out.puts "- #{result.domain}" }
|
|
66
|
+
@out.puts
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docheck
|
|
4
|
+
# Base class for all Docheck errors.
|
|
5
|
+
class Error < StandardError; end
|
|
6
|
+
|
|
7
|
+
# Raised when a name is not a valid DNS label.
|
|
8
|
+
class InvalidNameError < Error; end
|
|
9
|
+
|
|
10
|
+
# Raised when the RDAP bootstrap data is malformed.
|
|
11
|
+
class BootstrapError < Error; end
|
|
12
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "openssl"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
module Docheck
|
|
8
|
+
# Queries one RDAP domain URL and maps the HTTP response to a status.
|
|
9
|
+
#
|
|
10
|
+
# It sends HEAD, not GET (RFC 7480 section 4.1). The status code is all it
|
|
11
|
+
# needs, and some registries (Verisign) end a GET body by closing TLS without
|
|
12
|
+
# close_notify, which OpenSSL 3 reports as an error.
|
|
13
|
+
class HttpClient
|
|
14
|
+
TIMEOUT = 3
|
|
15
|
+
MAX_REDIRECTS = 1
|
|
16
|
+
RETRIES = 1
|
|
17
|
+
|
|
18
|
+
# +requester+ takes a URI and returns a Net::HTTPResponse. Tests pass a
|
|
19
|
+
# fake one; the default performs a real HTTPS HEAD request.
|
|
20
|
+
def initialize(timeout: TIMEOUT, requester: nil)
|
|
21
|
+
@timeout = timeout
|
|
22
|
+
@requester = requester || method(:head)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns +:registered+, +:available+, or +:unknown+ for +url+.
|
|
26
|
+
def status(url)
|
|
27
|
+
fetch_status(URI(url), MAX_REDIRECTS, RETRIES)
|
|
28
|
+
rescue URI::Error
|
|
29
|
+
:unknown
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
NETWORK_ERRORS = [IOError, SystemCallError, SocketError, OpenSSL::SSL::SSLError, Net::ProtocolError].freeze
|
|
35
|
+
private_constant :NETWORK_ERRORS
|
|
36
|
+
|
|
37
|
+
def fetch_status(uri, redirects_left, retries_left)
|
|
38
|
+
return :unknown unless uri.is_a?(URI::HTTPS)
|
|
39
|
+
|
|
40
|
+
response = @requester.call(uri)
|
|
41
|
+
case response
|
|
42
|
+
when Net::HTTPOK then :registered
|
|
43
|
+
when Net::HTTPNotFound then :available
|
|
44
|
+
when Net::HTTPRedirection then follow(uri, response["location"], redirects_left, retries_left)
|
|
45
|
+
when Net::HTTPServerError then retry_once(uri, redirects_left, retries_left)
|
|
46
|
+
else :unknown
|
|
47
|
+
end
|
|
48
|
+
rescue Timeout::Error
|
|
49
|
+
retry_once(uri, redirects_left, retries_left)
|
|
50
|
+
rescue *NETWORK_ERRORS
|
|
51
|
+
:unknown
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def retry_once(uri, redirects_left, retries_left)
|
|
55
|
+
return :unknown unless retries_left.positive?
|
|
56
|
+
|
|
57
|
+
fetch_status(uri, redirects_left, retries_left - 1)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def follow(uri, location, redirects_left, retries_left)
|
|
61
|
+
return :unknown if redirects_left.zero? || location.nil?
|
|
62
|
+
|
|
63
|
+
fetch_status(uri.merge(location), redirects_left - 1, retries_left)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def head(uri)
|
|
67
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: true,
|
|
68
|
+
open_timeout: @timeout, read_timeout: @timeout,
|
|
69
|
+
ssl_timeout: @timeout) do |http|
|
|
70
|
+
request = Net::HTTP::Head.new(uri)
|
|
71
|
+
request["Accept"] = "application/rdap+json"
|
|
72
|
+
request["User-Agent"] = "docheck/#{VERSION} (+https://github.com/kuntoaji/docheck)"
|
|
73
|
+
http.request(request)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
data/lib/docheck/name.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docheck
|
|
4
|
+
# Validates the second-level name that Docheck appends each TLD to.
|
|
5
|
+
module Name
|
|
6
|
+
# One LDH (letter, digit, hyphen) label of 1 to 63 characters that does
|
|
7
|
+
# not start or end with a hyphen. IDNs must be passed in punycode (xn--).
|
|
8
|
+
LABEL = /\A[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\z/
|
|
9
|
+
|
|
10
|
+
# Returns +name+ stripped and downcased, or raises InvalidNameError.
|
|
11
|
+
def self.normalize(name)
|
|
12
|
+
label = name.to_s.strip.downcase
|
|
13
|
+
return label if LABEL.match?(label)
|
|
14
|
+
|
|
15
|
+
raise InvalidNameError,
|
|
16
|
+
"#{name.to_s.inspect} is not a valid domain name label " \
|
|
17
|
+
"(1-63 letters, digits, or hyphens, no leading or trailing hyphen)"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docheck
|
|
4
|
+
# The availability of one domain name.
|
|
5
|
+
#
|
|
6
|
+
# +status+ is one of:
|
|
7
|
+
# - +:available+: the registry has no record of the domain
|
|
8
|
+
# - +:registered+: the registry has a record of the domain
|
|
9
|
+
# - +:unknown+: the lookup failed (timeout, rate limit, or server error)
|
|
10
|
+
# - +:unsupported+: the TLD has no RDAP server in the bootstrap data
|
|
11
|
+
Result = Data.define(:domain, :status) do
|
|
12
|
+
def initialize(domain:, status:)
|
|
13
|
+
raise ArgumentError, "unknown status: #{status.inspect}" unless Result::STATUSES.include?(status)
|
|
14
|
+
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def available? = status == :available
|
|
19
|
+
def registered? = status == :registered
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Result::STATUSES = %i[available registered unknown unsupported].freeze
|
|
23
|
+
end
|
data/lib/docheck/version.rb
CHANGED
data/lib/docheck.rb
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
require_relative "docheck/version"
|
|
4
|
+
require_relative "docheck/errors"
|
|
5
|
+
require_relative "docheck/name"
|
|
6
|
+
require_relative "docheck/result"
|
|
7
|
+
require_relative "docheck/bootstrap"
|
|
8
|
+
require_relative "docheck/http_client"
|
|
9
|
+
require_relative "docheck/checker"
|
|
10
|
+
require_relative "docheck/application"
|
|
11
|
+
|
|
12
|
+
# Domain name availability checker built on RDAP.
|
|
13
|
+
module Docheck
|
|
14
|
+
# Checks +name+ against the default TLDs. See Checker#check.
|
|
15
|
+
def self.check(name)
|
|
16
|
+
Checker.new.check(name)
|
|
17
|
+
end
|
|
18
|
+
end
|
metadata
CHANGED
|
@@ -1,70 +1,47 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docheck
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kunto Aji Kristianto
|
|
8
|
-
|
|
9
|
-
bindir: bin
|
|
8
|
+
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - '='
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 3.6.5
|
|
20
|
-
type: :runtime
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - '='
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: 3.6.5
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: shoulda
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: 3.6.0
|
|
34
|
-
type: :development
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: 3.6.0
|
|
41
|
-
description: " Domain name availability checker.\n"
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Checks whether a domain name is available or registered across generic
|
|
13
|
+
TLDs, using RDAP.
|
|
42
14
|
email: kuntoaji@kaklabs.com
|
|
43
15
|
executables:
|
|
44
16
|
- docheck
|
|
45
17
|
extensions: []
|
|
46
18
|
extra_rdoc_files:
|
|
47
|
-
- README.rdoc
|
|
48
19
|
- LICENSE
|
|
20
|
+
- README.rdoc
|
|
49
21
|
files:
|
|
50
|
-
-
|
|
51
|
-
- Gemfile
|
|
52
|
-
- Gemfile.lock
|
|
22
|
+
- CHANGELOG.md
|
|
53
23
|
- LICENSE
|
|
54
24
|
- README.rdoc
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
- docheck.gemspec
|
|
25
|
+
- data/rdap_dns.json
|
|
26
|
+
- exe/docheck
|
|
58
27
|
- lib/docheck.rb
|
|
59
28
|
- lib/docheck/application.rb
|
|
60
|
-
- lib/docheck/
|
|
29
|
+
- lib/docheck/bootstrap.rb
|
|
30
|
+
- lib/docheck/checker.rb
|
|
31
|
+
- lib/docheck/cli.rb
|
|
32
|
+
- lib/docheck/errors.rb
|
|
33
|
+
- lib/docheck/http_client.rb
|
|
34
|
+
- lib/docheck/name.rb
|
|
35
|
+
- lib/docheck/result.rb
|
|
61
36
|
- lib/docheck/version.rb
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
37
|
+
homepage: https://github.com/kuntoaji/docheck
|
|
38
|
+
licenses:
|
|
39
|
+
- MIT
|
|
40
|
+
metadata:
|
|
41
|
+
source_code_uri: https://github.com/kuntoaji/docheck
|
|
42
|
+
changelog_uri: https://github.com/kuntoaji/docheck/blob/master/CHANGELOG.md
|
|
43
|
+
bug_tracker_uri: https://github.com/kuntoaji/docheck/issues
|
|
44
|
+
rubygems_mfa_required: 'true'
|
|
68
45
|
rdoc_options:
|
|
69
46
|
- "--main"
|
|
70
47
|
- README.rdoc
|
|
@@ -74,15 +51,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
74
51
|
requirements:
|
|
75
52
|
- - ">="
|
|
76
53
|
- !ruby/object:Gem::Version
|
|
77
|
-
version:
|
|
54
|
+
version: '3.2'
|
|
78
55
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
56
|
requirements:
|
|
80
57
|
- - ">="
|
|
81
58
|
- !ruby/object:Gem::Version
|
|
82
59
|
version: '0'
|
|
83
60
|
requirements: []
|
|
84
|
-
rubygems_version:
|
|
85
|
-
signing_key:
|
|
61
|
+
rubygems_version: 4.0.20
|
|
86
62
|
specification_version: 4
|
|
87
63
|
summary: Domain name availability checker
|
|
88
64
|
test_files: []
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
docheck (1.1.2)
|
|
5
|
-
whois (= 3.6.5)
|
|
6
|
-
|
|
7
|
-
GEM
|
|
8
|
-
remote: http://rubygems.org/
|
|
9
|
-
specs:
|
|
10
|
-
activesupport (5.2.3)
|
|
11
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
12
|
-
i18n (>= 0.7, < 2)
|
|
13
|
-
minitest (~> 5.1)
|
|
14
|
-
tzinfo (~> 1.1)
|
|
15
|
-
concurrent-ruby (1.1.5)
|
|
16
|
-
i18n (1.6.0)
|
|
17
|
-
concurrent-ruby (~> 1.0)
|
|
18
|
-
minitest (5.11.3)
|
|
19
|
-
shoulda (3.6.0)
|
|
20
|
-
shoulda-context (~> 1.0, >= 1.0.1)
|
|
21
|
-
shoulda-matchers (~> 3.0)
|
|
22
|
-
shoulda-context (1.2.2)
|
|
23
|
-
shoulda-matchers (3.1.3)
|
|
24
|
-
activesupport (>= 4.0.0)
|
|
25
|
-
thread_safe (0.3.6)
|
|
26
|
-
tzinfo (1.2.5)
|
|
27
|
-
thread_safe (~> 0.1)
|
|
28
|
-
whois (3.6.5)
|
|
29
|
-
activesupport (>= 3)
|
|
30
|
-
|
|
31
|
-
PLATFORMS
|
|
32
|
-
ruby
|
|
33
|
-
|
|
34
|
-
DEPENDENCIES
|
|
35
|
-
docheck!
|
|
36
|
-
shoulda (~> 3.6.0)
|
|
37
|
-
|
|
38
|
-
BUNDLED WITH
|
|
39
|
-
1.17.2
|
data/Rakefile
DELETED
data/bin/docheck
DELETED
data/docheck.gemspec
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
-
require "docheck/version"
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |s|
|
|
6
|
-
s.name = "docheck"
|
|
7
|
-
s.version = Docheck::VERSION
|
|
8
|
-
s.platform = Gem::Platform::RUBY
|
|
9
|
-
s.authors = "Kunto Aji Kristianto"
|
|
10
|
-
s.email = 'kuntoaji@kaklabs.com'
|
|
11
|
-
s.homepage = "http://github.com/kuntoaji/docheck"
|
|
12
|
-
s.summary = 'Domain name availability checker'
|
|
13
|
-
s.description = <<-EOF
|
|
14
|
-
Domain name availability checker.
|
|
15
|
-
EOF
|
|
16
|
-
|
|
17
|
-
s.files = `git ls-files`.split("\n")
|
|
18
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
20
|
-
s.require_paths = ["lib"]
|
|
21
|
-
|
|
22
|
-
s.rdoc_options = ['--main', 'README.rdoc']
|
|
23
|
-
s.extra_rdoc_files = ['README.rdoc', 'LICENSE']
|
|
24
|
-
|
|
25
|
-
s.required_ruby_version = '>= 1.9.2'
|
|
26
|
-
s.add_dependency('whois', '3.6.5')
|
|
27
|
-
s.add_development_dependency('shoulda', '~> 3.6.0')
|
|
28
|
-
end
|
data/lib/docheck/command.rb
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
begin
|
|
2
|
-
require File.expand_path('../../docheck.rb', __FILE__)
|
|
3
|
-
rescue LoadError
|
|
4
|
-
require 'rubygems'
|
|
5
|
-
require File.expand_path('../../docheck.rb', __FILE__)
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
require 'optparse'
|
|
9
|
-
|
|
10
|
-
begin
|
|
11
|
-
OptionParser.new do |opts|
|
|
12
|
-
opts.banner = "Usage: docheck -n [basename]. Example: docheck -n google"
|
|
13
|
-
|
|
14
|
-
opts.on("-v", "--version", "Show version") do
|
|
15
|
-
puts "Docheck #{Docheck::VERSION}"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
opts.on("-n", "--name NAME", "Execute domain name checker") do |name|
|
|
19
|
-
Docheck::Application.new(name).print
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
opts.on_tail("-h", "--help", "Show help") do
|
|
23
|
-
puts opts
|
|
24
|
-
exit
|
|
25
|
-
end
|
|
26
|
-
end.parse!
|
|
27
|
-
rescue OptionParser::InvalidOption
|
|
28
|
-
puts "Invalid option"
|
|
29
|
-
rescue OptionParser::MissingArgument
|
|
30
|
-
puts "Missing argument"
|
|
31
|
-
end
|