transmission-rpc-ruby 0.1.0

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,34 @@
1
+ module Transmission
2
+ class Arguments
3
+ class TorrentSet < Transmission::Arguments
4
+
5
+ ATTRIBUTES = [
6
+ 'bandwidthPriority',
7
+ 'downloadLimit',
8
+ 'downloadLimited',
9
+ 'downloadLimit',
10
+ 'files-wanted',
11
+ 'files-unwanted',
12
+ 'honorsSessionLimits',
13
+ 'ids',
14
+ 'location',
15
+ 'peer-limit',
16
+ 'priority-high',
17
+ 'priority-low',
18
+ 'priority-normal',
19
+ 'queuePosition',
20
+ 'seedIdleLimit',
21
+ 'seedIdleMode',
22
+ 'seedRatioLimit',
23
+ 'seedRatioMode',
24
+ 'trackerAdd',
25
+ 'trackerRemove',
26
+ 'trackerReplace',
27
+ 'uploadLimit',
28
+ 'uploadLimited',
29
+ 'uploadLimit'
30
+ ]
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module Transmission
2
+ class Config
3
+ class << self
4
+ def set(options = {})
5
+ @@config = options
6
+ @@connector = Transmission::RPC.new @@config
7
+ end
8
+
9
+ def get
10
+ @@config
11
+ end
12
+
13
+ def get_connector
14
+ @@connector
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), 'model', 'torrent')
2
+ require File.join(File.dirname(__FILE__), 'model', 'session')
3
+
4
+ module Transmission
5
+ module Model
6
+
7
+ end
8
+ end
@@ -0,0 +1,35 @@
1
+ module Transmission
2
+ module Model
3
+ class Session
4
+ class SessionError < StandardError; end
5
+
6
+ attr_accessor :attributes
7
+
8
+ def initialize(session_object)
9
+ @attributes = session_object
10
+ end
11
+
12
+ def version
13
+ @attributes['version'].split(' ').first
14
+ end
15
+
16
+ def rpc_version
17
+ @attributes['rpc-version']
18
+ end
19
+
20
+ class << self
21
+ def get(options = {})
22
+ rpc = options[:connector] || connector
23
+ session_body = rpc.get_session options
24
+ session_stats_body = rpc.get_session_stats options
25
+ merged_body = session_body.merge(session_stats_body)
26
+ Session.new merged_body
27
+ end
28
+
29
+ def connector
30
+ Transmission::Config.get_connector
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,97 @@
1
+ module Transmission
2
+ module Model
3
+ class Torrent
4
+ class TorrentError < StandardError; end
5
+ class TorrentNotFoundError < StandardError; end
6
+ class MissingAttributesError < StandardError; end
7
+ class DuplicateTorrentError < StandardError; end
8
+
9
+ attr_accessor :attributes, :deleted
10
+
11
+ def initialize(torrent_object)
12
+ @attributes = torrent_object
13
+ end
14
+
15
+ def delete!(remove_local_data = false)
16
+ Torrent.connector.remove_torrent [self.attributes['id']], remove_local_data
17
+ @deleted = true
18
+ end
19
+
20
+ def set
21
+
22
+ end
23
+
24
+ def move_up
25
+
26
+ end
27
+
28
+ def move_down
29
+
30
+ end
31
+
32
+ def move_top
33
+
34
+ end
35
+
36
+ def move_bottom
37
+
38
+ end
39
+
40
+ def start
41
+
42
+ end
43
+
44
+ def start_now
45
+
46
+ end
47
+
48
+ def stop
49
+
50
+ end
51
+
52
+ def verify
53
+
54
+ end
55
+
56
+ def re_announce
57
+
58
+ end
59
+
60
+ def finished?
61
+
62
+ end
63
+
64
+ def to_json
65
+
66
+ end
67
+
68
+ class << self
69
+ def all(options = {})
70
+ rpc = options[:connector] || connector
71
+ body = rpc.get_torrent nil, options
72
+ body['torrents'].inject([]) do |torrents, torrent|
73
+ torrents << Torrent.new(torrent)
74
+ end
75
+ end
76
+
77
+ def find(id, options = {})
78
+ rpc = options[:connector] || connector
79
+ body = rpc.get_torrent [id], options
80
+ raise TorrentNotFoundError if body['torrents'].size == 0
81
+ Torrent.new body['torrents'].first
82
+ end
83
+
84
+ def add(options = {})
85
+ rpc = options[:connector] || connector
86
+ body = rpc.add_torrent options[:arguments]
87
+ raise DuplicateTorrentError if body['torrent-duplicate']
88
+ find body['torrent-added']['id']
89
+ end
90
+
91
+ def connector
92
+ Transmission::Config.get_connector
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,108 @@
1
+ require File.join(File.dirname(__FILE__), 'rpc', 'connector')
2
+
3
+ module Transmission
4
+ class RPC
5
+
6
+ attr_accessor :session, :connector
7
+
8
+ def initialize(options = {})
9
+ @connector = Connector.new options
10
+ end
11
+
12
+ def get_session(options = {})
13
+ fields = Transmission::Arguments::SessionGet.new(options[:fields])
14
+ arguments = {fields: fields.to_arguments}
15
+ @connector.post method: 'session-get', arguments: arguments
16
+ end
17
+
18
+ def set_session(arguments)
19
+ @connector.post method: 'session-set', arguments: arguments
20
+ end
21
+
22
+ def get_session_stats(options = {})
23
+ fields = Transmission::Arguments::SessionStats.new(options[:fields])
24
+ arguments = {fields: fields.to_arguments}
25
+ @connector.post method: 'session-stats', arguments: arguments
26
+ end
27
+
28
+ def close_session
29
+ @connector.post method: 'session-close'
30
+ end
31
+
32
+ def test_port
33
+ @connector.post method: 'port-test'
34
+ end
35
+
36
+ def blocklist
37
+ @connector.post method: 'blocklist-update'
38
+ end
39
+
40
+ def get_torrent(ids = nil, options = {})
41
+ fields = Transmission::Arguments::TorrentGet.new(options[:fields])
42
+ arguments = {fields: fields.to_arguments}
43
+ arguments[:ids] = ids if ids.is_a?(Array)
44
+ @connector.post method: 'torrent-get', arguments: arguments
45
+ end
46
+
47
+ def set_torrent
48
+ @connector.post method: 'torrent-set'
49
+ end
50
+
51
+ def add_torrent(arguments = {})
52
+ @connector.post method: 'torrent-add', arguments: arguments
53
+ end
54
+
55
+ def remove_torrent(ids, delete_local_data = false)
56
+ @connector.post method: 'torrent-remove', arguments: {ids: ids, 'delete-local-data' => delete_local_data}
57
+ end
58
+
59
+ def free_space
60
+ @connector.post method: 'free-space'
61
+ end
62
+
63
+ def start_torrent
64
+
65
+ end
66
+
67
+ def start_torrent_now
68
+
69
+ end
70
+
71
+ def stop_torrent
72
+
73
+ end
74
+
75
+ def verify_torrent
76
+
77
+ end
78
+
79
+ def re_announce
80
+
81
+ end
82
+
83
+ def set_torrent_location
84
+
85
+ end
86
+
87
+ def rename_torrent_path
88
+
89
+ end
90
+
91
+ def move_up_torrent
92
+
93
+ end
94
+
95
+ def move_down_torrent
96
+
97
+ end
98
+
99
+ def move_top_torrent
100
+
101
+ end
102
+
103
+ def move_bottom_torrent
104
+
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,69 @@
1
+ require 'faraday'
2
+ require 'json'
3
+
4
+ module Transmission
5
+ class RPC
6
+ class Connector
7
+ class AuthError < StandardError; end
8
+ class ConnectionError < StandardError; end
9
+ class InvalidSessionError < StandardError; end
10
+
11
+ attr_accessor :host, :port, :ssl, :credentials, :path, :session_id, :response
12
+
13
+ def initialize(options = {})
14
+ @host = options[:host] || 'localhost'
15
+ @port = options[:port] || 9091
16
+ @ssl = !!options[:ssl]
17
+ @credentials = options[:credentials] || nil
18
+ @path = options[:path] || '/transmission/rpc'
19
+ @session_id = options[:session_id] || ''
20
+ end
21
+
22
+ def post(params = {})
23
+ response = connection.post do |req|
24
+ req.url @path
25
+ req.headers['X-Transmission-Session-Id'] = @session_id
26
+ req.headers['Content-Type'] = 'application/json'
27
+ req.body = JSON.generate(params)
28
+ end
29
+ handle_response response
30
+ end
31
+
32
+ private
33
+
34
+ def json_body(response)
35
+ JSON.parse response.body
36
+ rescue
37
+ {}
38
+ end
39
+
40
+ def handle_response(response)
41
+ @response = response
42
+ if response.status == 409
43
+ @session_id = response.headers['x-transmission-session-id']
44
+ raise InvalidSessionError
45
+ end
46
+ body = json_body response
47
+ raise AuthError if response.status == 401
48
+ raise ConnectionError, body['result'] unless response.status == 200 && body['result'] == 'success'
49
+ body['arguments']
50
+ end
51
+
52
+ def connection
53
+ @connection ||= begin
54
+ connection = Faraday.new(:url => "#{scheme}://#{@host}:#{@port}", :ssl => {:verify => false}) do |faraday|
55
+ faraday.request :url_encoded
56
+ faraday.response :logger
57
+ faraday.adapter Faraday.default_adapter
58
+ end
59
+ connection.basic_auth(@credentials[:username], @credentials[:password]) if @credentials
60
+ connection
61
+ end
62
+ end
63
+
64
+ def scheme
65
+ @ssl ? 'https' : 'http'
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,60 @@
1
+ module Stubs
2
+
3
+ def stub_rpc_request(options = {})
4
+ host = options[:host] || 'localhost'
5
+ port = options[:port] || 9091
6
+ path = options[:path] || '/transmission/rpc'
7
+ scheme = !!options[:ssl] ? 'https' : 'http'
8
+ stub_request(:post, "#{scheme}://#{host}:#{port}#{path}")
9
+ end
10
+
11
+ def stub_get_torrent(body, torrents)
12
+ stub_rpc_request
13
+ .with(body: torrent_get_body(body))
14
+ .to_return(successful_response({arguments: {torrents: torrents}}))
15
+ end
16
+
17
+ def torrent_get_body(arguments = {})
18
+ args = {fields: Transmission::Arguments::TorrentGet.new.to_arguments}.merge(arguments)
19
+ {method: 'torrent-get', arguments: args}.to_json
20
+ end
21
+
22
+ def torrent_add_body(arguments = {})
23
+ {method: 'torrent-add', arguments: arguments}.to_json
24
+ end
25
+
26
+ def torrent_remove_body(arguments = {})
27
+ {method: 'torrent-remove', arguments: arguments}.to_json
28
+ end
29
+
30
+ def session_get_body(arguments = {})
31
+ {method: 'session-get', arguments: arguments}.to_json
32
+ end
33
+
34
+ def session_set_body(arguments = {})
35
+ {method: 'session-set', arguments: arguments}.to_json
36
+ end
37
+
38
+ def session_stats_body(arguments = {})
39
+ {method: 'session-stats', arguments: arguments}.to_json
40
+ end
41
+
42
+ def successful_response(options = {})
43
+ body = {result: 'success', arguments: (options[:arguments] || {})}
44
+ {status: 200, body: body.to_json, headers: options[:headers] || {}}
45
+ end
46
+
47
+ def unsuccessful_response(options = {})
48
+ body = {result: (options[:result] || ''), arguments: (options[:arguments] || {})}
49
+ {status: 200, body: body.to_json, headers: options[:headers] || {}}
50
+ end
51
+
52
+ def unauthorized_response(options = {})
53
+ {status: 401, body: (options[:body] || {}).to_json, headers: options[:headers] || {}}
54
+ end
55
+
56
+ def conflict_response(options = {})
57
+ {status: 409, body: (options[:body] || {}).to_json, headers: options[:headers] || {}}
58
+ end
59
+
60
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'webmock/rspec'
3
+
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'transmission')
5
+ require File.join(File.dirname(__FILE__), 'helpers', 'stubs')
6
+
7
+ ENV['TESTING'] = 'true'
8
+
9
+ RSpec.configure do |config|
10
+
11
+ config.include Stubs
12
+
13
+ end