transmission-ng 1.0.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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/transmission.rb +345 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a7e922da176f605b211f3bed6b3fdfdbf08f8f52
4
+ data.tar.gz: 2b68b61650148b7f0416188773764c235ed03b36
5
+ SHA512:
6
+ metadata.gz: 1d6f54565b898d83e51ff1caedb5bcc0bf81b7752886e86208d7849d6134abda8bc7cfc47c039b78d65f8bbd173b792b78f96b5d125b0b95285f4ac86e3e0759
7
+ data.tar.gz: 1e649a8abe139f01620d3ecedc6a0efed2cf970aec26462e6f8aa19a78376526d64f6e27bcee1c51a41c582c9dca8dd73ce1fd65f90ea460428f52e9dfa97726
@@ -0,0 +1,345 @@
1
+
2
+ require 'net/http'
3
+ require 'json'
4
+
5
+ $rpc_version = 15
6
+
7
+ class Transmission
8
+ attr_accessor :list_attributes
9
+ attr_accessor :settable_attributes
10
+
11
+ def initialize(config)
12
+ @config = config
13
+
14
+ @list_attributes = ['id','name','hashString','isFinished','isStalled','leftUntilDone','eta','percentDone','rateDownload',
15
+ 'status','totalSize','rateDownload']
16
+ @all_attributes = ['activityDate','addedDate','bandwidthPriority','comment','corruptEver','creator','dateCreated',
17
+ 'desiredAvailable','doneDate','downloadDir','downloadedEver','downloadLimit','downloadLimited','error',
18
+ 'errorString','eta','etaIdle','files','fileStats','hashString','haveUnchecked','haveValid','honorsSessionLimits',
19
+ 'id','isFinished','isPrivate','isStalled','leftUntilDone','magnetLink','manualAnnounceTime','maxConnectedPeers',
20
+ 'metadataPercentComplete','name','peer-limit','peers','peersConnected','peersFrom','peersGettingFromUs',
21
+ 'peersSendingToUs','percentDone','pieces','pieceCount','pieceSize','priorities','queuePosition','rateDownload',
22
+ 'rateUpload','recheckProgress','secondsDownloading','secondsSeeding','seedIdleLimit','seedIdleMode','seedRatioLimit',
23
+ 'seedRatioMode','sizeWhenDone','startDate','status','trackers','trackerStats','totalSize','torrentFile',
24
+ 'uploadedEver','uploadLimit','uploadLimited','uploadRatio','wanted','webseeds','webseedsSendingToUs']
25
+ @settable_attributes = ['bandwidthPriority','downloadLimit','downloadLimited','files-wanted','files-unwanted',
26
+ 'honorsSessionLimits','location','peer-limit','priority-high','priority-low','priority-normal','queuePosition',
27
+ 'seedIdleLimit','seedIdleMode','seedRatioLimit','seedRatioMode','trackerAdd','trackerRemove','trackerReplace',
28
+ 'uploadLimit','uploadLimited']
29
+ @session_attributes = ['alt-speed-down','alt-speed-enabled','alt-speed-time-begin','alt-speed-time-enabled',
30
+ 'alt-speed-time-end','alt-speed-time-day','alt-speed-up','blocklist-url','blocklist-enabled','blocklist-size',
31
+ 'cache-size-mb','config-dir','download-dir','download-queue-size','download-queue-enabled','dht-enabled',
32
+ 'encryption','idle-seeding-limit','idle-seeding-limit-enabled','incomplete-dir','incomplete-dir-enabled',
33
+ 'lpd-enabled','peer-limit-global','peer-limit-per-torrent','pex-enabled','peer-port','peer-port-random-on-start',
34
+ 'port-forwarding-enabled','queue-stalled-enabled','queue-stalled-minutes','rename-partial-files','rpc-version',
35
+ 'rpc-version-minimum','script-torrent-done-filename','script-torrent-done-enabled','seedRatioLimit','seedRatioLimited',
36
+ 'seed-queue-size','seed-queue-enabled','speed-limit-down','speed-limit-down-enabled','speed-limit-up',
37
+ 'speed-limit-up-enabled','start-added-torrents','trash-original-torrent-files','units','utp-enabled','version','units']
38
+ @session_settable_attributes = ['alt-speed-down','alt-speed-enabled','alt-speed-time-begin','alt-speed-time-enabled',
39
+ 'alt-speed-time-end','alt-speed-time-day','alt-speed-up','blocklist-url','blocklist-enabled','cache-size-mb',
40
+ 'download-dir','download-queue-size','download-queue-enabled','dht-enabled','encryption','idle-seeding-limit',
41
+ 'idle-seeding-limit-enabled','incomplete-dir','incomplete-dir-enabled','lpd-enabled','peer-limit-global',
42
+ 'peer-limit-per-torrent','pex-enabled','peer-port','peer-port-random-on-start','port-forwarding-enabled',
43
+ 'queue-stalled-enabled','queue-stalled-minutes','rename-partial-files','script-torrent-done-filename',
44
+ 'script-torrent-done-enabled','seedRatioLimit','seedRatioLimited','seed-queue-size','seed-queue-enabled',
45
+ 'speed-limit-down','speed-limit-down-enabled','speed-limit-up','speed-limit-up-enabled','start-added-torrents',
46
+ 'trash-original-torrent-files','units','utp-enabled','units']
47
+
48
+ rpc_version = session_get['rpc-version']
49
+
50
+ if rpc_version != $rpc_version
51
+ puts "--------------------------------------------------------"
52
+ puts "WARNING: RPC version is #{rpc_version} but we only support #{$rpc_version}."
53
+ puts "Some API methods may fail or produce unexpected results."
54
+ puts "Please check for an update to this gem."
55
+ puts "--------------------------------------------------------"
56
+ end
57
+ end
58
+
59
+ def rpc(method, args=[], session_id=nil)
60
+ url = URI.parse('http://' + @config[:host] + ':' + @config[:port].to_s + '/transmission/rpc')
61
+
62
+ http = Net::HTTP.new(url.host, url.port)
63
+
64
+ req = Net::HTTP::Post.new(url.path)
65
+ req.basic_auth @config[:user], @config[:pass]
66
+ req.body = {
67
+ 'method' => method,
68
+ 'arguments' => args
69
+ }.to_json
70
+ req['X-Transmission-Session-Id'] = session_id
71
+ req['Content-Type'] = 'application/json'
72
+
73
+ resp = http.request(req)
74
+
75
+ if resp.code == "409"
76
+ m = resp.body.match /X-Transmission-Session-Id: (.*?)</
77
+ return rpc(method, args, m[1])
78
+ end
79
+
80
+ response = JSON.parse(resp.body)
81
+
82
+ if response["result"] != "success"
83
+ raise "RPC error: " + response["result"]
84
+ end
85
+
86
+ response
87
+ end
88
+ private :rpc
89
+
90
+ def get(ids=[], attributes=[])
91
+ attributes.each do |attr|
92
+ if !@all_attributes.include? attr
93
+ raise "Unknown torrent attributes: #{attr}"
94
+ end
95
+ end
96
+
97
+ if attributes.empty?
98
+ attributes = @all_attributes
99
+ end
100
+
101
+ params = {
102
+ :fields => attributes
103
+ }
104
+
105
+ if ids.is_a? Fixnum
106
+ ids = [ids]
107
+ single = true
108
+ else
109
+ single = false
110
+ end
111
+
112
+ if !ids.empty?
113
+ params[:ids] = ids
114
+ end
115
+
116
+ resp = rpc('torrent-get', params)
117
+
118
+ for i in 0...resp["arguments"]["torrents"].length
119
+ resp["arguments"]["torrents"][i].each do |key, value|
120
+ if respond_to? "map_#{key}"
121
+ resp["arguments"]["torrents"][i][key] = self.send "map_#{key}", value
122
+ end
123
+ end
124
+ end
125
+
126
+ if single
127
+ return !resp["arguments"]["torrents"].empty? ? resp["arguments"]["torrents"][0] : false
128
+ end
129
+
130
+ resp["arguments"]["torrents"]
131
+ end
132
+
133
+ def list
134
+ get([], @list_attributes)
135
+ end
136
+
137
+ def list_by(field, operator, value=nil)
138
+ torrents = []
139
+
140
+ if value == nil
141
+ value = operator
142
+ operator = '='
143
+ end
144
+
145
+ list.each do |torrent|
146
+ if eval_operator(torrent[field], operator, value)
147
+ torrents.push torrent
148
+ end
149
+ end
150
+
151
+ torrents
152
+ end
153
+
154
+ def eval_operator(torrent_value, operator, value)
155
+ case operator
156
+ when '=','=='
157
+ return torrent_value == value
158
+ when '>'
159
+ return torrent_value > value
160
+ when '<'
161
+ return torrent_value < value
162
+ when '>='
163
+ return torrent_value >= value
164
+ when '<='
165
+ return torrent_value <= value
166
+ when '!=','<>'
167
+ return torrent_value != value
168
+ else
169
+ raise "Unknown comparison operator: #{operator}"
170
+ end
171
+ end
172
+ private :eval_operator
173
+
174
+ def map_status(code)
175
+ case code
176
+ when 0
177
+ return 'stopped'
178
+ when 1
179
+ return 'check-wait'
180
+ when 2
181
+ return 'checking'
182
+ when 3
183
+ return 'download-wait'
184
+ when 4
185
+ return 'downloading'
186
+ when 5
187
+ return 'seed-wait'
188
+ when 6
189
+ return 'seeding'
190
+ else
191
+ raise "Unknown status code: #{code}"
192
+ end
193
+ end
194
+
195
+ def map_percentDone(percent)
196
+ percent * 100
197
+ end
198
+
199
+ def get_attr(id, attribute)
200
+ resp = get([id], [attribute])
201
+
202
+ resp[0][attribute]
203
+ end
204
+
205
+ def get_attrs(ids, attributes)
206
+ get(ids, attributes)
207
+ end
208
+
209
+ def add(params={})
210
+ resp = rpc('torrent-add', params)
211
+
212
+ resp["arguments"]["torrent-added"]
213
+ end
214
+ private :add
215
+
216
+ def add_magnet(magnet_link, params={})
217
+ if !magnet_link.match /^magnet:\?/
218
+ raise "This doesn't look like a magnet link to me: #{magnet_link}"
219
+ end
220
+ add({'filename' => magnet_link}.merge(params))
221
+ end
222
+
223
+ def add_torrentfile(torrent_file, params={})
224
+ add({'filename' => torrent_file}.merge(params))
225
+ end
226
+
227
+ def add_torrentdata(torrent_data, params={})
228
+ add({'metainfo' => torrent_data}.merge(params))
229
+ end
230
+
231
+ def method_missing(method, *args, &block)
232
+ map = {
233
+ :start => 'torrent-start',
234
+ :stop => 'torrent-stop',
235
+ :verify => 'torrent-verify',
236
+ :reannounce => 'torrent-reannounce',
237
+ :queue_top => 'queue-move-top',
238
+ :queue_up => 'queue-move-up',
239
+ :queue_down => 'queue-move-down',
240
+ :queue_bottom => 'queue-move-bottom'
241
+ }
242
+
243
+ if map[method] == nil
244
+ raise "Unknown method: #{method}"
245
+ end
246
+
247
+ resp = rpc(map[method], {'ids' => args[0]})
248
+
249
+ true
250
+ end
251
+
252
+ def set(ids, keys)
253
+ keys.each do |key, value|
254
+ if !@settable_attributes.include? key
255
+ raise "Unknown attribute: #{key}"
256
+ end
257
+ end
258
+
259
+ resp = rpc('torrent-set',{
260
+ 'ids' => ids
261
+ }.merge(keys))
262
+
263
+ true
264
+ end
265
+
266
+ def delete(ids, delete_local_data=false)
267
+ resp = rpc('torrent-remove',{
268
+ 'ids' => ids,
269
+ 'delete-local-data' => delete_local_data
270
+ })
271
+
272
+ true
273
+ end
274
+
275
+ def set_location(ids, location, move=false)
276
+ resp = rpc('torrent-set-location',{
277
+ 'ids' => ids,
278
+ 'location' => location,
279
+ 'move' => move
280
+ })
281
+
282
+ true
283
+ end
284
+
285
+ def rename_path(ids, path, name)
286
+ resp = rpc('torrent-rename-path',{
287
+ 'ids' => ids,
288
+ 'path' => path,
289
+ 'name' => name
290
+ })
291
+
292
+ true
293
+ end
294
+
295
+ def session_get
296
+ resp = rpc('session-get')
297
+
298
+ resp['arguments']
299
+ end
300
+
301
+ def session_set(keys)
302
+ keys.each do |key, value|
303
+ if !@session_attributes.include? key
304
+ raise "Unknown session attribute: #{key}"
305
+ end
306
+ if !@session_settable_attributes.include? key
307
+ raise "Session attribute '#{key}' cannot be changed."
308
+ end
309
+ end
310
+
311
+ resp = rpc('session-set',keys)
312
+
313
+ true
314
+ end
315
+
316
+ def session_stats
317
+ resp = rpc('session-stats')
318
+
319
+ resp['arguments']
320
+ end
321
+
322
+ def blocklist_update
323
+ resp = rpc('blocklist-update')
324
+
325
+ resp['arguments']
326
+ end
327
+
328
+ def port_test
329
+ resp = rpc('port-test')
330
+
331
+ resp['arguments']['port-is-open']
332
+ end
333
+
334
+ def session_close
335
+ resp = rpc('session-close')
336
+
337
+ true
338
+ end
339
+
340
+ def free_space(path)
341
+ resp = rpc('free-space',{'path' => path})
342
+
343
+ resp['arguments']
344
+ end
345
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: transmission-ng
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - m4rkw
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A better API interface for the Transmission torrent client
14
+ email: m@rkw.io
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/transmission.rb
20
+ homepage: https://github.com/m4rkw/transmission-ng
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.4.5
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Transmission API gem
44
+ test_files: []