Skip to content

Commit

Permalink
Torrent status change callbacks and authentication support
Browse files Browse the repository at this point in the history
  • Loading branch information
dsander committed Feb 11, 2010
1 parent 4807c9d commit c7e144a
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 23 deletions.
39 changes: 24 additions & 15 deletions README.markdown
@@ -1,6 +1,6 @@
# transmission-client: A Transmission RPC Client

**Warning - The next release will drop support for the blocking api. Eventmachine will be required by then.**
**Please note, with the current release i dropped support for the blocking api. Eventmachine is now required.**

The goal is to support all requests described in the Transmission [RPC Specifications](http://trac.transmissionbt.com/browser/trunk/doc/rpc-spec.txt).

Expand All @@ -18,24 +18,10 @@ 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('127.0.0.1', 9091)
t.torrents.each do |torrent|
puts torrent.name
end

To use the EventMachine driven interface:

require 'eventmachine'
require 'transmission-client'

EventMachine.run do
t = Transmission::Client.new
Expand All @@ -47,5 +33,28 @@ To use the EventMachine driven interface:
end
end
end

Authentication support (thanks hornairs):

t = Transmission::Client.new('127.0.0.1', 9091, 'username', 'password')

Callbacks:

EventMachine.run do
t = Transmission::Client.new
t.on_download_finished do |torrent|
puts "Wha torrent finished"
end
t.on_torrent_stopped do |torrent|
puts "Oooh torrent stopped"
end
t.on_torrent_started do |torrent|
puts "Torrent started."
end
t.on_torrent_removed do |torrent|
puts "Darn torrent deleted."
end
end

RDoc is still to be written, at the meantime have a look at the code to find out which methods are supported.
50 changes: 48 additions & 2 deletions lib/transmission-client/client.rb
@@ -1,7 +1,14 @@
module Transmission
class Client
def on_download_finished(&blk); @on_download_finished = blk; callback_initialized; end
def on_torrent_added(&blk); @on_torrent_added = blk; callback_initialized; end
def on_torrent_stopped(&blk); @on_torrent_stopped = blk; callback_initialized; end
def on_torrent_started(&blk); @on_torrent_started = blk; callback_initialized; end
def on_torrent_removed(&blk); @on_torrent_removed = blk; callback_initialized; end

def initialize(host='localhost',port=9091, username = nil, password = nil)
Connection.init(host, port, username, password)
@torrents = nil
end

def start_all &cb
Expand Down Expand Up @@ -47,14 +54,53 @@ def session
Connection.request('session-get') { |resp| yield Session.new resp }
end

def torrents(fields = nil)
torrs = []
def torrents(fields = nil)
Connection.request('torrent-get', {'fields' => fields ? fields : Transmission::Torrent::ATTRIBUTES}) { |resp|
torrs = []
resp['torrents'].each do |t|
torrs << Torrent.new(t)
end
yield torrs
}
end

private
def callback_initialized
return if @torrent_poller
@torrent_poller = EM.add_periodic_timer(1) do
updated_torrents = {}
self.torrents do |tors|
tors.each do |torrent|
updated_torrents[torrent.id] = torrent
end
compare_torrent_status updated_torrents
@torrents = updated_torrents.dup
end


end
end

def compare_torrent_status updated_torrents
return false unless @torrents
updated_torrents.each_pair do |id, t|
old = @torrents[t.id] if @torrents[t.id]
if old == nil
@on_torrent_started.call t if @on_torrent_started
elsif old.downloading? && t.seeding?
@on_download_finished.call t if @on_download_finished
elsif old.stopped? && !t.stopped?
@on_torrent_started.call t if @on_torrent_started
elsif !old.stopped? && t.stopped?
@on_torrent_stopped.call t if @on_torrent_stopped
end
@torrents.delete t.id
end
if @torrents.length > 0 && @on_torrent_removed
@torrents.values.each do |t|
@on_torrent_removed.call t
end
end
end
end
end
37 changes: 31 additions & 6 deletions lib/transmission-client/torrent.rb 100755 → 100644
Expand Up @@ -3,39 +3,64 @@ class Torrent
ATTRIBUTES = ['activityDate', 'addedDate', 'bandwidthPriority', 'comment', 'corruptEver', 'creator', 'dateCreated', 'desiredAvailable', 'doneDate', 'downloadDir', 'downloadedEver', 'downloadLimit', 'downloadLimited', 'error', 'errorString', 'eta', 'hashString', 'haveUnchecked', 'haveValid', 'honorsSessionLimits', 'id', 'isPrivate', 'leftUntilDone', 'manualAnnounceTime', 'maxConnectedPeers', 'name', 'peer-limit', 'peersConnected', 'peersGettingFromUs', 'peersKnown', 'peersSendingToUs', 'percentDone', 'pieces', 'pieceCount', 'pieceSize', 'rateDownload', 'rateUpload', 'recheckProgress', 'seedRatioLimit', 'seedRatioMode', 'sizeWhenDone', 'startDate', 'status', 'swarmSpeed', 'totalSize', 'torrentFile', 'uploadedEver', 'uploadLimit', 'uploadLimited', 'uploadRatio', 'webseedsSendingToUs']
ADV_ATTRIBUTES = ['files', 'fileStats', 'peers', 'peersFrom', 'priorities', 'trackers', 'trackerStats', 'wanted', 'webseeds']
SETABLE_ATTRIBUTES = ['bandwidthPriority', 'downloadLimit', 'downloadLimited', 'files-wanted', 'files-unwanted', 'honorsSessionLimits', 'ids', 'location', 'peer-limit', 'priority-high', 'priority-low', 'priority-normal', 'seedRatioLimit', 'seedRatioMode', 'uploadLimit', 'uploadLimited']
CHECK_WAIT = 1
CHECK = 2
DOWNLOAD = 4
SEED = 8
STOPPED = 16

def initialize(attributes)
@attributes = attributes
end

def start
Connection.instance.send('torrent-start', {'ids' => @attributes['id']})
Connection.send('torrent-start', {'ids' => @attributes['id']})
end

def stop
Connection.instance.send('torrent-stop', {'ids' => @attributes['id']})
Connection.send('torrent-stop', {'ids' => @attributes['id']})
end

def verify
Connection.instance.send('torrent-verify', {'ids' => @attributes['id']})
Connection.send('torrent-verify', {'ids' => @attributes['id']})
end

def reannounce
Connection.instance.send('torrent-reannounce', {'ids' => @attributes['id']})
Connection.send('torrent-reannounce', {'ids' => @attributes['id']})
end

def remove(delete_data = false)
Connection.instance.send('torrent-remove', {'ids' => @attributes['id'], 'delete-local-data' => delete_data })
Connection.send('torrent-remove', {'ids' => @attributes['id'], 'delete-local-data' => delete_data })
end

def downloading?
self.status == DOWNLOAD
end

def stopped?
self.status == STOPPED
end

def checking?
self.status == CHECK || self.status == CHECK_WAIT
end

def seeding?
self.status == SEED
end

def id
@attributes['id']
end

def method_missing(m, *args, &block)
if ATTRIBUTES.include? m.to_s
return @attributes[m.to_s]
elsif ADV_ATTRIBUTES.include? m.to_s
raise "Attribute not yet supported."
elsif m[-1..-1] == '='
if SETABLE_ATTRIBUTES.include? m[0..-2]
Connection.instance.send('torrent-set', {'ids' => [@attributes['id']], m[0..-2] => args.first})
Connection.send('torrent-set', {'ids' => [@attributes['id']], m[0..-2] => args.first})
else
raise "Invalid Attribute."
end
Expand Down

0 comments on commit c7e144a

Please sign in to comment.