yandex_client 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 127336341ee7562468097e6427b89b5857a42077cf7ba695bcc814359b953391
4
- data.tar.gz: 67dabf7852dfe54843ba862fe792bf4a0350d5fdb872fe29181c9a4d655df30c
3
+ metadata.gz: 847c0309ab86bbacce9d7641f210b90bf9d821987349d0bb76f14dd7717891b5
4
+ data.tar.gz: b4ea99b824d51a3622fbb93cdd49d968870dfed4e21c88b6d7a0a6d3a7eef6c6
5
5
  SHA512:
6
- metadata.gz: e8b96434c25568ee87c4f301fd414dcc92489a31052a9c3fe43e5c0ed8728854607c9f5434065932b51dcc3676b51146a4065da5b46bab5e47ee06f89420c5fe
7
- data.tar.gz: d8ece1a32ac40135c878d4a86becd2fc9c94c90dac2e78ce10a850e6dce913b3a2c120973fc171a857465f1ff1ef49d9cd0f02d85c999c067390b911ee90c492
6
+ metadata.gz: 54728b848084d16efab9c6a5778df2df1792c8eacdcaaae7ae8a72affc339429e64476107fee94be0993cfc227b3562a9fc1a61084acbb61263eb15fffca9643
7
+ data.tar.gz: 96d47f2be5847ced46d1c01fa99e4443a3db673b5cc7be092ef3bbfbb8cfb1261932b43cd8f90234f64fd53bf97d1812a10c86c19c17822051483e686952242e
@@ -0,0 +1,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ['*']
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version: ["2.7", "3.0", "3.1"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v2
18
+
19
+ - name: Set up Ruby
20
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
21
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
22
+ # uses: ruby/setup-ruby@v1
23
+ uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby-version }}
26
+ bundler-cache: true
27
+ - name: rubocop
28
+ run: bundle exec ./rubocop --display-style-guide --extra-details
29
+ - name: tests
30
+ run: bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /log/*
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+ .idea
14
+ .byebug_history
15
+
16
+ Gemfile.lock
17
+ .irb-save-history
18
+ coverage
data/.pryrc ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ Pry.config.history_file = "#{File.dirname(__FILE__)}/.irb-save-history"
4
+
5
+ require 'bundler/setup'
6
+ require 'yandex_client'
data/.rspec ADDED
@@ -0,0 +1,6 @@
1
+ --color
2
+ --tty
3
+ --format progress
4
+ --order random
5
+ --backtrace
6
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,39 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.7
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+ Exclude:
6
+ - 'bin/**/*'
7
+ - '.pryrc'
8
+ - 'vendor/**/*'
9
+
10
+ Layout/LineLength:
11
+ Max: 120
12
+
13
+ Style/AsciiComments:
14
+ Enabled: false
15
+
16
+ Layout/SpaceInsideHashLiteralBraces:
17
+ EnforcedStyle: no_space
18
+
19
+ Style/Documentation:
20
+ Enabled: false
21
+
22
+ Layout/DotPosition:
23
+ EnforcedStyle: trailing
24
+
25
+ Style/EmptyMethod:
26
+ EnforcedStyle: expanded
27
+
28
+ Layout/MultilineMethodCallIndentation:
29
+ EnforcedStyle: indented
30
+
31
+ Metrics/BlockLength:
32
+ Exclude:
33
+ - spec/**/*
34
+
35
+ Gemspec/RequiredRubyVersion:
36
+ Enabled: false
37
+
38
+ Gemspec/RequireMFA:
39
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gem 'pry-byebug'
8
+ gem 'rubocop', require: false
9
+ gem 'rubocop-rspec', require: false
10
+
11
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Maxim Tretyakov
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.md ADDED
@@ -0,0 +1,65 @@
1
+ # YandexClient
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+ ```ruby
7
+ gem 'yandex_client', '>= 1'
8
+ ```
9
+
10
+ And then execute:
11
+ ```bash
12
+ $ bundle install
13
+ ```
14
+
15
+ Or install it yourself as:
16
+ ```bash
17
+ $ gem install yandex_client
18
+ ```
19
+
20
+ ## Disk webdav
21
+
22
+ https://tech.yandex.ru/disk/doc/dg/reference/put-docpage/
23
+
24
+ Chainable client:
25
+ ```ruby
26
+ YandexClient::Dav['your_access_token']
27
+ .put('1.txt', '/a/b/c/1.txt')
28
+ .put(File.open('1.txt', 'rb'), '/path/to/1.txt')
29
+ .put(Tempfile.new.tap { |t| t.write('say ni'); t.rewind }, '/path/to/tmp.txt')
30
+ .delete('/a/b/c/1.txt')
31
+ .mkcol('/a/b/c')
32
+ .propfind('/a/dip.yml', depth: 0)
33
+ .propfind('/a', depth: 1)
34
+ .propfind.to_a
35
+ ```
36
+
37
+ ## Disk rest api
38
+
39
+ https://yandex.ru/dev/disk/api/reference/capacity-docpage/
40
+ https://yandex.ru/dev/disk/api/reference/content-docpage/
41
+
42
+ ```ruby
43
+ YandexClient::Disk['access_token'].info
44
+ YandexClient::Disk['access_token'].download_url('path/to/file')
45
+ YandexClient::Disk['access_token'].upload_url('path/to/file', overwrite: false)
46
+ YandexClient::Disk['access_token'].move('path/to/file', 'new_path/to/new_file', overwrite: false)
47
+ ```
48
+
49
+ ## Auth
50
+
51
+ https://tech.yandex.ru/oauth/doc/dg/reference/refresh-client-docpage/
52
+ https://tech.yandex.ru/oauth/doc/dg/reference/auto-code-client-docpage/#auto-code-client__get-token
53
+
54
+ ```ruby
55
+ YandexClient.auth.create_token('9388894')
56
+ YandexClient.auth.refresh_token('refresh_token')
57
+ ```
58
+
59
+ ## Passport
60
+
61
+ https://tech.yandex.ru/passport/doc/dg/reference/request-docpage/
62
+
63
+ ```ruby
64
+ YandexClient::Passport::Client['access_token'].info
65
+ ```
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'yandex_client'
5
+
6
+ Pry.start
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
data/dip.yml ADDED
@@ -0,0 +1,43 @@
1
+ version: '3.3'
2
+
3
+ environment:
4
+ DOCKER_RUBY_VERSION: 3.1
5
+
6
+ compose:
7
+ files:
8
+ - docker/docker-compose.yml
9
+ project_name: yandex_client
10
+
11
+ interaction:
12
+ sh:
13
+ service: app
14
+
15
+ irb:
16
+ service: app
17
+ command: bundle exec pry
18
+
19
+ bundle:
20
+ service: app
21
+ command: bundle
22
+
23
+ rake:
24
+ service: app
25
+ command: bundle exec rake
26
+
27
+ rspec:
28
+ service: app
29
+ command: bundle exec rspec
30
+
31
+ rubocop:
32
+ service: app
33
+ command: bundle exec ./rubocop --display-style-guide --extra-details
34
+
35
+ clean:
36
+ service: app
37
+ command: rm -rf Gemfile.lock
38
+
39
+ provision:
40
+ - ./docker/prepare_env.sh
41
+ - docker volume create --name bundler_data
42
+ - dip clean
43
+ - dip bundle install
@@ -0,0 +1,8 @@
1
+ ARG DOCKER_RUBY_VERSION
2
+ FROM ruby:${DOCKER_RUBY_VERSION}-alpine
3
+
4
+ RUN gem update --system && \
5
+ apk add --update --no-cache tzdata less git build-base mc && \
6
+ cp /usr/share/zoneinfo/Asia/Yekaterinburg /etc/localtime && echo 'Asia/Yekaterinburg' > /etc/timezone
7
+
8
+ WORKDIR /app
@@ -0,0 +1,22 @@
1
+ version: '3.3'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ context: ../
7
+ dockerfile: ./docker/Dockerfile.dip
8
+ args:
9
+ DOCKER_RUBY_VERSION: $DOCKER_RUBY_VERSION
10
+ labels:
11
+ com.yandex-client.ruby.version: $DOCKER_RUBY_VERSION
12
+ environment:
13
+ - BUNDLE_PATH=/bundle/${DOCKER_RUBY_VERSION}
14
+ volumes:
15
+ - ..:/app
16
+ - bundler-data:/bundle
17
+ command: sh
18
+
19
+ volumes:
20
+ bundler-data:
21
+ external:
22
+ name: bundler_data
@@ -0,0 +1,11 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ for line in $(docker images -f "label=com.yandex-client.ruby.version" -q | uniq); do
6
+ ver=$(docker inspect --format '{{ index .Config.Labels "com.yandex-client.ruby.version"}}' $line)
7
+
8
+ if ! [ $ver = $DOCKER_RUBY_VERSION ]; then
9
+ docker image rm --force $line
10
+ fi
11
+ done
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YandexClient
4
+ # https://tech.yandex.ru/oauth/doc/dg/reference/refresh-client-docpage/
5
+ # https://tech.yandex.ru/oauth/doc/dg/reference/auto-code-client-docpage/#auto-code-client__get-token
6
+ #
7
+ # https://oauth.yandex.ru/authorize?response_type=code&client_id=ede5c51271164a9e833ab9119b4d3c26&force_confirm=false
8
+ #
9
+ # Example:
10
+ # token = Token.first
11
+ #
12
+ # YandexClient.auth.create_token('9388894')
13
+ # YandexClient.auth.refresh_token(token.refresh_token)
14
+ class Auth
15
+ include Configurable
16
+ include ErrorHandler
17
+
18
+ ACTION_URL = 'https://oauth.yandex.ru/token'
19
+
20
+ def create_token(code)
21
+ process_response with_config.post(
22
+ ACTION_URL,
23
+ headers: common_headers,
24
+ body: URI.encode_www_form(
25
+ request_body_for('authorization_code').merge!(code: code)
26
+ )
27
+ )
28
+ end
29
+
30
+ def refresh_token(refresh_token)
31
+ process_response with_config.post(
32
+ ACTION_URL,
33
+ headers: common_headers,
34
+ body: URI.encode_www_form(
35
+ request_body_for('refresh_token').merge!(refresh_token: refresh_token)
36
+ )
37
+ )
38
+ end
39
+
40
+ private
41
+
42
+ def common_headers
43
+ {'Content-type' => 'application/x-www-form-urlencoded'}
44
+ end
45
+
46
+ def request_body_for(grant_type)
47
+ {
48
+ grant_type: grant_type,
49
+ client_id: config.api_key,
50
+ client_secret: config.api_secret
51
+ }
52
+ end
53
+
54
+ def process_response(response)
55
+ if response.status.success?
56
+ JSON.parse(response.body, symbolize_names: true)
57
+ else
58
+ error_for_response(response)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YandexClient
4
+ module Configurable
5
+ def self.included(base)
6
+ base.extend Forwardable
7
+ base.def_delegator :YandexClient, :config
8
+ end
9
+
10
+ private
11
+
12
+ def with_config
13
+ req = HTTP.timeout(
14
+ connect: config.connect_timeout,
15
+ read: config.read_timeout,
16
+ write: config.write_timeout
17
+ )
18
+
19
+ if config.logger
20
+ req.use(logging: {logger: config.logger})
21
+ else
22
+ req
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ox'
4
+ require 'cgi'
5
+
6
+ module YandexClient
7
+ class Dav
8
+ class PropFindResponse
9
+ include Enumerable
10
+
11
+ SUCCESS_STATUS = 'HTTP/1.1 200 OK'
12
+
13
+ class Item
14
+ attr_reader :name, :created_at, :last_modified, :content_type
15
+
16
+ def initialize(name, node)
17
+ @name = name
18
+ @folder = node[:'d:resourcetype'].is_a?(Hash)
19
+
20
+ load_node_data(node)
21
+ end
22
+
23
+ def folder?
24
+ @folder
25
+ end
26
+
27
+ def file?
28
+ !@folder
29
+ end
30
+
31
+ private
32
+
33
+ def load_node_data(node)
34
+ @created_at = node.fetch(:'d:creationdate')
35
+ @last_modified = node.fetch(:'d:getlastmodified')
36
+
37
+ return if folder?
38
+
39
+ @etag = node.fetch(:'d:getetag')
40
+ @size = node.fetch(:'d:getcontentlength').to_i
41
+ @content_type = node.fetch(:'d:getcontenttype')
42
+
43
+ define_singleton_method(:etag) { @etag }
44
+ define_singleton_method(:size) { @size }
45
+ define_singleton_method(:content_type) { @content_type }
46
+ end
47
+ end
48
+
49
+ def initialize(xml)
50
+ @doc = Ox.load(
51
+ xml.dup.force_encoding('UTF-8'),
52
+ mode: :hash
53
+ )
54
+ end
55
+
56
+ def each
57
+ @doc[:'d:multistatus'].each do |node|
58
+ next if (response = node[:'d:response']).nil?
59
+
60
+ name = CGI.unescape(response.fetch(:'d:href'))
61
+ node_data = response.fetch(:'d:propstat')
62
+
63
+ raise ParseError unless node_data.fetch(:'d:status') == SUCCESS_STATUS
64
+
65
+ yield Item.new(name, node_data.fetch(:'d:prop'))
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,121 @@
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
+ # https://yandex.ru/dev/disk/doc/dg/reference/move.html
71
+ def move(source, dest, overwrite: false)
72
+ headers = auth_headers.merge!(
73
+ 'Destination' => absolute_path(dest),
74
+ 'Overwrite' => overwrite ? 'T' : 'F'
75
+ )
76
+
77
+ process_response with_config.request(
78
+ :move,
79
+ url_for(source),
80
+ headers: headers
81
+ )
82
+ end
83
+
84
+ def propfind(dest = '', depth = 1)
85
+ headers = auth_headers.merge!(
86
+ Depth: depth.to_s,
87
+ 'Content-Type' => 'application/x-www-form-urlencoded',
88
+ 'Content-Length' => PROPFIND_QUERY.length
89
+ )
90
+
91
+ response = with_config.request(:propfind, url_for(dest), headers: headers, body: PROPFIND_QUERY)
92
+ process_response(response)
93
+
94
+ PropFindResponse.new(response.body.to_s)
95
+ end
96
+
97
+ private
98
+
99
+ def auth_headers
100
+ {Authorization: "OAuth #{token}"}
101
+ end
102
+
103
+ def url_for(dest)
104
+ URI.parse(ACTION_URL).tap do |uri|
105
+ uri.path = absolute_path(dest)
106
+ end
107
+ end
108
+
109
+ def process_response(response)
110
+ return self if response.status.success?
111
+
112
+ error_for_response(response)
113
+ end
114
+
115
+ def absolute_path(path)
116
+ return path if path.match?(%r{^/})
117
+
118
+ "/#{path}"
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module YandexClient
6
+ # https://yandex.ru/dev/disk/api/reference/capacity.html
7
+ # https://yandex.ru/dev/disk/api/reference/content.html
8
+ # https://yandex.ru/dev/disk/api/reference/move.html
9
+ #
10
+ # YandexClient::Disk[access_token].info
11
+ # YandexClient::Disk[access_token].download_url('path/to/file')
12
+ # YandexClient::Disk[access_token].download_url('path/to/file', overwrite: false)
13
+ class Disk
14
+ include Configurable
15
+ include ErrorHandler
16
+
17
+ ACTION_URL = 'https://cloud-api.yandex.net'
18
+
19
+ attr_reader :token
20
+
21
+ class << self
22
+ def with_token(token)
23
+ new(token)
24
+ end
25
+
26
+ alias [] with_token
27
+ end
28
+
29
+ def initialize(token)
30
+ @token = token
31
+ end
32
+
33
+ def info
34
+ process_response(
35
+ with_config.get("#{ACTION_URL}/v1/disk/", headers: auth_headers)
36
+ )
37
+ end
38
+
39
+ def download_url(path)
40
+ url = URI.parse(ACTION_URL).tap do |uri|
41
+ uri.path = '/v1/disk/resources/download'
42
+ uri.query = URI.encode_www_form(path: path)
43
+ end
44
+
45
+ process_response(
46
+ with_config.get(url, headers: auth_headers)
47
+ ).fetch(:href)
48
+ end
49
+
50
+ def upload_url(path, overwrite: false)
51
+ url = URI.parse(ACTION_URL).tap do |uri|
52
+ uri.path = '/v1/disk/resources/upload'
53
+ uri.query = URI.encode_www_form(path: path, overwrite: overwrite)
54
+ end
55
+
56
+ process_response(
57
+ with_config.get(url, headers: auth_headers)
58
+ ).fetch(:href)
59
+ end
60
+
61
+ def move(from, to, overwrite: false)
62
+ url = URI.parse(ACTION_URL).tap do |uri|
63
+ uri.path = '/v1/disk/resources/move'
64
+ uri.query = URI.encode_www_form(from: from, path: to, overwrite: overwrite)
65
+ end
66
+
67
+ process_response(
68
+ with_config.post(url, headers: auth_headers)
69
+ ).fetch(:href)
70
+ end
71
+
72
+ private
73
+
74
+ def auth_headers
75
+ {Authorization: "OAuth #{@token}"}
76
+ end
77
+
78
+ def process_response(response)
79
+ return JSON.parse(response.body, symbolize_names: true) if response.status.success?
80
+
81
+ error_for_response(response)
82
+ end
83
+ end
84
+ 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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YandexClient
4
+ VERSION = '1.3.1'
5
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yandex_client/version'
4
+
5
+ require 'yandex_client/error_handler'
6
+ require 'yandex_client/configurable'
7
+
8
+ require 'yandex_client/dav'
9
+ require 'yandex_client/disk'
10
+ require 'yandex_client/auth'
11
+ require 'yandex_client/passport'
12
+
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
34
+ end
35
+
36
+ NotFoundError = Class.new(ApiRequestError)
37
+
38
+ class << self
39
+ def config
40
+ @config ||= Config.new(nil, nil, nil, 120, 600, 5)
41
+ end
42
+
43
+ def configure
44
+ yield config
45
+ end
46
+
47
+ def auth
48
+ @auth ||= Auth.new
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'yandex_client/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'yandex_client'
9
+ spec.version = YandexClient::VERSION
10
+ spec.authors = ['Maxim Tretyakov']
11
+ spec.email = ['max@tretyakov-ma.ru']
12
+
13
+ spec.summary = 'Yandex Client'
14
+ spec.description = 'Allows to use yandex disk as webdav nodes'
15
+ spec.homepage = 'https://github.com/yamax2/yandex_client'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+
22
+ spec.bindir = 'exe'
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_runtime_dependency 'http'
27
+ spec.add_runtime_dependency 'ox'
28
+
29
+ spec.add_development_dependency 'bundler'
30
+ spec.add_development_dependency 'rake', '>= 10'
31
+ spec.add_development_dependency 'rspec', '>= 3.0'
32
+ spec.add_development_dependency 'simplecov', '>= 0.9'
33
+ spec.add_development_dependency 'vcr'
34
+ spec.add_development_dependency 'webmock'
35
+
36
+ spec.required_ruby_version = '>= 2.4'
37
+ end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yandex_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.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
11
  date: 2022-09-11 00:00:00.000000000 Z
