neverbounce-api 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 (108) 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 +17 -0
  9. data/Gemfile.lock +48 -0
  10. data/LICENSE +9 -0
  11. data/README.md +235 -0
  12. data/lib/never_bounce/api/client.rb +259 -0
  13. data/lib/never_bounce/api/error.rb +21 -0
  14. data/lib/never_bounce/api/feature/basic_initialize.rb +20 -0
  15. data/lib/never_bounce/api/feature/eigencache.rb +48 -0
  16. data/lib/never_bounce/api/feature/igetset.rb +41 -0
  17. data/lib/never_bounce/api/feature/oattrs.rb +100 -0
  18. data/lib/never_bounce/api/feature/require_attr.rb +27 -0
  19. data/lib/never_bounce/api/request/account_info.rb +29 -0
  20. data/lib/never_bounce/api/request/base.rb +102 -0
  21. data/lib/never_bounce/api/request/jobs_create.rb +90 -0
  22. data/lib/never_bounce/api/request/jobs_delete.rb +34 -0
  23. data/lib/never_bounce/api/request/jobs_download.rb +34 -0
  24. data/lib/never_bounce/api/request/jobs_parse.rb +55 -0
  25. data/lib/never_bounce/api/request/jobs_results.rb +53 -0
  26. data/lib/never_bounce/api/request/jobs_search.rb +57 -0
  27. data/lib/never_bounce/api/request/jobs_start.rb +47 -0
  28. data/lib/never_bounce/api/request/jobs_status.rb +37 -0
  29. data/lib/never_bounce/api/request/single_check.rb +67 -0
  30. data/lib/never_bounce/api/response/account_info.rb +39 -0
  31. data/lib/never_bounce/api/response/account_info/job_counts.rb +26 -0
  32. data/lib/never_bounce/api/response/address_info.rb +43 -0
  33. data/lib/never_bounce/api/response/base.rb +15 -0
  34. data/lib/never_bounce/api/response/container.rb +126 -0
  35. data/lib/never_bounce/api/response/credits_info/base.rb +30 -0
  36. data/lib/never_bounce/api/response/credits_info/monthly.rb +16 -0
  37. data/lib/never_bounce/api/response/credits_info/paid.rb +20 -0
  38. data/lib/never_bounce/api/response/error_message.rb +17 -0
  39. data/lib/never_bounce/api/response/feature/job_status_fields.rb +68 -0
  40. data/lib/never_bounce/api/response/feature/job_status_fields/total.rb +46 -0
  41. data/lib/never_bounce/api/response/jobs_create.rb +10 -0
  42. data/lib/never_bounce/api/response/jobs_delete.rb +8 -0
  43. data/lib/never_bounce/api/response/jobs_download.rb +19 -0
  44. data/lib/never_bounce/api/response/jobs_parse.rb +10 -0
  45. data/lib/never_bounce/api/response/jobs_results.rb +34 -0
  46. data/lib/never_bounce/api/response/jobs_results/item.rb +65 -0
  47. data/lib/never_bounce/api/response/jobs_results/query.rb +20 -0
  48. data/lib/never_bounce/api/response/jobs_search.rb +33 -0
  49. data/lib/never_bounce/api/response/jobs_search/query.rb +16 -0
  50. data/lib/never_bounce/api/response/jobs_search/result.rb +13 -0
  51. data/lib/never_bounce/api/response/jobs_start.rb +10 -0
  52. data/lib/never_bounce/api/response/jobs_status.rb +11 -0
  53. data/lib/never_bounce/api/response/message.rb +32 -0
  54. data/lib/never_bounce/api/response/single_check.rb +68 -0
  55. data/lib/never_bounce/api/response/status_message.rb +17 -0
  56. data/lib/never_bounce/api/response/success_message.rb +12 -0
  57. data/lib/never_bounce/api/session.rb +141 -0
  58. data/lib/never_bounce/api/version.rb +4 -0
  59. data/lib/neverbounce-api.rb +4 -0
  60. data/lib/neverbounce.rb +3 -0
  61. data/neverbounce-api.gemspec +20 -0
  62. data/spec/lib/never_bounce/api/client_spec.rb +199 -0
  63. data/spec/lib/never_bounce/api/feature/basic_initialize_spec.rb +25 -0
  64. data/spec/lib/never_bounce/api/feature/eigencache_spec.rb +28 -0
  65. data/spec/lib/never_bounce/api/feature/igetset_spec.rb +45 -0
  66. data/spec/lib/never_bounce/api/feature/oattrs_spec.rb +72 -0
  67. data/spec/lib/never_bounce/api/feature/require_attr_spec.rb +25 -0
  68. data/spec/lib/never_bounce/api/request/account_info_spec.rb +29 -0
  69. data/spec/lib/never_bounce/api/request/base_spec.rb +6 -0
  70. data/spec/lib/never_bounce/api/request/jobs_create_spec.rb +89 -0
  71. data/spec/lib/never_bounce/api/request/jobs_delete_spec.rb +31 -0
  72. data/spec/lib/never_bounce/api/request/jobs_download_spec.rb +31 -0
  73. data/spec/lib/never_bounce/api/request/jobs_parse_spec.rb +44 -0
  74. data/spec/lib/never_bounce/api/request/jobs_results_spec.rb +42 -0
  75. data/spec/lib/never_bounce/api/request/jobs_search_spec.rb +40 -0
  76. data/spec/lib/never_bounce/api/request/jobs_start_spec.rb +44 -0
  77. data/spec/lib/never_bounce/api/request/jobs_status_spec.rb +31 -0
  78. data/spec/lib/never_bounce/api/request/single_check_spec.rb +44 -0
  79. data/spec/lib/never_bounce/api/response/account_info/job_counts_spec.rb +7 -0
  80. data/spec/lib/never_bounce/api/response/account_info_spec.rb +9 -0
  81. data/spec/lib/never_bounce/api/response/address_info_spec.rb +7 -0
  82. data/spec/lib/never_bounce/api/response/base_spec.rb +6 -0
  83. data/spec/lib/never_bounce/api/response/container_spec.rb +142 -0
  84. data/spec/lib/never_bounce/api/response/credits_info/base_spec.rb +31 -0
  85. data/spec/lib/never_bounce/api/response/credits_info/monthly_spec.rb +11 -0
  86. data/spec/lib/never_bounce/api/response/credits_info/paid_spec.rb +11 -0
  87. data/spec/lib/never_bounce/api/response/feature/job_status_fields/total_spec.rb +7 -0
  88. data/spec/lib/never_bounce/api/response/feature/job_status_fields_spec.rb +42 -0
  89. data/spec/lib/never_bounce/api/response/jobs_create_spec.rb +7 -0
  90. data/spec/lib/never_bounce/api/response/jobs_delete_spec.rb +7 -0
  91. data/spec/lib/never_bounce/api/response/jobs_download_spec.rb +7 -0
  92. data/spec/lib/never_bounce/api/response/jobs_parse_spec.rb +7 -0
  93. data/spec/lib/never_bounce/api/response/jobs_results/jobs_results_item_spec.rb +7 -0
  94. data/spec/lib/never_bounce/api/response/jobs_results/jobs_results_query_spec.rb +7 -0
  95. data/spec/lib/never_bounce/api/response/jobs_results_spec.rb +7 -0
  96. data/spec/lib/never_bounce/api/response/jobs_search/jobs_search_query_spec.rb +7 -0
  97. data/spec/lib/never_bounce/api/response/jobs_search/jobs_search_result_spec.rb +7 -0
  98. data/spec/lib/never_bounce/api/response/jobs_search_spec.rb +7 -0
  99. data/spec/lib/never_bounce/api/response/jobs_start_spec.rb +7 -0
  100. data/spec/lib/never_bounce/api/response/jobs_status_spec.rb +7 -0
  101. data/spec/lib/never_bounce/api/response/single_check_spec.rb +7 -0
  102. data/spec/lib/never_bounce/api/response/spec_helper.rb +8 -0
  103. data/spec/lib/never_bounce/api/session_spec.rb +140 -0
  104. data/spec/lib/never_bounce/api_spec.rb +8 -0
  105. data/spec/spec_helper.rb +49 -0
  106. data/spec/spec_support/include_dir_context.rb +22 -0
  107. data/spec/spec_support/simplecov.rb +18 -0
  108. metadata +210 -0
