/
client.rb
157 lines (138 loc) · 4.7 KB
/
client.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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 = Connection.new(host, port, username, password)
@torrents = nil
end
def start_all &cb
@connection.send('torrent-start') do |resp|
yield resp if block_given?
end
end
def start(id)
@connection.send('torrent-start', {'ids' => [*id].map(&:to_i)}) do |resp|
yield resp if block_given?
end
end
def stop(id)
@connection.send('torrent-stop', {'ids' => [*id].map(&:to_i)}) do |resp|
yield resp if block_given?
end
end
def stop_all &cb
@connection.send('torrent-stop') do |resp|
yield resp if block_given?
end
end
def remove(id, delete_data = false)
@connection.send('torrent-remove', {'ids' => [*id].map(&:to_i), 'delete-local-data' => delete_data }) do |resp|
yield resp if block_given?
end
end
def remove_all(delete_data = false)
@connection.send('torrent-remove', {'delete-local-data' => delete_data }) do |resp|
yield resp if block_given?
end
end
def add_tracker(id, announce = 'http://retracker.local/announce')
@connection.send('torrent-set', {'ids' => [*id].map(&:to_i), 'trackerAdd' => [*announce] }) do |resp|
yield resp if block_given?
end
end
def get_trackers(id)
@connection.request('torrent-get', {'ids' => [*id].map(&:to_i), 'fields' => ['trackers'] }) do |resp|
yield resp
end
end
def add_torrent(a)
if a['filename'].nil? && a['metainfo'].nil?
raise "You need to provide either a 'filename' or 'metainfo'."
end
@connection.send('torrent-add', a) do |resp|
yield resp if block_given?
end
end
def add_torrent_by_file(filename)
add_torrent({'filename' => filename}) do |resp|
yield resp if block_given?
end
end
def add_torrent_by_data(data)
add_torrent({'metainfo' => data}) do |resp|
yield resp if block_given?
end
end
#TODO handler for resp['status'] != 'success'
def session
@connection.request('session-get') do |resp|
if resp == :connection_error
yield :connection_error
else
yield Session.new(resp)
end
end
end
def session_stat
@connection.request('session-stats') { |resp| yield SessionStat.new(resp) }
end
def get_torrent(id, &block)
self.torrents("ids" => [id.to_i]) do |torrents|
block.call(torrents.first)
end
end
#TODO handler for resp['status'] != 'success'
# options = { 'fields' => ['id'], 'ids' => [1,4,6] }
def torrents(options = {})
options = { 'fields' => options } if options.is_a? Array
params = { 'fields' => Transmission::Torrent::ATTRIBUTES}.merge options
@connection.request('torrent-get', params) do |resp|
if resp == :connection_error
yield :connection_error
else
torrs = resp['torrents'].map { |t| Torrent.new(t, @connection) }
yield torrs
end
end
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(@torrents, updated_torrents) if @torrents
@torrents = updated_torrents
end
end
end
def compare_torrent_status(old_torrents, updated_torrents)
old_torrents = old_torrents.dup
updated_torrents.each_pair do |id, t|
old = old_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
old_torrents.delete t.id
end
if @on_torrent_removed
old_torrents.values.each do |t|
@on_torrent_removed.call t
end
end
end
end
end