nomius 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.dockerignore +5 -0
- data/.editorconfig +12 -0
- data/.overcommit.yml +29 -0
- data/.rspec +3 -0
- data/.rubocop.yml +27 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +133 -0
- data/CONTRIBUTING.md +63 -0
- data/Dockerfile +11 -0
- data/Gemfile +20 -0
- data/LICENSE +21 -0
- data/README.md +297 -0
- data/Rakefile +12 -0
- data/exe/nomius +6 -0
- data/lib/nomius/bulk_checker.rb +39 -0
- data/lib/nomius/checker.rb +30 -0
- data/lib/nomius/cli/command.rb +106 -0
- data/lib/nomius/cli/parser/file_parser/csv_parser.rb +31 -0
- data/lib/nomius/cli/parser/file_parser/txt_parser.rb +40 -0
- data/lib/nomius/cli/parser/file_parser.rb +27 -0
- data/lib/nomius/cli/parser/strings_parser.rb +37 -0
- data/lib/nomius/cli/parser.rb +22 -0
- data/lib/nomius/cli/runner.rb +42 -0
- data/lib/nomius/cli/writer/console_writer.rb +68 -0
- data/lib/nomius/cli/writer/csv_writer.rb +51 -0
- data/lib/nomius/cli.rb +24 -0
- data/lib/nomius/detector/base_domain_name_detector.rb +86 -0
- data/lib/nomius/detector/base_url_detector.rb +46 -0
- data/lib/nomius/detector/dockerhub_detector.rb +26 -0
- data/lib/nomius/detector/domain_com_detector.rb +15 -0
- data/lib/nomius/detector/domain_org_detector.rb +15 -0
- data/lib/nomius/detector/github_detector.rb +26 -0
- data/lib/nomius/detector/npmjs_detector.rb +26 -0
- data/lib/nomius/detector/pypi_detector.rb +26 -0
- data/lib/nomius/detector/rubygems_detector.rb +26 -0
- data/lib/nomius/detector/util/http_requester.rb +78 -0
- data/lib/nomius/detector.rb +28 -0
- data/lib/nomius/logger/silent.rb +31 -0
- data/lib/nomius/logger/verbose.rb +47 -0
- data/lib/nomius/logger.rb +18 -0
- data/lib/nomius/name.rb +26 -0
- data/lib/nomius/status/available.rb +22 -0
- data/lib/nomius/status/base.rb +16 -0
- data/lib/nomius/status/formatter/ascii_mark.rb +24 -0
- data/lib/nomius/status/formatter/mark.rb +24 -0
- data/lib/nomius/status/unavailable.rb +22 -0
- data/lib/nomius/status/unresolved.rb +22 -0
- data/lib/nomius/status.rb +5 -0
- data/lib/nomius/version.rb +5 -0
- data/lib/nomius.rb +13 -0
- metadata +229 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "checker"
|
4
|
+
require_relative "detector"
|
5
|
+
require_relative "name"
|
6
|
+
require_relative "logger/silent"
|
7
|
+
require_relative "status/formatter/mark"
|
8
|
+
|
9
|
+
module Nomius
|
10
|
+
# BulkChecker
|
11
|
+
class BulkChecker
|
12
|
+
RESULT = Struct.new(:name, :results, keyword_init: true)
|
13
|
+
|
14
|
+
attr_reader :names, :detectors, :logger
|
15
|
+
|
16
|
+
def self.check(*args, **kwargs)
|
17
|
+
new(*args, **kwargs).check
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(names: [], detectors: Detector.all, logger: Logger::Silent.new)
|
21
|
+
@names = names.compact.map { |name| Name.for(name) }
|
22
|
+
@detectors = detectors
|
23
|
+
@logger = logger
|
24
|
+
end
|
25
|
+
|
26
|
+
def check
|
27
|
+
logger.start_batch_processing(names.count)
|
28
|
+
|
29
|
+
names.map do |name|
|
30
|
+
logger.batch_record_processing(name) do
|
31
|
+
RESULT.new(
|
32
|
+
name: name,
|
33
|
+
results: Checker.check(name: name, detectors: detectors, logger: logger)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "detector"
|
4
|
+
require_relative "name"
|
5
|
+
require_relative "logger/silent"
|
6
|
+
|
7
|
+
module Nomius
|
8
|
+
# Checker
|
9
|
+
class Checker
|
10
|
+
attr_reader :name, :detectors, :logger
|
11
|
+
|
12
|
+
def self.check(*args, **kwargs)
|
13
|
+
new(*args, **kwargs).check
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(name:, detectors: Detector.all, logger: Logger::Silent.new)
|
17
|
+
@name = Name.for(name)
|
18
|
+
@detectors = detectors
|
19
|
+
@logger = logger
|
20
|
+
end
|
21
|
+
|
22
|
+
def check
|
23
|
+
detectors.map do |detector|
|
24
|
+
logger.log_detector_status do
|
25
|
+
detector.status(name: name, logger: logger)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tty-option"
|
4
|
+
require_relative "../version"
|
5
|
+
|
6
|
+
module Nomius
|
7
|
+
class CLI
|
8
|
+
# Console options parser
|
9
|
+
class Command
|
10
|
+
include TTY::Option
|
11
|
+
|
12
|
+
usage do
|
13
|
+
program "nomius"
|
14
|
+
no_command
|
15
|
+
desc "Nomius — bulk domain & package name availability checker."
|
16
|
+
example <<~DESCRIPTION
|
17
|
+
Basic usage
|
18
|
+
Check "firstname" and "othername" names.
|
19
|
+
$ nomius firstname othername
|
20
|
+
|
21
|
+
Usage with a TXT file
|
22
|
+
$ nomius --input names.txt
|
23
|
+
or
|
24
|
+
$ cat names.txt | nomius
|
25
|
+
or
|
26
|
+
$ nomius < names.txt
|
27
|
+
|
28
|
+
Usage with a CSV file
|
29
|
+
$ nomius --input names.csv
|
30
|
+
|
31
|
+
Usage with a CSV file and output to a CSV file
|
32
|
+
$ nomius --input names.csv --output results.csv
|
33
|
+
DESCRIPTION
|
34
|
+
end
|
35
|
+
|
36
|
+
flag :help do
|
37
|
+
short "-h"
|
38
|
+
long "--help"
|
39
|
+
desc "Print usage"
|
40
|
+
end
|
41
|
+
|
42
|
+
flag :silent do
|
43
|
+
short "-s"
|
44
|
+
long "--silent"
|
45
|
+
desc "Print less output"
|
46
|
+
end
|
47
|
+
|
48
|
+
flag :version do
|
49
|
+
long "--version"
|
50
|
+
desc "Print version"
|
51
|
+
end
|
52
|
+
|
53
|
+
option :input do
|
54
|
+
short "-i"
|
55
|
+
long "--input string"
|
56
|
+
desc <<~DESCRIPTION
|
57
|
+
Input file. Could be:
|
58
|
+
- TXT with each name on a separate line;
|
59
|
+
- CSV file with 2 columns: "name","comment" ("comment" is optional).
|
60
|
+
DESCRIPTION
|
61
|
+
end
|
62
|
+
|
63
|
+
option :output do
|
64
|
+
short "-o"
|
65
|
+
long "--output string"
|
66
|
+
desc "Output CSV file"
|
67
|
+
end
|
68
|
+
|
69
|
+
argument :names do
|
70
|
+
arity zero_or_more
|
71
|
+
# Read from STDIN to support piping.
|
72
|
+
default -> { $stdin.tty? ? [] : $stdin.each_line.to_a }
|
73
|
+
convert :list
|
74
|
+
end
|
75
|
+
|
76
|
+
def run
|
77
|
+
check_help!
|
78
|
+
check_version!
|
79
|
+
check_input!
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def check_help!
|
85
|
+
return unless params[:help]
|
86
|
+
|
87
|
+
print help
|
88
|
+
exit
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_version!
|
92
|
+
return unless params[:version]
|
93
|
+
|
94
|
+
puts Nomius::VERSION
|
95
|
+
exit
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_input!
|
99
|
+
return unless params[:names].empty? && params[:input].nil?
|
100
|
+
|
101
|
+
print help
|
102
|
+
exit(1)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "csv"
|
4
|
+
require_relative "../../../name"
|
5
|
+
|
6
|
+
module Nomius
|
7
|
+
class CLI
|
8
|
+
class Parser
|
9
|
+
class FileParser
|
10
|
+
# Parser for CSV files
|
11
|
+
class CSVParser
|
12
|
+
attr_reader :file_name
|
13
|
+
|
14
|
+
def self.names(file_name:)
|
15
|
+
new(file_name: file_name).names
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(file_name:)
|
19
|
+
@file_name = file_name
|
20
|
+
end
|
21
|
+
|
22
|
+
def names
|
23
|
+
CSV.read(file_name, skip_blanks: true, liberal_parsing: true).map do |name, comment|
|
24
|
+
Name.new(name: name, comment: comment)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../../name"
|
4
|
+
|
5
|
+
module Nomius
|
6
|
+
class CLI
|
7
|
+
class Parser
|
8
|
+
class FileParser
|
9
|
+
# Parser for TXT files
|
10
|
+
class TXTParser
|
11
|
+
attr_reader :file_name
|
12
|
+
|
13
|
+
def self.names(file_name:)
|
14
|
+
new(file_name: file_name).names
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(file_name:)
|
18
|
+
@file_name = file_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def names
|
22
|
+
cleared_names.map do |name|
|
23
|
+
Name.new(name: name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def cleared_names
|
30
|
+
File
|
31
|
+
.readlines(file_name)
|
32
|
+
.reject { |name| name.strip.empty? }
|
33
|
+
.sort
|
34
|
+
.uniq
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../name"
|
4
|
+
require_relative "file_parser/txt_parser"
|
5
|
+
require_relative "file_parser/csv_parser"
|
6
|
+
|
7
|
+
module Nomius
|
8
|
+
class CLI
|
9
|
+
class Parser
|
10
|
+
# Parser for files
|
11
|
+
class FileParser
|
12
|
+
FALLBACK_PARSER = TXTParser
|
13
|
+
|
14
|
+
PARSER_BY_FILE_EXTENSION = {
|
15
|
+
".csv" => CSVParser
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
def self.names(file_name:, **_kwargs)
|
19
|
+
PARSER_BY_FILE_EXTENSION
|
20
|
+
.fetch(File.extname(file_name), FALLBACK_PARSER)
|
21
|
+
.new(file_name: file_name)
|
22
|
+
.names
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../name"
|
4
|
+
|
5
|
+
module Nomius
|
6
|
+
class CLI
|
7
|
+
class Parser
|
8
|
+
# Parser for array of strings
|
9
|
+
class StringsParser
|
10
|
+
def self.names(strings:, **_kwargs)
|
11
|
+
new(strings: strings).names
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(strings:, **_kwargs)
|
15
|
+
@strings = strings
|
16
|
+
end
|
17
|
+
|
18
|
+
def names
|
19
|
+
cleared_names.map do |name|
|
20
|
+
Name.new(name: name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :strings
|
27
|
+
|
28
|
+
def cleared_names
|
29
|
+
strings
|
30
|
+
.reject { |name| name.strip.empty? }
|
31
|
+
.sort
|
32
|
+
.uniq
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "parser/file_parser"
|
4
|
+
require_relative "parser/strings_parser"
|
5
|
+
|
6
|
+
module Nomius
|
7
|
+
class CLI
|
8
|
+
# ParserChooser
|
9
|
+
class Parser
|
10
|
+
PARSER_BY_INPUT_FILE_PRESENCE = {
|
11
|
+
true => FileParser,
|
12
|
+
false => StringsParser
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
def self.names(file_name: nil, strings: [])
|
16
|
+
PARSER_BY_INPUT_FILE_PRESENCE
|
17
|
+
.fetch(!file_name.nil?)
|
18
|
+
.names(file_name: file_name, strings: strings)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "parser"
|
4
|
+
require_relative "writer/console_writer"
|
5
|
+
require_relative "writer/csv_writer"
|
6
|
+
require_relative "../bulk_checker"
|
7
|
+
require_relative "../logger"
|
8
|
+
|
9
|
+
module Nomius
|
10
|
+
class CLI
|
11
|
+
# CLI Runner
|
12
|
+
class Runner
|
13
|
+
attr_reader :names, :silent, :input, :output
|
14
|
+
|
15
|
+
def self.run(*args, **kwargs)
|
16
|
+
new(*args, **kwargs).run
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(names: [], silent: false, input: nil, output: nil)
|
20
|
+
@names = names
|
21
|
+
@silent = silent
|
22
|
+
@input = input
|
23
|
+
@output = output
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
logger = Logger.for(silent: silent)
|
28
|
+
writers = [Writer::ConsoleWriter]
|
29
|
+
writers << Writer::CSVWriter if output
|
30
|
+
|
31
|
+
results = BulkChecker.check(
|
32
|
+
names: Parser.names(file_name: input, strings: names),
|
33
|
+
logger: logger
|
34
|
+
)
|
35
|
+
|
36
|
+
writers.each do |writer|
|
37
|
+
writer.write!(results: results, file_name: output)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tty-table"
|
4
|
+
require_relative "../../status/formatter/mark"
|
5
|
+
|
6
|
+
module Nomius
|
7
|
+
class CLI
|
8
|
+
class Writer
|
9
|
+
# ConsoleWriter
|
10
|
+
class ConsoleWriter
|
11
|
+
attr_reader :results
|
12
|
+
|
13
|
+
TTY_TABLE_WIDTH = {
|
14
|
+
"fixed" => 80,
|
15
|
+
"flexible" => nil
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
TTY_TABLE_OPTIONS = {
|
19
|
+
padding: [0, 1],
|
20
|
+
multiline: true,
|
21
|
+
width: TTY_TABLE_WIDTH.fetch(ENV.fetch("TTY_TABLE_WIDTH", "flexible"))
|
22
|
+
}.compact.freeze
|
23
|
+
|
24
|
+
def self.write!(*args, **kwargs)
|
25
|
+
new(*args, **kwargs).write!
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(results: [], **_kwargs)
|
29
|
+
@results = results
|
30
|
+
end
|
31
|
+
|
32
|
+
def write!
|
33
|
+
table = TTY::Table.new(headers, rows)
|
34
|
+
renderer = TTY::Table::Renderer::Unicode.new(table, TTY_TABLE_OPTIONS)
|
35
|
+
|
36
|
+
puts renderer.render
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def headers
|
42
|
+
[
|
43
|
+
"Name",
|
44
|
+
*results.first.results.map(&:detector).map(&:detector_short_name),
|
45
|
+
"Comment"
|
46
|
+
]
|
47
|
+
end
|
48
|
+
|
49
|
+
def rows
|
50
|
+
results.map do |result|
|
51
|
+
[
|
52
|
+
result.name.name,
|
53
|
+
*result.results.map { |status| status_mark_cell(status) },
|
54
|
+
result.name.comment
|
55
|
+
]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def status_mark_cell(status)
|
60
|
+
{
|
61
|
+
value: Status::Formatter::Mark.for(status),
|
62
|
+
alignment: :center
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "csv"
|
4
|
+
require_relative "../../status/formatter/ascii_mark"
|
5
|
+
|
6
|
+
module Nomius
|
7
|
+
class CLI
|
8
|
+
class Writer
|
9
|
+
# CSVWriter
|
10
|
+
class CSVWriter
|
11
|
+
attr_reader :results, :file_name
|
12
|
+
|
13
|
+
def self.write!(*args, **kwargs)
|
14
|
+
new(*args, **kwargs).write!
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(file_name:, results: [], **_kwargs)
|
18
|
+
@results = results
|
19
|
+
@file_name = file_name
|
20
|
+
end
|
21
|
+
|
22
|
+
def write!
|
23
|
+
CSV.open(file_name, "w") do |f|
|
24
|
+
f << headers
|
25
|
+
rows.each { |row| f << row }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def headers
|
32
|
+
[
|
33
|
+
"Name",
|
34
|
+
"Comment",
|
35
|
+
*results.first.results.map(&:detector).map(&:detector_name)
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
def rows
|
40
|
+
results.map do |result|
|
41
|
+
[
|
42
|
+
result.name.name,
|
43
|
+
result.name.comment,
|
44
|
+
*result.results.map { |status| Status::Formatter::ASCIIMark.for(status) }
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/nomius/cli.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "cli/command"
|
4
|
+
require_relative "cli/runner"
|
5
|
+
|
6
|
+
module Nomius
|
7
|
+
# CLI
|
8
|
+
class CLI
|
9
|
+
attr_reader :names, :silent, :input, :output
|
10
|
+
|
11
|
+
def self.run(args = ARGV)
|
12
|
+
cmd = Command.new.parse(args)
|
13
|
+
cmd.run
|
14
|
+
params = cmd.params
|
15
|
+
|
16
|
+
Runner.run(
|
17
|
+
names: params[:names],
|
18
|
+
silent: params[:silent],
|
19
|
+
input: params[:input],
|
20
|
+
output: params[:output]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "resolv"
|
4
|
+
require "retriable"
|
5
|
+
require "whois"
|
6
|
+
require "whois-parser"
|
7
|
+
require_relative "../status"
|
8
|
+
|
9
|
+
module Nomius
|
10
|
+
class Detector
|
11
|
+
# Detects domain is taken.
|
12
|
+
# Works in 2 steps:
|
13
|
+
# 1. Resolve DNS A record.
|
14
|
+
# 2. If there is no A record, check WHOIS record.
|
15
|
+
class BaseDomainNameDetector
|
16
|
+
# NOTE: OpenDNS servers (https://www.opendns.com/)
|
17
|
+
NANE_SERVERS = ["208.67.222.222", "208.67.220.220"].freeze
|
18
|
+
|
19
|
+
STATUS_RESOLVER = {
|
20
|
+
true => Status::Available,
|
21
|
+
false => Status::Unavailable
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
attr_reader :name, :logger
|
25
|
+
|
26
|
+
def self.status(*args, **kwargs)
|
27
|
+
new(*args, **kwargs).status
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(name:, logger: Logger::Silent)
|
31
|
+
@name = name
|
32
|
+
@logger = logger
|
33
|
+
end
|
34
|
+
|
35
|
+
def tld
|
36
|
+
".org"
|
37
|
+
end
|
38
|
+
|
39
|
+
def detector_name
|
40
|
+
"#{name.name}#{tld}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def detector_short_name
|
44
|
+
tld
|
45
|
+
end
|
46
|
+
|
47
|
+
def status
|
48
|
+
status_class.new(name: name, detector: self)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def status_class
|
54
|
+
STATUS_RESOLVER.fetch(availabile_by_dns? && availabile_by_whois?)
|
55
|
+
rescue Whois::ConnectionError, Whois::ParserError, Timeout::Error => e
|
56
|
+
logger.log_error(message: "Can't resolve: #{full_domain_name}", detalis: e.message)
|
57
|
+
Status::Unresolved
|
58
|
+
end
|
59
|
+
|
60
|
+
def full_domain_name
|
61
|
+
"#{name.name}#{tld}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def availabile_by_dns?
|
65
|
+
Resolv::DNS
|
66
|
+
.new(nameserver: NANE_SERVERS)
|
67
|
+
.getresources(Resolv::DNS::Name.create(full_domain_name), Resolv::DNS::Resource::IN::SOA)
|
68
|
+
.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
def availabile_by_whois?
|
72
|
+
Retriable.retriable(
|
73
|
+
on: [Whois::ConnectionError, Timeout::Error],
|
74
|
+
tries: 6, multiplier: 2, base_interval: 1
|
75
|
+
) do
|
76
|
+
Whois.whois(full_domain_name).parser.available?
|
77
|
+
end
|
78
|
+
rescue Whois::ParserError => e
|
79
|
+
# NOTE: Hotfix for whois-parser broken parser for .org.
|
80
|
+
return true if e.message.include?("Domain not found")
|
81
|
+
|
82
|
+
raise e
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../status"
|
4
|
+
require_relative "util/http_requester"
|
5
|
+
module Nomius
|
6
|
+
class Detector
|
7
|
+
# Base class for detectors.
|
8
|
+
class BaseURLDetector
|
9
|
+
STATUS_RESOLVER = {
|
10
|
+
Util::HTTPRequester::NotFound => Status::Available,
|
11
|
+
Util::HTTPRequester::OK => Status::Unavailable,
|
12
|
+
Util::HTTPRequester::Unresolved => Status::Unresolved
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
attr_reader :name, :logger
|
16
|
+
|
17
|
+
def self.status(*args, **kwargs)
|
18
|
+
new(*args, **kwargs).status
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(name:, logger: Logger::Silent, http_requester: Util::HTTPRequester)
|
22
|
+
@name = name
|
23
|
+
@logger = logger
|
24
|
+
@http_requester = http_requester
|
25
|
+
end
|
26
|
+
|
27
|
+
def detector_name
|
28
|
+
"Undefined"
|
29
|
+
end
|
30
|
+
|
31
|
+
def detector_short_name
|
32
|
+
"Undefined"
|
33
|
+
end
|
34
|
+
|
35
|
+
def status
|
36
|
+
STATUS_RESOLVER
|
37
|
+
.fetch(http_requester.response_status(uri: uri, logger: logger))
|
38
|
+
.new(name: name, detector: self)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
attr_reader :http_requester
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base_url_detector"
|
4
|
+
|
5
|
+
module Nomius
|
6
|
+
class Detector
|
7
|
+
# Check name availability for https://hub.docker.com/
|
8
|
+
class DockerhubDetector < BaseURLDetector
|
9
|
+
BASE_URL = "https://hub.docker.com/v2/orgs"
|
10
|
+
|
11
|
+
def detector_name
|
12
|
+
"hub.docker.com"
|
13
|
+
end
|
14
|
+
|
15
|
+
def detector_short_name
|
16
|
+
"Docker"
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def uri
|
22
|
+
"#{BASE_URL}/#{name.name}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
require_relative "base_domain_name_detector"
|
5
|
+
|
6
|
+
module Nomius
|
7
|
+
class Detector
|
8
|
+
# Check .com domain name availability
|
9
|
+
class DomainComDetector < BaseDomainNameDetector
|
10
|
+
def tld
|
11
|
+
".com"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|