trans-api 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- data = METHODS[:session_get]
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
- data = METHODS[:session_stats]
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
- data = METHODS[:session_set]
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
- data = METHODS[:session_close]
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
- data = METHODS[:torrent_get]
101
- data[:arguments] = argument_name_to_api arguments
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
- data = METHODS[:torrent_set]
111
- data[:arguments] = argument_name_to_api arguments
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
- data = METHODS[:torrent_start]
122
- data[:arguments] = argument_name_to_api arguments
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
- data = METHODS[:torrent_start_now]
133
- data[:arguments] = argument_name_to_api arguments
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
- data = METHODS[:torrent_stop]
144
- data[:arguments] = argument_name_to_api arguments
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
- data = METHODS[:torrent_add]
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 torrents[:arguments][:torrent_duplicate] if torrents[:arguments].include?(:torrent_duplicate)
160
- torrents[:arguments][:torrent_added]
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
- data = METHODS[:torrent_remove]
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
- data = METHODS[:torrent_verify]
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
- data = METHODS[:torrent_reannounce]
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
- data = METHODS[:torrent_set_location]
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
- data = METHODS[:blocklist_update]
207
- ret = self.do(:post, data)
208
- torrents = JSON.parse ret[:response].body.gsub("-","_"), {symbolize_names: true}
209
- raise torrents[:result] unless valid? torrents, data[:tag]
210
- torrents[:arguments]
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
- data = METHODS[:port_test]
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
- data = METHODS[:queue_move_top]
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
- data = METHODS[:queue_move_up]
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
- data = METHODS[:queue_move_down]
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
- data = METHODS[:queue_move_bottom]
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 = http.get(uri.request_uri, data.to_json, headers) if method == :get
283
- resp = http.post(uri.request_uri, data.to_json, headers) if method == :post
284
- raise "not implemented #{method} request!!" if method != :get && method != :post
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
@@ -81,6 +81,14 @@ module Trans
81
81
  @client.connect.blocklist_update
82
82
  end
83
83
 
84
+ def connected?
85
+ begin
86
+ s = self.stats!
87
+ return s.is_a?(Hash)
88
+ rescue StandardError
89
+ false
90
+ end
91
+ end
84
92
 
85
93
  # blocklist-update
86
94
 
@@ -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
- @fields = @client.connect.torrent_get( @fields.map{|k,v| k}, [self.id]).first
101
- @old_fields = @fields.clone
102
- @last_error = {error: "", message: ""}
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 &amp; 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
- # keep trying task (and refreshing the torrent file)
301
- while true do
302
- @target_object.reset!
303
- t = @task.call @target_object
304
- break if t # task achieved!
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
 
@@ -1,5 +1,5 @@
1
1
  module Trans
2
2
  module Api
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
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
- if Boolean.nil?
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
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/trans-api")
4
+
5
+ # require 'coveralls'
6
+ # Coveralls.wear!