nucleo-client 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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/.env.sample +2 -0
  3. data/.gitignore +16 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +31 -0
  7. data/Rakefile +37 -0
  8. data/lib/nucleo/client.rb +172 -0
  9. data/lib/nucleo/client/version.rb +5 -0
  10. data/lib/nucleo/configuration.rb +83 -0
  11. data/lib/nucleo/configurations.rb +6 -0
  12. data/lib/nucleo/configurations/default.rb +100 -0
  13. data/lib/nucleo/connection.rb +44 -0
  14. data/lib/nucleo/errors.rb +7 -0
  15. data/lib/nucleo/errors/invalid_uri_error.rb +6 -0
  16. data/lib/nucleo/errors/record_not_found.rb +6 -0
  17. data/lib/nucleo/logger.rb +36 -0
  18. data/lib/nucleo/models.rb +50 -0
  19. data/lib/nucleo/models/change_types.rb +10 -0
  20. data/lib/nucleo/models/change_types/base.rb +81 -0
  21. data/lib/nucleo/models/change_types/seo.rb +13 -0
  22. data/lib/nucleo/models/change_types/seo/base.rb +50 -0
  23. data/lib/nucleo/models/change_types/seo/meta_description.rb +10 -0
  24. data/lib/nucleo/models/change_types/seo/page_title.rb +10 -0
  25. data/lib/nucleo/models/changes.rb +50 -0
  26. data/lib/nucleo/models/check_js.rb +41 -0
  27. data/lib/nucleo/models/check_types.rb +11 -0
  28. data/lib/nucleo/models/check_types/base.rb +25 -0
  29. data/lib/nucleo/models/check_types/count.rb +26 -0
  30. data/lib/nucleo/models/check_types/length.rb +26 -0
  31. data/lib/nucleo/models/check_types/not_exists.rb +8 -0
  32. data/lib/nucleo/models/checks.rb +56 -0
  33. data/lib/nucleo/models/concerns.rb +7 -0
  34. data/lib/nucleo/models/concerns/count.rb +57 -0
  35. data/lib/nucleo/models/concerns/length.rb +57 -0
  36. data/lib/nucleo/models/date_range.rb +66 -0
  37. data/lib/nucleo/models/element.rb +40 -0
  38. data/lib/nucleo/models/elements.rb +47 -0
  39. data/lib/nucleo/models/feed.rb +141 -0
  40. data/lib/nucleo/models/feed_types.rb +11 -0
  41. data/lib/nucleo/models/feed_types/analytics.rb +18 -0
  42. data/lib/nucleo/models/feed_types/analytics/base.rb +12 -0
  43. data/lib/nucleo/models/feed_types/analytics/page/channels.rb +61 -0
  44. data/lib/nucleo/models/feed_types/analytics/page/pages.rb +58 -0
  45. data/lib/nucleo/models/feed_types/analytics/page/referrers.rb +61 -0
  46. data/lib/nucleo/models/feed_types/analytics/page/social.rb +61 -0
  47. data/lib/nucleo/models/feed_types/analytics/site/channels.rb +61 -0
  48. data/lib/nucleo/models/feed_types/analytics/site/pages.rb +61 -0
  49. data/lib/nucleo/models/feed_types/analytics/site/referrers.rb +61 -0
  50. data/lib/nucleo/models/feed_types/analytics/site/social.rb +61 -0
  51. data/lib/nucleo/models/feed_types/base.rb +182 -0
  52. data/lib/nucleo/models/feed_types/seo.rb +22 -0
  53. data/lib/nucleo/models/feed_types/seo/page/base.rb +47 -0
  54. data/lib/nucleo/models/feed_types/seo/page/img_alt.rb +90 -0
  55. data/lib/nucleo/models/feed_types/seo/page/meta_description.rb +49 -0
  56. data/lib/nucleo/models/feed_types/seo/page/meta_robots.rb +48 -0
  57. data/lib/nucleo/models/feed_types/seo/page/page_title.rb +48 -0
  58. data/lib/nucleo/models/feed_types/seo/page/seo_summary.rb +53 -0
  59. data/lib/nucleo/models/feed_types/seo/page/summary.rb +52 -0
  60. data/lib/nucleo/models/feed_types/seo/site/base.rb +22 -0
  61. data/lib/nucleo/models/feed_types/seo/site/img_alt.rb +14 -0
  62. data/lib/nucleo/models/feed_types/seo/site/meta_description.rb +14 -0
  63. data/lib/nucleo/models/feed_types/seo/site/meta_robots.rb +14 -0
  64. data/lib/nucleo/models/feed_types/seo/site/page_title.rb +14 -0
  65. data/lib/nucleo/models/feeds.rb +126 -0
  66. data/lib/nucleo/models/metric.rb +54 -0
  67. data/lib/nucleo/models/metric_period.rb +97 -0
  68. data/lib/nucleo/models/metric_period_row.rb +125 -0
  69. data/lib/nucleo/models/metric_period_rows.rb +34 -0
  70. data/lib/nucleo/models/metric_period_totals.rb +121 -0
  71. data/lib/nucleo/models/metric_periods.rb +78 -0
  72. data/lib/nucleo/models/metric_periods_comparison.rb +80 -0
  73. data/lib/nucleo/models/metric_periods_comparisons.rb +73 -0
  74. data/lib/nucleo/models/metric_periods_totals.rb +58 -0
  75. data/lib/nucleo/models/page.rb +147 -0
  76. data/lib/nucleo/models/page_alerts.rb +27 -0
  77. data/lib/nucleo/models/page_metric.rb +58 -0
  78. data/lib/nucleo/models/page_rank.rb +28 -0
  79. data/lib/nucleo/models/pages.rb +40 -0
  80. data/lib/nucleo/models/seo_score.rb +28 -0
  81. data/lib/nucleo/models/site_feed.rb +82 -0
  82. data/lib/nucleo/models/tag.rb +48 -0
  83. data/lib/nucleo/models/tags.rb +35 -0
  84. data/lib/nucleo/requests.rb +14 -0
  85. data/lib/nucleo/requests/analyzer.rb +35 -0
  86. data/lib/nucleo/requests/check_js.rb +56 -0
  87. data/lib/nucleo/requests/feed.rb +58 -0
  88. data/lib/nucleo/requests/page.rb +113 -0
  89. data/lib/nucleo/requests/page_alerts.rb +36 -0
  90. data/lib/nucleo/requests/page_changes.rb +44 -0
  91. data/lib/nucleo/requests/site.rb +26 -0
  92. data/lib/nucleo/requests/site_changes.rb +56 -0
  93. data/lib/nucleo/requests/site_feed.rb +41 -0
  94. data/lib/nucleo/response.rb +52 -0
  95. data/lib/nucleo/utilities.rb +7 -0
  96. data/lib/nucleo/utilities/status_code_mapper.rb +53 -0
  97. data/lib/nucleo/webhook.rb +26 -0
  98. data/nucleo-client.gemspec +35 -0
  99. data/spec/data/models/feed_types/seo/heading_tag_length.json +55 -0
  100. data/spec/data/models/feed_types/seo/internal_link_count.json +149 -0
  101. data/spec/data/models/feed_types/seo/no_follow_link_count.json +142 -0
  102. data/spec/spec_helper.rb +15 -0
  103. data/spec/unit/nucleo/models/concerns/count_spec.rb +103 -0
  104. data/spec/unit/nucleo/models/concerns/length_spec.rb +79 -0
  105. data/spec/unit/nucleo/models/feed_types/analytics/site/pages_no_data_spec.rb +39 -0
  106. data/spec/unit/nucleo/models/metric_periods_comparison_spec.rb +50 -0
  107. data/spec/unit/nucleo/models/metric_periods_comparisons_spec.rb +58 -0
  108. metadata +341 -0
