majestic-api 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1e1e35e83bb4074c2fea067e5049b0b7407ae08237b8d85ace5a76b081243fa9
4
+ data.tar.gz: afaf42abf89b9efbd9f79acfaea72ac20d26d0375843ab044f7a2d1a151ae69a
5
+ SHA512:
6
+ metadata.gz: c6e2531fcae909e043e635e2ff75b40f992bcbf42ce18a5a19a9c12f61ce9cbabab6a659ef2c7ba9ffab05c73e6011fc49743fd8e92140a6a1db3d61a4300293
7
+ data.tar.gz: 25f597ae88854e0ce91cf2c5490ab9d8079aca5b1bdb6d6220f2371f1beea291f8e1fa77beeeb008f0bf8fa87c82eb8988e56434263e1a0a7f45cdc8e7fed586
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ /spec/tmp/
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
14
+
15
+ /bin/.pry_history
16
+ .pry_history
17
+
18
+ credentials.yml
19
+ .ruby-version
20
+ .ruby-gemset
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at sebastian.johnsson@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in scrapely.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,115 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ majestic-api (1.4.0)
5
+ faraday (>= 0.15.4)
6
+ faraday_middleware (>= 0.13.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionpack (5.2.2.1)
12
+ actionview (= 5.2.2.1)
13
+ activesupport (= 5.2.2.1)
14
+ rack (~> 2.0)
15
+ rack-test (>= 0.6.3)
16
+ rails-dom-testing (~> 2.0)
17
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
18
+ actionview (5.2.2.1)
19
+ activesupport (= 5.2.2.1)
20
+ builder (~> 3.1)
21
+ erubi (~> 1.4)
22
+ rails-dom-testing (~> 2.0)
23
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
24
+ activesupport (5.2.2.1)
25
+ concurrent-ruby (~> 1.0, >= 1.0.2)
26
+ i18n (>= 0.7, < 2)
27
+ minitest (~> 5.1)
28
+ tzinfo (~> 1.1)
29
+ addressable (2.6.0)
30
+ public_suffix (>= 2.0.2, < 4.0)
31
+ builder (3.2.3)
32
+ coderay (1.1.2)
33
+ concurrent-ruby (1.1.5)
34
+ crack (0.4.3)
35
+ safe_yaml (~> 1.0.0)
36
+ crass (1.0.4)
37
+ diff-lcs (1.3)
38
+ erubi (1.8.0)
39
+ faraday (0.15.4)
40
+ multipart-post (>= 1.2, < 3)
41
+ faraday_middleware (0.13.1)
42
+ faraday (>= 0.7.4, < 1.0)
43
+ generator_spec (0.9.4)
44
+ activesupport (>= 3.0.0)
45
+ railties (>= 3.0.0)
46
+ hashdiff (0.3.8)
47
+ i18n (1.6.0)
48
+ concurrent-ruby (~> 1.0)
49
+ loofah (2.2.3)
50
+ crass (~> 1.0.2)
51
+ nokogiri (>= 1.5.9)
52
+ method_source (0.9.2)
53
+ mini_portile2 (2.4.0)
54
+ minitest (5.11.3)
55
+ multipart-post (2.0.0)
56
+ nokogiri (1.10.1)
57
+ mini_portile2 (~> 2.4.0)
58
+ pry (0.12.2)
59
+ coderay (~> 1.1.0)
60
+ method_source (~> 0.9.0)
61
+ public_suffix (3.0.3)
62
+ rack (2.0.6)
63
+ rack-test (1.1.0)
64
+ rack (>= 1.0, < 3)
65
+ rails-dom-testing (2.0.3)
66
+ activesupport (>= 4.2.0)
67
+ nokogiri (>= 1.6)
68
+ rails-html-sanitizer (1.0.4)
69
+ loofah (~> 2.2, >= 2.2.2)
70
+ railties (5.2.2.1)
71
+ actionpack (= 5.2.2.1)
72
+ activesupport (= 5.2.2.1)
73
+ method_source
74
+ rake (>= 0.8.7)
75
+ thor (>= 0.19.0, < 2.0)
76
+ rake (12.3.2)
77
+ rspec (3.8.0)
78
+ rspec-core (~> 3.8.0)
79
+ rspec-expectations (~> 3.8.0)
80
+ rspec-mocks (~> 3.8.0)
81
+ rspec-core (3.8.0)
82
+ rspec-support (~> 3.8.0)
83
+ rspec-expectations (3.8.2)
84
+ diff-lcs (>= 1.2.0, < 2.0)
85
+ rspec-support (~> 3.8.0)
86
+ rspec-mocks (3.8.0)
87
+ diff-lcs (>= 1.2.0, < 2.0)
88
+ rspec-support (~> 3.8.0)
89
+ rspec-support (3.8.0)
90
+ safe_yaml (1.0.5)
91
+ thor (0.20.3)
92
+ thread_safe (0.3.6)
93
+ tzinfo (1.2.5)
94
+ thread_safe (~> 0.1)
95
+ vcr (4.0.0)
96
+ webmock (3.5.1)
97
+ addressable (>= 2.3.6)
98
+ crack (>= 0.3.2)
99
+ hashdiff
100
+
101
+ PLATFORMS
102
+ ruby
103
+
104
+ DEPENDENCIES
105
+ bundler (>= 1.17)
106
+ generator_spec (>= 0.9.4)
107
+ majestic-api!
108
+ pry (~> 0.12.2)
109
+ rake (>= 10.0)
110
+ rspec (>= 3.0)
111
+ vcr (>= 4.0)
112
+ webmock (>= 3.5.1)
113
+
114
+ BUNDLED WITH
115
+ 1.17.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Sebastian
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,25 @@
1
+ # Majestic Ruby API Client #
2
+
3
+ Client intended to be used with [Majestic's API](http://developer-support.majesticseo.com/).
4
+
5
+ This gem is forked/rewritten based on [https://github.com/SebastianJ/Majestic-SEO-Api](https://github.com/SebastianJ/Majestic-SEO-Api).
6
+
7
+ Majestic dropped the "SEO" brand a long time ago and the previous client's name was out of sync with this change.
8
+
9
+ The client has also been slightly rewritten and prepared to be easier to maintain.
10
+
11
+ ## Installation ##
12
+ ```
13
+ gem install majestic-api
14
+ ```
15
+
16
+ ## Configuration ##
17
+ ```
18
+ Majestic::Api.configure do |config|
19
+ config.environment = :production # The environment to use, valid values: :sandbox, :production
20
+ config.api_key = 'api_key' # Your API key provided by Majestic
21
+ config.verbose = false # Set to true to enable Faraday's logging middleware to get more information
22
+ end
23
+ ```
24
+
25
+ If you're using Rails, create an initializer in config/initializers/majestic.rb to configure the client globally in your app.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "majestic/api"
5
+ require "yaml"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ cfg_path = File.join(File.dirname(__FILE__), "../credentials.yml")
15
+
16
+ if File.exists?(cfg_path)
17
+ yaml = YAML.load_file(cfg_path)["development"]
18
+
19
+ Majestic::Api.configure do |config|
20
+ config.environment = yaml.fetch("environment", :sandbox)
21
+ config.api_key = yaml.fetch("api_key", nil)
22
+ config.verbose = true
23
+ end
24
+ end
25
+
26
+ # You can add fixtures and/or initialization code here to make experimenting
27
+ # with your gem easier. You can also use a different console, if you like.
28
+
29
+ require "pry"
30
+ Pry.config.history.file = File.join(__FILE__, "../.pry_history")
31
+ Pry.start
32
+
33
+ #require "irb"
34
+ #IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,40 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ require 'majestic/api/version'
5
+
6
+ if !String.instance_methods(false).include?(:underscore)
7
+ require 'majestic/api/extensions/string'
8
+ end
9
+
10
+ require 'majestic/api/configuration'
11
+
12
+ require 'majestic/api/logger'
13
+ require 'majestic/api/exceptions'
14
+
15
+ require 'majestic/api/response'
16
+ require 'majestic/api/item_info_response'
17
+ require 'majestic/api/item_info'
18
+ require 'majestic/api/client'
19
+
20
+ require 'majestic/api/railtie' if defined?(Rails)
21
+
22
+ module Majestic
23
+ module Api
24
+ class << self
25
+ attr_writer :configuration
26
+ end
27
+
28
+ def self.configuration
29
+ @configuration ||= ::Majestic::Api::Configuration.new
30
+ end
31
+
32
+ def self.reset
33
+ @configuration = ::Majestic::Api::Configuration.new
34
+ end
35
+
36
+ def self.configure
37
+ yield(configuration)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,106 @@
1
+ module Majestic
2
+ module Api
3
+
4
+ class Client
5
+ attr_accessor :configuration, :connection, :api_url
6
+ include Majestic::Api::Logger
7
+
8
+ def initialize(configuration: ::Majestic::Api.configuration)
9
+ self.configuration = configuration
10
+
11
+ set_api_url
12
+ set_connection
13
+ end
14
+
15
+ def set_api_url(format = :json)
16
+ self.api_url = case self.configuration.environment.to_sym
17
+ when :sandbox then "http://developer.majestic.com/api/#{format}"
18
+ when :production then "http://api.majestic.com/api/#{format}"
19
+ else
20
+ "http://developer.majestic.com/api/#{format}"
21
+ end
22
+ end
23
+
24
+ def set_connection(headers: {})
25
+ headers = {
26
+ "User-Agent" => self.configuration.user_agent,
27
+ "Content-Type" => "application/json"
28
+ }.merge(headers)
29
+
30
+ self.connection = Faraday.new(url: self.api_url, ssl: {verify: false}) do |builder|
31
+ builder.headers = headers
32
+
33
+ builder.request :url_encoded
34
+ builder.request :retry
35
+ builder.response :json
36
+ builder.response :logger if self.configuration.verbose
37
+ builder.adapter :net_http
38
+ end
39
+ end
40
+
41
+ def get_index_item_info(urls:, params: {}, options: {})
42
+ request_parameters = {}
43
+ request_parameters[:datasource] = params.fetch(:data_source, "historic")
44
+ request_parameters[:items] = urls.size
45
+
46
+ urls.each_with_index do |url, index|
47
+ request_parameters["item#{index}"] = url
48
+ end
49
+
50
+ response = self.execute_command("GetIndexItemInfo", params: request_parameters, options: options)
51
+ response = Majestic::Api::ItemInfoResponse.new(response)
52
+
53
+ return response
54
+ end
55
+
56
+ # This method will execute the specified command as an api request.
57
+ # 'name' is the name of the command you wish to execute, e.g. GetIndexItemInfo
58
+ # 'parameters' a hash containing the command parameters.
59
+ # 'timeout' specifies the amount of time to wait before aborting the transaction. This defaults to 5 seconds.
60
+ def execute_command(name, params: {}, options: {})
61
+ params.merge!({
62
+ app_api_key: self.configuration.api_key,
63
+ cmd: name
64
+ })
65
+
66
+ self.execute_request(params: params, options: options)
67
+ end
68
+
69
+ # This will execute the specified command as an OpenApp request.
70
+ # 'command_name' is the name of the command you wish to execute, e.g. GetIndexItemInfo
71
+ # 'parameters' a hash containing the command parameters.
72
+ # 'access_token' the token provided by the user to access their resources.
73
+ # 'timeout' specifies the amount of time to wait before aborting the transaction. This defaults to 5 seconds.
74
+ def execute_open_app_request(command_name, access_token, params: {}, options: {})
75
+ params.merge!({
76
+ accesstoken: access_token,
77
+ cmd: command_name,
78
+ privatekey: self.configuration.api_key
79
+ })
80
+
81
+ self.execute_request(params: params, options: options)
82
+ end
83
+
84
+ # 'parameters' a hash containing the command parameters.
85
+ # 'options' a hash containing command/call options (timeout, proxy settings etc)
86
+ def execute_request(params: {}, options: {})
87
+ response = nil
88
+
89
+ log(:info, "[Majestic::Api::Client] - Sending API Request to Majestic SEO. Parameters: #{params.inspect}. Options: #{options.inspect}")
90
+
91
+ response = self.connection.get do |request|
92
+ request.params = params if params && !params.empty?
93
+ request.options = options if options && !options.empty?
94
+ end
95
+
96
+ return response
97
+ end
98
+
99
+ def verbose
100
+ self.configuration.verbose
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,15 @@
1
+ module Majestic
2
+ module Api
3
+ class Configuration
4
+ attr_accessor :environment, :api_key, :verbose, :user_agent
5
+
6
+ def initialize
7
+ self.environment = :sandbox
8
+ self.api_key = nil
9
+ self.verbose = false
10
+ self.user_agent = "Ruby Majestic API Client v#{Majestic::Api::VERSION}"
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module Majestic
2
+ module Api
3
+ class InsufficientIndexItemInfoUnitsException < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ class String
2
+ def underscore
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+ end
10
+
@@ -0,0 +1,203 @@
1
+ module Majestic
2
+ module Api
3
+ class ItemInfo
4
+ attr_accessor :data, :mappings
5
+ attr_accessor :index, :type, :url, :result_code, :success, :error_message, :status
6
+ attr_accessor :external_backlinks, :referring_domains, :indexed_urls, :analysis_results_unit_cost, :ac_rank
7
+ attr_accessor :get_top_backlinks_analysis_results_unit_cost, :download_backlinks_analysis_results_unit_cost, :download_referring_domains_analysis_results_unit_cost
8
+ attr_accessor :referring_ip_addresses, :referring_subnets
9
+ attr_accessor :referring_edu_domains, :external_edu_backlinks, :referring_gov_domains, :external_gov_backlinks
10
+ attr_accessor :exact_referring_edu_domains, :exact_external_edu_backlinks, :exact_referring_gov_domains, :exact_external_gov_backlinks
11
+ attr_accessor :crawled, :last_crawl_date, :last_crawl_result, :redirecting, :final_redirect_result, :last_seen
12
+ attr_accessor :outbound_domain_links, :outbound_external_backliks, :outbound_internal_backlinks, :outbound_links_pages
13
+ attr_accessor :title, :redirecting_to
14
+ attr_accessor :citation_flow, :trust_flow, :trust_metric
15
+ attr_accessor :crawled_urls, :root_domain_ip_address
16
+ attr_accessor :language_codes, :language_descriptions, :language_confidences, :language_page_ratios, :language_total_pages
17
+ attr_accessor :referring_language_codes, :referring_language_descriptions, :referring_language_confidences, :referring_language_page_ratios, :referring_language_total_pages
18
+ attr_accessor :total_non_unique_links, :non_unique_link_types, :non_unique_link_types_mappings
19
+ attr_accessor :referring_domain_types, :referring_domain_types_mappings
20
+ attr_accessor :hash_mappings
21
+ attr_accessor :topical_trust_flows
22
+
23
+ # This method returns a new instance of the Response class.
24
+ # If one of the parameters are not provided, it will default to nil.
25
+ def initialize(data)
26
+ self.data = data
27
+
28
+ self.mappings = {
29
+ "ItemNum" => {:index => :integer},
30
+ "ItemType" => {:type => :integer},
31
+ "Item" => {:url => :string},
32
+ "ResultCode" => {:result_code => :string},
33
+ "Status" => {:status => :string},
34
+ "ExtBackLinks" => {:external_backlinks => :integer},
35
+ "RefDomains" => {:referring_domains => :integer},
36
+ "IndexedURLs" => {:indexed_urls => :integer},
37
+ "AnalysisResUnitsCost" => {:analysis_results_unit_cost => :integer},
38
+ "ACRank" => {:ac_rank => :integer},
39
+ "GetTopBackLinksAnalysisResUnitsCost" => {:get_top_backlinks_analysis_results_unit_cost => :integer},
40
+ "DownloadBacklinksAnalysisResUnitsCost" => {:download_backlinks_analysis_results_unit_cost => :integer},
41
+ "DownloadRefDomainBacklinksAnalysisResUnitsCost" => {:download_referring_domains_analysis_results_unit_cost => :integer},
42
+ "RefIPs" => {:referring_ip_addresses => :integer},
43
+ "RefSubNets" => {:referring_subnets => :integer},
44
+ "RefDomainsEDU" => {:referring_edu_domains => :integer},
45
+ "ExtBackLinksEDU" => {:external_edu_backlinks => :integer},
46
+ "RefDomainsGOV" => {:referring_gov_domains => :integer},
47
+ "ExtBackLinksGOV" => {:external_gov_backlinks => :integer},
48
+ "RefDomainsEDU_Exact" => {:exact_referring_edu_domains => :integer},
49
+ "ExtBackLinksEDU_Exact" => {:exact_external_edu_backlinks => :integer},
50
+ "RefDomainsGOV_Exact" => {:exact_referring_gov_domains => :integer},
51
+ "ExtBackLinksGOV_Exact" => {:exact_external_gov_backlinks => :integer},
52
+ "CrawledFlag" => {:crawled => :boolean},
53
+ "LastCrawlDate" => {:last_crawl_date => :date},
54
+ "LastCrawlResult" => {:last_crawl_result => :string},
55
+ "RedirectFlag" => {:redirecting => :boolean},
56
+ "FinalRedirectResult" => {:final_redirect_result => :string},
57
+ "LastSeen" => {:last_seen => :string},
58
+ "OutDomainsExternal" => {:outbound_domain_links => :integer},
59
+ "OutLinksExternal" => {:outbound_external_backliks => :integer},
60
+ "OutLinksInternal" => {:outbound_internal_backlinks => :integer},
61
+ "OutLinksPages" => {:outbound_links_pages => :integer},
62
+ "Title" => {:title => :string},
63
+ "RedirectTo" => {:redirecting_to => :string},
64
+ "CitationFlow" => {:citation_flow => :integer},
65
+ "TrustFlow" => {:trust_flow => :integer},
66
+ "TrustMetric" => {:trust_metric => :integer},
67
+ "CrawledURLs" => {:crawled_urls => :integer},
68
+ "RootDomainIPAddress" => {:root_domain_ip_address => :string},
69
+ "Language" => {:language_codes => :string_array},
70
+ "LanguageDesc" => {:language_descriptions => :string_array},
71
+ "LanguageConfidence" => {:language_confidences => :integer_array},
72
+ "LanguagePageRatios" => {:language_page_ratios => :float_array},
73
+ "LanguageTotalPages" => {:language_total_pages => :integer},
74
+ "RefLanguage" => {:referring_language_codes => :string_array},
75
+ "RefLanguageDesc" => {:referring_language_descriptions => :string_array},
76
+ "RefLanguageConfidence" => {:referring_language_confidences => :integer_array},
77
+ "RefLanguagePageRatios" => {:referring_language_page_ratios => :float_array},
78
+ "RefLanguageTotalPages" => {:referring_language_total_pages => :integer},
79
+ "TotalNonUniqueLinks" => {:total_non_unique_links => :integer},
80
+ }
81
+
82
+ self.non_unique_link_types = {}
83
+
84
+ self.non_unique_link_types_mappings = {
85
+ "NonUniqueLinkTypeHomepages" => {:homepages => :integer},
86
+ "NonUniqueLinkTypeIndirect" => {:indirect => :integer},
87
+ "NonUniqueLinkTypeDeleted" => {:deleted => :integer},
88
+ "NonUniqueLinkTypeNoFollow" => {:no_follow => :integer},
89
+ "NonUniqueLinkTypeProtocolHTTPS" => {:https => :integer},
90
+ "NonUniqueLinkTypeFrame" => {:frame => :integer},
91
+ "NonUniqueLinkTypeImageLink" => {:image_link => :integer},
92
+ "NonUniqueLinkTypeRedirect" => {:redirect => :integer},
93
+ "NonUniqueLinkTypeTextLink" => {:text_link => :integer},
94
+ }
95
+
96
+ self.referring_domain_types = {}
97
+
98
+ self.referring_domain_types_mappings = {
99
+ "RefDomainTypeLive" => {:live => :integer},
100
+ "RefDomainTypeFollow" => {:follow => :integer},
101
+ "RefDomainTypeHomepageLink" => {:homepage_link => :integer},
102
+ "RefDomainTypeDirect" => {:direct => :integer},
103
+ "RefDomainTypeProtocolHTTPS" => {:https => :integer},
104
+ }
105
+
106
+ self.hash_mappings = {
107
+ /^NonUniqueLinkType/i => :non_unique_link_types,
108
+ /^RefDomainType/i => :referring_domain_types
109
+ }
110
+
111
+ self.topical_trust_flows = {}
112
+
113
+ parse_item_info
114
+ end
115
+
116
+ def parse_item_info
117
+ self.data.each do |api_column, api_value|
118
+ column, value = parse_field(self.mappings, api_column, api_value)
119
+ self.send("#{column}=", value) if !column.nil? && !value.nil?
120
+ end
121
+
122
+ parse_hashes
123
+ parse_topical_trust_flows
124
+ set_result_status
125
+ set_item_type
126
+ end
127
+
128
+ def parse_hashes
129
+ self.data.each do |api_column, api_value|
130
+ self.hash_mappings.each do |regex, mappings_symbol|
131
+ if api_column =~ regex
132
+ column_mapping = self.send("#{mappings_symbol}_mappings".to_sym)
133
+ column, value = parse_field(column_mapping, api_column, api_value)
134
+ self.send(mappings_symbol)[column] = value if !column.nil? && !value.nil?
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ def parse_topical_trust_flows
141
+ self.data.each do |api_column, api_value|
142
+ if api_column =~ /^TopicalTrustFlow_Topic_\d*/i
143
+ topic = api_value.to_s
144
+ index = api_column.match(/TopicalTrustFlow_Topic_(?<index>\d*)/i)[:index].to_i
145
+ value = self.data.fetch("TopicalTrustFlow_Value_#{index}", nil)
146
+
147
+ self.topical_trust_flows[index] = {topic: topic, value: value.to_i} if !index.nil? && !topic.empty? && !value.nil?
148
+ end
149
+ end
150
+ end
151
+
152
+ def parse_field(column_mapping, api_column, api_value)
153
+ column = nil
154
+ value = nil
155
+
156
+ mapping = column_mapping.fetch(api_column, nil)
157
+
158
+ mapping.each do |col, data_type|
159
+ column = col
160
+ value = convert_value(api_value.to_s, col, data_type)
161
+ end if mapping && !mapping.empty? && !api_value.to_s.empty?
162
+
163
+ return column, value
164
+ end
165
+
166
+ def convert_value(value, column, data_type)
167
+ return case data_type
168
+ when :string
169
+ value.to_s
170
+ when :integer
171
+ value.to_i
172
+ when :float
173
+ value.to_f
174
+ when :date
175
+ value.to_s
176
+ when :boolean
177
+ value.to_s.downcase.eql?("true")
178
+ when :string_array
179
+ value.to_s.include?(",") ? value.to_s.split(",").collect { |val| val.to_s } : [value.to_s]
180
+ when :integer_array
181
+ value.to_s.include?(",") ? value.to_s.split(",").collect { |val| val.to_i } : [value.to_s]
182
+ when :float_array
183
+ value.to_s.include?(",") ? value.to_s.split(",").collect { |val| val.to_f } : [value.to_s]
184
+ end
185
+ end
186
+
187
+ def set_result_status
188
+ self.success = (self.result_code && self.result_code.downcase.eql?("ok"))
189
+ self.error_message = self.success ? "" : self.result_code
190
+ end
191
+
192
+ def set_item_type
193
+ self.type = case self.type
194
+ when 1 then :root_domain
195
+ when 2 then :sub_domain
196
+ when 3 then :url
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ end
203
+ end
@@ -0,0 +1,28 @@
1
+ module Majestic
2
+ module Api
3
+ class ItemInfoResponse < Response
4
+
5
+ def initialize(response)
6
+ super(response)
7
+
8
+ raise_exceptions_if_necessary
9
+ parse_item_info_objects
10
+ end
11
+
12
+ def raise_exceptions_if_necessary
13
+ case self.code
14
+ when 'InsufficientIndexItemInfoUnits'
15
+ raise Majestic::Api::InsufficientIndexItemInfoUnitsException.new(self.error_message)
16
+ end unless success?
17
+ end
18
+
19
+ def parse_item_info_objects
20
+ self.parsed_items.each do |parsed_item|
21
+ item_info = Majestic::Api::ItemInfo.new(parsed_item)
22
+ self.items << item_info unless self.items.include?(item_info)
23
+ end if self.parsed_items && self.parsed_items.any?
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ module Majestic
2
+ module Api
3
+ module Logger
4
+
5
+ def log(level, message)
6
+ if (self.respond_to?(:verbose) && self.verbose)
7
+ (defined?(Rails) && Rails.logger) ? Rails.logger.send(level, message) : puts(message)
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,12 @@
1
+ require 'majestic/api'
2
+ require 'rails'
3
+
4
+ module Majestic
5
+ class Railtie < Rails::Railtie
6
+
7
+ #rake_tasks do
8
+ # Dir[File.join(File.dirname(__FILE__), '../tasks/*.rake')].each { |ext| load ext }
9
+ #end
10
+
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ module Majestic
2
+ module Api
3
+ class Response
4
+ attr_accessor :response, :code, :success, :error_message, :full_error, :items, :parsed_items
5
+
6
+ def initialize(response = nil)
7
+ self.response = response
8
+ self.success = false
9
+ self.items = []
10
+ self.parsed_items = []
11
+
12
+ parse_response
13
+ end
14
+
15
+ def parse_response
16
+ if self.response.is_a?(Faraday::Response)
17
+ self.response = (self.response && self.response.body) ? self.response.body : nil
18
+
19
+ if self.response
20
+ self.code = self.response.fetch("Code", "")
21
+ self.success = self.code.downcase.eql?("ok")
22
+ self.error_message = self.response.fetch("ErrorMessage", "")
23
+ self.full_error = self.response.fetch("FullError", "")
24
+
25
+ if success?
26
+ self.parsed_items = self.response.fetch("DataTables", {}).fetch("Results", {}).fetch("Data", [])
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def success?
33
+ self.success
34
+ end
35
+
36
+ def stacktrace
37
+ self.full_error
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
44
+
@@ -0,0 +1,5 @@
1
+ module Majestic
2
+ module Api
3
+ VERSION = "1.4.0"
4
+ end
5
+ end
@@ -0,0 +1,49 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "majestic/api/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "majestic-api"
8
+ spec.version = Majestic::Api::VERSION
9
+ spec.authors = ["Sebastian Johnsson"]
10
+ spec.email = ["sebastian.johnsson@gmail.com"]
11
+
12
+ spec.summary = %q{Majestic Ruby API Client}
13
+ spec.description = %q{Ruby client to interact with Majestic's API}
14
+ spec.homepage = "https://github.com/SebastianJ/majestic-api"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata["homepage_uri"] = spec.homepage
21
+ spec.metadata["source_code_uri"] = "https://github.com/SebastianJ/majestic-api"
22
+ spec.metadata["changelog_uri"] = "https://github.com/SebastianJ/majestic-api/CHANGELOG.md"
23
+ else
24
+ raise "RubyGems 2.0 or newer is required to protect against " \
25
+ "public gem pushes."
26
+ end
27
+
28
+ # Specify which files should be added to the gem when it is released.
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+ spec.bindir = "exe"
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ["lib"]
36
+
37
+ spec.add_dependency "faraday", ">= 0.15.4"
38
+ spec.add_dependency "faraday_middleware", ">= 0.13.1"
39
+
40
+ spec.add_development_dependency "bundler", ">= 1.17"
41
+ spec.add_development_dependency "rake", ">= 10.0"
42
+ spec.add_development_dependency "rspec", ">= 3.0"
43
+ spec.add_development_dependency "vcr", ">= 4.0"
44
+ spec.add_development_dependency "webmock", ">= 3.5.1"
45
+
46
+ spec.add_development_dependency "generator_spec", ">= 0.9.4"
47
+
48
+ spec.add_development_dependency "pry", "~> 0.12.2"
49
+ end
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: majestic-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Sebastian Johnsson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-03-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.15.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.15.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.13.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.13.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.17'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '1.17'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: vcr
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '4.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '4.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 3.5.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 3.5.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: generator_spec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 0.9.4
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 0.9.4
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.12.2
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.12.2
139
+ description: Ruby client to interact with Majestic's API
140
+ email:
141
+ - sebastian.johnsson@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".DS_Store"
147
+ - ".gitignore"
148
+ - CODE_OF_CONDUCT.md
149
+ - Gemfile
150
+ - Gemfile.lock
151
+ - LICENSE.txt
152
+ - README.markdown
153
+ - Rakefile
154
+ - bin/console
155
+ - bin/setup
156
+ - lib/majestic/api.rb
157
+ - lib/majestic/api/client.rb
158
+ - lib/majestic/api/configuration.rb
159
+ - lib/majestic/api/exceptions.rb
160
+ - lib/majestic/api/extensions/string.rb
161
+ - lib/majestic/api/item_info.rb
162
+ - lib/majestic/api/item_info_response.rb
163
+ - lib/majestic/api/logger.rb
164
+ - lib/majestic/api/railtie.rb
165
+ - lib/majestic/api/response.rb
166
+ - lib/majestic/api/version.rb
167
+ - majestic-api.gemspec
168
+ homepage: https://github.com/SebastianJ/majestic-api
169
+ licenses:
170
+ - MIT
171
+ metadata:
172
+ homepage_uri: https://github.com/SebastianJ/majestic-api
173
+ source_code_uri: https://github.com/SebastianJ/majestic-api
174
+ changelog_uri: https://github.com/SebastianJ/majestic-api/CHANGELOG.md
175
+ post_install_message:
176
+ rdoc_options: []
177
+ require_paths:
178
+ - lib
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ requirements: []
190
+ rubygems_version: 3.0.3
191
+ signing_key:
192
+ specification_version: 4
193
+ summary: Majestic Ruby API Client
194
+ test_files: []