nomius 0.1.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 +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
|