neverbounce-cli 1.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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +8 -0
  3. data/.gitignore +21 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +1161 -0
  6. data/.travis.yml +27 -0
  7. data/.yardopts +2 -0
  8. data/Gemfile +19 -0
  9. data/Gemfile.lock +60 -0
  10. data/LICENSE +9 -0
  11. data/README.md +138 -0
  12. data/exe/nb-account-info +5 -0
  13. data/exe/nb-jobs-create +5 -0
  14. data/exe/nb-jobs-delete +5 -0
  15. data/exe/nb-jobs-download +5 -0
  16. data/exe/nb-jobs-parse +5 -0
  17. data/exe/nb-jobs-results +5 -0
  18. data/exe/nb-jobs-search +5 -0
  19. data/exe/nb-jobs-start +5 -0
  20. data/exe/nb-jobs-status +5 -0
  21. data/exe/nb-single-check +5 -0
  22. data/lib/never_bounce/cli/feature/basic_initialize.rb +20 -0
  23. data/lib/never_bounce/cli/feature/eigencache.rb +47 -0
  24. data/lib/never_bounce/cli/feature/envars/examples_mapper.rb +38 -0
  25. data/lib/never_bounce/cli/feature/envars/item.rb +41 -0
  26. data/lib/never_bounce/cli/feature/envars.rb +82 -0
  27. data/lib/never_bounce/cli/feature/igetset.rb +41 -0
  28. data/lib/never_bounce/cli/feature/require_attr.rb +25 -0
  29. data/lib/never_bounce/cli/script/account_info.rb +85 -0
  30. data/lib/never_bounce/cli/script/base.rb +101 -0
  31. data/lib/never_bounce/cli/script/error.rb +16 -0
  32. data/lib/never_bounce/cli/script/feature/requires_job_id.rb +28 -0
  33. data/lib/never_bounce/cli/script/feature/uses_pagination.rb +45 -0
  34. data/lib/never_bounce/cli/script/jobs_create/supplied_input_parser.rb +48 -0
  35. data/lib/never_bounce/cli/script/jobs_create.rb +157 -0
  36. data/lib/never_bounce/cli/script/jobs_delete.rb +55 -0
  37. data/lib/never_bounce/cli/script/jobs_download.rb +44 -0
  38. data/lib/never_bounce/cli/script/jobs_parse.rb +73 -0
  39. data/lib/never_bounce/cli/script/jobs_results.rb +105 -0
  40. data/lib/never_bounce/cli/script/jobs_search.rb +135 -0
  41. data/lib/never_bounce/cli/script/jobs_start.rb +73 -0
  42. data/lib/never_bounce/cli/script/jobs_status.rb +96 -0
  43. data/lib/never_bounce/cli/script/manifest.rb +22 -0
  44. data/lib/never_bounce/cli/script/meaningful.rb +233 -0
  45. data/lib/never_bounce/cli/script/request_maker.rb +169 -0
  46. data/lib/never_bounce/cli/script/single_check.rb +146 -0
  47. data/lib/never_bounce/cli/script/table.rb +43 -0
  48. data/lib/never_bounce/cli/user_config/file_content.rb +66 -0
  49. data/lib/never_bounce/cli/user_config.rb +51 -0
  50. data/lib/never_bounce/cli/version.rb +4 -0
  51. data/lib/neverbounce-cli.rb +3 -0
  52. data/neverbounce-cli.gemspec +24 -0
  53. data/spec/lib/never_bounce/cli/feature/basic_initialize_spec.rb +26 -0
  54. data/spec/lib/never_bounce/cli/feature/eigencache_spec.rb +28 -0
  55. data/spec/lib/never_bounce/cli/feature/envars/examples_mapper_spec.rb +26 -0
  56. data/spec/lib/never_bounce/cli/feature/envars/item_spec.rb +9 -0
  57. data/spec/lib/never_bounce/cli/feature/envars_spec.rb +55 -0
  58. data/spec/lib/never_bounce/cli/feature/igetset_spec.rb +45 -0
  59. data/spec/lib/never_bounce/cli/feature/require_attr_spec.rb +25 -0
  60. data/spec/lib/never_bounce/cli/script/account_info_spec.rb +65 -0
  61. data/spec/lib/never_bounce/cli/script/base_spec.rb +56 -0
  62. data/spec/lib/never_bounce/cli/script/feature/requires_job_id_spec.rb +17 -0
  63. data/spec/lib/never_bounce/cli/script/feature/uses_pagination_spec.rb +21 -0
  64. data/spec/lib/never_bounce/cli/script/jobs_create/supplied_input_parser_spec.rb +35 -0
  65. data/spec/lib/never_bounce/cli/script/jobs_create_spec.rb +118 -0
  66. data/spec/lib/never_bounce/cli/script/jobs_delete_spec.rb +33 -0
  67. data/spec/lib/never_bounce/cli/script/jobs_download_spec.rb +37 -0
  68. data/spec/lib/never_bounce/cli/script/jobs_parse_spec.rb +45 -0
  69. data/spec/lib/never_bounce/cli/script/jobs_results_spec.rb +40 -0
  70. data/spec/lib/never_bounce/cli/script/jobs_search_spec.rb +59 -0
  71. data/spec/lib/never_bounce/cli/script/jobs_start_spec.rb +45 -0
  72. data/spec/lib/never_bounce/cli/script/jobs_status_spec.rb +37 -0
  73. data/spec/lib/never_bounce/cli/script/manifest_spec.rb +6 -0
  74. data/spec/lib/never_bounce/cli/script/meaningful_spec.rb +93 -0
  75. data/spec/lib/never_bounce/cli/script/request_maker_spec.rb +67 -0
  76. data/spec/lib/never_bounce/cli/script/single_check_spec.rb +94 -0
  77. data/spec/lib/never_bounce/cli/script/spec_helper.rb +59 -0
  78. data/spec/lib/never_bounce/cli/script/table_spec.rb +6 -0
  79. data/spec/lib/never_bounce/cli/user_config/file_content_spec.rb +43 -0
  80. data/spec/lib/never_bounce/cli/user_config_spec.rb +12 -0
  81. data/spec/lib/never_bounce/cli_spec.rb +6 -0
  82. data/spec/spec_helper.rb +51 -0
  83. metadata +193 -0
