trans-api 0.0.4 → 0.0.5
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 +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +12 -0
- data/.vagrant/bootstrap/settings.json +70 -0
- data/.vagrant/bootstrap/testing.sh +34 -0
- data/Gemfile.lock +34 -8
- data/README.md +121 -38
- data/Rakefile +14 -0
- data/Vagrantfile +18 -0
- data/lib/trans-api/client.rb +8 -2
- data/lib/trans-api/connect.rb +59 -133
- data/lib/trans-api/session.rb +8 -0
- data/lib/trans-api/torrent.rb +39 -9
- data/lib/trans-api/version.rb +1 -1
- data/lib/trans-api.rb +3 -1
- data/test/test_helper.rb +6 -0
- data/test/unit/trans_connect.rb +14 -150
- data/test/unit/trans_session_object.rb +15 -9
- data/test/unit/trans_torrent_object.rb +129 -26
- data/trans-api.gemspec +3 -1
- metadata +48 -13
data/lib/trans-api/connect.rb
CHANGED
@@ -8,6 +8,7 @@ module Trans
|
|
8
8
|
require 'json'
|
9
9
|
require 'nokogiri'
|
10
10
|
require 'net/http'
|
11
|
+
require 'timeout'
|
11
12
|
|
12
13
|
|
13
14
|
METHODS = {
|
@@ -58,209 +59,120 @@ module Trans
|
|
58
59
|
|
59
60
|
# handles
|
60
61
|
|
61
|
-
#TODO: need to refactor these redundant functions!!
|
62
|
-
|
63
62
|
def session_get
|
64
|
-
|
65
|
-
ret = self.do(:post, data)
|
66
|
-
# a little dirty, but works great :)
|
67
|
-
session = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
68
|
-
raise session[:result] unless valid? session, data[:tag]
|
69
|
-
session[:arguments]
|
63
|
+
self.get_method(:session_get) {|b| b.gsub("-","_")}
|
70
64
|
end
|
71
65
|
|
72
66
|
def session_stats
|
73
|
-
|
74
|
-
ret = self.do(:post, data)
|
75
|
-
session = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
76
|
-
raise session[:result] unless valid? session, data[:tag]
|
77
|
-
session[:arguments]
|
67
|
+
self.get_method(:session_stats) {|b| b.gsub("-","_")}
|
78
68
|
end
|
79
69
|
|
80
70
|
def session_set(arguments={})
|
81
|
-
|
82
|
-
data[:arguments] = argument_name_to_api arguments
|
83
|
-
ret = self.do :post, data
|
84
|
-
session = JSON.parse ret[:response].body, {symbolize_names: true}
|
85
|
-
raise session[:result] unless valid? session, data[:tag]
|
86
|
-
session[:arguments]
|
71
|
+
self.get_method(:session_set, arguments)
|
87
72
|
end
|
88
73
|
|
89
74
|
def session_close
|
90
|
-
|
91
|
-
ret = self.do :post, data
|
92
|
-
session = JSON.parse ret[:response].body, {symbolize_names: true}
|
93
|
-
raise session[:result] unless valid? session, data[:tag]
|
94
|
-
session[:arguments]
|
75
|
+
self.get_method(:session_close)
|
95
76
|
end
|
96
77
|
|
97
78
|
def torrent_get(fields = [:id, :name, :status], ids = [])
|
98
79
|
arguments = { fields: fields }
|
99
80
|
arguments[:ids] = ids unless ids.empty?
|
100
|
-
|
101
|
-
|
102
|
-
ret = self.do(:post, data)
|
103
|
-
torrents = JSON.parse ret[:response].body, {symbolize_names: true}
|
104
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
105
|
-
torrents[:arguments][:torrents]
|
81
|
+
args = self.get_method(:torrent_get, arguments)
|
82
|
+
args[:torrents]
|
106
83
|
end
|
107
84
|
|
108
85
|
def torrent_set(arguments={}, ids = [])
|
109
86
|
arguments[:ids] = ids unless ids.empty?
|
110
|
-
|
111
|
-
|
112
|
-
ret = self.do(:post, data)
|
113
|
-
torrents = JSON.parse ret[:response].body, {symbolize_names: true}
|
114
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
115
|
-
torrents[:arguments][:torrents]
|
87
|
+
args = self.get_method(:torrent_set, arguments)
|
88
|
+
args[:torrents]
|
116
89
|
end
|
117
90
|
|
118
91
|
def torrent_start(ids = [])
|
119
92
|
arguments = {}
|
120
93
|
arguments[:ids] = ids unless ids.empty?
|
121
|
-
|
122
|
-
|
123
|
-
ret = self.do(:post, data)
|
124
|
-
torrents = JSON.parse ret[:response].body, {symbolize_names: true}
|
125
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
126
|
-
torrents[:arguments][:torrents]
|
94
|
+
args = self.get_method(:torrent_start, arguments)
|
95
|
+
args[:torrents]
|
127
96
|
end
|
128
97
|
|
129
98
|
def torrent_start_now(ids = [])
|
130
99
|
arguments = {}
|
131
100
|
arguments[:ids] = ids unless ids.empty?
|
132
|
-
|
133
|
-
|
134
|
-
ret = self.do(:post, data)
|
135
|
-
torrents = JSON.parse ret[:response].body, {symbolize_names: true}
|
136
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
137
|
-
torrents[:arguments][:torrents]
|
101
|
+
args = self.get_method(:torrent_start_now, arguments)
|
102
|
+
args[:torrents]
|
138
103
|
end
|
139
104
|
|
140
105
|
def torrent_stop(ids = [])
|
141
106
|
arguments = {}
|
142
107
|
arguments[:ids] = ids unless ids.empty?
|
143
|
-
|
144
|
-
|
145
|
-
ret = self.do(:post, data)
|
146
|
-
torrents = JSON.parse ret[:response].body, {symbolize_names: true}
|
147
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
148
|
-
torrents[:arguments][:torrents]
|
108
|
+
args = self.get_method(:torrent_stop, arguments)
|
109
|
+
args[:torrents]
|
149
110
|
end
|
150
111
|
|
151
112
|
def torrent_add(arguments={})
|
152
|
-
|
153
|
-
data[:arguments] = argument_name_to_api arguments
|
154
|
-
ret = self.do(:post, data)
|
155
|
-
# puts JSON.parse(ret[:response].body).inspect
|
156
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
157
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
113
|
+
args = self.get_method(:torrent_add, arguments) {|b| b.gsub("-","_")}
|
158
114
|
# omiting BUG: https://trac.transmissionbt.com/ticket/5614
|
159
|
-
return
|
160
|
-
|
115
|
+
return args[:torrent_duplicate] if args.include?(:torrent_duplicate)
|
116
|
+
args[:torrent_added]
|
161
117
|
end
|
162
118
|
|
163
119
|
def torrent_remove(arguments={}, ids=[])
|
164
120
|
arguments[:ids] = ids unless ids.empty?
|
165
|
-
|
166
|
-
data[:arguments] = argument_name_to_api arguments
|
167
|
-
ret = self.do(:post, data)
|
168
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
169
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
170
|
-
torrents[:arguments]
|
121
|
+
self.get_method(:torrent_remove, arguments) {|b| b.gsub("-","_")}
|
171
122
|
end
|
172
123
|
|
173
124
|
def torrent_verify(ids = [])
|
174
125
|
arguments = {}
|
175
126
|
arguments[:ids] = ids unless ids.empty?
|
176
|
-
|
177
|
-
data[:arguments] = argument_name_to_api arguments
|
178
|
-
ret = self.do(:post, data)
|
179
|
-
torrents = JSON.parse ret[:response].body, {symbolize_names: true}
|
180
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
181
|
-
torrents[:arguments]
|
127
|
+
self.get_method(:torrent_verify, arguments)
|
182
128
|
end
|
183
129
|
|
184
130
|
def torrent_reannounce(ids=[])
|
185
131
|
arguments = {}
|
186
132
|
arguments[:ids] = ids unless ids.empty?
|
187
|
-
|
188
|
-
data[:arguments] = argument_name_to_api arguments
|
189
|
-
ret = self.do(:post, data)
|
190
|
-
torrents = JSON.parse ret[:response].body, {symbolize_names: true}
|
191
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
192
|
-
torrents[:arguments]
|
133
|
+
self.get_method(:torrent_reannounce, arguments)
|
193
134
|
end
|
194
135
|
|
195
136
|
def torrent_set_location(arguments={}, ids=[])
|
196
137
|
arguments[:ids] = ids unless ids.empty?
|
197
|
-
|
198
|
-
data[:arguments] = argument_name_to_api arguments
|
199
|
-
ret = self.do(:post, data)
|
200
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
201
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
202
|
-
torrents[:arguments]
|
138
|
+
self.get_method(:torrent_set_location, arguments) {|b| b.gsub("-","_")}
|
203
139
|
end
|
204
140
|
|
205
141
|
def blocklist_update
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
142
|
+
tm = @conn[:timeout]
|
143
|
+
@conn[:timeout] = (@conn[:timeout] + 5) * 3
|
144
|
+
arg = self.get_method(:blocklist_update) {|b| b.gsub("-","_")}
|
145
|
+
@conn[:timeout] = tm
|
146
|
+
arg
|
211
147
|
end
|
212
148
|
|
213
149
|
def port_test
|
214
|
-
|
215
|
-
ret = self.do(:post, data)
|
216
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
217
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
218
|
-
torrents[:arguments]
|
150
|
+
self.get_method(:port_test) {|b| b.gsub("-","_")}
|
219
151
|
end
|
220
152
|
|
221
153
|
|
222
154
|
def queue_move_top(ids=[])
|
223
155
|
arguments = {}
|
224
156
|
arguments[:ids] = ids unless ids.empty?
|
225
|
-
|
226
|
-
data[:arguments] = argument_name_to_api arguments
|
227
|
-
ret = self.do(:post, data)
|
228
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
229
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
230
|
-
torrents[:arguments]
|
157
|
+
self.get_method(:queue_move_top, arguments) {|b| b.gsub("-","_")}
|
231
158
|
end
|
232
159
|
|
233
160
|
def queue_move_up(ids=[])
|
234
161
|
arguments = {}
|
235
162
|
arguments[:ids] = ids unless ids.empty?
|
236
|
-
|
237
|
-
data[:arguments] = argument_name_to_api arguments
|
238
|
-
ret = self.do(:post, data)
|
239
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
240
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
241
|
-
torrents[:arguments]
|
163
|
+
self.get_method(:queue_move_up, arguments) {|b| b.gsub("-","_")}
|
242
164
|
end
|
243
165
|
|
244
166
|
def queue_move_down(ids=[])
|
245
167
|
arguments = {}
|
246
168
|
arguments[:ids] = ids unless ids.empty?
|
247
|
-
|
248
|
-
data[:arguments] = argument_name_to_api arguments
|
249
|
-
ret = self.do(:post, data)
|
250
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
251
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
252
|
-
torrents[:arguments]
|
169
|
+
self.get_method(:queue_move_down, arguments) {|b| b.gsub("-","_")}
|
253
170
|
end
|
254
171
|
|
255
172
|
def queue_move_bottom(ids=[])
|
256
173
|
arguments = {}
|
257
174
|
arguments[:ids] = ids unless ids.empty?
|
258
|
-
|
259
|
-
data[:arguments] = argument_name_to_api arguments
|
260
|
-
ret = self.do(:post, data)
|
261
|
-
torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
|
262
|
-
raise torrents[:result] unless valid? torrents, data[:tag]
|
263
|
-
torrents[:arguments]
|
175
|
+
self.get_method(:queue_move_bottom, arguments) {|b| b.gsub("-","_")}
|
264
176
|
end
|
265
177
|
|
266
178
|
|
@@ -268,21 +180,42 @@ module Trans
|
|
268
180
|
|
269
181
|
# request
|
270
182
|
|
183
|
+
|
184
|
+
protected
|
185
|
+
|
186
|
+
def get_method(method_name, arguments=nil, &block)
|
187
|
+
data = METHODS[method_name]
|
188
|
+
data[:arguments] = argument_name_to_api(arguments) unless arguments.nil?
|
189
|
+
ret = self.do(:post, data)
|
190
|
+
body = ret[:response].body
|
191
|
+
# call block with body data (for gsub etc.)
|
192
|
+
body = block.call(body) if block.is_a?(Proc)
|
193
|
+
session = JSON.parse(body, {symbolize_names: true})
|
194
|
+
# puts session
|
195
|
+
raise session[:result] unless valid? session, data[:tag]
|
196
|
+
session[:arguments]
|
197
|
+
end
|
198
|
+
|
271
199
|
def do(method = :get, data = nil)
|
272
200
|
headers = @conn[:headers]
|
273
|
-
|
274
201
|
uri = URI.parse "http://localhost/"
|
275
202
|
uri.scheme = @conn[:scheme]
|
276
203
|
uri.host = @conn[:host]
|
277
204
|
uri.port = @conn[:port]
|
278
205
|
uri.path = @conn[:path]
|
279
|
-
|
280
206
|
# request
|
281
207
|
http = Net::HTTP.new uri.host, uri.port
|
282
|
-
resp =
|
283
|
-
|
284
|
-
|
285
|
-
|
208
|
+
resp = nil
|
209
|
+
Timeout::timeout(@conn[:timeout]) do
|
210
|
+
# sleep 5
|
211
|
+
if method == :get
|
212
|
+
resp = http.get(uri.request_uri, data.to_json, headers)
|
213
|
+
elsif method == :post
|
214
|
+
resp = http.post(uri.request_uri, data.to_json, headers)
|
215
|
+
else
|
216
|
+
raise "not implemented #{method} request!!"
|
217
|
+
end
|
218
|
+
end
|
286
219
|
# authorize via session id
|
287
220
|
if resp.code.to_i == 409
|
288
221
|
tmp = Nokogiri::HTML resp.body
|
@@ -291,15 +224,11 @@ module Trans
|
|
291
224
|
# recursion!!!!
|
292
225
|
return self.do(:post, data)
|
293
226
|
end
|
294
|
-
|
295
227
|
ret = {request: http, response: resp}
|
296
228
|
handle_request_error(ret, data)
|
297
229
|
ret
|
298
230
|
end
|
299
231
|
|
300
|
-
|
301
|
-
private
|
302
|
-
|
303
232
|
def valid?(body, tag)
|
304
233
|
body[:result] == "success" && body[:tag] == tag
|
305
234
|
end
|
@@ -314,12 +243,10 @@ module Trans
|
|
314
243
|
end
|
315
244
|
|
316
245
|
# error handling
|
317
|
-
|
318
246
|
def handle_request_error(ret, data)
|
319
247
|
raise "error handling: #{data[:method]}, #{request_str ret[:response]}" if ret[:response].code.to_i != 200
|
320
248
|
end
|
321
249
|
|
322
|
-
|
323
250
|
def request_str(response)
|
324
251
|
ret = []
|
325
252
|
ret << "[code: #{response.code}]"
|
@@ -327,7 +254,6 @@ module Trans
|
|
327
254
|
ret.join "\n"
|
328
255
|
end
|
329
256
|
|
330
|
-
|
331
257
|
end
|
332
258
|
|
333
259
|
end
|
data/lib/trans-api/session.rb
CHANGED
data/lib/trans-api/torrent.rb
CHANGED
@@ -53,6 +53,10 @@ module Trans
|
|
53
53
|
self.attach_methods!
|
54
54
|
end
|
55
55
|
|
56
|
+
def last_error
|
57
|
+
@last_error
|
58
|
+
end
|
59
|
+
|
56
60
|
# placeholder for fields
|
57
61
|
def metaclass
|
58
62
|
class << self; self; end
|
@@ -75,6 +79,7 @@ module Trans
|
|
75
79
|
@client.connect.torrent_set changed, [self.id]
|
76
80
|
@old_fields = @fields.clone
|
77
81
|
end
|
82
|
+
nil
|
78
83
|
end
|
79
84
|
|
80
85
|
# get registered fields
|
@@ -97,9 +102,14 @@ module Trans
|
|
97
102
|
|
98
103
|
# reload current object
|
99
104
|
def reset!
|
100
|
-
|
101
|
-
|
102
|
-
|
105
|
+
begin
|
106
|
+
@fields = @client.connect.torrent_get( @fields.map{|k,v| k}, [self.id]).first
|
107
|
+
@old_fields = @fields.clone unless @fields.nil?
|
108
|
+
@last_error = {error: "", message: ""}
|
109
|
+
rescue Exception => e
|
110
|
+
@last_error = {error: "reset_exception", message: "cannot reset torrent (probably removed)"}
|
111
|
+
end
|
112
|
+
nil
|
103
113
|
end
|
104
114
|
|
105
115
|
def start!
|
@@ -213,6 +223,21 @@ module Trans
|
|
213
223
|
Torrent.new torrent: torrent
|
214
224
|
end
|
215
225
|
|
226
|
+
def add_magnet(uri, options={})
|
227
|
+
#TODO: urlencode & dn= in name not checked
|
228
|
+
uri_match = uri.match(/dn=([\S]+)[&]/)
|
229
|
+
raise "no name found" if uri_match.size != 2
|
230
|
+
filename = uri_match[1]
|
231
|
+
# filter duplicates
|
232
|
+
find = Trans::Api::Torrent.find_by_field_value(:name, ::File.basename(filename, ".*"))
|
233
|
+
return find unless find.nil?
|
234
|
+
client = Client.new
|
235
|
+
options[:filename] = uri
|
236
|
+
torrent = client.connect.torrent_add options
|
237
|
+
torrent = client.connect.torrent_get( @@default_fields, [torrent[:id]]).first
|
238
|
+
Torrent.new torrent: torrent
|
239
|
+
end
|
240
|
+
|
216
241
|
def add_metainfo(metainfo, name, options={})
|
217
242
|
raise "name empty" if name.nil? || name == ""
|
218
243
|
options[:metainfo] = metainfo
|
@@ -287,7 +312,7 @@ module Trans
|
|
287
312
|
def method_missing(method, *args)
|
288
313
|
|
289
314
|
unless args.empty?
|
290
|
-
@target_object.send method, args
|
315
|
+
@target_object.send method, *args
|
291
316
|
else
|
292
317
|
@target_object.send method
|
293
318
|
end
|
@@ -297,11 +322,16 @@ module Trans
|
|
297
322
|
end
|
298
323
|
|
299
324
|
def wait
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
325
|
+
begin
|
326
|
+
# keep trying task (and refreshing the torrent file)
|
327
|
+
while true do
|
328
|
+
@target_object.reset!
|
329
|
+
t = @task.call @target_object
|
330
|
+
break if t # task achieved!
|
331
|
+
end
|
332
|
+
rescue Exception => e
|
333
|
+
# some error has occured ()
|
334
|
+
@@last_error = {error: "wait_exception", message: e.message}
|
305
335
|
end
|
306
336
|
end
|
307
337
|
|
data/lib/trans-api/version.rb
CHANGED
data/lib/trans-api.rb
CHANGED
@@ -6,7 +6,9 @@ require File.expand_path(File.dirname(__FILE__) + "/trans-api/torrent")
|
|
6
6
|
require File.expand_path(File.dirname(__FILE__) + "/trans-api/file")
|
7
7
|
|
8
8
|
# boolean helper
|
9
|
-
|
9
|
+
begin
|
10
|
+
Boolean.nil?
|
11
|
+
rescue NameError
|
10
12
|
module Boolean; end
|
11
13
|
class TrueClass; include Boolean; end
|
12
14
|
class FalseClass; include Boolean; end
|