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.
@@ -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!