webmaster 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,9 @@
1
+ class Object
2
+ def blank?
3
+ !self
4
+ end unless method_defined? :blank?
5
+
6
+ def present?
7
+ !blank?
8
+ end unless method_defined? :present?
9
+ end