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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +8 -0
- data/.gitignore +21 -0
- data/.rspec +4 -0
- data/.rubocop.yml +1161 -0
- data/.travis.yml +27 -0
- data/.yardopts +2 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +60 -0
- data/LICENSE +9 -0
- data/README.md +138 -0
- data/exe/nb-account-info +5 -0
- data/exe/nb-jobs-create +5 -0
- data/exe/nb-jobs-delete +5 -0
- data/exe/nb-jobs-download +5 -0
- data/exe/nb-jobs-parse +5 -0
- data/exe/nb-jobs-results +5 -0
- data/exe/nb-jobs-search +5 -0
- data/exe/nb-jobs-start +5 -0
- data/exe/nb-jobs-status +5 -0
- data/exe/nb-single-check +5 -0
- data/lib/never_bounce/cli/feature/basic_initialize.rb +20 -0
- data/lib/never_bounce/cli/feature/eigencache.rb +47 -0
- data/lib/never_bounce/cli/feature/envars/examples_mapper.rb +38 -0
- data/lib/never_bounce/cli/feature/envars/item.rb +41 -0
- data/lib/never_bounce/cli/feature/envars.rb +82 -0
- data/lib/never_bounce/cli/feature/igetset.rb +41 -0
- data/lib/never_bounce/cli/feature/require_attr.rb +25 -0
- data/lib/never_bounce/cli/script/account_info.rb +85 -0
- data/lib/never_bounce/cli/script/base.rb +101 -0
- data/lib/never_bounce/cli/script/error.rb +16 -0
- data/lib/never_bounce/cli/script/feature/requires_job_id.rb +28 -0
- data/lib/never_bounce/cli/script/feature/uses_pagination.rb +45 -0
- data/lib/never_bounce/cli/script/jobs_create/supplied_input_parser.rb +48 -0
- data/lib/never_bounce/cli/script/jobs_create.rb +157 -0
- data/lib/never_bounce/cli/script/jobs_delete.rb +55 -0
- data/lib/never_bounce/cli/script/jobs_download.rb +44 -0
- data/lib/never_bounce/cli/script/jobs_parse.rb +73 -0
- data/lib/never_bounce/cli/script/jobs_results.rb +105 -0
- data/lib/never_bounce/cli/script/jobs_search.rb +135 -0
- data/lib/never_bounce/cli/script/jobs_start.rb +73 -0
- data/lib/never_bounce/cli/script/jobs_status.rb +96 -0
- data/lib/never_bounce/cli/script/manifest.rb +22 -0
- data/lib/never_bounce/cli/script/meaningful.rb +233 -0
- data/lib/never_bounce/cli/script/request_maker.rb +169 -0
- data/lib/never_bounce/cli/script/single_check.rb +146 -0
- data/lib/never_bounce/cli/script/table.rb +43 -0
- data/lib/never_bounce/cli/user_config/file_content.rb +66 -0
- data/lib/never_bounce/cli/user_config.rb +51 -0
- data/lib/never_bounce/cli/version.rb +4 -0
- data/lib/neverbounce-cli.rb +3 -0
- data/neverbounce-cli.gemspec +24 -0
- data/spec/lib/never_bounce/cli/feature/basic_initialize_spec.rb +26 -0
- data/spec/lib/never_bounce/cli/feature/eigencache_spec.rb +28 -0
- data/spec/lib/never_bounce/cli/feature/envars/examples_mapper_spec.rb +26 -0
- data/spec/lib/never_bounce/cli/feature/envars/item_spec.rb +9 -0
- data/spec/lib/never_bounce/cli/feature/envars_spec.rb +55 -0
- data/spec/lib/never_bounce/cli/feature/igetset_spec.rb +45 -0
- data/spec/lib/never_bounce/cli/feature/require_attr_spec.rb +25 -0
- data/spec/lib/never_bounce/cli/script/account_info_spec.rb +65 -0
- data/spec/lib/never_bounce/cli/script/base_spec.rb +56 -0
- data/spec/lib/never_bounce/cli/script/feature/requires_job_id_spec.rb +17 -0
- data/spec/lib/never_bounce/cli/script/feature/uses_pagination_spec.rb +21 -0
- data/spec/lib/never_bounce/cli/script/jobs_create/supplied_input_parser_spec.rb +35 -0
- data/spec/lib/never_bounce/cli/script/jobs_create_spec.rb +118 -0
- data/spec/lib/never_bounce/cli/script/jobs_delete_spec.rb +33 -0
- data/spec/lib/never_bounce/cli/script/jobs_download_spec.rb +37 -0
- data/spec/lib/never_bounce/cli/script/jobs_parse_spec.rb +45 -0
- data/spec/lib/never_bounce/cli/script/jobs_results_spec.rb +40 -0
- data/spec/lib/never_bounce/cli/script/jobs_search_spec.rb +59 -0
- data/spec/lib/never_bounce/cli/script/jobs_start_spec.rb +45 -0
- data/spec/lib/never_bounce/cli/script/jobs_status_spec.rb +37 -0
- data/spec/lib/never_bounce/cli/script/manifest_spec.rb +6 -0
- data/spec/lib/never_bounce/cli/script/meaningful_spec.rb +93 -0
- data/spec/lib/never_bounce/cli/script/request_maker_spec.rb +67 -0
- data/spec/lib/never_bounce/cli/script/single_check_spec.rb +94 -0
- data/spec/lib/never_bounce/cli/script/spec_helper.rb +59 -0
- data/spec/lib/never_bounce/cli/script/table_spec.rb +6 -0
- data/spec/lib/never_bounce/cli/user_config/file_content_spec.rb +43 -0
- data/spec/lib/never_bounce/cli/user_config_spec.rb +12 -0
- data/spec/lib/never_bounce/cli_spec.rb +6 -0
- data/spec/spec_helper.rb +51 -0
- metadata +193 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
require "never_bounce/cli/feature/basic_initialize"
|
|
3
|
+
require "never_bounce/cli/feature/igetset"
|
|
4
|
+
|
|
5
|
+
require_relative "../envars"
|
|
6
|
+
|
|
7
|
+
module NeverBounce; module CLI; module Feature; module Envars
|
|
8
|
+
# Single envar item container.
|
|
9
|
+
class Item
|
|
10
|
+
CLI::Feature::BasicInitialize.load(self)
|
|
11
|
+
CLI::Feature::Igetset.load(self)
|
|
12
|
+
|
|
13
|
+
# @return [String]
|
|
14
|
+
attr_accessor :name
|
|
15
|
+
|
|
16
|
+
# @return [String]
|
|
17
|
+
attr_accessor :comment
|
|
18
|
+
|
|
19
|
+
attr_writer :default, :examples, :is_mandatory
|
|
20
|
+
|
|
21
|
+
# Default value. Default is <tt>nil</tt>.
|
|
22
|
+
# @return [mixed]
|
|
23
|
+
def default
|
|
24
|
+
igetset(:default) { nil }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Value examples. Default is <tt>[]</tt>.
|
|
28
|
+
# @return [Array]
|
|
29
|
+
def examples
|
|
30
|
+
@examples ||= []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# True if this envar is mandatory. Default is <tt>false</tt>.
|
|
34
|
+
# @return [bool]
|
|
35
|
+
def is_mandatory
|
|
36
|
+
igetset(:is_mandatory) { false }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
alias_method :mandatory?, :is_mandatory
|
|
40
|
+
end
|
|
41
|
+
end; end; end; end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
|
|
2
|
+
module NeverBounce; module CLI; module Feature
|
|
3
|
+
# Declare and manage environment variables of the class.
|
|
4
|
+
module Envars
|
|
5
|
+
require_relative "envars/examples_mapper"
|
|
6
|
+
require_relative "envars/item"
|
|
7
|
+
|
|
8
|
+
# @param owner [Class]
|
|
9
|
+
# @return [nil]
|
|
10
|
+
def self.load(owner)
|
|
11
|
+
return if owner < InstanceMethods
|
|
12
|
+
owner.extend(ClassMethods)
|
|
13
|
+
owner.send(:include, InstanceMethods)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module ClassMethods
|
|
17
|
+
attr_writer :envars
|
|
18
|
+
|
|
19
|
+
def envars
|
|
20
|
+
@envars ||= if superclass.respond_to? :envars
|
|
21
|
+
superclass.envars.dup
|
|
22
|
+
else
|
|
23
|
+
[]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#---------------------------------------
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Define an envar in a formal way.
|
|
31
|
+
# @param name [String]
|
|
32
|
+
# @param comment [String]
|
|
33
|
+
# @return [Item]
|
|
34
|
+
def define_envar(name, comment, is_mandatory: false, examples: [], default: nil)
|
|
35
|
+
Item.new({
|
|
36
|
+
name: name,
|
|
37
|
+
|
|
38
|
+
comment: comment,
|
|
39
|
+
default: default,
|
|
40
|
+
examples: examples,
|
|
41
|
+
is_mandatory: is_mandatory,
|
|
42
|
+
}).tap { |_| envars << _ }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Declare an envar in a concise and magical way.
|
|
46
|
+
#
|
|
47
|
+
# envar "ID", "Job ID"
|
|
48
|
+
# => define_envar "ID", "Job ID"
|
|
49
|
+
# envar "API_KEY*", "API key", ["2ed45186c72f9319dc64338cdf16ab76b44cf3d1"]
|
|
50
|
+
# # => define_envar "API_KEY", "API key", is_mandatory: true, examples: [...]
|
|
51
|
+
# envar "RAW", "Print raw response body", ["y", default: "N"]
|
|
52
|
+
# # => define_envar "RAW", "Print raw response body", examples: ["y", "N"], default: "N"
|
|
53
|
+
def envar(name, comment, examples = [])
|
|
54
|
+
options = {}
|
|
55
|
+
|
|
56
|
+
real_name = if name[-1] == "*"
|
|
57
|
+
options[:is_mandatory] = true
|
|
58
|
+
name[0..-2]
|
|
59
|
+
else
|
|
60
|
+
name
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if not examples.empty?
|
|
64
|
+
h = ExamplesMapper.new[examples]
|
|
65
|
+
options[:examples] = h[:values]
|
|
66
|
+
options[:default] = h[:default] if h.include?(:default)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
define_envar(real_name, comment, options)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
module InstanceMethods
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end; end; end
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Implementation notes:
|
|
80
|
+
#
|
|
81
|
+
# * `envars` belongs to the class, but considering its superclasses.
|
|
82
|
+
# We don't use @@var to avoid unnecessary side effect.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
module NeverBounce; module CLI; module Feature
|
|
3
|
+
# @see InstanceMethods#igetset
|
|
4
|
+
module Igetset
|
|
5
|
+
# @param owner [Class]
|
|
6
|
+
# @return [nil]
|
|
7
|
+
def self.load(owner)
|
|
8
|
+
return if owner < InstanceMethods
|
|
9
|
+
owner.send(:include, InstanceMethods)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module InstanceMethods
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
# Get/set an OTF instance variable of any type.
|
|
16
|
+
#
|
|
17
|
+
# Ruby's <tt>||=</tt> works nicely with object instances, but requires special bulky treatment for <tt>nil</tt> and <tt>false</tt>.
|
|
18
|
+
# For example, this will cause a hidden glitch since <tt>==</tt> can evaluate to <tt>false</tt>:
|
|
19
|
+
#
|
|
20
|
+
# @is_verbose ||= begin
|
|
21
|
+
# # This clause will be evaluated *every time* if its value is `false`.
|
|
22
|
+
# ENV["VERBOSE"] == "y"
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# There's a number of solutions to this problem, all of which involve calling <tt>instance_variable_*</tt> a few times per attribute accessor.
|
|
26
|
+
#
|
|
27
|
+
# <tt>igetset</tt> does this job for you. All you have to do is specify a block to compute the value.
|
|
28
|
+
#
|
|
29
|
+
# igetset(:is_verbose) { ENV["VERBOSE"] == "y" }
|
|
30
|
+
#
|
|
31
|
+
# See source for details.
|
|
32
|
+
def igetset(name, &compute)
|
|
33
|
+
if instance_variable_defined?(k = "@#{name}")
|
|
34
|
+
instance_variable_get(k)
|
|
35
|
+
else
|
|
36
|
+
instance_variable_set(k, compute.call)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end; end; end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
module NeverBounce; module CLI; module Feature
|
|
3
|
+
# Provide attribute validation method(s) to the owner class.
|
|
4
|
+
# @see InstanceMethods#initialize
|
|
5
|
+
module RequireAttr
|
|
6
|
+
# @param owner [Class]
|
|
7
|
+
# @return [nil]
|
|
8
|
+
def self.load(owner)
|
|
9
|
+
return if owner < InstanceMethods
|
|
10
|
+
owner.send(:include, InstanceMethods)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module InstanceMethods
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
# Require attribute to be set. Return attribute value.
|
|
17
|
+
# @return [mixed]
|
|
18
|
+
def require_attr(name)
|
|
19
|
+
send(name).tap do |_|
|
|
20
|
+
raise "Attribute must be set: #{name}" if _.nil?
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end; end; end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
|
|
2
|
+
require "neverbounce"
|
|
3
|
+
|
|
4
|
+
require_relative "request_maker"
|
|
5
|
+
|
|
6
|
+
module NeverBounce; module CLI; module Script
|
|
7
|
+
class AccountInfo < RequestMaker
|
|
8
|
+
# An <tt>API::Request::AccountInfo</tt>.
|
|
9
|
+
# @!attribute request
|
|
10
|
+
# @return [Object]
|
|
11
|
+
def request
|
|
12
|
+
@request ||= API::Request::AccountInfo.new({
|
|
13
|
+
api_key: api_key,
|
|
14
|
+
})
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#--------------------------------------- Manifest
|
|
18
|
+
|
|
19
|
+
# @!attribute manifest
|
|
20
|
+
# @return [Manifest]
|
|
21
|
+
def manifest
|
|
22
|
+
@manifest ||= Manifest.new(
|
|
23
|
+
name: "nb-account-info",
|
|
24
|
+
function: "Check account balance",
|
|
25
|
+
cmdline: "[options] [VAR1=value] [VAR2=value] ...",
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#--------------------------------------- Main
|
|
30
|
+
|
|
31
|
+
# @return [Integer]
|
|
32
|
+
def slim_main
|
|
33
|
+
"Response".tap do |label|
|
|
34
|
+
headings = [
|
|
35
|
+
["ExecTime", :execution_time, :right],
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
table = Table.new(
|
|
39
|
+
headings: headings.map { |ar| ar[0] },
|
|
40
|
+
rows: [headings.map { |ar| get_table_value(response, ar) }],
|
|
41
|
+
).align!(headings)
|
|
42
|
+
|
|
43
|
+
stdout.puts "\n#{label}:"
|
|
44
|
+
stdout.puts table
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
"Credits".tap do |label|
|
|
48
|
+
headings = [
|
|
49
|
+
["FreeRmn", :free_credits_remaining, :right],
|
|
50
|
+
["FreeUsed", :free_credits_used, :right],
|
|
51
|
+
(["MonthlyUsage", :monthly_api_usage, :right] if response.credits_info.monthly?),
|
|
52
|
+
(["PaidRmn", :paid_credits_remaining, :right] if response.credits_info.paid?),
|
|
53
|
+
(["PaidUsed", :paid_credits_used, :right] if response.credits_info.paid?),
|
|
54
|
+
].compact
|
|
55
|
+
|
|
56
|
+
table = Table.new(
|
|
57
|
+
headings: headings.map { |ar| ar[0] },
|
|
58
|
+
rows: [headings.map { |ar| get_table_value(response.credits_info, ar) }],
|
|
59
|
+
).align!(headings)
|
|
60
|
+
|
|
61
|
+
stdout.puts "\n#{label}:"
|
|
62
|
+
stdout.puts table
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
"JobCounts".tap do |label|
|
|
66
|
+
headings = [
|
|
67
|
+
["Completed", :completed, :right],
|
|
68
|
+
["Processing", :processing, :right],
|
|
69
|
+
["Queued", :queued, :right],
|
|
70
|
+
["UnderReview", :under_review, :right],
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
table = Table.new(
|
|
74
|
+
headings: headings.map { |ar| ar[0] },
|
|
75
|
+
rows: [headings.map { |ar| get_table_value(response.job_counts, ar) }],
|
|
76
|
+
).align!(headings)
|
|
77
|
+
|
|
78
|
+
stdout.puts "\n#{label}:"
|
|
79
|
+
stdout.puts table
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
0
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end; end; end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
|
|
2
|
+
require "shellwords"
|
|
3
|
+
|
|
4
|
+
require "never_bounce/cli/feature/basic_initialize"
|
|
5
|
+
require "never_bounce/cli/feature/require_attr"
|
|
6
|
+
|
|
7
|
+
module NeverBounce; module CLI; module Script
|
|
8
|
+
# Barebones script base class.
|
|
9
|
+
# @abstract
|
|
10
|
+
# @see CLI::Feature::BasicInitialize
|
|
11
|
+
# @see CLI::Feature::RequireAttr
|
|
12
|
+
class Base
|
|
13
|
+
CLI::Feature::BasicInitialize.load(self)
|
|
14
|
+
CLI::Feature::RequireAttr.load(self)
|
|
15
|
+
|
|
16
|
+
attr_writer :argv, :env, :stderr, :stdout
|
|
17
|
+
|
|
18
|
+
# Command-line arguments. Default is <tt>ARGV</tt>.
|
|
19
|
+
# @return [Array]
|
|
20
|
+
def argv
|
|
21
|
+
@argv ||= ARGV
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# A *copy* of the environment for value-reading purposes. Default is <tt>ENV.to_h</tt>.
|
|
25
|
+
# @!attribute env
|
|
26
|
+
# @return [Hash]
|
|
27
|
+
def env
|
|
28
|
+
# Ruby's `ENV` is a weird thing.
|
|
29
|
+
# It's a direct `Object` which acts like `Hash`.
|
|
30
|
+
# It can't be reliably dup'd cloned, at the same time writes to it are invocation-global.
|
|
31
|
+
# This implicit read/write nature of `ENV` is a major hassle in tests, since it creates unnecessary side effects we have to tackle with specifically.
|
|
32
|
+
# Solution for now:
|
|
33
|
+
#
|
|
34
|
+
# 1. Since 99% of the time our script isn't interested in *writing* to ENV, this method deals with the READ case as the most widely used one.
|
|
35
|
+
# 2. If we ever need to write to ENV in order to *create* the environment for a child process or something, we'll find a way to do it with grace.
|
|
36
|
+
#
|
|
37
|
+
# Everything above is a comment to `.to_h`, mysteriously present on the next line.
|
|
38
|
+
@env ||= ENV.to_h
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Script's error stream. Default is <tt>STDERR</tt>.
|
|
42
|
+
# @return [IO]
|
|
43
|
+
def stderr
|
|
44
|
+
@stderr ||= STDERR
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Script's output stream. Default is <tt>STDOUT</tt>.
|
|
48
|
+
# @return [IO]
|
|
49
|
+
def stdout
|
|
50
|
+
@stdout ||= STDOUT
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# <tt>true</tt> if the script should be verbose.
|
|
54
|
+
# @return [true]
|
|
55
|
+
def verbose?
|
|
56
|
+
true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#--------------------------------------- Service
|
|
60
|
+
|
|
61
|
+
# @see #env_truthy?
|
|
62
|
+
def env_falsey?(k)
|
|
63
|
+
!env_truthy?(k)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Return <tt>true</tt> if environment variable <tt>k</tt> is truthy.
|
|
67
|
+
#
|
|
68
|
+
# env_truthy? "WITH_HTTP" # => `true` or `false`
|
|
69
|
+
# env_truthy? :WITH_HTTP # same as above
|
|
70
|
+
def env_truthy?(k)
|
|
71
|
+
self.class.env_value_truthy?(env[k.to_s])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Return <tt>true</tt> if environment variable value is truthy.
|
|
75
|
+
#
|
|
76
|
+
# # These are truthy.
|
|
77
|
+
# DEBUG=1
|
|
78
|
+
# DEBUG=true
|
|
79
|
+
# DEBUG=y
|
|
80
|
+
# DEBUG=yes
|
|
81
|
+
def self.env_value_truthy?(s)
|
|
82
|
+
["1", "true", "y", "yes"].include? s.to_s.downcase
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Run system command, print it if verbose.
|
|
86
|
+
# @return [mixed] Result of <tt>Kernel.system</tt>.
|
|
87
|
+
def system(cmd, *args)
|
|
88
|
+
puts "### #{cmd} #{args.map(&:shellescape).join(' ')}" if verbose?
|
|
89
|
+
Kernel.system(cmd, *args)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#---------------------------------------
|
|
93
|
+
|
|
94
|
+
# Main routine.
|
|
95
|
+
# @abstract
|
|
96
|
+
# @return [Integer]
|
|
97
|
+
def main
|
|
98
|
+
raise NotImplementedError, "Redefine `main` in your class: #{self.class}"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end; end; end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
module NeverBounce; module CLI; module Script
|
|
3
|
+
# Base script error class.
|
|
4
|
+
class Error < StandardError; end
|
|
5
|
+
|
|
6
|
+
# Something went wrong in the protocol land.
|
|
7
|
+
class ProtocolError < Error; end
|
|
8
|
+
|
|
9
|
+
# User didn't provide sufficient options, other stuff of that kind.
|
|
10
|
+
class UsageError < Error; end
|
|
11
|
+
end; end; end
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
# Implementation notes:
|
|
15
|
+
#
|
|
16
|
+
# * The file is named after the base class to follow the convention.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
module NeverBounce; module CLI; module Script; module Feature
|
|
3
|
+
# Common traits for scripts which require job ID.
|
|
4
|
+
# @see InstanceMethods
|
|
5
|
+
module RequiresJobId
|
|
6
|
+
# @param owner [Class]
|
|
7
|
+
# @return [nil]
|
|
8
|
+
def self.load(owner)
|
|
9
|
+
return if owner < InstanceMethods
|
|
10
|
+
owner.send(:include, InstanceMethods)
|
|
11
|
+
|
|
12
|
+
owner.class_eval do
|
|
13
|
+
attr_writer :job_id
|
|
14
|
+
|
|
15
|
+
envar "ID", "Job ID", ["276816"]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module InstanceMethods
|
|
20
|
+
# Job ID. Default is <tt>env["ID"]</tt>.
|
|
21
|
+
# @!attribute job_id
|
|
22
|
+
# @return [String]
|
|
23
|
+
def job_id
|
|
24
|
+
@job_id ||= env[k = "ID"] or raise UsageError, "Job ID not given, use `#{k}=`"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end; end; end; end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
module NeverBounce; module CLI; module Script; module Feature
|
|
3
|
+
# Common traits for scripts which support pagination.
|
|
4
|
+
# @see InstanceMethods
|
|
5
|
+
module UsesPagination
|
|
6
|
+
# @param owner [Class]
|
|
7
|
+
# @return [nil]
|
|
8
|
+
def self.load(owner)
|
|
9
|
+
return if owner < InstanceMethods
|
|
10
|
+
owner.send(:include, InstanceMethods)
|
|
11
|
+
|
|
12
|
+
owner.class_eval do
|
|
13
|
+
attr_writer :page, :per_page
|
|
14
|
+
|
|
15
|
+
envar "PAGE", "Fetch page number N", [{default: 1}, 5]
|
|
16
|
+
envar "PER_PAGE", "Paginate results N items per page", [10, default: 1000]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module InstanceMethods
|
|
21
|
+
# Page number. Default is <tt>env["PAGE"]</tt>.
|
|
22
|
+
# @!attribute page
|
|
23
|
+
# @return [Integer]
|
|
24
|
+
def page
|
|
25
|
+
# OPTIMIZE: Consider default-less behaviour some day.
|
|
26
|
+
@page ||= if (v = env["PAGE"])
|
|
27
|
+
Integer(v)
|
|
28
|
+
else
|
|
29
|
+
1
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Items per page. Default is <tt>env["PER_PAGE"]</tt>.
|
|
34
|
+
# @!attribute per_page
|
|
35
|
+
# @return [Integer]
|
|
36
|
+
def per_page
|
|
37
|
+
@per_page ||= if (v = env["PER_PAGE"])
|
|
38
|
+
Integer(v)
|
|
39
|
+
else
|
|
40
|
+
1000
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end; end; end; end
|