@@ -128,12 +128,37 @@ email:
128
128
  executables: []
129
129
  extensions: []
130
130
  extra_rdoc_files: []
131
- files: []
131
+ files:
132
+ - ".github/workflows/main.yml"
133
+ - ".gitignore"
134
+ - ".pryrc"
135
+ - ".rspec"
136
+ - ".rubocop.yml"
137
+ - Gemfile
138
+ - LICENSE.txt
139
+ - README.md
140
+ - Rakefile
141
+ - bin/console
142
+ - bin/setup
143
+ - dip.yml
144
+ - docker/Dockerfile.dip
145
+ - docker/docker-compose.yml
146
+ - docker/prepare_env.sh
147
+ - lib/yandex_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
155
+ - lib/yandex_client/version.rb
156
+ - yandex_client.gemspec
132
157
  homepage: https://github.com/yamax2/yandex_client
133
158
  licenses:
134
159
  - MIT
135
160
  metadata: {}
136
- post_install_message:
161
+ post_install_message:
137
162
  rdoc_options: []
138
163
  require_paths:
139
164
  - lib
@@ -148,8 +173,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
173
  - !ruby/object:Gem::Version
149
174
  version: '0'
150
175
  requirements: []
151
- rubygems_version: 3.3.22
152
- signing_key:
176
+ rubygems_version: 3.3.5
177
+ signing_key:
153
178
  specification_version: 4
154
179
  summary: Yandex Client
155
180
  test_files: []