nucleo-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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