webmaster 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +85 -0
- data/LICENSE.txt +20 -0
- data/README.md +94 -0
- data/Rakefile +46 -0
- data/lib/webmaster.rb +66 -0
- data/lib/webmaster/api/authorization.rb +59 -0
- data/lib/webmaster/api/connection.rb +87 -0
- data/lib/webmaster/api/request.rb +62 -0
- data/lib/webmaster/base.rb +159 -0
- data/lib/webmaster/client.rb +15 -0
- data/lib/webmaster/configuration.rb +111 -0
- data/lib/webmaster/core_ext/hash.rb +87 -0
- data/lib/webmaster/core_ext/object.rb +9 -0
- data/lib/webmaster/core_ext/string.rb +9 -0
- data/lib/webmaster/errors.rb +21 -0
- data/lib/webmaster/host.rb +154 -0
- data/lib/webmaster/hosts/crawling.rb +24 -0
- data/lib/webmaster/hosts/verification.rb +77 -0
- data/lib/webmaster/request/oauth2.rb +26 -0
- data/lib/webmaster/response/hashify.rb +59 -0
- data/lib/webmaster/version.rb +12 -0
- data/test/helper.rb +18 -0
- data/test/test_webmaster.rb +7 -0
- data/webmaster.gemspec +196 -0
- metadata +796 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Webmaster
|
4
|
+
module Api
|
5
|
+
|
6
|
+
# Defines HTTP verbs
|
7
|
+
module Request
|
8
|
+
|
9
|
+
METHODS = [:get, :post, :put, :delete]
|
10
|
+
METHODS_WITH_BODIES = [:post, :put]
|
11
|
+
|
12
|
+
def get_request(path, params={}, options={})
|
13
|
+
request(:get, path, params, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_request(path, params={}, options={})
|
17
|
+
request(:post, path, params, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def put_request(path, params={}, options={})
|
21
|
+
request(:put, path, params, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_request(path, params={}, options={})
|
25
|
+
request(:delete, path, params, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def request(method, path, params = {}, options = {})
|
29
|
+
if !METHODS.include?(method)
|
30
|
+
raise ArgumentError, "unkown http method: #{method}"
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "EXECUTED: #{method} - #{path} with #{params} and #{options}" if ENV['DEBUG']
|
34
|
+
|
35
|
+
conn = connection(options)
|
36
|
+
if conn.path_prefix != '/' && path.index(conn.path_prefix) != 0 && !path.start_with?('https://', 'http://')
|
37
|
+
path = (conn.path_prefix + path).gsub(/\/(\/)*/, '/')
|
38
|
+
end
|
39
|
+
|
40
|
+
response = conn.send(method) do |request|
|
41
|
+
case method.to_sym
|
42
|
+
when *(METHODS - METHODS_WITH_BODIES)
|
43
|
+
request.body = params.delete('data') if params.has_key?('data')
|
44
|
+
request.url(path, params)
|
45
|
+
when *METHODS_WITH_BODIES
|
46
|
+
request.url(path)
|
47
|
+
request.body = self.extract_data_from_params(params) unless params.empty?
|
48
|
+
request.headers['Content-Length'] = request.body.size.to_s
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def extract_data_from_params(params) # :nodoc:
|
56
|
+
return params['data'] if params.is_a?(Hash) && params.has_key?('data') && !params['data'].nil?
|
57
|
+
return params[:data] if params.is_a?(Hash) && params.has_key?(:data) && !params[:data].nil?
|
58
|
+
return params
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'webmaster/configuration'
|
4
|
+
|
5
|
+
require 'webmaster/api/authorization'
|
6
|
+
require 'webmaster/api/connection'
|
7
|
+
require 'webmaster/api/request'
|
8
|
+
|
9
|
+
module Webmaster
|
10
|
+
class Base
|
11
|
+
include Api::Authorization
|
12
|
+
include Api::Connection
|
13
|
+
include Api::Request
|
14
|
+
|
15
|
+
attr_accessor :configuration
|
16
|
+
|
17
|
+
def initialize(attributes = {})
|
18
|
+
self.configuration = Webmaster::Configuration.instance.setup(attributes.delete(:configuration) || {})
|
19
|
+
self.attributes = attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
def attributes=(attributes = {})
|
23
|
+
attributes.each do |attr,value|
|
24
|
+
self.send("#{attr}=", value) if self.respond_to?("#{attr}=")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
inspection = if self.respond_to?(:attributes) && self.attributes.any?
|
30
|
+
self.attributes.collect { |attribute, value|
|
31
|
+
"#{attribute}: #{value}" if value.present?
|
32
|
+
}.compact.join(', ')
|
33
|
+
else
|
34
|
+
self.instance_variables.map{ |variable|
|
35
|
+
"#{variable}: #{instance_variable_get(variable).inspect}"
|
36
|
+
}.compact.join(', ')
|
37
|
+
end
|
38
|
+
|
39
|
+
"#<#{self.class} #{inspection}>"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Configure options and process basic authorization
|
43
|
+
# def setup(options={})
|
44
|
+
# options = Webmaster.options.merge(options)
|
45
|
+
# self.current_options = options
|
46
|
+
# Configuration.keys.each do |key|
|
47
|
+
# send("#{key}=", options[key])
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
|
51
|
+
# Responds to attribute query or attribute clear
|
52
|
+
def method_missing(method, *args, &block) # :nodoc:
|
53
|
+
case method.to_s
|
54
|
+
when /^(.*)\?$/
|
55
|
+
return !!self.send($1.to_s)
|
56
|
+
when /^clear_(.*)$/
|
57
|
+
self.send("#{$1.to_s}=", nil)
|
58
|
+
else
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Acts as setter and getter for api requests arguments parsing.
|
64
|
+
#
|
65
|
+
# Returns Arguments instance.
|
66
|
+
#
|
67
|
+
def arguments(args=(not_set = true), options={}, &block)
|
68
|
+
if not_set
|
69
|
+
@arguments
|
70
|
+
else
|
71
|
+
@arguments = Arguments.new(self, options).parse(*args, &block)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Scope for passing request required arguments.
|
76
|
+
#
|
77
|
+
def with(args)
|
78
|
+
case args
|
79
|
+
when Hash
|
80
|
+
set args
|
81
|
+
when /.*\/.*/i
|
82
|
+
user, repo = args.split('/')
|
83
|
+
set :user => user, :repo => repo
|
84
|
+
else
|
85
|
+
::Kernel.raise ArgumentError, 'This api does not support passed in arguments'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Set an option to a given value
|
90
|
+
def set(option, value=(not_set=true), ignore_setter=false, &block)
|
91
|
+
raise ArgumentError, 'value not set' if block and !not_set
|
92
|
+
return self if !not_set and value.nil?
|
93
|
+
|
94
|
+
if not_set
|
95
|
+
set_options option
|
96
|
+
return self
|
97
|
+
end
|
98
|
+
|
99
|
+
if respond_to?("#{option}=") and not ignore_setter
|
100
|
+
return __send__("#{option}=", value)
|
101
|
+
end
|
102
|
+
|
103
|
+
define_accessors option, value
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
protected
|
108
|
+
|
109
|
+
# Set multiple options
|
110
|
+
#
|
111
|
+
def set_options(options)
|
112
|
+
unless options.respond_to?(:each)
|
113
|
+
raise ArgumentError, 'cannot iterate over value'
|
114
|
+
end
|
115
|
+
options.each { |key, value| set(key, value) }
|
116
|
+
end
|
117
|
+
|
118
|
+
def define_accessors(option, value)
|
119
|
+
setter = proc { |val| set option, val, true }
|
120
|
+
getter = proc { value }
|
121
|
+
|
122
|
+
define_singleton_method("#{option}=", setter) if setter
|
123
|
+
define_singleton_method(option, getter) if getter
|
124
|
+
end
|
125
|
+
|
126
|
+
# Dynamically define a method for setting request option
|
127
|
+
#
|
128
|
+
def define_singleton_method(method_name, content=Proc.new)
|
129
|
+
(class << self; self; end).class_eval do
|
130
|
+
undef_method(method_name) if method_defined?(method_name)
|
131
|
+
if String === content
|
132
|
+
class_eval("def #{method_name}() #{content}; end")
|
133
|
+
else
|
134
|
+
define_method(method_name, &content)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def objects_from_response(klass, response, prefix)
|
140
|
+
self.objects_from_array(klass, self.fetch_value(response, prefix))
|
141
|
+
end
|
142
|
+
|
143
|
+
def fetch_value(response, prefix)
|
144
|
+
response.body[prefix]
|
145
|
+
end
|
146
|
+
|
147
|
+
# @param klass [Class]
|
148
|
+
# @param array [Array]
|
149
|
+
# @return [Array<Class>]
|
150
|
+
def objects_from_array(klass, array)
|
151
|
+
array.map do |attributes|
|
152
|
+
instance = klass.new
|
153
|
+
instance.configuration = self.configuration
|
154
|
+
instance.attributes = attributes
|
155
|
+
instance
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Webmaster
|
4
|
+
class Client < Base
|
5
|
+
def hosts(reload = false)
|
6
|
+
@hosts = nil if reload
|
7
|
+
@hosts ||= self.objects_from_response(Webmaster::Host, self.request(:get, '/hosts'), :host)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_host(name)
|
11
|
+
xml = "<host><name>#{name}</name></host>"
|
12
|
+
self.request(:post, '/hosts', xml)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Webmaster
|
6
|
+
class Configuration
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
VALID_OPTIONS_KEYS = [
|
10
|
+
:adapter,
|
11
|
+
:app_id,
|
12
|
+
:app_password,
|
13
|
+
:oauth_token,
|
14
|
+
:endpoint,
|
15
|
+
:site,
|
16
|
+
:ssl,
|
17
|
+
:user_agent,
|
18
|
+
:connection_options
|
19
|
+
].freeze
|
20
|
+
|
21
|
+
# Other adapters are :typhoeus, :patron, :em_synchrony, :excon, :test
|
22
|
+
DEFAULT_ADAPTER = :net_http
|
23
|
+
|
24
|
+
# By default, don't set an application id
|
25
|
+
DEFAULT_APP_ID = nil
|
26
|
+
|
27
|
+
# By default, don't set an application password
|
28
|
+
DEFAULT_APP_PASSWORD = nil
|
29
|
+
|
30
|
+
# By default, don't set a user oauth access token
|
31
|
+
DEFAULT_OAUTH_TOKEN = nil
|
32
|
+
|
33
|
+
# By default, don't set a user login name
|
34
|
+
DEFAULT_LOGIN = nil
|
35
|
+
|
36
|
+
# By default, don't set a user password
|
37
|
+
DEFAULT_PASSWORD = nil
|
38
|
+
|
39
|
+
# By default, don't set a user basic authentication
|
40
|
+
DEFAULT_BASIC_AUTH = nil
|
41
|
+
|
42
|
+
# The api endpoint used to connect to Yandex.Webmaster if none is set
|
43
|
+
DEFAULT_ENDPOINT = 'https://webmaster.yandex.ru/api/v2/'.freeze
|
44
|
+
|
45
|
+
# The web endpoint used to connect to Yandex.Webmaster if none is set
|
46
|
+
DEFAULT_SITE = 'https://oauth.yandex.ru/'.freeze
|
47
|
+
|
48
|
+
# The default SSL configuration
|
49
|
+
DEFAULT_SSL = {}
|
50
|
+
|
51
|
+
# The value sent in the http header for 'User-Agent' if none is set
|
52
|
+
DEFAULT_USER_AGENT = "Webmaster Ruby Gem #{Webmaster::Version::STRING}".freeze
|
53
|
+
|
54
|
+
# By default uses the Faraday connection options if none is set
|
55
|
+
DEFAULT_CONNECTION_OPTIONS = {}
|
56
|
+
|
57
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
58
|
+
|
59
|
+
def initialize
|
60
|
+
super
|
61
|
+
self.reset!
|
62
|
+
end
|
63
|
+
|
64
|
+
def keys
|
65
|
+
VALID_OPTIONS_KEYS
|
66
|
+
end
|
67
|
+
|
68
|
+
def current
|
69
|
+
VALID_OPTIONS_KEYS.inject({}) { |h, k| h[k] = send(k); h }
|
70
|
+
end
|
71
|
+
|
72
|
+
def setup(options = {})
|
73
|
+
raise ArgumentError if (options.symbolize_keys!.keys - VALID_OPTIONS_KEYS).any?
|
74
|
+
options.each { |k,v| send("#{k}=", v) }
|
75
|
+
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
# Reset configuration options to their defaults
|
80
|
+
#
|
81
|
+
def reset!
|
82
|
+
self.adapter = DEFAULT_ADAPTER
|
83
|
+
self.app_id = DEFAULT_APP_ID
|
84
|
+
self.app_password = DEFAULT_APP_PASSWORD
|
85
|
+
self.oauth_token = DEFAULT_OAUTH_TOKEN
|
86
|
+
self.endpoint = DEFAULT_ENDPOINT
|
87
|
+
self.site = DEFAULT_SITE
|
88
|
+
self.ssl = DEFAULT_SSL
|
89
|
+
self.user_agent = DEFAULT_USER_AGENT
|
90
|
+
self.connection_options = DEFAULT_CONNECTION_OPTIONS
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
# Convenience method to allow for global setting of configuration options
|
95
|
+
def configure
|
96
|
+
yield self
|
97
|
+
end
|
98
|
+
|
99
|
+
# Responds to attribute query or attribute clear
|
100
|
+
def method_missing(method, *args, &block) # :nodoc:
|
101
|
+
case method.to_s
|
102
|
+
when /^(.*)\?$/
|
103
|
+
return !!self.send($1.to_s)
|
104
|
+
when /^clear_(.*)$/
|
105
|
+
self.send("#{$1.to_s}=", nil)
|
106
|
+
else
|
107
|
+
super
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
class Hash # :nodoc:
|
2
|
+
|
3
|
+
def except(*items) # :nodoc:
|
4
|
+
self.dup.except!(*items)
|
5
|
+
end unless method_defined?(:except)
|
6
|
+
|
7
|
+
def except!(*keys) # :nodoc:
|
8
|
+
copy = self.dup
|
9
|
+
keys.each { |key| copy.delete!(key) }
|
10
|
+
copy
|
11
|
+
end unless method_defined?(:except!)
|
12
|
+
|
13
|
+
def slice(*keys)
|
14
|
+
keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
|
15
|
+
hash = self.class.new
|
16
|
+
keys.each { |k| hash[k] = self[k] if has_key?(k) }
|
17
|
+
hash
|
18
|
+
end unless method_defined?(:slice)
|
19
|
+
|
20
|
+
def slice!(*keys)
|
21
|
+
keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
|
22
|
+
omit = slice(*self.keys - keys)
|
23
|
+
hash = slice(*keys)
|
24
|
+
replace(hash)
|
25
|
+
omit
|
26
|
+
end unless method_defined?(:slice!)
|
27
|
+
|
28
|
+
def symbolize_keys # :nodoc:
|
29
|
+
inject({}) do |hash, (key, value)|
|
30
|
+
hash[(key.to_sym rescue key) || key] = value
|
31
|
+
hash
|
32
|
+
end
|
33
|
+
end unless method_defined?(:symbolize_keys)
|
34
|
+
|
35
|
+
def symbolize_keys! # :nodoc:
|
36
|
+
hash = symbolize_keys
|
37
|
+
hash.each do |key, val|
|
38
|
+
hash[key] = case val
|
39
|
+
when Hash
|
40
|
+
val.symbolize_keys!
|
41
|
+
when Array
|
42
|
+
val.map do |item|
|
43
|
+
item.is_a?(Hash) ? item.symbolize_keys! : item
|
44
|
+
end
|
45
|
+
else
|
46
|
+
val
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return hash
|
50
|
+
end unless method_defined?(:symbolize_keys!)
|
51
|
+
|
52
|
+
def serialize # :nodoc:
|
53
|
+
self.map { |key, val| [key, val].join("=") }.join("&")
|
54
|
+
end unless method_defined?(:serialize)
|
55
|
+
|
56
|
+
def all_keys # :nodoc:
|
57
|
+
keys = self.keys
|
58
|
+
keys.each do |key|
|
59
|
+
if self[key].is_a?(Hash)
|
60
|
+
keys << self[key].all_keys.compact.flatten
|
61
|
+
next
|
62
|
+
end
|
63
|
+
end
|
64
|
+
keys.flatten
|
65
|
+
end unless method_defined?(:all_keys)
|
66
|
+
|
67
|
+
def has_deep_key?(key)
|
68
|
+
self.all_keys.include? key
|
69
|
+
end unless method_defined?(:has_deep_key?)
|
70
|
+
|
71
|
+
def self.hash_traverse(hash, &block)
|
72
|
+
hash.each do |key, val|
|
73
|
+
block.call(key)
|
74
|
+
case val
|
75
|
+
when Hash
|
76
|
+
val.keys.each do |k|
|
77
|
+
_hash_traverse(val, &block)
|
78
|
+
end
|
79
|
+
when Array
|
80
|
+
val.each do |item|
|
81
|
+
_hash_traverse(item, &block)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
return hash
|
86
|
+
end
|
87
|
+
end # Hash
|