diff --git a/README.markdown b/README.markdown index 6af56ae..b56caf6 100755 --- a/README.markdown +++ b/README.markdown @@ -6,7 +6,7 @@ The goal is to support all requests described in the Transmission [RPC Specifica You need to have http://gemcutter.org in you gem sources. To add it you can execute either sudo gem install gemcutter - sudo gem tumble` + sudo gem tumble or @@ -15,14 +15,35 @@ or To install transmission-client: sudo gem install transmission-client + +If you want to use EventMachine (optional) you need to install the eventmachine gem and igrigorik's em-http-request: + sudo gem install eventmachine + sudo gem install em-http-request + ## Usage Get a list of torrents and print its file names: require 'transmission-client' - t = Transmission::Client.new('192.168.0.2') + t = Transmission::Client.new('127.0.0.1', 9091) t.torrents.each do |torrent| - puts torrent.name + puts torrent.name end - + +To use the EventMachine driven interface: + + require 'eventmachine' + require 'transmission-client' + + EventMachine.run do + t = Transmission::Client.new + EM.add_periodic_timer(1) do + t.torrents do |torrents| + torrents.each do |tor| + puts tor.percentDone + end + end + end + end + RDoc is still to be written, at the meantime have a look at the code to find out which methods are supported. diff --git a/README.rdoc b/README.rdoc index ac2e574..b56caf6 100755 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,4 @@ -# tranmission-client: A Transmission RPC Client +# transmission-client: A Transmission RPC Client The goal is to support all requests described in the Transmission [RPC Specifications](http://trac.transmissionbt.com/browser/trunk/doc/rpc-spec.txt). @@ -6,7 +6,7 @@ The goal is to support all requests described in the Transmission [RPC Specifica You need to have http://gemcutter.org in you gem sources. To add it you can execute either sudo gem install gemcutter - sudo gem tumble` + sudo gem tumble or @@ -15,14 +15,35 @@ or To install transmission-client: sudo gem install transmission-client + +If you want to use EventMachine (optional) you need to install the eventmachine gem and igrigorik's em-http-request: + sudo gem install eventmachine + sudo gem install em-http-request + ## Usage Get a list of torrents and print its file names: require 'transmission-client' - t = Transmission::Client.new('192.168.0.2') + t = Transmission::Client.new('127.0.0.1', 9091) t.torrents.each do |torrent| - puts torrent.name + puts torrent.name end - + +To use the EventMachine driven interface: + + require 'eventmachine' + require 'transmission-client' + + EventMachine.run do + t = Transmission::Client.new + EM.add_periodic_timer(1) do + t.torrents do |torrents| + torrents.each do |tor| + puts tor.percentDone + end + end + end + end + RDoc is still to be written, at the meantime have a look at the code to find out which methods are supported. diff --git a/lib/transmission-client.rb b/lib/transmission-client.rb index 3f6a477..5ac0d7f 100755 --- a/lib/transmission-client.rb +++ b/lib/transmission-client.rb @@ -1,11 +1,21 @@ require 'net/http' require 'singleton' require 'json' - +require 'rubygems' $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) require 'transmission-client/client' -require 'transmission-client/connection' + +if defined? EM + begin + require 'em-http' + require 'transmission-client/em-connection' + rescue LoadError + require 'transmission-client/connection' + end +else + require 'transmission-client/connection' +end require 'transmission-client/torrent' require 'transmission-client/session' diff --git a/lib/transmission-client/client.rb b/lib/transmission-client/client.rb index 1d076a4..ccc67c2 100755 --- a/lib/transmission-client/client.rb +++ b/lib/transmission-client/client.rb @@ -4,55 +4,68 @@ def initialize(host='localhost',port=9091) Connection.instance.init(host, port) end - def start_all - Connection.instance.send('torrent-start') + def start_all &cb + Connection.instance.send('torrent-start', &cb) end - def start(id) - Connection.instance.send('torrent-start', {'ids' => id.class == Array ? id : [id]}) + def start(id, &cb) + Connection.instance.send('torrent-start', {'ids' => id.class == Array ? id : [id]}, &cb) end - def stop(id) - Connection.instance.send('torrent-stop', {'ids' => id.class == Array ? id : [id]}) + def stop(id, &cb) + Connection.instance.send('torrent-stop', {'ids' => id.class == Array ? id : [id]}, &cb) end - def stop_all - Connection.instance.send('torrent-stop') + def stop_all &cb + Connection.instance.send('torrent-stop', &cb) end - def remove(id, delete_data = false) - Connection.instance.send('torrent-remove', {'ids' => id.class == Array ? id : [id], 'delete-local-data' => delete_data }) + def remove(id, delete_data = false, &cb) + Connection.instance.send('torrent-remove', {'ids' => id.class == Array ? id : [id], 'delete-local-data' => delete_data }, &cb) end - def remove_all(delete_data = false) - Connection.instance.send('torrent-remove', {'delete-local-data' => delete_data }) + def remove_all(delete_data = false, &cb) + Connection.instance.send('torrent-remove', {'delete-local-data' => delete_data }, &cb) end - def add_torrent(a) + def add_torrent(a, &cb) if a['filename'].nil? && a['metainfo'].nil? raise "You need to provide either a 'filename' or 'metainfo'." end - Connection.instance.send('torrent-add', a) + Connection.instance.send('torrent-add', a, &cb) end - def add_torrent_by_file(filename) - add_torrent({'filename' => filename}) + def add_torrent_by_file(filename, &cb) + add_torrent({'filename' => filename}, &cb) end - def add_torrent_by_data(data) - add_torrent({'metainfo' => data}) + def add_torrent_by_data(data, &cb) + add_torrent({'metainfo' => data}, &cb) end - def session - Session.new Connection.instance.request('session-get') + def session &cb + if cb + Connection.instance.request('session-get') { |resp| cb.call Session.new resp } + else + Session.new Connection.instance.request('session-get') + end end - def torrents(fields = nil) + def torrents(fields = nil, &cb) torrs = [] - Connection.instance.request('torrent-get', {'fields' => fields ? fields : Transmission::Torrent::ATTRIBUTES})['torrents'].each do |t| - torrs << Torrent.new(t) - end - torrs + if cb + Connection.instance.request('torrent-get', {'fields' => fields ? fields : Transmission::Torrent::ATTRIBUTES}) { |resp| + resp['torrents'].each do |t| + torrs << Torrent.new(t) + end + cb.call torrs + } + else + Connection.instance.request('torrent-get', {'fields' => fields ? fields : Transmission::Torrent::ATTRIBUTES})['torrents'].each do |t| + torrs << Torrent.new(t) + end + torrs + end end end end \ No newline at end of file diff --git a/lib/transmission-client/em-connection.rb b/lib/transmission-client/em-connection.rb new file mode 100755 index 0000000..4a5784a --- /dev/null +++ b/lib/transmission-client/em-connection.rb @@ -0,0 +1,51 @@ +module Transmission + class Connection + include Singleton + #include EM::Deferrable + + def init(host, port) + @host = host + @port = port + uri = URI.parse("http://#{@host}:#{@port}/transmission/rpc") + #@conn = Net::HTTP.start(uri.host, uri.port) + @conn = EventMachine::HttpRequest.new(uri) + @header = {} #{"Accept-Encoding" => "deflate"} deflate is broken somewhere + end + + def request(method, attributes={}, &cb) + req = @conn.post(:body => build_json(method,attributes), :head => @header ) + req.callback { + if req.response_header.status == 409 #&& @header['x-transmission-session-id'].nil? + @header['x-transmission-session-id'] = req.response_header['X_TRANSMISSION_SESSION_ID'] + request(method,attributes, &cb) + elsif req.response_header.status == 200 + resp = JSON.parse(req.response) + if resp["result"] == 'success' + cb.call resp['arguments'] if cb + else + cb.call resp if cb + end + end + } + req.errback { + puts 'errback' + pp req + } + end + + def send(method, attributes={}, &cb) + request(method, attributes) do |resp| + cb.call resp if cb + end + end + + def build_json(method,attributes = {}) + if attributes.length == 0 + {'method' => method}.to_json + else + {'method' => method, 'arguments' => attributes }.to_json + end + end + + end +end \ No newline at end of file diff --git a/lib/transmission-client/torrent.rb b/lib/transmission-client/torrent.rb index 6010cf9..e4491f2 100755 --- a/lib/transmission-client/torrent.rb +++ b/lib/transmission-client/torrent.rb @@ -29,7 +29,6 @@ def remove(delete_data = false) end def method_missing(m, *args, &block) - pp m if ATTRIBUTES.include? m.to_s return @attributes[m.to_s] elsif ADV_ATTRIBUTES.include? m.to_s