yandex_client 1.3.0 → 1.3.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 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: []