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,61 @@
1
+ module Nucleo
2
+ module Models
3
+ module FeedTypes
4
+ module Analytics
5
+ module Site
6
+
7
+ class Social < Nucleo::Models::FeedTypes::Analytics::Base
8
+ DIMENSION_NAME = 'ga:socialNetwork'.freeze
9
+ METRIC_NAME = 'ga:pageviews'.freeze
10
+
11
+ # Returns the specific Metric for this page
12
+ #
13
+ # @return [Nucleo::Models::Metric]
14
+ def metric
15
+ params = {
16
+ 'metric' => METRIC_NAME,
17
+ 'dimension' => DIMENSION_NAME,
18
+ 'classification' => @attributes['classification'],
19
+ 'totals' => data['totals'],
20
+ 'current_period' => data['current_period'],
21
+ 'prior_period' => data['prior_period']
22
+ }
23
+
24
+ Nucleo::Models::Metric.new(params)
25
+ end
26
+
27
+ # Delegates to the Totals
28
+ #
29
+ # @return [Nucleo::Models::MetricPeriodsTotals]
30
+ def totals
31
+ self.metric.metric_periods.totals
32
+ end
33
+
34
+ # Delegates to the Metric Period
35
+ #
36
+ # @return [Nucleo::Models::MetricPeriod]
37
+ def current_period
38
+ self.metric.metric_periods.current_period
39
+ end
40
+
41
+ # Delegates to the Metric Period
42
+ #
43
+ # @return [Nucleo::Models::MetricPeriod]
44
+ def prior_period
45
+ self.metric.metric_periods.prior_period
46
+ end
47
+ alias :previous_period :prior_period
48
+
49
+ # Delegates to the Metric Period
50
+ #
51
+ # @return [Nucleo::Models::MetricPeriodsComparisons]
52
+ def periods_comparisons
53
+ self.metric.metric_periods.periods_comparisons
54
+ end
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,182 @@
1
+ require File.expand_path('../../page', __FILE__)
2
+
3
+ module Nucleo
4
+ module Models
5
+ module FeedTypes
6
+ class Base
7
+ include Comparable
8
+
9
+ # Return an instance of the Feed domain model
10
+ #
11
+ # @param attributes [Hash]
12
+ #
13
+ # @return [Nucleo::Models::Feed]
14
+ def initialize(attributes={})
15
+ @attributes = attributes
16
+ end
17
+
18
+ # Sort by the executed at attribute
19
+ def <=>(other)
20
+ self.executed_at <=> other.executed_at
21
+ end
22
+
23
+ # Returns the page, if present
24
+ #
25
+ # @note: We have to inject the ID back in as it's
26
+ # not present in the `page` response.
27
+ #
28
+ # @return [Nucleo::Models::Page,nil]
29
+ def page
30
+ value = @attributes['page']
31
+
32
+ return nil if value.nil? || value.empty?
33
+
34
+ Nucleo::Models::Page.new(value)
35
+ end
36
+
37
+ # Returns true if there is an attached page
38
+ #
39
+ # @return [Boolean]
40
+ def page?
41
+ !self.page.nil?
42
+ end
43
+
44
+ # Returns the page recommendation ID
45
+ #
46
+ # @return [String]
47
+ def page_recommendation_id
48
+ @attributes['page_recommendation_id']
49
+ end
50
+
51
+ # Returns the site analytic ID
52
+ #
53
+ # @return [String]
54
+ def site_analytic_id
55
+ @attributes['site_analytic_id']
56
+ end
57
+
58
+ # Return the record ID
59
+ #
60
+ # @note: This is to support instantiation from `children`
61
+ #
62
+ # @return [String]
63
+ def record_id
64
+ @attributes['id']
65
+ end
66
+
67
+ # Return the ID of this recommendation
68
+ #
69
+ # @return [String]
70
+ def id
71
+ (self.page_recommendation_id || self.site_analytic_id || self.record_id)
72
+ end
73
+
74
+ # Returns the ID of the site
75
+ #
76
+ # @return [Integer]
77
+ def site_id
78
+ @attributes['site_id']
79
+ end
80
+
81
+ # Returns the Category of the recommendation
82
+ #
83
+ # @todo: Create a Category model that can handle answering
84
+ # some basic questions.
85
+ #
86
+ # @return [String]
87
+ def category
88
+ @attributes['category']
89
+ end
90
+ alias :category_name :category
91
+
92
+ # Returns the Type of the recommendation
93
+ #
94
+ # @return [String]
95
+ def type
96
+ @attributes['type']
97
+ end
98
+ alias :type_name :type
99
+
100
+ # Returns the Status of the recommendation
101
+ #
102
+ # @return [String]
103
+ def status
104
+ @attributes['status']
105
+ end
106
+ alias :status_name :status
107
+
108
+ # Returns the Context of the recommendation
109
+ #
110
+ # @return [String]
111
+ def context
112
+ @attributes['context']
113
+ end
114
+ alias :context_name :context
115
+
116
+ # Return the time of execution of this recommendation
117
+ #
118
+ # @return [DateTime,nil]
119
+ def executed_at
120
+ begin
121
+ DateTime.parse(@attributes['executed_at'])
122
+ rescue
123
+ nil
124
+ end
125
+ end
126
+
127
+ # Returns true if this is for seo
128
+ #
129
+ # @return [Boolean]
130
+ def seo_category?
131
+ 'seo' == self.category
132
+ end
133
+
134
+ # Returns true if this is for analytics
135
+ #
136
+ # @return [Boolean]
137
+ def analytics_category?
138
+ 'analytics' == self.category
139
+ end
140
+
141
+ # Returns true if this is a page context
142
+ #
143
+ # @return [Boolean]
144
+ def page_context?
145
+ 'page' == self.context
146
+ end
147
+
148
+ # Returns true if this is a site context
149
+ #
150
+ # @return [Boolean]
151
+ def site_context?
152
+ 'site' == self.context
153
+ end
154
+
155
+ # Return the child recommendations
156
+ #
157
+ # @return [Nucleo::Models::Feeds]
158
+ def children
159
+ Nucleo::Models::Feeds.new(children_collection)
160
+ end
161
+ alias :issues :children
162
+
163
+ # Returns true if there are children
164
+ #
165
+ # @return [Boolean]
166
+ def children?
167
+ self.children.any?
168
+ end
169
+ alias :issues? :children?
170
+
171
+ protected
172
+ def data
173
+ @attributes.fetch('data', {})
174
+ end
175
+
176
+ def children_collection
177
+ data.fetch('child_recommendations', [])
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../seo/page/base', __FILE__)
2
+ require File.expand_path('../seo/page/seo_summary', __FILE__)
3
+ require File.expand_path('../seo/page/summary', __FILE__)
4
+ require File.expand_path('../seo/page/img_alt', __FILE__)
5
+ require File.expand_path('../seo/page/meta_description', __FILE__)
6
+ # require File.expand_path('../seo/page/meta_robots', __FILE__) # TODO: Add back when action for this alert type is available
7
+ require File.expand_path('../seo/page/page_title', __FILE__)
8
+
9
+ require File.expand_path('../seo/site/base', __FILE__)
10
+ require File.expand_path('../seo/site/img_alt', __FILE__)
11
+ require File.expand_path('../seo/site/meta_description', __FILE__)
12
+ # require File.expand_path('../seo/site/meta_robots', __FILE__) # TODO: Add back when action for this alert type is available
13
+ require File.expand_path('../seo/site/page_title', __FILE__)
14
+
15
+ module Nucleo
16
+ module Models
17
+ module FeedTypes
18
+ module Seo
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,47 @@
1
+ require File.expand_path('../../../base', __FILE__)
2
+
3
+ module Nucleo
4
+ module Models
5
+ module FeedTypes
6
+ module Seo
7
+ module Page
8
+
9
+ class Base < Nucleo::Models::FeedTypes::Base
10
+
11
+ # Returns the checks
12
+ #
13
+ # @return [Array]
14
+ def checks
15
+ Nucleo::Models::Checks.new(data.fetch('checks',[]))
16
+ end
17
+
18
+ def check_count
19
+ checks.count
20
+ end
21
+
22
+ def element
23
+ Nucleo::Models::Element.new(data.fetch('element',{}))
24
+ end
25
+
26
+ def element_content
27
+ self.element.content
28
+ end
29
+
30
+ def element_content?
31
+ self.element_content.present?
32
+ end
33
+
34
+ def points
35
+ data.fetch('points', 0).to_i
36
+ end
37
+
38
+ def find_content
39
+ self.checks.find_content
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,90 @@
1
+ require 'uri'
2
+
3
+ module Nucleo
4
+ module Models
5
+ module FeedTypes
6
+ module Seo
7
+ module Page
8
+
9
+ class ImgAlt < Nucleo::Models::FeedTypes::Seo::Page::Base
10
+
11
+ def image_src(site_url = nil)
12
+ url_template = '%{scheme}://%{host}/%{path}?%{query}#%{fragment}'
13
+
14
+ if site_url.present?
15
+ begin
16
+ site_host = URI(site_url).host
17
+ rescue
18
+ Nucleo::Client.configuration.logger.fatal("Unable to parse site_url %s" % [site_url])
19
+ end
20
+ end
21
+
22
+ img = self.element.src
23
+ begin
24
+ url = URI(img)
25
+
26
+ # Check if url is a valid http/https url
27
+ if url.kind_of?(URI::HTTP)
28
+ return url.to_s
29
+ end
30
+
31
+ # Attempt to create new url from fragments
32
+ new_url = URI(url_template % {
33
+ scheme: (url.scheme or 'http'),
34
+ host: (url.host or site_host),
35
+ path: url.path,
36
+ query: url.query,
37
+ fragment: url.fragment
38
+ })
39
+ return new_url.to_s if new_url.kind_of?(URI::HTTP)
40
+
41
+ rescue
42
+ Nucleo::Client.configuration.logger.fatal("Could not validate image url %s" % [img])
43
+ end
44
+ end
45
+
46
+ def alt_content
47
+ self.element.alt
48
+ end
49
+
50
+ # Returns the class level feed summary title
51
+ #
52
+ # @return [String]
53
+ def self.feed_summary
54
+ "<strong>img alt</strong> feed summary"
55
+ end
56
+
57
+ # Delegate to the class level feed summary
58
+ #
59
+ # @return [String]
60
+ def feed_summary
61
+ self.class.feed_summary
62
+ end
63
+
64
+ # Returns the headline based on the length of the content
65
+ #
66
+ # @return [String]
67
+ def headline
68
+ "img alt headline"
69
+ end
70
+
71
+ # Returns the detailed summary
72
+ #
73
+ # @return [String]
74
+ def long_summary
75
+ "img alts long summary"
76
+ end
77
+
78
+ # Returns the short summary
79
+ #
80
+ # @return [String]
81
+ def short_summary
82
+ "Images with <strong>Alt</strong> text are searchable with images search."
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,49 @@
1
+ module Nucleo
2
+ module Models
3
+ module FeedTypes
4
+ module Seo
5
+ module Page
6
+
7
+ class MetaDescription < Nucleo::Models::FeedTypes::Seo::Page::Base
8
+
9
+ # Returns the class level feed summary title
10
+ #
11
+ # @return [String]
12
+ def self.feed_summary
13
+ "<strong>Meta Description</strong> feed summary"
14
+ end
15
+
16
+ # Delegate to the class level feed summary
17
+ #
18
+ # @return [String]
19
+ def feed_summary
20
+ self.class.feed_summary
21
+ end
22
+
23
+ # Returns the headline based on the length of the content
24
+ #
25
+ # @return [String]
26
+ def headline
27
+ "Meta description headline"
28
+ end
29
+
30
+ # Returns the detailed summary
31
+ #
32
+ # @return [String]
33
+ def long_summary
34
+ "Meta descriptions long summary"
35
+ end
36
+
37
+ # Returns the short summary
38
+ #
39
+ # @return [String]
40
+ def short_summary
41
+ "Meta descriptions improve how your site looks in search results."
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end