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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +5 -0
  3. data/.editorconfig +12 -0
  4. data/.overcommit.yml +29 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +27 -0
  7. data/CHANGELOG.md +5 -0
  8. data/CODE_OF_CONDUCT.md +133 -0
  9. data/CONTRIBUTING.md +63 -0
  10. data/Dockerfile +11 -0
  11. data/Gemfile +20 -0
  12. data/LICENSE +21 -0
  13. data/README.md +297 -0
  14. data/Rakefile +12 -0
  15. data/exe/nomius +6 -0
  16. data/lib/nomius/bulk_checker.rb +39 -0
  17. data/lib/nomius/checker.rb +30 -0
  18. data/lib/nomius/cli/command.rb +106 -0
  19. data/lib/nomius/cli/parser/file_parser/csv_parser.rb +31 -0
  20. data/lib/nomius/cli/parser/file_parser/txt_parser.rb +40 -0
  21. data/lib/nomius/cli/parser/file_parser.rb +27 -0
  22. data/lib/nomius/cli/parser/strings_parser.rb +37 -0
  23. data/lib/nomius/cli/parser.rb +22 -0
  24. data/lib/nomius/cli/runner.rb +42 -0
  25. data/lib/nomius/cli/writer/console_writer.rb +68 -0
  26. data/lib/nomius/cli/writer/csv_writer.rb +51 -0
  27. data/lib/nomius/cli.rb +24 -0
  28. data/lib/nomius/detector/base_domain_name_detector.rb +86 -0
  29. data/lib/nomius/detector/base_url_detector.rb +46 -0
  30. data/lib/nomius/detector/dockerhub_detector.rb +26 -0
  31. data/lib/nomius/detector/domain_com_detector.rb +15 -0
  32. data/lib/nomius/detector/domain_org_detector.rb +15 -0
  33. data/lib/nomius/detector/github_detector.rb +26 -0
  34. data/lib/nomius/detector/npmjs_detector.rb +26 -0
  35. data/lib/nomius/detector/pypi_detector.rb +26 -0
  36. data/lib/nomius/detector/rubygems_detector.rb +26 -0
  37. data/lib/nomius/detector/util/http_requester.rb +78 -0
  38. data/lib/nomius/detector.rb +28 -0
  39. data/lib/nomius/logger/silent.rb +31 -0
  40. data/lib/nomius/logger/verbose.rb +47 -0
  41. data/lib/nomius/logger.rb +18 -0
  42. data/lib/nomius/name.rb +26 -0
  43. data/lib/nomius/status/available.rb +22 -0
  44. data/lib/nomius/status/base.rb +16 -0
  45. data/lib/nomius/status/formatter/ascii_mark.rb +24 -0
  46. data/lib/nomius/status/formatter/mark.rb +24 -0
  47. data/lib/nomius/status/unavailable.rb +22 -0
  48. data/lib/nomius/status/unresolved.rb +22 -0
  49. data/lib/nomius/status.rb +5 -0
  50. data/lib/nomius/version.rb +5 -0
  51. data/lib/nomius.rb +13 -0
  52. metadata +229 -0
