yandex_client 0.2.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module YandexClient
4
- VERSION = '0.2.0'
4
+ VERSION = '1.0.1'
5
5
  end
data/lib/yandex_client.rb CHANGED
@@ -2,35 +2,50 @@
2
2
 
3
3
  require 'yandex_client/version'
4
4
 
5
- module YandexClient
6
- Config = Struct.new(:api_key, :api_secret, :logger, :read_timeout)
5
+ require 'yandex_client/error_handler'
6
+ require 'yandex_client/configurable'
7
7
 
8
- def self.config
9
- @config ||= Config.new(nil, nil, nil, 10)
10
- end
8
+ require 'yandex_client/dav'
9
+ require 'yandex_client/disk'
10
+ require 'yandex_client/auth'
11
+ require 'yandex_client/passport'
11
12
 
12
- def self.configure
13
- yield config
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
- autoload :Client, 'yandex_client/client'
17
- autoload :ApiRequestError, 'yandex_client/api_request_error'
18
- autoload :NotFoundError, 'yandex_client/not_found_error'
36
+ NotFoundError = Class.new(ApiRequestError)
19
37
 
20
- module Auth
21
- autoload :Client, 'yandex_client/auth/client'
22
- end
38
+ class << self
39
+ def config
40
+ @config ||= Config.new(nil, nil, nil, 120, 600, 5)
41
+ end
23
42
 
24
- module Disk
25
- autoload :Client, 'yandex_client/disk/client'
26
- end
27
-
28
- module Passport
29
- autoload :Client, 'yandex_client/passport/client'
30
- end
43
+ def configure
44
+ yield config
45
+ end
31
46
 
32
- module Dav
33
- autoload :Client, 'yandex_client/dav/client'
34
- autoload :PropfindParser, 'yandex_client/dav/propfind_parser'
47
+ def auth
48
+ @auth ||= Auth.new
49
+ end
35
50
  end
36
51
  end
@@ -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 'oj'
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.2.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: 2020-01-24 00:00:00.000000000 Z
11
+ date: 2021-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: oj
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.2.6
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/api_request_error.rb
134
- - lib/yandex_client/auth/client.rb
135
- - lib/yandex_client/client.rb
136
- - lib/yandex_client/dav/client.rb
137
- - lib/yandex_client/dav/propfind_parser.rb
138
- - lib/yandex_client/disk/client.rb
139
- - lib/yandex_client/not_found_error.rb
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.0.6
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: []
data/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.6.5
5
- before_install: gem install bundler
6
- before_script:
7
- - bundle install
8
- script: bundle exec rspec
9
- notifications:
10
- email:
11
- on_success: never
12
- on_failure: always