putio-rb 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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