qbt_client 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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +78 -0
- data/Rakefile +7 -0
- data/lib/qbt_client/version.rb +3 -0
- data/lib/qbt_client/web_ui.rb +608 -0
- data/lib/qbt_client.rb +6 -0
- data/qbt_client.gemspec +28 -0
- data/spec/lib/qbt_client/web_ui_spec.rb +642 -0
- data/spec/lib/qbt_client_spec.rb +11 -0
- data/spec/spec_helper.rb +161 -0
- metadata +146 -0
@@ -0,0 +1,608 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# File:: web_ui.rb
|
3
|
+
# Purpose:: Web UI client for qBittorrent.
|
4
|
+
#
|
5
|
+
# Author:: Jeff McAffee 2015-02-07
|
6
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
7
|
+
# Website:: http://ktechsystems.com
|
8
|
+
##############################################################################
|
9
|
+
|
10
|
+
require 'json/pure'
|
11
|
+
require 'httparty'
|
12
|
+
require 'digest'
|
13
|
+
|
14
|
+
|
15
|
+
module QbtClient
|
16
|
+
|
17
|
+
class WebUI
|
18
|
+
include HTTParty
|
19
|
+
|
20
|
+
#debug_output $stdout
|
21
|
+
|
22
|
+
###
|
23
|
+
# constructor
|
24
|
+
#
|
25
|
+
def initialize(ip, port, user, pass)
|
26
|
+
@ip = ip
|
27
|
+
@port = port
|
28
|
+
@user = user
|
29
|
+
@pass = pass
|
30
|
+
|
31
|
+
self.class.digest_auth(user, pass)
|
32
|
+
self.class.base_uri "#{ip}:#{port}"
|
33
|
+
end
|
34
|
+
|
35
|
+
###
|
36
|
+
# Get array of all torrents
|
37
|
+
#
|
38
|
+
# Example response:
|
39
|
+
# [
|
40
|
+
# {
|
41
|
+
# "dlspeed"=>"3.1 MiB/s",
|
42
|
+
# "eta"=>"9m",
|
43
|
+
# "hash"=>"156b69b8643bd11849a5d8f2122e13fbb61bd041",
|
44
|
+
# "name"=>"slackware64-14.1-iso",
|
45
|
+
# "num_leechs"=>"1 (14)",
|
46
|
+
# "num_seeds"=>"97 (270)",
|
47
|
+
# "priority"=>"*",
|
48
|
+
# "progress"=>0.172291,
|
49
|
+
# "ratio"=>"0.0",
|
50
|
+
# "size"=>"2.2 GiB",
|
51
|
+
# "state"=>"downloading",
|
52
|
+
# "upspeed"=>"0 B/s"
|
53
|
+
# },
|
54
|
+
# {
|
55
|
+
# "dlspeed"=>"1.8 KiB/s",
|
56
|
+
# "eta"=>"28d 1h",
|
57
|
+
# "hash"=>"1fe5775d32d3e58e48b3a96dd2883c5250882cda",
|
58
|
+
# "name"=>"Grimm.S04E12.720p.HDTV.X264-DIMENSION.mkv",
|
59
|
+
# "num_leechs"=>"7 (471)",
|
60
|
+
# "num_seeds"=>"15 (1866)",
|
61
|
+
# "priority"=>"*",
|
62
|
+
# "progress"=>1.53669e-07,
|
63
|
+
# "ratio"=>"0.0",
|
64
|
+
# "size"=>"825.4 MiB",
|
65
|
+
# "state"=>"downloading",
|
66
|
+
# "upspeed"=>"0 B/s"
|
67
|
+
# }
|
68
|
+
# ]
|
69
|
+
#
|
70
|
+
def torrent_list
|
71
|
+
self.class.format :json
|
72
|
+
self.class.get('/json/torrents').parsed_response
|
73
|
+
end
|
74
|
+
|
75
|
+
def torrent_data torrent_hash
|
76
|
+
torrents = torrent_list
|
77
|
+
|
78
|
+
torrents.each do |t|
|
79
|
+
if t["hash"] == torrent_hash
|
80
|
+
return t
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
###
|
86
|
+
# Get properties of a torrent (different data than what's returned
|
87
|
+
# in #torrent_list).
|
88
|
+
#
|
89
|
+
# Example response:
|
90
|
+
# {
|
91
|
+
# "comment"=>"Visit us: https://eztv.ch/ - Bitcoin: 1EZTVaGQ6UsjYJ9fwqGnd45oZ6HGT7WKZd",
|
92
|
+
# "creation_date"=>"Friday, February 6, 2015 8:01:22 PM MST",
|
93
|
+
# "dl_limit"=>"∞",
|
94
|
+
# "nb_connections"=>"0 (100 max)",
|
95
|
+
# "piece_size"=>"512.0 KiB",
|
96
|
+
# "save_path"=>"/home/jeff/Downloads/",
|
97
|
+
# "share_ratio"=>"0.0",
|
98
|
+
# "time_elapsed"=>"< 1m",
|
99
|
+
# "total_downloaded"=>"646.8 KiB (657.8 KiB this session)",
|
100
|
+
# "total_uploaded"=>"0 B (0 B this session)",
|
101
|
+
# "total_wasted"=>"428 B",
|
102
|
+
# "up_limit"=>"∞"
|
103
|
+
# }
|
104
|
+
#
|
105
|
+
def properties torrent_hash
|
106
|
+
self.class.format :json
|
107
|
+
self.class.get('/json/propertiesGeneral/' + torrent_hash).parsed_response
|
108
|
+
end
|
109
|
+
|
110
|
+
###
|
111
|
+
# Get tracker data for a torrent
|
112
|
+
#
|
113
|
+
# Example response:
|
114
|
+
# [
|
115
|
+
# {
|
116
|
+
# "msg"=>"",
|
117
|
+
# "num_peers"=>"0",
|
118
|
+
# "status"=>"Working",
|
119
|
+
# "url"=>"udp://open.demonii.com:1337"},
|
120
|
+
# {
|
121
|
+
# "msg"=>"",
|
122
|
+
# "num_peers"=>"0",
|
123
|
+
# "status"=>"Not contacted yet",
|
124
|
+
# "url"=>"udp://tracker.coppersurfer.tk:6969"},
|
125
|
+
# {
|
126
|
+
# "msg"=>"",
|
127
|
+
# "num_peers"=>"0",
|
128
|
+
# "status"=>"Not contacted yet",
|
129
|
+
# "url"=>"udp://tracker.leechers-paradise.org:6969"},
|
130
|
+
# {
|
131
|
+
# "msg"=>"",
|
132
|
+
# "num_peers"=>"0",
|
133
|
+
# "status"=>"Not contacted yet",
|
134
|
+
# "url"=>"udp://exodus.desync.com:6969"}
|
135
|
+
# ]
|
136
|
+
#
|
137
|
+
def trackers torrent_hash
|
138
|
+
self.class.format :json
|
139
|
+
self.class.get('/json/propertiesTrackers/' + torrent_hash).parsed_response
|
140
|
+
end
|
141
|
+
|
142
|
+
###
|
143
|
+
# Add one or more trackers to a torrent
|
144
|
+
#
|
145
|
+
# If passing mulitple urls, pass them as an array.
|
146
|
+
#
|
147
|
+
def add_trackers torrent_hash, urls
|
148
|
+
urls = Array(urls)
|
149
|
+
# Ampersands in urls must be escaped.
|
150
|
+
urls = urls.map { |url| url.gsub('&', '%26') }
|
151
|
+
urls = urls.join('%0A')
|
152
|
+
|
153
|
+
options = {
|
154
|
+
body: "hash=#{torrent_hash}&urls=#{urls}"
|
155
|
+
}
|
156
|
+
|
157
|
+
self.class.post('/command/addTrackers', options)
|
158
|
+
end
|
159
|
+
|
160
|
+
###
|
161
|
+
# Get torrent contents (files data)
|
162
|
+
#
|
163
|
+
# Example response:
|
164
|
+
# [
|
165
|
+
# {
|
166
|
+
# "is_seed"=>false,
|
167
|
+
# "name"=>"Grimm.S04E12.720p.HDTV.X264-DIMENSION.mkv",
|
168
|
+
# "priority"=>1,
|
169
|
+
# "progress"=>0.0,
|
170
|
+
# "size"=>"825.4 MiB"
|
171
|
+
# }
|
172
|
+
# ]
|
173
|
+
#
|
174
|
+
def contents torrent_hash
|
175
|
+
self.class.format :json
|
176
|
+
self.class.get('/json/propertiesFiles/' + torrent_hash).parsed_response
|
177
|
+
end
|
178
|
+
|
179
|
+
###
|
180
|
+
# Get application transfer info
|
181
|
+
#
|
182
|
+
# Example response:
|
183
|
+
# {
|
184
|
+
# "dl_info"=>"D: 0 B/s/s - T: 657.8 KiB",
|
185
|
+
# "up_info"=>"U: 0 B/s/s - T: 0 B"
|
186
|
+
# }
|
187
|
+
#
|
188
|
+
def transfer_info
|
189
|
+
self.class.format :json
|
190
|
+
self.class.get('/json/transferInfo').parsed_response
|
191
|
+
end
|
192
|
+
|
193
|
+
###
|
194
|
+
# Get application preferences (options)
|
195
|
+
#
|
196
|
+
# Example response:
|
197
|
+
# {
|
198
|
+
# "alt_dl_limit"=>10,
|
199
|
+
# "alt_up_limit"=>10,
|
200
|
+
# "anonymous_mode"=>false,
|
201
|
+
# "autorun_enabled"=>false,
|
202
|
+
# "autorun_program"=>"",
|
203
|
+
# "bypass_local_auth"=>false,
|
204
|
+
# "dht"=>true,
|
205
|
+
# "dhtSameAsBT"=>true,
|
206
|
+
# "dht_port"=>6881,
|
207
|
+
# "dl_limit"=>-1,
|
208
|
+
# "dont_count_slow_torrents"=>false,
|
209
|
+
# "download_in_scan_dirs"=>[],
|
210
|
+
# "dyndns_domain"=>"changeme.dyndns.org",
|
211
|
+
# "dyndns_enabled"=>false,
|
212
|
+
# "dyndns_password"=>"",
|
213
|
+
# "dyndns_service"=>0,
|
214
|
+
# "dyndns_username"=>"",
|
215
|
+
# "enable_utp"=>true,
|
216
|
+
# "encryption"=>0,
|
217
|
+
# "export_dir"=>"",
|
218
|
+
# "export_dir_enabled"=>false,
|
219
|
+
# "incomplete_files_ext"=>false,
|
220
|
+
# "ip_filter_enabled"=>false,
|
221
|
+
# "ip_filter_path"=>"",
|
222
|
+
# "limit_tcp_overhead"=>false,
|
223
|
+
# "limit_utp_rate"=>true,
|
224
|
+
# "listen_port"=>6881,
|
225
|
+
# "locale"=>"en_US",
|
226
|
+
# "lsd"=>true,
|
227
|
+
# "mail_notification_auth_enabled"=>false,
|
228
|
+
# "mail_notification_email"=>"",
|
229
|
+
# "mail_notification_enabled"=>false,
|
230
|
+
# "mail_notification_password"=>"",
|
231
|
+
# "mail_notification_smtp"=>"smtp.changeme.com",
|
232
|
+
# "mail_notification_ssl_enabled"=>false,
|
233
|
+
# "mail_notification_username"=>"",
|
234
|
+
# "max_active_downloads"=>3,
|
235
|
+
# "max_active_torrents"=>5,
|
236
|
+
# "max_active_uploads"=>3,
|
237
|
+
# "max_connec"=>500,
|
238
|
+
# "max_connec_per_torrent"=>100,
|
239
|
+
# "max_uploads_per_torrent"=>4,
|
240
|
+
# "pex"=>true,
|
241
|
+
# "preallocate_all"=>false,
|
242
|
+
# "proxy_auth_enabled"=>false,
|
243
|
+
# "proxy_ip"=>"0.0.0.0",
|
244
|
+
# "proxy_password"=>"",
|
245
|
+
# "proxy_peer_connections"=>false,
|
246
|
+
# "proxy_port"=>8080,
|
247
|
+
# "proxy_type"=>-1,
|
248
|
+
# "proxy_username"=>"",
|
249
|
+
# "queueing_enabled"=>false,
|
250
|
+
# "save_path"=>"/home/jeff/Downloads",
|
251
|
+
# "scan_dirs"=>[],
|
252
|
+
# "schedule_from_hour"=>8,
|
253
|
+
# "schedule_from_min"=>0,
|
254
|
+
# "schedule_to_hour"=>20,
|
255
|
+
# "schedule_to_min"=>0,
|
256
|
+
# "scheduler_days"=>0,
|
257
|
+
# "scheduler_enabled"=>false,
|
258
|
+
# "ssl_cert"=>"",
|
259
|
+
# "ssl_key"=>"",
|
260
|
+
# "temp_path"=>"/home/jeff/Downloads/temp",
|
261
|
+
# "temp_path_enabled"=>false,
|
262
|
+
# "up_limit"=>50,
|
263
|
+
# "upnp"=>true,
|
264
|
+
# "use_https"=>false,
|
265
|
+
# "web_ui_password"=>"ae150cdc82b40c4373d2e15e0ffe8f67",
|
266
|
+
# "web_ui_port"=>8083,
|
267
|
+
# "web_ui_username"=>"admin"
|
268
|
+
# }
|
269
|
+
#
|
270
|
+
def preferences
|
271
|
+
self.class.format :json
|
272
|
+
self.class.get('/json/preferences').parsed_response
|
273
|
+
end
|
274
|
+
|
275
|
+
###
|
276
|
+
# Set application preferences
|
277
|
+
#
|
278
|
+
# Note: When setting password, pass it as plain text.
|
279
|
+
# You can send only the key/value pairs you want to change (in a hash),
|
280
|
+
# rather than the entire set of data.
|
281
|
+
#
|
282
|
+
def set_preferences pref_hash
|
283
|
+
pref_hash = Hash(pref_hash)
|
284
|
+
options = {
|
285
|
+
body: "json=#{pref_hash.to_json}"
|
286
|
+
}
|
287
|
+
|
288
|
+
self.class.post('/command/setPreferences', options)
|
289
|
+
end
|
290
|
+
|
291
|
+
###
|
292
|
+
# Pause a torrent
|
293
|
+
#
|
294
|
+
def pause torrent_hash
|
295
|
+
options = {
|
296
|
+
body: "hash=#{torrent_hash}"
|
297
|
+
}
|
298
|
+
|
299
|
+
self.class.post('/command/pause', options)
|
300
|
+
end
|
301
|
+
|
302
|
+
###
|
303
|
+
# Pause all torrents
|
304
|
+
#
|
305
|
+
def pause_all
|
306
|
+
self.class.post('/command/pauseall')
|
307
|
+
end
|
308
|
+
|
309
|
+
###
|
310
|
+
# Resume downloading/seeding of a torrent
|
311
|
+
#
|
312
|
+
def resume torrent_hash
|
313
|
+
options = {
|
314
|
+
body: "hash=#{torrent_hash}"
|
315
|
+
}
|
316
|
+
|
317
|
+
self.class.post('/command/resume', options)
|
318
|
+
end
|
319
|
+
|
320
|
+
###
|
321
|
+
# Resume downloading/seeding of all torrents
|
322
|
+
#
|
323
|
+
def resume_all
|
324
|
+
self.class.post('/command/resumeall')
|
325
|
+
end
|
326
|
+
|
327
|
+
###
|
328
|
+
# Begin downloading one or more torrents.
|
329
|
+
#
|
330
|
+
# If passing mulitple urls, pass them as an array.
|
331
|
+
#
|
332
|
+
def download urls
|
333
|
+
urls = Array(urls)
|
334
|
+
urls = urls.join('%0A')
|
335
|
+
|
336
|
+
options = {
|
337
|
+
body: "urls=#{urls}"
|
338
|
+
}
|
339
|
+
|
340
|
+
self.class.post('/command/download', options)
|
341
|
+
end
|
342
|
+
|
343
|
+
###
|
344
|
+
# Delete one or more torrents AND THEIR DATA
|
345
|
+
#
|
346
|
+
# If passing multiple torrent hashes, pass them as an array.
|
347
|
+
#
|
348
|
+
def delete_torrent_and_data torrent_hashes
|
349
|
+
torrent_hashes = Array(torrent_hashes)
|
350
|
+
torrent_hashes = torrent_hashes.join('|')
|
351
|
+
|
352
|
+
options = {
|
353
|
+
body: "hashes=#{torrent_hashes}"
|
354
|
+
}
|
355
|
+
|
356
|
+
self.class.post('/command/deletePerm', options)
|
357
|
+
end
|
358
|
+
|
359
|
+
###
|
360
|
+
# Delete one or more torrents (doesn't delete their data)
|
361
|
+
#
|
362
|
+
# If passing multiple torrent hashes, pass them as an array.
|
363
|
+
#
|
364
|
+
def delete torrent_hashes
|
365
|
+
torrent_hashes = Array(torrent_hashes)
|
366
|
+
torrent_hashes = torrent_hashes.join('|')
|
367
|
+
|
368
|
+
options = {
|
369
|
+
body: "hashes=#{torrent_hashes}"
|
370
|
+
}
|
371
|
+
|
372
|
+
self.class.post('/command/delete', options)
|
373
|
+
end
|
374
|
+
|
375
|
+
###
|
376
|
+
# Recheck a torrent
|
377
|
+
#
|
378
|
+
def recheck torrent_hash
|
379
|
+
options = {
|
380
|
+
body: "hash=#{torrent_hash}"
|
381
|
+
}
|
382
|
+
|
383
|
+
self.class.post('/command/recheck', options)
|
384
|
+
end
|
385
|
+
|
386
|
+
###
|
387
|
+
# Increase the priority of one or more torrents
|
388
|
+
#
|
389
|
+
# If passing multiple torrent hashes, pass them as an array.
|
390
|
+
# Note: This does nothing unless queueing has been enabled
|
391
|
+
# via preferences.
|
392
|
+
#
|
393
|
+
def increase_priority torrent_hashes
|
394
|
+
torrent_hashes = Array(torrent_hashes)
|
395
|
+
torrent_hashes = torrent_hashes.join('|')
|
396
|
+
|
397
|
+
options = {
|
398
|
+
body: "hashes=#{torrent_hashes}"
|
399
|
+
}
|
400
|
+
|
401
|
+
self.class.post('/command/increasePrio', options)
|
402
|
+
end
|
403
|
+
|
404
|
+
###
|
405
|
+
# Decrease the priority of one or more torrents
|
406
|
+
#
|
407
|
+
# If passing multiple torrent hashes, pass them as an array.
|
408
|
+
# Note: This does nothing unless queueing has been enabled
|
409
|
+
# via preferences.
|
410
|
+
#
|
411
|
+
def decrease_priority torrent_hashes
|
412
|
+
torrent_hashes = Array(torrent_hashes)
|
413
|
+
torrent_hashes = torrent_hashes.join('|')
|
414
|
+
|
415
|
+
options = {
|
416
|
+
body: "hashes=#{torrent_hashes}"
|
417
|
+
}
|
418
|
+
|
419
|
+
self.class.post('/command/decreasePrio', options)
|
420
|
+
end
|
421
|
+
|
422
|
+
###
|
423
|
+
# Increase the priority of one or more torrents to the maximum value
|
424
|
+
#
|
425
|
+
# If passing multiple torrent hashes, pass them as an array.
|
426
|
+
# Note: This does nothing unless queueing has been enabled
|
427
|
+
# via preferences.
|
428
|
+
#
|
429
|
+
def maximize_priority torrent_hashes
|
430
|
+
torrent_hashes = Array(torrent_hashes)
|
431
|
+
torrent_hashes = torrent_hashes.join('|')
|
432
|
+
|
433
|
+
options = {
|
434
|
+
body: "hashes=#{torrent_hashes}"
|
435
|
+
}
|
436
|
+
|
437
|
+
self.class.post('/command/topPrio', options)
|
438
|
+
end
|
439
|
+
|
440
|
+
###
|
441
|
+
# Decrease the priority of one or more torrents to the minimum value
|
442
|
+
#
|
443
|
+
# If passing multiple torrent hashes, pass them as an array.
|
444
|
+
# Note: This does nothing unless queueing has been enabled
|
445
|
+
# via preferences.
|
446
|
+
#
|
447
|
+
def minimize_priority torrent_hashes
|
448
|
+
torrent_hashes = Array(torrent_hashes)
|
449
|
+
torrent_hashes = torrent_hashes.join('|')
|
450
|
+
|
451
|
+
options = {
|
452
|
+
body: "hashes=#{torrent_hashes}"
|
453
|
+
}
|
454
|
+
|
455
|
+
self.class.post('/command/bottomPrio', options)
|
456
|
+
end
|
457
|
+
|
458
|
+
###
|
459
|
+
# Set the download priority of a file within a torrent
|
460
|
+
#
|
461
|
+
# file_id is a 0 based position of the file within the torrent
|
462
|
+
#
|
463
|
+
def set_file_priority torrent_hash, file_id, priority
|
464
|
+
query = ["hash=#{torrent_hash}", "id=#{file_id}", "priority=#{priority}"]
|
465
|
+
|
466
|
+
options = {
|
467
|
+
body: query.join('&')
|
468
|
+
}
|
469
|
+
|
470
|
+
self.class.post('/command/setFilePrio', options)
|
471
|
+
end
|
472
|
+
|
473
|
+
###
|
474
|
+
# Get the application's global download limit
|
475
|
+
#
|
476
|
+
# A limit of 0 means unlimited.
|
477
|
+
#
|
478
|
+
# Returns an integer (bytes)
|
479
|
+
#
|
480
|
+
def global_download_limit
|
481
|
+
self.class.format :json
|
482
|
+
self.class.post('/command/getGlobalDlLimit').parsed_response
|
483
|
+
end
|
484
|
+
|
485
|
+
###
|
486
|
+
# Set the application's global download limit
|
487
|
+
#
|
488
|
+
# A limit of 0 means unlimited.
|
489
|
+
#
|
490
|
+
# limit: integer (bytes)
|
491
|
+
#
|
492
|
+
def set_global_download_limit limit
|
493
|
+
query = "limit=#{limit}"
|
494
|
+
|
495
|
+
options = {
|
496
|
+
body: query
|
497
|
+
}
|
498
|
+
|
499
|
+
self.class.post('/command/setGlobalDlLimit', options)
|
500
|
+
end
|
501
|
+
|
502
|
+
###
|
503
|
+
# Get the application's global upload limit
|
504
|
+
#
|
505
|
+
# A limit of 0 means unlimited.
|
506
|
+
#
|
507
|
+
# Returns an integer (bytes)
|
508
|
+
#
|
509
|
+
def global_upload_limit
|
510
|
+
self.class.format :json
|
511
|
+
self.class.post('/command/getGlobalUpLimit').parsed_response
|
512
|
+
end
|
513
|
+
|
514
|
+
###
|
515
|
+
# Set the application's global upload limit
|
516
|
+
#
|
517
|
+
# A limit of 0 means unlimited.
|
518
|
+
#
|
519
|
+
# limit: integer (bytes)
|
520
|
+
#
|
521
|
+
def set_global_upload_limit limit
|
522
|
+
query = "limit=#{limit}"
|
523
|
+
|
524
|
+
options = {
|
525
|
+
body: query
|
526
|
+
}
|
527
|
+
|
528
|
+
self.class.post('/command/setGlobalUpLimit', options)
|
529
|
+
end
|
530
|
+
|
531
|
+
###
|
532
|
+
# Get a torrent's download limit
|
533
|
+
#
|
534
|
+
# A limit of 0 means unlimited.
|
535
|
+
#
|
536
|
+
# Returns an integer (bytes)
|
537
|
+
#
|
538
|
+
def download_limit torrent_hash
|
539
|
+
self.class.format :json
|
540
|
+
|
541
|
+
options = {
|
542
|
+
body: "hash=#{torrent_hash}"
|
543
|
+
}
|
544
|
+
|
545
|
+
self.class.post('/command/getTorrentDlLimit', options).parsed_response
|
546
|
+
end
|
547
|
+
|
548
|
+
###
|
549
|
+
# Set a torrent's download limit
|
550
|
+
#
|
551
|
+
# A limit of 0 means unlimited.
|
552
|
+
#
|
553
|
+
# torrent_hash: string
|
554
|
+
# limit: integer (bytes)
|
555
|
+
#
|
556
|
+
def set_download_limit torrent_hash, limit
|
557
|
+
query = ["hash=#{torrent_hash}", "limit=#{limit}"]
|
558
|
+
|
559
|
+
options = {
|
560
|
+
body: query.join('&')
|
561
|
+
}
|
562
|
+
|
563
|
+
self.class.post('/command/setTorrentDlLimit', options)
|
564
|
+
end
|
565
|
+
|
566
|
+
###
|
567
|
+
# Get a torrent's upload limit
|
568
|
+
#
|
569
|
+
# A limit of 0 means unlimited.
|
570
|
+
#
|
571
|
+
# Returns an integer (bytes)
|
572
|
+
#
|
573
|
+
def upload_limit torrent_hash
|
574
|
+
self.class.format :json
|
575
|
+
|
576
|
+
options = {
|
577
|
+
body: "hash=#{torrent_hash}"
|
578
|
+
}
|
579
|
+
|
580
|
+
self.class.post('/command/getTorrentUpLimit', options).parsed_response
|
581
|
+
end
|
582
|
+
|
583
|
+
###
|
584
|
+
# Set a torrent's upload limit
|
585
|
+
#
|
586
|
+
# A limit of 0 means unlimited.
|
587
|
+
#
|
588
|
+
# torrent_hash: string
|
589
|
+
# limit: integer (bytes)
|
590
|
+
#
|
591
|
+
def set_upload_limit torrent_hash, limit
|
592
|
+
query = ["hash=#{torrent_hash}", "limit=#{limit}"]
|
593
|
+
|
594
|
+
options = {
|
595
|
+
body: query.join('&')
|
596
|
+
}
|
597
|
+
|
598
|
+
self.class.post('/command/setTorrentUpLimit', options)
|
599
|
+
end
|
600
|
+
|
601
|
+
private
|
602
|
+
|
603
|
+
def md5 str
|
604
|
+
Digest::MD5.hexdigest str
|
605
|
+
end
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
data/lib/qbt_client.rb
ADDED
data/qbt_client.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'qbt_client/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "qbt_client"
|
8
|
+
spec.version = QbtClient::VERSION
|
9
|
+
spec.authors = ["Jeff McAffee"]
|
10
|
+
spec.email = ["jeff@ktechsystems.com"]
|
11
|
+
spec.summary = %q{qBittorent client}
|
12
|
+
spec.description = %q{qBittorrent client}
|
13
|
+
spec.homepage = "https://github.com/jmcaffee/qbt_client"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "httparty", "~> 0.7"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "pry-byebug"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
end
|