@@ -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 .org domain name availability
9
+ class DomainOrgDetector < BaseDomainNameDetector
10
+ def tld
11
+ ".org"
12
+ end
13
+ end
14
+ end
15
+ 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://github.com/
8
+ class GithubDetector < BaseURLDetector
9
+ BASE_URL = "https://github.com"
10
+
11
+ def detector_name
12
+ "GitHub.com"
13
+ end
14
+
15
+ def detector_short_name
16
+ "GH"
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,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://www.npmjs.com/
8
+ class NpmjsDetector < BaseURLDetector
9
+ BASE_URL = "https://registry.npmjs.org"
10
+
11
+ def detector_name
12
+ "NPMjs.com"
13
+ end
14
+
15
+ def detector_short_name
16
+ "npm"
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,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://pypi.org/
8
+ class PypiDetector < BaseURLDetector
9
+ BASE_URL = "https://pypi.org/project"
10
+
11
+ def detector_name
12
+ "PyPi.org"
13
+ end
14
+
15
+ def detector_short_name
16
+ "pip"
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,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://rubygems.org/
8
+ class RubygemsDetector < BaseURLDetector
9
+ BASE_URL = "https://rubygems.org/api/v1/gems"
10
+
11
+ def detector_name
12
+ "RubyGems.org"
13
+ end
14
+
15
+ def detector_short_name
16
+ "gem"
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,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "faraday/retry"
5
+ require "faraday/follow_redirects"
6
+
7
+ require_relative "../../version"
8
+
9
+ module Nomius
10
+ class Detector
11
+ class Util
12
+ # Encapsulates HTTP request handling.
13
+ # Using Faraday gem. But could be easily replaced with any other HTTP client.
14
+ class HTTPRequester
15
+ # rubocop:disable Lint/EmptyClass
16
+ class OK; end
17
+ class NotFound; end
18
+ class Unresolved; end
19
+ # rubocop:enable Lint/EmptyClass
20
+
21
+ HEADERS = {
22
+ "User-Agent" => "Nomius/#{Nomius::VERSION}"
23
+ }.freeze
24
+
25
+ FALLBACK_STATUS = Unresolved
26
+
27
+ RESPONSE_STATUS_RESOLVER = {
28
+ 200 => OK,
29
+ 404 => NotFound
30
+ }.freeze
31
+
32
+ RETRY_STATUSES = [
33
+ 400, 401, 403, 408, 409, 418, 425, 429,
34
+ 500, 502, 503, 504
35
+ ].freeze
36
+
37
+ RETRY_OPTIONS = {
38
+ max: 5,
39
+ interval: 1,
40
+ interval_randomness: 0.5,
41
+ backoff_factor: 2,
42
+ retry_statuses: RETRY_STATUSES
43
+ }.freeze
44
+
45
+ attr_reader :uri, :logger
46
+
47
+ def self.response_status(uri:, logger:)
48
+ new(uri: uri, logger: logger).response_status
49
+ end
50
+
51
+ def initialize(uri:, logger:)
52
+ @uri = uri.to_s
53
+ @logger = logger
54
+ end
55
+
56
+ def response_status
57
+ # HEAD request is used to avoid downloading the whole page.
58
+ response = connection.head
59
+
60
+ unless RESPONSE_STATUS_RESOLVER.key?(response.status)
61
+ logger.log_error(message: uri, details: response.to_hash.to_json)
62
+ end
63
+
64
+ RESPONSE_STATUS_RESOLVER.fetch(response.status, FALLBACK_STATUS)
65
+ end
66
+
67
+ private
68
+
69
+ def connection
70
+ @connection ||= Faraday.new(url: uri, headers: HEADERS) do |faraday|
71
+ faraday.request :retry, RETRY_OPTIONS
72
+ faraday.response :follow_redirects
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "detector/dockerhub_detector"
4
+ require_relative "detector/domain_com_detector"
5
+ require_relative "detector/domain_org_detector"
6
+ require_relative "detector/github_detector"
7
+ require_relative "detector/npmjs_detector"
8
+ require_relative "detector/pypi_detector"
9
+ require_relative "detector/rubygems_detector"
10
+
11
+ module Nomius
12
+ # Detectors
13
+ class Detector
14
+ DETECTORS = [
15
+ DomainComDetector,
16
+ DomainOrgDetector,
17
+ GithubDetector,
18
+ DockerhubDetector,
19
+ NpmjsDetector,
20
+ PypiDetector,
21
+ RubygemsDetector
22
+ ].freeze
23
+
24
+ def self.all
25
+ DETECTORS
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nomius
4
+ class Logger
5
+ # Silent logger
6
+ class Silent
7
+ def start_batch_processing(_count)
8
+ # Intentionally do nothing
9
+ end
10
+
11
+ def batch_record_processing(_name)
12
+ # Intentionally do nothing
13
+ yield
14
+ end
15
+
16
+ def log_detector_status
17
+ # Intentionally do nothing
18
+ yield
19
+ end
20
+
21
+ def log_info(_message)
22
+ # Intentionally do nothing
23
+ end
24
+
25
+ def log_error(message: "", details: "")
26
+ warn message
27
+ warn details
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-progressbar"
4
+ require_relative "../status/formatter/mark"
5
+
6
+ module Nomius
7
+ class Logger
8
+ # Verbose logger
9
+ class Verbose
10
+ def start_batch_processing(count)
11
+ @progress_bar = TTY::ProgressBar.new("[:bar] :current/:total ET::elapsed ETA::eta") do |config|
12
+ config.total = count
13
+ config.interval = 5
14
+ end
15
+ end
16
+
17
+ def batch_record_processing(name)
18
+ log_info("Processing #{name.name}...")
19
+ result = yield
20
+ log_info("")
21
+ progress_bar.advance
22
+
23
+ result
24
+ end
25
+
26
+ def log_detector_status
27
+ status = yield
28
+ log_info("#{status.detector.detector_short_name} #{Status::Formatter::Mark.for(status)}")
29
+
30
+ status
31
+ end
32
+
33
+ def log_info(message)
34
+ progress_bar.log(message)
35
+ end
36
+
37
+ def log_error(message: "", details: "")
38
+ warn message
39
+ warn details
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :progress_bar
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "logger/silent"
4
+ require_relative "logger/verbose"
5
+
6
+ module Nomius
7
+ # Logger factory
8
+ class Logger
9
+ LOGGER_BY_SILENT = {
10
+ true => Silent,
11
+ false => Verbose
12
+ }.freeze
13
+
14
+ def self.for(silent: false)
15
+ LOGGER_BY_SILENT.fetch(silent).new
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nomius
4
+ # Name object
5
+ class Name
6
+ attr_reader :name, :comment
7
+
8
+ def self.for(name)
9
+ return name if name.is_a?(self)
10
+
11
+ new(name: name.to_s)
12
+ end
13
+
14
+ def initialize(name:, comment: "")
15
+ @name = name.to_s.strip.downcase
16
+ @comment = comment.to_s.strip.downcase
17
+ validate!
18
+ end
19
+
20
+ private
21
+
22
+ def validate!
23
+ raise ArgumentError, "Name cannot be blank" if name.empty?
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Nomius
6
+ module Status
7
+ # Status for name available.
8
+ class Available < Base
9
+ def available?
10
+ true
11
+ end
12
+
13
+ def unavailalbe?
14
+ false
15
+ end
16
+
17
+ def unresolved?
18
+ false
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nomius
4
+ module Status
5
+ # Status for available domains.
6
+ class Base
7
+ attr_reader :name, :detector, :exception
8
+
9
+ def initialize(name:, detector:, exception: nil)
10
+ @name = name
11
+ @detector = detector
12
+ @exception = exception
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../available"
4
+ require_relative "../unavailable"
5
+ require_relative "../unresolved"
6
+
7
+ module Nomius
8
+ module Status
9
+ module Formatter
10
+ # Generate status text for Status
11
+ class ASCIIMark
12
+ STATUS_MAPPER = {
13
+ Status::Available => "+",
14
+ Status::Unavailable => "-",
15
+ Status::Unresolved => "?"
16
+ }.freeze
17
+
18
+ def self.for(status)
19
+ STATUS_MAPPER.fetch(status.class)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../available"
4
+ require_relative "../unavailable"
5
+ require_relative "../unresolved"
6
+
7
+ module Nomius
8
+ module Status
9
+ module Formatter
10
+ # Generate status mark for Status
11
+ class Mark
12
+ STATUS_MAPPER = {
13
+ Status::Available => "✅",
14
+ Status::Unavailable => "❌",
15
+ Status::Unresolved => "❓"
16
+ }.freeze
17
+
18
+ def self.for(status)
19
+ STATUS_MAPPER.fetch(status.class)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Nomius
6
+ module Status
7
+ # Status for name unavailable.
8
+ class Unavailable < Base
9
+ def available?
10
+ false
11
+ end
12
+
13
+ def unavailalbe?
14
+ true
15
+ end
16
+
17
+ def unresolved?
18
+ false
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Nomius
6
+ module Status
7
+ # Status for name availability unresolved. Should be checked manually.
8
+ class Unresolved < Base
9
+ def available?
10
+ false
11
+ end
12
+
13
+ def unavailalbe?
14
+ false
15
+ end
16
+
17
+ def unresolved?
18
+ true
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "status/available"
4
+ require_relative "status/unavailable"
5
+ require_relative "status/unresolved"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nomius
4
+ VERSION = "0.1.0"
5
+ end
data/lib/nomius.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "nomius/bulk_checker"
4
+ require_relative "nomius/checker"
5
+ require_relative "nomius/detector"
6
+ require_relative "nomius/logger"
7
+ require_relative "nomius/name"
8
+ require_relative "nomius/status"
9
+ require_relative "nomius/version"
10
+
11
+ # Nomius
12
+ module Nomius
13
+ end