putio-rb 0.0.2

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.
@@ -0,0 +1,26 @@
1
+ require 'putio/resource/transfer'
2
+
3
+ module Putio
4
+
5
+ class Client
6
+
7
+ module Transfers
8
+ # Get all the transfers
9
+ #
10
+ # @return [Array]
11
+ def list_transfers
12
+ resp = get '/transfers/list'
13
+
14
+ resp.body.fetch('transfers').inject([]) do |memo, data|
15
+ memo.push transfer_factory.call(data)
16
+ end
17
+ end
18
+ alias :transfers :list_transfers
19
+
20
+ private
21
+ def transfer_factory
22
+ @transfer_factory ||= Putio::Resource::Transfer.public_method(:new)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ module Putio
2
+
3
+ # Configuration options for {Client}, defaulting to values
4
+ # in {Default}
5
+ module Configurable
6
+
7
+ # @!attribute [w] access_token
8
+ # @see https://put.io/v2/docs/gettingstarted.html#authentication-and-access
9
+ # @return [String] OAuth2 access token for authentication
10
+ # @!attribute api_endpoint
11
+ # @return [URI] Base URL for API requests. default: https://api.put.io/
12
+ # @!attribute api_version
13
+ # @return [String] API version to use. default: v2
14
+ # @!attribute user_agent
15
+ # @return [String] User agent for http requests. default: 'putio-rb ruby client'
16
+ # @!attribute default_headers
17
+ # @return [Hash] Headers to use in http requests.
18
+ attr_accessor :access_token, :api_endpoint, :api_version, :user_agent, :default_headers
19
+
20
+ # List of configurable keys for {Putio::Client}
21
+ # @return [Array] of option keys
22
+ def self.keys
23
+ @keys ||= %i{ access_token api_endpoint api_version user_agent default_headers }
24
+ end
25
+
26
+ # Configure options with a block
27
+ def configure
28
+ yield self
29
+ end
30
+
31
+ # Reset configuration options to default values
32
+ def reset!
33
+ Putio::Configurable.keys.each do |key|
34
+ public_send("#{key}=".to_sym, Putio::Defaults.options[key])
35
+ end
36
+ self
37
+ end
38
+ alias setup reset!
39
+
40
+ def options
41
+ Hash[Putio::Configurable.keys.map { |key| [key, public_send(key.to_sym)] }]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,68 @@
1
+ require 'json'
2
+ require 'uri'
3
+ require 'net/http'
4
+
5
+ module Putio
6
+
7
+ class Connection
8
+ VERB_MAP = {
9
+ get: Net::HTTP::Get,
10
+ post: Net::HTTP::Post,
11
+ put: Net::HTTP::Put,
12
+ delete: Net::HTTP::Delete
13
+ }
14
+
15
+ def initialize(endpoint:, headers:{})
16
+ @endpoint = URI.parse(endpoint)
17
+ @headers = headers
18
+ end
19
+
20
+ def request_json(method, path, params)
21
+ response = request(method, path, params)
22
+
23
+ case response.code.to_i
24
+ when 200 || 201
25
+ body = JSON.parse(response.body)
26
+ response_factory.call(code: response.code.to_i, body: body)
27
+ when (400..499)
28
+ fail 'bad request'
29
+ when (500..599)
30
+ fail 'server problems'
31
+ end
32
+ end
33
+
34
+ def request(method, path, params)
35
+ case method
36
+ when :get
37
+ full_path = encode_path_params(path, params)
38
+ request = VERB_MAP[method].new(full_path)
39
+ else
40
+ request = VERB_MAP[method].new(path)
41
+ request.set_form_data(params)
42
+ end
43
+
44
+ http.request(request)
45
+ end
46
+
47
+ private
48
+ attr_reader :endpoint
49
+
50
+ def http
51
+ @http ||= begin
52
+ http = Net::HTTP.new(endpoint.host, endpoint.port)
53
+ http.use_ssl = endpoint.scheme == 'https'
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
55
+ http
56
+ end
57
+ end
58
+
59
+ def encode_path_params(path, params)
60
+ encoded = URI.encode_www_form(params)
61
+ [path, encoded].join('?')
62
+ end
63
+
64
+ def response_factory
65
+ @response_factory ||= ->(*args) { OpenStruct.new(*args) }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,59 @@
1
+ require 'uri'
2
+
3
+ module Putio
4
+
5
+ # Default configuration options for the client
6
+ module Defaults
7
+
8
+ # Default API endpoint
9
+ API_ENDPOINT = 'https://api.put.io'
10
+
11
+ # Default API version
12
+ API_VERSION = 'v2'
13
+
14
+ # Default User Agent
15
+ USER_AGENT = 'putio-rb ruby client'
16
+
17
+ class << self
18
+ # Configuration options
19
+ # @return [Hash]
20
+ def options
21
+ Hash[Putio::Configurable.keys.map { |k| [k, public_send(k)] }]
22
+ end
23
+
24
+ # Default access token from ENV
25
+ # @return [String]
26
+ def access_token
27
+ ENV['PUTIO_ACCESS_TOKEN']
28
+ end
29
+
30
+ # Default API endpoint from ENV or {API_ENDPOINT}
31
+ # @return [String]
32
+ def api_endpoint
33
+ ENV.fetch('API_ENDPOINT', API_ENDPOINT)
34
+ end
35
+
36
+ # Default API version from ENV or {API_VERSION}
37
+ # @return [String]
38
+ def api_version
39
+ ENV.fetch('API_VERSION', API_VERSION)
40
+ end
41
+
42
+ # Default User Agent from ENV or {USER_AGENT}
43
+ # @return [String]
44
+ def user_agent
45
+ ENV.fetch('USER_AGENT', USER_AGENT)
46
+ end
47
+
48
+ # Default headers for our http requests
49
+ # @return [Hash]
50
+ def default_headers
51
+ {
52
+ 'User-Agent' => "#{user_agent}",
53
+ 'Accept' => 'application/json'
54
+ }
55
+ end
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,33 @@
1
+ module Putio
2
+ module Resource
3
+ class File
4
+ VALID_KEYS = %i{ id name content_type is_mp4_available opensubtitles_hash
5
+ icon created_at parent_id first_accessed_at size screenshot is_shared
6
+ crc32 }.freeze
7
+
8
+ attr_reader *VALID_KEYS
9
+
10
+ def initialize(params = {})
11
+ params.reject! { |k,_| VALID_KEYS.include?(k) }
12
+ params.map { |k,v| instance_variable_set("@#{k}", v) }
13
+ end
14
+
15
+ def directory?
16
+ content_type == 'application/x-directory'
17
+ end
18
+
19
+ def shared?
20
+ is_shared
21
+ end
22
+
23
+ def mp4_available?
24
+ is_mp4_available
25
+ end
26
+
27
+ def created_at
28
+ created_at = super
29
+ Time.parse(created_at) if created_at
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ module Putio
2
+ module Resource
3
+ class Transfer
4
+ VALID_KEYS = %i{}
5
+
6
+ def initialize(params = {})
7
+
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Putio
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'putio/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'putio-rb'
8
+ s.version = Putio::VERSION
9
+ s.date = '2014-08-07'
10
+ s.summary = 'A gem to access put.io api'
11
+ s.description = 'putio-rb is a wrapper around put.io api v2 written in ruby.'
12
+ s.authors = ['Thibault Gautriaud']
13
+ s.email = 'thibault.gautriaud@gmail.com'
14
+ s.homepage = 'https://github.com/hubb/putio.rb'
15
+
16
+ s.required_ruby_version = '>= 2.0'
17
+ s.require_paths = ['lib']
18
+ s.files = `git ls-files`.split($/)
19
+ s.test_files = `git ls-files -- spec/*`.split($/)
20
+
21
+ s.add_development_dependency 'bundler'
22
+ end
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Putio::Client Files behaviour' do
4
+ let(:files) { File.read('spec/support/files.json') }
5
+ subject(:client) { Putio::Client.new(access_token: 'foobar') }
6
+
7
+ it { expect(client).to respond_to(:list_files) }
8
+ it { expect(client).to respond_to(:files) }
9
+
10
+ describe 'files' do
11
+ before do
12
+ stub_request(:get, "https://api.put.io/v2/files/list?oauth_token=foobar&parent_id=0").
13
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
14
+ to_return(:status => 200, :body => files, :headers => {})
15
+ end
16
+
17
+ it 'should return a collection of Putio::Resource::File' do
18
+ expect(client.list_files).to be_kind_of(Array)
19
+ expect(client.list_files.first).to be_kind_of(Putio::Resource::File)
20
+ end
21
+
22
+ context 'when the response is empty' do
23
+ before do
24
+ stub_request(:get, "https://api.put.io/v2/files/list?oauth_token=foobar&parent_id=0").
25
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
26
+ to_return(:status => 200, :body => "{\"files\":[]}", :headers => {})
27
+ end
28
+
29
+ it 'should return an empty collection' do
30
+ expect(client.list_files).to be_kind_of(Array)
31
+ expect(client.list_files).to be_empty
32
+ end
33
+ end
34
+ end
35
+
36
+ describe 'search' do
37
+ before do
38
+ stub_request(:get, "https://api.put.io/v2/files/search/foobar?oauth_token=foobar").
39
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
40
+ to_return(:status => 200, :body => files, :headers => {})
41
+ end
42
+
43
+ it 'should return a collection of Putio::Resource::File' do
44
+ result = client.search(query: 'foobar')
45
+
46
+ expect(result).to be_kind_of(Array)
47
+ expect(result.first).to be_kind_of(Putio::Resource::File)
48
+ end
49
+
50
+ context 'when the response is empty' do
51
+ before do
52
+ stub_request(:get, "https://api.put.io/v2/files/search/foobar?oauth_token=foobar").
53
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
54
+ to_return(:status => 200, :body => "{\"files\":[]}", :headers => {})
55
+ end
56
+
57
+ it 'should return an empty collection' do
58
+ result = client.search(query: 'foobar')
59
+
60
+ expect(result).to be_kind_of(Array)
61
+ expect(result).to be_empty
62
+ end
63
+ end
64
+
65
+ context 'without query' do
66
+ it { expect { client.search }.to raise_error }
67
+ end
68
+
69
+ context 'with a page' do
70
+ it 'should query the right page' do
71
+ mock_request = stub_request(:get, "https://api.put.io/v2/files/search/foobar/page/2?oauth_token=foobar").
72
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
73
+ to_return(:status => 200, :body => "{\"files\":[]}", :headers => {})
74
+
75
+ client.search(query: 'foobar', options: { page: 2 })
76
+
77
+ assert_requested(mock_request)
78
+ end
79
+ end
80
+
81
+ context 'with other search syntax option' do
82
+ it 'should query with the right options' do
83
+ mock_request = stub_request(:get, "https://api.put.io/v2/files/search/foobar?ext=mp4&from=me&oauth_token=foobar&time=thisweek&type=video").
84
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
85
+ to_return(:status => 200, :body => "{\"files\":[]}", :headers => {})
86
+
87
+ client.search(query: 'foobar', options: { from: 'me', type: 'video', ext: 'mp4', time: 'thisweek' })
88
+
89
+ assert_requested(mock_request)
90
+ end
91
+ end
92
+ end
93
+
94
+ describe 'file' do
95
+ let(:file) { File.read('spec/support/file.json') }
96
+
97
+ it 'should query the right endpoint' do
98
+ mock_request = stub_request(:get, "https://api.put.io/v2/files/123?oauth_token=foobar&parent_id=0").
99
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
100
+ to_return(:status => 200, :body => "{\"file\":[]}", :headers => {})
101
+
102
+ client.file(id: 123)
103
+
104
+ assert_requested(mock_request)
105
+ end
106
+
107
+ it 'should return a Putio::Resource::File' do
108
+ stub_request(:get, "https://api.put.io/v2/files/123?oauth_token=foobar&parent_id=0").
109
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
110
+ to_return(:status => 200, :body => file, :headers => {})
111
+
112
+ expect(client.file(id: 123)).to be_kind_of(Putio::Resource::File)
113
+ end
114
+
115
+ context 'with a parent_id option' do
116
+ it 'should query with the right option' do
117
+ mock_request = stub_request(:get, "https://api.put.io/v2/files/123?oauth_token=foobar&parent_id=1234").
118
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
119
+ to_return(:status => 200, :body => "{\"file\":[]}", :headers => {})
120
+
121
+ client.file(id: 123, options: { parent_id: 1234 })
122
+
123
+ assert_requested(mock_request)
124
+ end
125
+ end
126
+ end
127
+
128
+ describe 'delete_files' do
129
+ before do
130
+ @mock_request = stub_request(:post, "https://api.put.io/v2/files/delete").
131
+ with(:body => {"file_ids"=>"1,2,3", "oauth_token"=>"foobar"},
132
+ :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
133
+ to_return(:status => 200, :body => "{\"status\": \"OK\"}", :headers => {})
134
+ end
135
+
136
+ it { expect(client.delete_files(1,2,3)).to be_truthy }
137
+
138
+ it 'should query the right endpoint with options' do
139
+ client.delete_files(1,2,3)
140
+
141
+ assert_requested(@mock_request)
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'putio/client'
3
+
4
+ describe Putio::Client do
5
+ let(:access_token) { 'foobar' }
6
+ subject(:client) { described_class.new(access_token: access_token) }
7
+
8
+ it_behaves_like 'a configurable'
9
+
10
+ # TODO: extract to files shared examples
11
+ it { expect(client).to respond_to(:list_files) }
12
+ # TODO: extract to transfers shared examples
13
+ it { expect(client).to respond_to(:list_transfers) }
14
+
15
+ describe 'inspect' do
16
+ it { expect(client.inspect).to be_kind_of(String) }
17
+
18
+ it 'should hide the access token' do
19
+ expect(client.inspect).not_to include(access_token)
20
+ expect(client.inspect).to include('*******')
21
+ end
22
+ end
23
+
24
+ it { expect(subject).to respond_to(:get) }
25
+ it { expect(subject).to respond_to(:post) }
26
+ it { expect(subject).to respond_to(:put) }
27
+ it { expect(subject).to respond_to(:delete) }
28
+
29
+ describe 'request' do
30
+ let(:connection) { double }
31
+ before do
32
+ allow(connection).to receive(:request_json).and_return(true)
33
+ client.connection = connection
34
+ end
35
+
36
+ it 'should add the access_token to the params' do
37
+ expect(connection).to receive(:request_json).with(anything, anything, hash_including(:oauth_token))
38
+ client.get('/foo/bar')
39
+ end
40
+
41
+ it 'should prepend the path with the api version' do
42
+ expect(connection).to receive(:request_json).with(anything, '/v2/foo/bar', anything)
43
+ client.get('/foo/bar')
44
+ end
45
+
46
+ %i{ get post put delete }.each do |method|
47
+ context "when the method is #{method.upcase}" do
48
+ it "should make a #{method.upcase} request" do
49
+ expect(connection).to receive(:request_json).with(method, anything, anything)
50
+ client.public_send(method, '/foo/bar')
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ describe 'connection' do
57
+ let(:connection) { double(request_json: true) }
58
+
59
+ it 'should be initialised with the client endpoint and default_headers' do
60
+ expect(Putio::Connection).to receive(:new)
61
+ .with(endpoint: client.api_endpoint, headers: client.default_headers)
62
+ .and_return(connection)
63
+
64
+ client.get('/foo/bar')
65
+ end
66
+ end
67
+ end