@@ -0,0 +1,48 @@
1
+
2
+ require "never_bounce/cli/feature/basic_initialize"
3
+
4
+ require_relative "../jobs_create"
5
+
6
+ module NeverBounce; module CLI; module Script; class JobsCreate
7
+ # The parser for <tt>SUPPLIED_INPUT=</tt> environment variable.
8
+ # @see #process
9
+ # @see CLI::Feature::BasicInitialize
10
+ class SuppliedInputParser
11
+ CLI::Feature::BasicInitialize.load(self)
12
+
13
+ attr_writer :separator
14
+
15
+ # @return [Regexp]
16
+ def separator
17
+ @separator ||= /[;,\n]/
18
+ end
19
+
20
+ #---------------------------------------
21
+
22
+ # Process content, return parsed structure.
23
+ #
24
+ # NOTE: The parser doesn't validate e-mail addresses.
25
+ #
26
+ # process("alice@isp.com Alice Roberts;bob.smith@gmail.com Bob Smith")
27
+ # # => [["alice@isp.com", "Alice Roberts"], ["bob.smith@gmail.com", "Bob Smith"]]
28
+ #
29
+ # @return [Array<email, name>]
30
+ def process(content)
31
+ # NOTE: Keep it stage-procedural for easier debugging.
32
+ chunks = content.split(separator).map(&:strip).reject(&:empty?)
33
+
34
+ out = chunks.map do |chunk|
35
+ if (chunk =~ /^(.+?)\s+(.+)$/)
36
+ [$1, $2]
37
+ else
38
+ [chunk, ""]
39
+ end
40
+ end
41
+
42
+ out.empty? and raise ArgumentError, "Empty content"
43
+
44
+ out
45
+ end
46
+ alias_method :[], :process
47
+ end
48
+ end; end; end; end
@@ -0,0 +1,157 @@
1
+
2
+ require "neverbounce"
3
+
4
+ require_relative "request_maker"
5
+
6
+ module NeverBounce; module CLI; module Script
7
+ class JobsCreate < RequestMaker
8
+ require_relative "jobs_create/supplied_input_parser"
9
+
10
+ attr_writer :auto_parse, :auto_start, :filename, :input, :input_location, :now, :remote_input, :run_sample, :supplied_input, :supplied_input_array, :supplied_input_parser
11
+
12
+ envar "AUTO_PARSE", "Start parsing the job immediately after creation", ["y", "n"]
13
+ envar "FILENAME", "Original CSV filename", [{default: "YYYYMMDD-HHMMSS.csv"}, "My data.csv"]
14
+ envar "REMOTE_INPUT", "Remote URL with CSV of e-mails to verify", ["http://site.com/emails.csv"]
15
+ envar "SUPPLIED_INPUT", "List of e-mails to verify", ["alice@isp.com Alice Roberts;bob.smith@gmail.com Bob Smith"]
16
+ envar (k = "AUTO_START"), *SHARED_ENVARS[k]
17
+ envar (k = "RUN_SAMPLE"), *SHARED_ENVARS[k]
18
+
19
+ # @return [true]
20
+ # @return [false]
21
+ # @return [nil]
22
+ def auto_parse
23
+ igetset(:auto_parse) do
24
+ if env.has_key?(k = "AUTO_PARSE")
25
+ env_truthy?(k)
26
+ end
27
+ end
28
+ end
29
+
30
+ # @return [true]
31
+ # @return [false]
32
+ # @return [nil]
33
+ def auto_start
34
+ igetset(:auto_start) do
35
+ if env.has_key?(k = "AUTO_START")
36
+ env_truthy?(k)
37
+ end
38
+ end
39
+ end
40
+
41
+ def filename
42
+ igetset(:filename) { env["FILENAME"] || now.strftime("%Y%m%d-%H%M%S.csv") }
43
+ end
44
+
45
+ # @return [String] An URL if remote input.
46
+ # @return [Array] An array of e-mails if supplied input.
47
+ def input
48
+ input_location # Touch for sanity/completeness checks etc.
49
+ remote_input || supplied_input_array
50
+ end
51
+
52
+ # @return [String] <tt>"remote_url"</tt> or <tt>"supplied"</tt>
53
+ def input_location
54
+ @input_location ||= begin
55
+ # Sanity check.
56
+ raise UsageError, "`REMOTE_INPUT` and `SUPPLIED_INPUT` can't both be given" if remote_input? && supplied_input?
57
+
58
+ if remote_input?
59
+ "remote_url"
60
+ elsif supplied_input?
61
+ "supplied"
62
+ else
63
+ raise UsageError, "Input not given, use `REMOTE_INPUT=` or `SUPPLIED_INPUT=`"
64
+ end
65
+ end
66
+ end
67
+
68
+ def now
69
+ @now ||= Time.now
70
+ end
71
+
72
+ def remote_input
73
+ igetset(:remote_input) { env["REMOTE_INPUT"] }
74
+ end
75
+
76
+ def remote_input?
77
+ !!remote_input
78
+ end
79
+
80
+ # @return [true]
81
+ # @return [false]
82
+ # @return [nil]
83
+ def run_sample
84
+ igetset(:run_sample) do
85
+ if env.has_key?(k = "RUN_SAMPLE")
86
+ env_truthy?(k)
87
+ end
88
+ end
89
+ end
90
+
91
+ def supplied_input
92
+ igetset(:supplied_input) { env["SUPPLIED_INPUT"] }
93
+ end
94
+
95
+ def supplied_input?
96
+ !!supplied_input
97
+ end
98
+
99
+ def supplied_input_array
100
+ @supplied_input_array ||= require_attr(:supplied_input_parser)[require_attr(:supplied_input)]
101
+ end
102
+
103
+ def supplied_input_parser
104
+ @supplied_input_parser ||= SuppliedInputParser.new
105
+ end
106
+
107
+ # An <tt>API::Request::JobsCreate</tt>.
108
+ # @!attribute request
109
+ # @return [Object]
110
+ def request
111
+ @request ||= API::Request::JobsCreate.new({
112
+ api_key: api_key,
113
+ auto_parse: auto_parse,
114
+ auto_start: auto_start,
115
+ filename: filename,
116
+ input: input,
117
+ input_location: input_location,
118
+ run_sample: run_sample,
119
+ })
120
+ end
121
+
122
+ #--------------------------------------- Manifest
123
+
124
+ # @!attribute manifest
125
+ # @return [Manifest]
126
+ def manifest
127
+ @manifest ||= Manifest.new(
128
+ name: "nb-jobs-create",
129
+ function: "Create a job",
130
+ cmdline: "[options] [VAR1=value] [VAR2=value] ...",
131
+ )
132
+ end
133
+
134
+ #--------------------------------------- Main
135
+
136
+ # @return [Integer]
137
+ def slim_main
138
+ "Response".tap do |label|
139
+ headings = [
140
+ ["JobId", :job_id],
141
+
142
+ ["ExecTime", :execution_time, :right],
143
+ ]
144
+
145
+ table = Table.new(
146
+ headings: headings.map { |ar| ar[0] },
147
+ rows: [headings.map { |ar| get_table_value(response, ar) }],
148
+ ).align!(headings)
149
+
150
+ stdout.puts "\n#{label}:"
151
+ stdout.puts table
152
+ end
153
+
154
+ 0
155
+ end
156
+ end
157
+ end; end; end
@@ -0,0 +1,55 @@
1
+
2
+ require "neverbounce"
3
+
4
+ require "never_bounce/cli/script/feature/requires_job_id"
5
+
6
+ require_relative "request_maker"
7
+
8
+ module NeverBounce; module CLI; module Script
9
+ class JobsDelete < RequestMaker
10
+ Script::Feature::RequiresJobId.load(self)
11
+
12
+ # An <tt>API::Request::JobsDelete</tt>.
13
+ # @!attribute request
14
+ # @return [Object]
15
+ def request
16
+ @request ||= API::Request::JobsDelete.new({
17
+ api_key: api_key,
18
+ job_id: job_id,
19
+ })
20
+ end
21
+
22
+ #--------------------------------------- Manifest
23
+
24
+ # @!attribute manifest
25
+ # @return [Manifest]
26
+ def manifest
27
+ @manifest ||= Manifest.new(
28
+ name: "nb-jobs-delete",
29
+ function: "Delete a job",
30
+ cmdline: "[options] [VAR1=value] [VAR2=value] ...",
31
+ )
32
+ end
33
+
34
+ #--------------------------------------- Main
35
+
36
+ # @return [Integer]
37
+ def slim_main
38
+ "Response".tap do |label|
39
+ headings = [
40
+ ["ExecTime", :execution_time, :right],
41
+ ]
42
+
43
+ table = Table.new(
44
+ headings: headings.map { |ar| ar[0] },
45
+ rows: [headings.map { |ar| get_table_value(response, ar) }],
46
+ ).align!(headings)
47
+
48
+ stdout.puts "\n#{label}:"
49
+ stdout.puts table
50
+ end
51
+
52
+ 0
53
+ end
54
+ end
55
+ end; end; end
@@ -0,0 +1,44 @@
1
+
2
+ require "neverbounce"
3
+
4
+ require "never_bounce/cli/script/feature/requires_job_id"
5
+
6
+ require_relative "request_maker"
7
+
8
+ module NeverBounce; module CLI; module Script
9
+ class JobsDownload < RequestMaker
10
+ Script::Feature::RequiresJobId.load(self)
11
+
12
+ # An <tt>API::Request::JobsDownload</tt>.
13
+ # @!attribute request
14
+ # @return [Object]
15
+ def request
16
+ @request ||= API::Request::JobsDownload.new({
17
+ api_key: api_key,
18
+ job_id: job_id,
19
+ })
20
+ end
21
+
22
+ #--------------------------------------- Manifest
23
+
24
+ # @!attribute manifest
25
+ # @return [Manifest]
26
+ def manifest
27
+ @manifest ||= Manifest.new(
28
+ name: "nb-jobs-download",
29
+ function: "Download job results as CSV",
30
+ cmdline: "[options] [VAR1=value] [VAR2=value] ...",
31
+ )
32
+ end
33
+
34
+ #--------------------------------------- Main
35
+
36
+ # @return [Integer]
37
+ def slim_main
38
+ # Print CSV as is.
39
+ stdout.puts server_raw
40
+
41
+ 0
42
+ end
43
+ end
44
+ end; end; end
@@ -0,0 +1,73 @@
1
+
2
+ require "neverbounce"
3
+
4
+ require "never_bounce/cli/script/feature/requires_job_id"
5
+
6
+ require_relative "request_maker"
7
+
8
+ module NeverBounce; module CLI; module Script
9
+ class JobsParse < RequestMaker
10
+ Script::Feature::RequiresJobId.load(self)
11
+
12
+ attr_writer :auto_start
13
+
14
+ envar (k = "AUTO_START"), *SHARED_ENVARS[k]
15
+
16
+ # @return [true]
17
+ # @return [false]
18
+ # @return [nil]
19
+ def auto_start
20
+ igetset(:auto_start) do
21
+ if env.has_key?(k = "AUTO_START")
22
+ env_truthy?(k)
23
+ end
24
+ end
25
+ end
26
+
27
+ # An <tt>API::Request::JobsParse</tt>.
28
+ # @!attribute request
29
+ # @return [Object]
30
+ def request
31
+ @request ||= API::Request::JobsParse.new({
32
+ api_key: api_key,
33
+ auto_start: auto_start,
34
+ job_id: job_id,
35
+ })
36
+ end
37
+
38
+ #--------------------------------------- Manifest
39
+
40
+ # @!attribute manifest
41
+ # @return [Manifest]
42
+ def manifest
43
+ @manifest ||= Manifest.new(
44
+ name: "nb-jobs-parse",
45
+ function: "Issue a job parse command to the server",
46
+ cmdline: "[options] [VAR1=value] [VAR2=value] ...",
47
+ )
48
+ end
49
+
50
+ #--------------------------------------- Main
51
+
52
+ # @return [Integer]
53
+ def slim_main
54
+ "Response".tap do |label|
55
+ headings = [
56
+ ["QueueId", :queue_id],
57
+
58
+ ["ExecTime", :execution_time, :right],
59
+ ]
60
+
61
+ table = Table.new(
62
+ headings: headings.map { |ar| ar[0] },
63
+ rows: [headings.map { |ar| get_table_value(response, ar) }],
64
+ ).align!(headings)
65
+
66
+ stdout.puts "\n#{label}:"
67
+ stdout.puts table
68
+ end
69
+
70
+ 0
71
+ end
72
+ end
73
+ end; end; end
@@ -0,0 +1,105 @@
1
+
2
+ require "neverbounce"
3
+
4
+ require "never_bounce/cli/script/feature/requires_job_id"
5
+ require "never_bounce/cli/script/feature/uses_pagination"
6
+
7
+ require_relative "request_maker"
8
+
9
+ module NeverBounce; module CLI; module Script
10
+ class JobsResults < RequestMaker
11
+ Script::Feature::RequiresJobId.load(self)
12
+ Script::Feature::UsesPagination.load(self)
13
+
14
+ # An <tt>API::Request::JobsResults</tt>.
15
+ # @!attribute request
16
+ # @return [Object]
17
+ def request
18
+ @request ||= API::Request::JobsResults.new({
19
+ api_key: api_key,
20
+ job_id: job_id,
21
+ page: page,
22
+ per_page: per_page,
23
+ })
24
+ end
25
+
26
+ #--------------------------------------- Manifest
27
+
28
+ # @!attribute manifest
29
+ # @return [Manifest]
30
+ def manifest
31
+ @manifest ||= Manifest.new(
32
+ name: "nb-jobs-results",
33
+ function: "Get job execution results",
34
+ cmdline: "[options] [VAR1=value] [VAR2=value] ...",
35
+ )
36
+ end
37
+
38
+ #--------------------------------------- Main
39
+
40
+ # @return [Integer]
41
+ def slim_main
42
+ "Response".tap do |label|
43
+ headings = [
44
+ ["nPages", :total_pages, :right],
45
+ ["nResults", :total_results, :right],
46
+
47
+ ["ExecTime", :execution_time, :right],
48
+ ]
49
+
50
+ table = Table.new(
51
+ headings: headings.map { |ar| ar[0] },
52
+ rows: [headings.map { |ar| get_table_value(response, ar) }],
53
+ ).align!(headings)
54
+
55
+ stdout.puts "\n#{label}:"
56
+ stdout.puts table
57
+ end
58
+
59
+ "Query".tap do |label|
60
+ headings = [
61
+ ["JobId", :job_id, :right],
62
+ ["Page", :page, :right],
63
+ ["PerPage", :items_per_page, :right],
64
+ ]
65
+
66
+ table = Table.new(
67
+ headings: headings.map { |ar| ar[0] },
68
+ rows: [headings.map { |ar| get_table_value(response.query, ar) }],
69
+ ).align!(headings)
70
+
71
+ stdout.puts "\n#{label}:"
72
+ stdout.puts table
73
+ end
74
+
75
+ "Results".tap do |label|
76
+ headings = [
77
+ ["Email", :email],
78
+ ["Result", :result, :center],
79
+
80
+ [
81
+ "Flags",
82
+ ->(r) { r.flags.sort.join("\n") },
83
+ ],
84
+
85
+ ["SuggCorr", :suggested_correction],
86
+ ]
87
+
88
+ table = Table.new(
89
+ headings: headings.map { |ar| ar[0] },
90
+ rows: response.items.map do |r|
91
+ headings.map do |ar|
92
+ get_table_value(r, ar)
93
+ end
94
+ end,
95
+ ).align!(headings)
96
+
97
+ stdout.puts "\n#{label}:"
98
+ stdout.puts table
99
+ end
100
+
101
+
102
+ 0
103
+ end
104
+ end
105
+ end; end; end