yandex_client 0.2.0 → 1.0.1
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.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +30 -0
- data/.gitignore +2 -0
- data/.pryrc +6 -0
- data/.rubocop.yml +7 -1
- data/Gemfile +2 -0
- data/README.md +31 -94
- data/dip.yml +8 -11
- data/docker/Dockerfile.dip +8 -0
- data/docker/docker-compose.yml +16 -8
- data/docker/prepare_env.sh +11 -0
- data/lib/yandex_client/auth.rb +62 -0
- data/lib/yandex_client/configurable.rb +26 -0
- data/lib/yandex_client/dav/prop_find_response.rb +70 -0
- data/lib/yandex_client/dav.rb +104 -0
- data/lib/yandex_client/disk.rb +60 -0
- data/lib/yandex_client/error_handler.rb +20 -0
- data/lib/yandex_client/passport.rb +45 -0
- data/lib/yandex_client/version.rb +1 -1
- data/lib/yandex_client.rb +38 -23
- data/yandex_client.gemspec +2 -1
- metadata +32 -18
- data/.travis.yml +0 -12
- data/docker/Dockerfile.2.6 +0 -13
- data/docker/docker-compose.development.yml +0 -18
- data/lib/yandex_client/api_request_error.rb +0 -15
- data/lib/yandex_client/auth/client.rb +0 -57
- data/lib/yandex_client/client.rb +0 -98
- data/lib/yandex_client/dav/client.rb +0 -117
- data/lib/yandex_client/dav/propfind_parser.rb +0 -51
- data/lib/yandex_client/disk/client.rb +0 -47
- data/lib/yandex_client/not_found_error.rb +0 -6
- data/lib/yandex_client/passport/client.rb +0 -36
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
require 'http'
|
5
|
+
require 'yandex_client/dav/prop_find_response'
|
6
|
+
|
7
|
+
module YandexClient
|
8
|
+
# https://tech.yandex.ru/disk/doc/dg/reference/put-docpage/
|
9
|
+
#
|
10
|
+
# Chainable client:
|
11
|
+
#
|
12
|
+
# YandexClient::Dav[access_token]
|
13
|
+
# .put('1.txt', '/a/b/c/1.txt')
|
14
|
+
# .put(File.open('1.txt', 'rb'), '/path/to/1.txt')
|
15
|
+
# .put(Tempfile.new.tap { |t| t.write('say ni'); t.rewind }, '/path/to/tmp.txt')
|
16
|
+
# .delete('/a/b/c/1.txt')
|
17
|
+
# .mkcol('/a/b/c')
|
18
|
+
# .propfind('/a/dip.yml', depth: 0)
|
19
|
+
# .propfind('/a', depth: 1)
|
20
|
+
# .propfind.to_a
|
21
|
+
class Dav
|
22
|
+
include Configurable
|
23
|
+
include ErrorHandler
|
24
|
+
|
25
|
+
ACTION_URL = 'https://webdav.yandex.ru'
|
26
|
+
PROPFIND_QUERY = '<?xml version="1.0" encoding="utf-8"?><propfind xmlns="DAV:"></propfind>'
|
27
|
+
|
28
|
+
attr_reader :token
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def with_token(token)
|
32
|
+
new(token)
|
33
|
+
end
|
34
|
+
|
35
|
+
alias [] with_token
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(token)
|
39
|
+
@token = token
|
40
|
+
end
|
41
|
+
|
42
|
+
def put(file, dest, etag: nil, sha256: nil, size: nil)
|
43
|
+
io = file.is_a?(String) ? File.open(file, 'rb') : file
|
44
|
+
|
45
|
+
headers = auth_headers.merge!(
|
46
|
+
'Etag' => etag || Digest::MD5.file(io.path),
|
47
|
+
'Sha256' => sha256 || Digest::SHA256.file(io.path),
|
48
|
+
'Expect' => '100-continue',
|
49
|
+
'Content-Length' => (size || File.size(io.path)).to_s
|
50
|
+
)
|
51
|
+
|
52
|
+
process_response with_config.put(url_for(dest), body: io, headers: headers)
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete(dest)
|
56
|
+
process_response with_config.delete(
|
57
|
+
url_for(dest),
|
58
|
+
headers: auth_headers
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def mkcol(dest)
|
63
|
+
process_response with_config.request(
|
64
|
+
:mkcol,
|
65
|
+
url_for(dest),
|
66
|
+
headers: auth_headers
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def propfind(dest = '', depth = 1)
|
71
|
+
headers = auth_headers.merge!(
|
72
|
+
Depth: depth.to_s,
|
73
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
74
|
+
'Content-Length' => PROPFIND_QUERY.length
|
75
|
+
)
|
76
|
+
|
77
|
+
response = with_config.request(:propfind, url_for(dest), headers: headers, body: PROPFIND_QUERY)
|
78
|
+
process_response(response)
|
79
|
+
|
80
|
+
PropFindResponse.new(response.body.to_s)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def auth_headers
|
86
|
+
{Authorization: "OAuth #{token}"}
|
87
|
+
end
|
88
|
+
|
89
|
+
def url_for(dest)
|
90
|
+
URI.parse(ACTION_URL).tap do |uri|
|
91
|
+
path = dest
|
92
|
+
path = "/#{path}" unless path.match?(%r{^/})
|
93
|
+
|
94
|
+
uri.path = path
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def process_response(response)
|
99
|
+
return self if response.status.success?
|
100
|
+
|
101
|
+
error_for_response(response)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module YandexClient
|
6
|
+
# https://yandex.ru/dev/disk/api/reference/capacity-docpage/
|
7
|
+
# https://yandex.ru/dev/disk/api/reference/content-docpage/
|
8
|
+
#
|
9
|
+
# YandexClient::Disk[access_token].info
|
10
|
+
# YandexClient::Disk[access_token].download_url('path/to/file')
|
11
|
+
class Disk
|
12
|
+
include Configurable
|
13
|
+
include ErrorHandler
|
14
|
+
|
15
|
+
ACTION_URL = 'https://cloud-api.yandex.net'
|
16
|
+
|
17
|
+
attr_reader :token
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def with_token(token)
|
21
|
+
new(token)
|
22
|
+
end
|
23
|
+
|
24
|
+
alias [] with_token
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(token)
|
28
|
+
@token = token
|
29
|
+
end
|
30
|
+
|
31
|
+
def info
|
32
|
+
process_response(
|
33
|
+
with_config.get("#{ACTION_URL}/v1/disk/", headers: auth_headers)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def download_url(path)
|
38
|
+
url = URI.parse(ACTION_URL).tap do |uri|
|
39
|
+
uri.path = '/v1/disk/resources/download'
|
40
|
+
uri.query = URI.encode_www_form(path: path)
|
41
|
+
end
|
42
|
+
|
43
|
+
process_response(
|
44
|
+
with_config.get(url, headers: auth_headers)
|
45
|
+
).fetch(:href)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def auth_headers
|
51
|
+
{Authorization: "OAuth #{@token}"}
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_response(response)
|
55
|
+
return JSON.parse(response.body, symbolize_names: true) if response.status.success?
|
56
|
+
|
57
|
+
error_for_response(response)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YandexClient
|
4
|
+
module ErrorHandler
|
5
|
+
private
|
6
|
+
|
7
|
+
def error_for_response(response)
|
8
|
+
msg = response.body.empty? ? response.status.to_s : response.body.to_s.force_encoding('UTF-8')
|
9
|
+
err =
|
10
|
+
case response.code
|
11
|
+
when 404
|
12
|
+
NotFoundError.new(msg, http_code: 404)
|
13
|
+
else
|
14
|
+
ApiRequestError.new(msg, http_code: response.code)
|
15
|
+
end
|
16
|
+
|
17
|
+
raise err
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YandexClient
|
4
|
+
# https://tech.yandex.ru/passport/doc/dg/reference/request-docpage/
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# YandexClient::Passport::Client[Token.first.access_token].info
|
8
|
+
class Passport
|
9
|
+
include Configurable
|
10
|
+
include ErrorHandler
|
11
|
+
|
12
|
+
ACTION_URL = 'https://login.yandex.ru/info'
|
13
|
+
|
14
|
+
attr_reader :token
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def with_token(token)
|
18
|
+
new(token)
|
19
|
+
end
|
20
|
+
|
21
|
+
alias [] with_token
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(token)
|
25
|
+
@token = token
|
26
|
+
end
|
27
|
+
|
28
|
+
def info
|
29
|
+
process_response \
|
30
|
+
with_config.get(ACTION_URL, headers: auth_headers)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def auth_headers
|
36
|
+
{Authorization: "Bearer #{@token}"}
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_response(response)
|
40
|
+
return JSON.parse(response.body, symbolize_names: true) if response.status.success?
|
41
|
+
|
42
|
+
error_for_response(response)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/yandex_client.rb
CHANGED
@@ -2,35 +2,50 @@
|
|
2
2
|
|
3
3
|
require 'yandex_client/version'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
require 'yandex_client/error_handler'
|
6
|
+
require 'yandex_client/configurable'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
require 'yandex_client/dav'
|
9
|
+
require 'yandex_client/disk'
|
10
|
+
require 'yandex_client/auth'
|
11
|
+
require 'yandex_client/passport'
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
module YandexClient
|
14
|
+
Config = Struct.new \
|
15
|
+
:api_key,
|
16
|
+
:api_secret,
|
17
|
+
:logger,
|
18
|
+
:read_timeout,
|
19
|
+
:write_timeout,
|
20
|
+
:connect_timeout
|
21
|
+
|
22
|
+
class ApiRequestError < StandardError
|
23
|
+
attr_reader :http_code
|
24
|
+
|
25
|
+
def initialize(msg = nil, http_code: nil)
|
26
|
+
if http_code
|
27
|
+
super "#{msg}, (http code #{http_code})"
|
28
|
+
else
|
29
|
+
super msg
|
30
|
+
end
|
31
|
+
|
32
|
+
@http_code = http_code
|
33
|
+
end
|
14
34
|
end
|
15
35
|
|
16
|
-
|
17
|
-
autoload :ApiRequestError, 'yandex_client/api_request_error'
|
18
|
-
autoload :NotFoundError, 'yandex_client/not_found_error'
|
36
|
+
NotFoundError = Class.new(ApiRequestError)
|
19
37
|
|
20
|
-
|
21
|
-
|
22
|
-
|
38
|
+
class << self
|
39
|
+
def config
|
40
|
+
@config ||= Config.new(nil, nil, nil, 120, 600, 5)
|
41
|
+
end
|
23
42
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
module Passport
|
29
|
-
autoload :Client, 'yandex_client/passport/client'
|
30
|
-
end
|
43
|
+
def configure
|
44
|
+
yield config
|
45
|
+
end
|
31
46
|
|
32
|
-
|
33
|
-
|
34
|
-
|
47
|
+
def auth
|
48
|
+
@auth ||= Auth.new
|
49
|
+
end
|
35
50
|
end
|
36
51
|
end
|
data/yandex_client.gemspec
CHANGED
@@ -23,12 +23,13 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
-
spec.add_runtime_dependency '
|
26
|
+
spec.add_runtime_dependency 'http'
|
27
27
|
spec.add_runtime_dependency 'ox'
|
28
28
|
|
29
29
|
spec.add_development_dependency 'bundler'
|
30
30
|
spec.add_development_dependency 'rake', '>= 10'
|
31
31
|
spec.add_development_dependency 'rspec', '>= 3.0'
|
32
|
+
spec.add_development_dependency 'simplecov', '>= 0.9'
|
32
33
|
spec.add_development_dependency 'vcr'
|
33
34
|
spec.add_development_dependency 'webmock'
|
34
35
|
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yandex_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxim Tretyakov
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: http
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.9'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.9'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: vcr
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -115,10 +129,11 @@ executables: []
|
|
115
129
|
extensions: []
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
132
|
+
- ".github/workflows/main.yml"
|
118
133
|
- ".gitignore"
|
134
|
+
- ".pryrc"
|
119
135
|
- ".rspec"
|
120
136
|
- ".rubocop.yml"
|
121
|
-
- ".travis.yml"
|
122
137
|
- Gemfile
|
123
138
|
- LICENSE.txt
|
124
139
|
- README.md
|
@@ -126,25 +141,24 @@ files:
|
|
126
141
|
- bin/console
|
127
142
|
- bin/setup
|
128
143
|
- dip.yml
|
129
|
-
- docker/Dockerfile.
|
130
|
-
- docker/docker-compose.development.yml
|
144
|
+
- docker/Dockerfile.dip
|
131
145
|
- docker/docker-compose.yml
|
146
|
+
- docker/prepare_env.sh
|
132
147
|
- lib/yandex_client.rb
|
133
|
-
- lib/yandex_client/
|
134
|
-
- lib/yandex_client/
|
135
|
-
- lib/yandex_client/
|
136
|
-
- lib/yandex_client/dav/
|
137
|
-
- lib/yandex_client/
|
138
|
-
- lib/yandex_client/
|
139
|
-
- lib/yandex_client/
|
140
|
-
- lib/yandex_client/passport/client.rb
|
148
|
+
- lib/yandex_client/auth.rb
|
149
|
+
- lib/yandex_client/configurable.rb
|
150
|
+
- lib/yandex_client/dav.rb
|
151
|
+
- lib/yandex_client/dav/prop_find_response.rb
|
152
|
+
- lib/yandex_client/disk.rb
|
153
|
+
- lib/yandex_client/error_handler.rb
|
154
|
+
- lib/yandex_client/passport.rb
|
141
155
|
- lib/yandex_client/version.rb
|
142
156
|
- yandex_client.gemspec
|
143
157
|
homepage: https://github.com/yamax2/yandex_client
|
144
158
|
licenses:
|
145
159
|
- MIT
|
146
160
|
metadata: {}
|
147
|
-
post_install_message:
|
161
|
+
post_install_message:
|
148
162
|
rdoc_options: []
|
149
163
|
require_paths:
|
150
164
|
- lib
|
@@ -159,8 +173,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
173
|
- !ruby/object:Gem::Version
|
160
174
|
version: '0'
|
161
175
|
requirements: []
|
162
|
-
rubygems_version: 3.
|
163
|
-
signing_key:
|
176
|
+
rubygems_version: 3.2.26
|
177
|
+
signing_key:
|
164
178
|
specification_version: 4
|
165
179
|
summary: Yandex Client
|
166
180
|
test_files: []
|