@@ -0,0 +1,25 @@
1
+ module Nucleo
2
+ module Models
3
+ module CheckTypes
4
+ class Base
5
+ include Comparable
6
+
7
+ # Return an instance of the Rule Type domain model
8
+ #
9
+ # @param attributes [Hash]
10
+ #
11
+ # @return [Nucleo::Models::RuleType::Base]
12
+ def initialize(attributes={})
13
+ @attributes = attributes
14
+ end
15
+
16
+ # Returns the elements in the rule
17
+ #
18
+ # @return [String]
19
+ def elements
20
+ Nucleo::Models::Elements.new(@attributes['elements'])
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ module Nucleo
2
+ module Models
3
+ module CheckTypes
4
+ class Count < Nucleo::Models::CheckTypes::Base
5
+
6
+ def type
7
+ 'count'
8
+ end
9
+
10
+ # Returns the min allowed count
11
+ #
12
+ # @return [String]
13
+ def min_count
14
+ Integer(@attributes['min_count'])
15
+ end
16
+
17
+ # Returns the max allowed count
18
+ #
19
+ # @return [String]
20
+ def max_count
21
+ Integer(@attributes['max_count'])
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Nucleo
2
+ module Models
3
+ module CheckTypes
4
+ class Length < Nucleo::Models::CheckTypes::Base
5
+
6
+ def type
7
+ 'length'
8
+ end
9
+
10
+ # Returns the min allowed length
11
+ #
12
+ # @return [String]
13
+ def min_length
14
+ Integer(@attributes['min_length'])
15
+ end
16
+
17
+ # Returns the max allowed length
18
+ #
19
+ # @return [String]
20
+ def max_length
21
+ Integer(@attributes['max_length'])
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ module Nucleo
2
+ module Models
3
+ module CheckTypes
4
+ class NotExists < Nucleo::Models::CheckTypes::Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,56 @@
1
+ module Nucleo
2
+ module Models
3
+ class Checks
4
+ include Enumerable
5
+
6
+ # Return an instance of the Rules collection domain model
7
+ #
8
+ # @param collection [Array]
9
+ #
10
+ # @return [Nucleo::Models::Changes]
11
+ def initialize(collection)
12
+ @collection = Array(collection)
13
+ end
14
+
15
+ def each(&block)
16
+ internal_collection.each(&block)
17
+ end
18
+
19
+ # Retrieve a check by type
20
+ #
21
+ # @return [Nucleo::Models::ChangeType]
22
+ def find_by_type(type)
23
+ self.find { |record| record.type == type }
24
+ end
25
+
26
+ def find_content
27
+ content = self.collect { |r| r.elements.find_content }.flatten.first
28
+ return "" if content.blank?
29
+
30
+ content
31
+ end
32
+
33
+ def find_image_src
34
+ self.collect { |r| r.elements.find_image_src }.flatten
35
+ end
36
+
37
+ private
38
+ def internal_collection
39
+ core_collection = []
40
+
41
+ @collection.inject(core_collection) do |collection,record|
42
+ begin
43
+ const_name = ['nucleo', 'models', 'check_types', record['check']].map(&:camelcase).join('::')
44
+ collection.push(Object.const_get(const_name).new(record))
45
+ rescue
46
+ Nucleo::Client.configuration.logger.fatal("Could not instantiate: %s" % [const_name])
47
+ end
48
+
49
+ collection
50
+ end
51
+
52
+ Array(core_collection)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path('../concerns/count', __FILE__)
2
+ require File.expand_path('../concerns/length', __FILE__)
3
+
4
+ module Nucleo
5
+ module Concerns
6
+ end
7
+ end
@@ -0,0 +1,57 @@
1
+ module Nucleo
2
+ module Models
3
+ module Concerns
4
+ class Count
5
+ attr_reader :count, :min, :max
6
+
7
+ # Returns an instance of the Count concern domain model
8
+ #
9
+ # @param total [Integer]
10
+ # @param min [Integer]
11
+ # @param max [Integer]
12
+ #
13
+ # @return [Nucleo::Concerns::Count]
14
+ def initialize(count, min, max)
15
+ @count = count.to_i
16
+ @min = min.to_i
17
+ @max = max.to_i
18
+ end
19
+
20
+ # Returns true if missing
21
+ #
22
+ # @return [Boolean]
23
+ def missing?
24
+ (self.count < 1)
25
+ end
26
+
27
+ # Returns true if multiple
28
+ #
29
+ # @return [Boolean]
30
+ def multiple?
31
+ (self.count > 1)
32
+ end
33
+
34
+ # Returns true if too few
35
+ #
36
+ # @return [Boolean]
37
+ def too_few?
38
+ (self.count < self.min)
39
+ end
40
+
41
+ # Returns true if there is a max
42
+ #
43
+ # @return [Boolean]
44
+ def max?
45
+ (self.max > 0)
46
+ end
47
+
48
+ # Returns true if there is too many
49
+ #
50
+ # @return [Boolean]
51
+ def too_many?
52
+ (self.max? && (self.count > self.max))
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ module Nucleo
2
+ module Models
3
+ module Concerns
4
+ class Length
5
+ attr_reader :length, :min, :max
6
+
7
+ # Returns an instance of the Length concern domain model
8
+ #
9
+ # @param length [Integer]
10
+ # @param min [Integer]
11
+ # @param max [Integer]
12
+ #
13
+ # @return [Nucleo::Concerns::Length]
14
+ def initialize(length, min, max)
15
+ @length = length.to_i
16
+ @min = min.to_i
17
+ @max = max.to_i
18
+ end
19
+
20
+ # Returns true if there is a max
21
+ #
22
+ # @return [Boolean]
23
+ def max?
24
+ (self.max > 0)
25
+ end
26
+
27
+ # Returns true if too short
28
+ #
29
+ # @return [Boolean]
30
+ def too_short?
31
+ (self.length <= self.min)
32
+ end
33
+
34
+ # Returns the too short length
35
+ #
36
+ # @return [Integer]
37
+ def too_short_length
38
+ (self.min - self.length)
39
+ end
40
+
41
+ # Returns true if too long
42
+ #
43
+ # @return [Boolean]
44
+ def too_long?
45
+ (self.max? && (self.length > self.max))
46
+ end
47
+
48
+ # Returns the too long length
49
+ #
50
+ # @return [Integer]
51
+ def too_long_length
52
+ (self.length - self.max)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,66 @@
1
+ module Nucleo
2
+ module Models
3
+ class DateRange
4
+ # Returns an instance of the DateRange domain model
5
+ #
6
+ # @param attributes [Hash]
7
+ #
8
+ # @return [Nucleo::Models::DateRange]
9
+ def initialize(attributes={})
10
+ @attributes = attributes
11
+ end
12
+
13
+ # Returns the inclusive days for this range
14
+ #
15
+ # @return [Integer]
16
+ def days
17
+ return nil unless both_dates?
18
+
19
+ ((self.end_date - self.start_date) + 1).to_i
20
+ end
21
+
22
+ # Returns the start date
23
+ #
24
+ # @return [Date,nil]
25
+ def start_date
26
+ begin
27
+ Date.parse(start_date_value)
28
+ rescue
29
+ nil
30
+ end
31
+ end
32
+
33
+ # Returns the end date
34
+ #
35
+ # @return [Date,nil]
36
+ def end_date
37
+ begin
38
+ Date.parse(end_date_value)
39
+ rescue
40
+ nil
41
+ end
42
+ end
43
+
44
+ private
45
+ def start_date_value
46
+ @attributes['startDate']
47
+ end
48
+
49
+ def start_date_value?
50
+ !start_date_value.nil?
51
+ end
52
+
53
+ def end_date_value
54
+ @attributes['endDate']
55
+ end
56
+
57
+ def end_date_value?
58
+ !end_date_value.nil?
59
+ end
60
+
61
+ def both_dates?
62
+ start_date_value? && end_date_value?
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,40 @@
1
+ module Nucleo
2
+ module Models
3
+ class Element
4
+ include Comparable
5
+
6
+ def initialize(attributes={})
7
+ @attributes = attributes
8
+ end
9
+
10
+ def content
11
+ @attributes.fetch('content', '')
12
+ end
13
+
14
+ def src
15
+ @attributes.fetch('src', '')
16
+ end
17
+
18
+ def alt
19
+ @attributes.fetch('alt', '')
20
+ end
21
+
22
+ def content_length
23
+ self.content.length
24
+ end
25
+
26
+ def content_empty?
27
+ self.content.empty?
28
+ end
29
+
30
+ def content_present?
31
+ self.content.present?
32
+ end
33
+
34
+ def html
35
+ @attributes.fetch('html', '')
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+ module Nucleo
2
+ module Models
3
+ class Elements
4
+ include Enumerable
5
+
6
+ # Return an instance of the Rules collection domain model
7
+ #
8
+ # @param collection [Array]
9
+ #
10
+ # @return [Nucleo::Models::Changes]
11
+ def initialize(collection)
12
+ @collection = Array(collection)
13
+ end
14
+
15
+ def each(&block)
16
+ internal_collection.each(&block)
17
+ end
18
+
19
+ def find_content
20
+ self.collect { |r| r.content if r.content_present? }
21
+ end
22
+
23
+ def find_image_src
24
+ self.collect { |r| r.image_src if r.image? }
25
+ end
26
+
27
+ private
28
+ def internal_collection
29
+ core_collection = []
30
+
31
+ @collection.inject(core_collection) do |collection,record|
32
+ const_name = ['nucleo', 'models', 'element'].map(&:camelcase).join('::')
33
+
34
+ begin
35
+ collection.push(Object.const_get(const_name).new(record))
36
+ rescue
37
+ Nucleo::Client.configuration.logger.fatal("Could not instantiate: %s" % [const_name])
38
+ end
39
+
40
+ collection
41
+ end
42
+
43
+ Array(core_collection)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,141 @@
1
+ require File.expand_path('../page', __FILE__)
2
+
3
+ module Nucleo
4
+ module Models
5
+ class Feed
6
+ include Comparable
7
+
8
+ # Return an instance of the Feed domain model
9
+ #
10
+ # @param attributes [Hash]
11
+ #
12
+ # @return [Nucleo::Models::Feed]
13
+ def initialize(attributes={})
14
+ @attributes = attributes
15
+ end
16
+
17
+ def self.for_record(attributes={})
18
+ const_name = ['nucleo', 'models', 'feed_types', attributes['category'], attributes['type']].map(&:camelcase).join('::')
19
+
20
+ record = nil
21
+
22
+ begin
23
+ record = Object.const_get(const_name).new(attributes)
24
+ rescue
25
+ Nucleo::Client.configuration.logger.fatal("Could not instantiate %s" % [const_name])
26
+ end
27
+
28
+ record
29
+ end
30
+
31
+ # Sort by the executed at attribute
32
+ def <=>(other)
33
+ self.executed_at <=> other.executed_at
34
+ end
35
+
36
+ # Returns the page id
37
+ #
38
+ # @return [String]
39
+ def page_id
40
+ @attributes['page_id']
41
+ end
42
+
43
+ # Returns the page, if present
44
+ #
45
+ # @note: We have to inject the ID back in as it's
46
+ # not present in the `page` response.
47
+ #
48
+ # @return [Nucleo::Models::Page,nil]
49
+ def page
50
+ value = @attributes['page']
51
+
52
+ return nil if value.nil? || value.empty?
53
+
54
+ value.merge!('id' => self.page_id)
55
+
56
+ Nucleo::Models::Page.new(value)
57
+ end
58
+
59
+ # Returns true if there is an attached page
60
+ #
61
+ # @return [Boolean]
62
+ def page?
63
+ !self.page.nil?
64
+ end
65
+
66
+ # Returns the page recommendation ID
67
+ #
68
+ # @return [String]
69
+ def page_recommendation_id
70
+ @attributes['page_recommendation_id']
71
+ end
72
+
73
+ # Returns the site analytic ID
74
+ #
75
+ # @return [String]
76
+ def site_analytic_id
77
+ @attributes['site_analytic_id']
78
+ end
79
+
80
+ # Return the ID of this recommendation
81
+ #
82
+ # @return [String]
83
+ def id
84
+ (self.page_recommendation_id || self.site_analytic_id)
85
+ end
86
+
87
+ # Returns the ID of the site
88
+ #
89
+ # @return [Integer]
90
+ def site_id
91
+ @attributes['site_id']
92
+ end
93
+
94
+ # Returns the Category of the recommendation
95
+ #
96
+ # @todo: Create a Category model that can handle answering
97
+ # some basic questions.
98
+ #
99
+ # @return [String]
100
+ def category
101
+ @attributes['category']
102
+ end
103
+ alias :category_name :category
104
+
105
+ # Returns the Type of the recommendation
106
+ #
107
+ # @return [String]
108
+ def type
109
+ @attributes['type']
110
+ end
111
+ alias :type_name :type
112
+
113
+ # Returns the Status of the recommendation
114
+ #
115
+ # @return [String]
116
+ def status
117
+ @attributes['status']
118
+ end
119
+ alias :status_name :status
120
+
121
+ # Returns the Context of the recommendation
122
+ #
123
+ # @return [String]
124
+ def context
125
+ @attributes['context']
126
+ end
127
+ alias :context_name :context
128
+
129
+ # Return the time of execution of this recommendation
130
+ #
131
+ # @return [DateTime,nil]
132
+ def executed_at
133
+ begin
134
+ DateTime.parse(@attributes['executed_at'])
135
+ rescue
136
+ nil
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end