@@ -0,0 +1,43 @@
1
+
2
+ require_relative "container"
3
+
4
+ module NeverBounce; module API; module Response
5
+ # Generic address info used in a number of responses.
6
+ class AddressInfo < Container
7
+ # @!attribute addr
8
+ # @return [String]
9
+ oattr :addr, :scalar
10
+
11
+ # @!attribute alias
12
+ # @return [String]
13
+ oattr :alias, :scalar
14
+
15
+ # @!attribute domain
16
+ # @return [String]
17
+ oattr :domain, :scalar
18
+
19
+ # @!attribute fqdn
20
+ # @return [String]
21
+ oattr :fqdn, :scalar
22
+
23
+ # @!attribute host
24
+ # @return [String]
25
+ oattr :host, :scalar
26
+
27
+ # @!attribute normalized_email
28
+ # @return [String]
29
+ oattr :normalized_email, :scalar
30
+
31
+ # @!attribute original_email
32
+ # @return [String]
33
+ oattr :original_email, :scalar
34
+
35
+ # @!attribute subdomain
36
+ # @return [String]
37
+ oattr :subdomain, :scalar
38
+
39
+ # @!attribute tld
40
+ # @return [String]
41
+ oattr :tld, :scalar
42
+ end
43
+ end; end; end
@@ -0,0 +1,15 @@
1
+
2
+ require "never_bounce/api/feature/basic_initialize"
3
+ require "never_bounce/api/feature/igetset"
4
+ require "never_bounce/api/feature/require_attr"
5
+
6
+ module NeverBounce; module API; module Response
7
+ # @see API::Feature::BasicInitialize
8
+ # @see API::Feature::Igetset
9
+ # @see API::Feature::RequireAttr
10
+ class Base
11
+ API::Feature::BasicInitialize.load(self)
12
+ API::Feature::Igetset.load(self)
13
+ API::Feature::RequireAttr.load(self)
14
+ end
15
+ end; end; end
@@ -0,0 +1,126 @@
1
+
2
+ require "json"
3
+
4
+ require "never_bounce/api/feature/eigencache"
5
+ require "never_bounce/api/feature/oattrs"
6
+ require "never_bounce/api/feature/require_attr"
7
+
8
+ require_relative "base"
9
+
10
+ module NeverBounce; module API; module Response
11
+ # A container with values, by default supports JSON parsing.
12
+ # @see API::Feature::Eigencache
13
+ # @see API::Feature::Oattrs
14
+ # @see API::Feature::RequireAttr
15
+ class Container < Base
16
+ API::Feature::Eigencache.load(self)
17
+ API::Feature::Oattrs.load(self)
18
+ API::Feature::RequireAttr.load(self)
19
+
20
+ # Container data. Default is JSON-parsed {#raw}.
21
+ # @!attribute body_hash
22
+ # @return [Hash]
23
+ def body_hash
24
+ _cache[:body_hash] ||= JSON.parse(require_attr(:raw))
25
+ end
26
+
27
+ def body_hash=(value)
28
+ _cache[:body_hash] = value
29
+ end
30
+
31
+ # Raw response body.
32
+ # @!attribute raw
33
+ # @return [String]
34
+ def raw
35
+ _cache[:raw]
36
+ end
37
+
38
+ def raw=(value)
39
+ _cache[:raw] ||= value
40
+ end
41
+
42
+ #--------------------------------------- Misc
43
+
44
+ class << self
45
+ private
46
+
47
+ # Declare & register an oattr.
48
+ #
49
+ # oattr :first_name, :scalar # => :first_name
50
+ # oattr ... # Handled by `Feature::Oattrs`.
51
+ #
52
+ # @return [Symbol] <tt>name</tt>.
53
+ # @see Feature::Oattrs::ClassMethods#oattr
54
+ def oattr(name, type, *args)
55
+ if type == :scalar
56
+ scalar_oattr(name, *args)
57
+ name.tap { oattrs << name }
58
+ else
59
+ # Handle other types in parent class.
60
+ super
61
+ end
62
+ end
63
+
64
+ # Build a generic scalar oattr.
65
+ #
66
+ # scalar_oattr :first_name
67
+ # scalar_oattr :page, type: :integer
68
+ # scalar_oattr :total_valid, type: :integer, allow_nil: true
69
+ #
70
+ # @return [Symbol]
71
+ def scalar_oattr(name, options = {})
72
+ o, options = {}, options.dup
73
+ o[k = :allow_nil] = options.include?(k) ? options.delete(k) : false
74
+ o[k = :key] = options.delete(k) || name
75
+ o[k = :type] = options.delete(k) || :any
76
+ raise ArgumentError, "Unknown options: #{options.inspect}" if not options.empty?
77
+
78
+ code = []
79
+ code << %{attr_writer :#{name}}
80
+
81
+ code << case o[:type]
82
+ when :any
83
+ %{def #{name}; @#{name} ||= body_hash.fetch("#{o[:key]}"); end}
84
+ when :float
85
+ if o[:allow_nil]
86
+ %{
87
+ def #{name}
88
+ @#{name} ||= unless (v = body_hash.fetch("#{o[:key]}")).nil?
89
+ Float(v)
90
+ end
91
+ end
92
+ }
93
+ else
94
+ %{def #{name}; @#{name} ||= Float(body_hash.fetch("#{o[:key]}")); end}
95
+ end
96
+ when :integer
97
+ if o[:allow_nil]
98
+ %{
99
+ def #{name}
100
+ @#{name} ||= unless (v = body_hash.fetch("#{o[:key]}")).nil?
101
+ Integer(v)
102
+ end
103
+ end
104
+ }
105
+ else
106
+ %{def #{name}; @#{name} ||= Integer(body_hash.fetch("#{o[:key]}")); end}
107
+ end
108
+ else
109
+ raise ArgumentError, "Unknown type: #{o[:type].inspect}"
110
+ end
111
+
112
+ class_eval code.join(";")
113
+
114
+ name
115
+ end
116
+ end # class << self
117
+ end
118
+ end; end; end
119
+
120
+ #
121
+ # Implementation notes:
122
+ #
123
+ # * I go for `class_eval` rather than `define_method` in order to use Ruby's `||=`.
124
+ # Going without it would require a bunch of `instance_variable_*` calls per each attribute access.
125
+ # * The container performs its own value validation according to attribute definitions.
126
+ # Thus, when creating a sub-container, it's more correct to pass `body` or `body_hash` to let this validation happen in the sub-container class.
@@ -0,0 +1,30 @@
1
+
2
+ require_relative "../container"
3
+
4
+ module NeverBounce; module API; module Response; module CreditsInfo
5
+ class Base < Container
6
+ # @!attribute free_credits_remaining
7
+ # @return [Integer]
8
+ oattr :free_credits_remaining, :scalar, type: :integer
9
+
10
+ # @!attribute free_credits_used
11
+ # @return [Integer]
12
+ oattr :free_credits_used, :scalar, type: :integer
13
+
14
+ # <tt>:monthly</tt> or <tt>:paid</tt>.
15
+ # @return [Symbol]
16
+ def subscription_type
17
+ raise NotImplementedError, "Redefine `subscription_type` in final class: #{self.class}"
18
+ end
19
+
20
+ # <tt>true</tt> if monthly subscription.
21
+ def monthly?
22
+ subscription_type == :monthly
23
+ end
24
+
25
+ # <tt>true</tt> if paid subscription.
26
+ def paid?
27
+ subscription_type == :paid
28
+ end
29
+ end
30
+ end; end; end; end
@@ -0,0 +1,16 @@
1
+
2
+ require_relative "base"
3
+
4
+ module NeverBounce; module API; module Response; module CreditsInfo
5
+ class Monthly < Base
6
+ # @!attribute monthly_api_usage
7
+ # @return [Integer]
8
+ oattr :monthly_api_usage, :scalar, type: :integer
9
+
10
+ # Always <tt>:monthly</tt>.
11
+ # @return [Symbol]
12
+ def subscription_type
13
+ :monthly
14
+ end
15
+ end
16
+ end; end; end; end
@@ -0,0 +1,20 @@
1
+
2
+ require_relative "base"
3
+
4
+ module NeverBounce; module API; module Response; module CreditsInfo
5
+ class Paid < Base
6
+ # @!attribute paid_credits_remaining
7
+ # @return [Integer]
8
+ oattr :paid_credits_remaining, :scalar, type: :integer
9
+
10
+ # @!attribute paid_credits_used
11
+ # @return [Integer]
12
+ oattr :paid_credits_used, :scalar, type: :integer
13
+
14
+ # Always <tt>:paid</tt>.
15
+ # @return [Symbol]
16
+ def subscription_type
17
+ :paid
18
+ end
19
+ end
20
+ end; end; end; end
@@ -0,0 +1,17 @@
1
+
2
+ require_relative "status_message"
3
+
4
+ module NeverBounce; module API; module Response
5
+ # A failure (error) response from the server.
6
+ # @see https://developers.neverbounce.com/v4.0/reference#error-handling
7
+ class ErrorMessage < StatusMessage
8
+ # @!attribute message
9
+ # @return [String]
10
+ oattr :message, :scalar
11
+
12
+ # @return [false]
13
+ def success?
14
+ false
15
+ end
16
+ end
17
+ end; end; end
@@ -0,0 +1,68 @@
1
+
2
+ require "never_bounce/api/response/container"
3
+
4
+ module NeverBounce; module API; module Response; module Feature
5
+ # Common traits for message/container of the job status.
6
+ # @see InstanceMethods
7
+ module JobStatusFields
8
+ require_relative "job_status_fields/total"
9
+
10
+ # @param owner [Class]
11
+ # @return [nil]
12
+ def self.load(owner)
13
+ # Validate owner, or calls to `oattr` will fail.
14
+ raise ArgumentError, "Class #{owner} is not an ancestor of Response::Container" if not owner < Response::Container
15
+
16
+ return if owner < InstanceMethods
17
+ owner.send(:include, InstanceMethods)
18
+
19
+ owner.class_eval do
20
+ oattr :id, :scalar, type: :integer
21
+
22
+ oattr :job_status, :scalar
23
+
24
+ oattr :bounce_estimate, :scalar, type: :float
25
+ oattr :filename, :scalar
26
+ oattr :percent_complete, :scalar, type: :integer
27
+
28
+ oattr :total, :writer
29
+
30
+ oattr :created_at, :scalar
31
+ oattr :finished_at, :scalar
32
+ oattr :started_at, :scalar
33
+ end
34
+ end
35
+
36
+ # @!attribute id
37
+ # @return [Integer]
38
+ # @!attribute job_status
39
+ # @return [String]
40
+ # @!attribute bounce_estimate
41
+ # @return [Float]
42
+ # @!attribute filename
43
+ # @return [String]
44
+ # @!attribute percent_complete
45
+ # @return [Integer]
46
+ # @!attribute total
47
+ # @return [Total]
48
+ # @!attribute created_at
49
+ # @return [String]
50
+ # @!attribute finished_at
51
+ # @return [String]
52
+ # @!attribute started_at
53
+ # @return [String]
54
+ module InstanceMethods
55
+ def total
56
+ @total ||= Total.new(body_hash: body_hash.fetch("total"))
57
+ end
58
+ end
59
+ end
60
+ end; end; end; end
61
+
62
+ #
63
+ # Implementation notes:
64
+ #
65
+ # * (!) No means discovered to tell YARD that class A inherits methods from here.
66
+ # Thus, we use a regular `@see` in those using this and other features.
67
+ # * YARD can't read `@!attribute` from inside `class_eval`, just ignores the comments.
68
+ # * YARD sorts all attributes alphabetically, we maintain our order, which is logical+alpha.
@@ -0,0 +1,46 @@
1
+
2
+ require_relative "../job_status_fields"
3
+
4
+ module NeverBounce; module API; module Response; module Feature; module JobStatusFields
5
+ class Total < Container
6
+ # @!attribute bad_syntax
7
+ # @return [Integer]
8
+ oattr :bad_syntax, :scalar, type: :integer, allow_nil: true
9
+
10
+ # @!attribute billable
11
+ # @return [Integer]
12
+ oattr :billable, :scalar, type: :integer, allow_nil: true
13
+
14
+ # @!attribute catchall
15
+ # @return [Integer]
16
+ oattr :catchall, :scalar, type: :integer, allow_nil: true
17
+
18
+ # @!attribute disposable
19
+ # @return [Integer]
20
+ oattr :disposable, :scalar, type: :integer, allow_nil: true
21
+
22
+ # @!attribute duplicates
23
+ # @return [Integer]
24
+ oattr :duplicates, :scalar, type: :integer, allow_nil: true
25
+
26
+ # @!attribute invalid
27
+ # @return [Integer]
28
+ oattr :invalid, :scalar, type: :integer, allow_nil: true
29
+
30
+ # @!attribute processed
31
+ # @return [Integer]
32
+ oattr :processed, :scalar, type: :integer, allow_nil: true
33
+
34
+ # @!attribute records
35
+ # @return [Integer]
36
+ oattr :records, :scalar, type: :integer, allow_nil: true
37
+
38
+ # @!attribute unknown
39
+ # @return [Integer]
40
+ oattr :unknown, :scalar, type: :integer, allow_nil: true
41
+
42
+ # @!attribute valid
43
+ # @return [Integer]
44
+ oattr :valid, :scalar, type: :integer, allow_nil: true
45
+ end
46
+ end; end; end; end; end
@@ -0,0 +1,10 @@
1
+
2
+ require_relative "success_message"
3
+
4
+ module NeverBounce; module API; module Response
5
+ class JobsCreate < SuccessMessage
6
+ # @!attribute job_id
7
+ # @return [Integer]
8
+ oattr :job_id, :scalar, type: :integer
9
+ end
10
+ end; end; end
@@ -0,0 +1,8 @@
1
+
2
+ require_relative "success_message"
3
+
4
+ module NeverBounce; module API; module Response
5
+ class JobsDelete < SuccessMessage
6
+ # No own attributes yet.
7
+ end
8
+ end; end; end
@@ -0,0 +1,19 @@
1
+
2
+ require_relative "message"
3
+
4
+ module NeverBounce; module API; module Response
5
+ # A response to <tt>jobs/download</tt>.
6
+ # Body is an octet-stream, not a JSON structure.
7
+ # @see https://developers.neverbounce.com/v4.0/reference#jobs-download
8
+ class JobsDownload < Message
9
+ # Always <tt>true</tt>.
10
+ def success?
11
+ true
12
+ end
13
+ end
14
+ end; end; end
15
+
16
+ #
17
+ # Implementation notes:
18
+ #
19
+ # * This class uses `body` in its literal form. All the rest basically JSON-parse it.
@@ -0,0 +1,10 @@
1
+
2
+ require_relative "success_message"
3
+
4
+ module NeverBounce; module API; module Response
5
+ class JobsParse < SuccessMessage
6
+ # @!attribute queue_id
7
+ # @return [String]
8
+ oattr :queue_id, :scalar
9
+ end
10
+ end; end; end