rhack 1.2.1 → 1.2.7
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 +13 -5
- data/README.md +21 -9
- data/ext/curb/curb.c +977 -977
- data/ext/curb/curb.h +52 -52
- data/ext/curb/curb_config.h +270 -270
- data/ext/curb/curb_easy.c +3437 -3434
- data/ext/curb/curb_easy.h +94 -94
- data/ext/curb/curb_errors.c +647 -647
- data/ext/curb/curb_errors.h +129 -129
- data/ext/curb/curb_macros.h +162 -162
- data/ext/curb/curb_multi.c +704 -702
- data/ext/curb/curb_multi.h +26 -26
- data/ext/curb/curb_postfield.c +523 -523
- data/ext/curb/curb_postfield.h +40 -40
- data/ext/curb/curb_upload.c +80 -80
- data/ext/curb/curb_upload.h +30 -30
- data/ext/curb-original/curb.c +977 -977
- data/ext/curb-original/curb.h +52 -52
- data/ext/curb-original/curb_config.h +238 -238
- data/ext/curb-original/curb_easy.c +3404 -3404
- data/ext/curb-original/curb_easy.h +90 -90
- data/ext/curb-original/curb_errors.c +647 -647
- data/ext/curb-original/curb_errors.h +129 -129
- data/ext/curb-original/curb_macros.h +159 -159
- data/ext/curb-original/curb_multi.c +633 -633
- data/ext/curb-original/curb_multi.h +26 -26
- data/ext/curb-original/curb_postfield.c +523 -523
- data/ext/curb-original/curb_postfield.h +40 -40
- data/ext/curb-original/curb_upload.c +80 -80
- data/ext/curb-original/curb_upload.h +30 -30
- data/lib/rhack/clients/base.rb +61 -10
- data/lib/rhack/clients/oauth.rb +4 -4
- data/lib/rhack/curl/easy.rb +1 -0
- data/lib/rhack/curl/global.rb +2 -0
- data/lib/rhack/curl/response.rb +4 -2
- data/lib/rhack/frame.rb +70 -32
- data/lib/rhack/js/browser/env.js +697 -697
- data/lib/rhack/js/browser/jquery.js +7180 -7180
- data/lib/rhack/js/browser/xmlsax.js +1564 -1564
- data/lib/rhack/js/browser/xmlw3cdom_1.js +1443 -1443
- data/lib/rhack/js/browser/xmlw3cdom_2.js +2744 -2744
- data/lib/rhack/page.rb +227 -68
- data/lib/rhack/scout.rb +52 -26
- data/lib/rhack/scout_squad.rb +10 -2
- data/lib/rhack/version.rb +1 -1
- data/rhack.gemspec +1 -1
- metadata +17 -17
data/lib/rhack/page.rb
CHANGED
@@ -33,89 +33,173 @@ module RHACK
|
|
33
33
|
# for debug, just enable L#debug, don't write tons of chaotic log-lines
|
34
34
|
__init__
|
35
35
|
attr_writer :title
|
36
|
-
attr_reader :
|
36
|
+
attr_reader :body, :loc, :data, :doc, :js, :curl, :curl_res, :failed
|
37
|
+
alias :hash :data # DEPRECATED
|
38
|
+
alias :html :body # DEPRECATED
|
39
|
+
|
37
40
|
# result of page processing been made in frame context
|
38
41
|
attr_accessor :res
|
39
42
|
# for johnson
|
40
43
|
@@ignore = /google|_gat|tracker|adver/i
|
41
44
|
|
42
|
-
|
45
|
+
# Frame calls it with no args
|
46
|
+
def initialize(obj='', loc=Hash.new(''), js=is_a?(HtmlPage)&&(Johnson::Runtime.browser||Johnson::Runtime.new))
|
43
47
|
loc = loc.parse:uri if !loc.is Hash
|
44
48
|
@js = js
|
45
49
|
if obj.is Curl::Easy or obj.kinda Scout
|
46
50
|
c = obj.kinda(Scout) ? obj.http : obj
|
47
|
-
@html = ''
|
48
51
|
# just (c, loc) would pass to #process opts variable that returns '' on any key
|
49
52
|
process(c, loc.b || {})
|
50
53
|
else
|
51
|
-
@
|
54
|
+
@body = obj
|
52
55
|
@loc = loc
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
56
59
|
def empty?
|
57
|
-
|
60
|
+
!@data && !@body.b
|
61
|
+
end
|
62
|
+
|
63
|
+
def size
|
64
|
+
if @data.nil?
|
65
|
+
(@body || '').size
|
66
|
+
elsif @data == false
|
67
|
+
0
|
68
|
+
else
|
69
|
+
@data.inspect.size
|
70
|
+
end
|
58
71
|
end
|
59
72
|
|
60
73
|
def inspect
|
61
|
-
|
62
|
-
|
74
|
+
sz = size
|
75
|
+
if !@data.nil?
|
76
|
+
"<##{self.class.name} (#{@data == false ? 'failed to parse' : sz.bytes}) #{@json ? 'json' : 'url params'}>"
|
63
77
|
else
|
64
|
-
"<##{self.class.name} #{
|
78
|
+
"<##{self.class.name} #{sz == 0 ? '(empty)' : "#{@failed ? @curl_res.header : '«'+title(false)+'»'} (#{sz.bytes})"}#{' js enabled' if @js and @doc}>"
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
68
|
-
def
|
69
|
-
@
|
82
|
+
def utf!
|
83
|
+
@body.utf!
|
70
84
|
end
|
71
85
|
|
72
|
-
def url
|
86
|
+
def url
|
87
|
+
@loc.href
|
88
|
+
end
|
73
89
|
alias :href :url
|
74
90
|
|
91
|
+
|
92
|
+
# override this in a subclass
|
93
|
+
def failed?(*)
|
94
|
+
@curl_res.code != 200
|
95
|
+
end
|
96
|
+
|
97
|
+
# override this in a subclass
|
98
|
+
def retry?(*)
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
102
|
+
# override this in a subclass
|
103
|
+
# MUST return self if successful
|
104
|
+
# MAY return false otherwise
|
105
|
+
def parse(opts={})
|
106
|
+
if failed?
|
107
|
+
failed!
|
108
|
+
if opts[:json] or opts[:hash]
|
109
|
+
@data = false
|
110
|
+
end
|
111
|
+
return self
|
112
|
+
end
|
113
|
+
|
114
|
+
if opts[:json]
|
115
|
+
parse_json opts
|
116
|
+
elsif opts[:hash]
|
117
|
+
parse_hash opts
|
118
|
+
elsif opts[:xml]
|
119
|
+
parse_xml opts
|
120
|
+
else
|
121
|
+
parse_html opts
|
122
|
+
end
|
123
|
+
|
124
|
+
self
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def failed!
|
130
|
+
@body = @curl_res.body
|
131
|
+
@failed = @curl_res.code
|
132
|
+
end
|
133
|
+
|
134
|
+
def log_failed(action)
|
135
|
+
L.debug "Failed #{action} from #{@curl.last_effective_url}, take a look at my @body for info; my object_id is #{object_id}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def parse_xml(*)
|
139
|
+
@body = @curl_res.body.xml_to_utf
|
140
|
+
to_xml
|
141
|
+
rescue StandardError => e
|
142
|
+
L.warn "Exception raised during `to_xml': #{e.inspect}"
|
143
|
+
log_failed "to parse page as XML"
|
144
|
+
failed!
|
145
|
+
end
|
146
|
+
|
147
|
+
def parse_html(opts={})
|
148
|
+
@body = @curl_res.body.xml_to_utf
|
149
|
+
to_html
|
150
|
+
if opts[:eval]
|
151
|
+
load_scripts opts[:load_scripts]
|
152
|
+
eval_js
|
153
|
+
end
|
154
|
+
rescue StandardError => e
|
155
|
+
L.warn "Exception raised during `to_html': #{e.inspect}"
|
156
|
+
log_failed "to parse page as HTML"
|
157
|
+
failed!
|
158
|
+
end
|
159
|
+
|
160
|
+
def parse_json(*)
|
161
|
+
@json = true
|
162
|
+
begin
|
163
|
+
@data = @curl_res.body.from_json
|
164
|
+
rescue StandardError => e
|
165
|
+
L.warn "Exception raised during `from_json': #{e.inspect}"
|
166
|
+
end
|
167
|
+
if !@data or @data.is String
|
168
|
+
log_failed "to get JSON"
|
169
|
+
failed!
|
170
|
+
@data = false
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def parse_hash(*)
|
175
|
+
if @curl_res.body.inline
|
176
|
+
@data = @curl_res.body.to_params
|
177
|
+
else
|
178
|
+
log_failed "to get url-params hash"
|
179
|
+
failed!
|
180
|
+
@data = false
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
public
|
185
|
+
|
75
186
|
# We can then alternate #process in Page subclasses
|
76
187
|
# Frame doesn't mind about value returned by #process
|
77
188
|
def process(c, opts={})
|
78
189
|
@loc = c.last_effective_url.parse:uri
|
190
|
+
@curl = c
|
79
191
|
@curl_res = c.res
|
80
|
-
|
81
|
-
if
|
82
|
-
|
83
|
-
|
84
|
-
@json = true
|
85
|
-
@hash = begin; body.from_json
|
86
|
-
rescue StandardError
|
87
|
-
false
|
88
|
-
end
|
89
|
-
if !@hash or @hash.is String
|
90
|
-
L.debug "failed to get json from #{c.last_effective_url}, take a look at my @doc for info; my object_id is #{object_id}"
|
91
|
-
@html = body; to_doc
|
92
|
-
@hash = false
|
93
|
-
end
|
94
|
-
|
95
|
-
elsif opts[:hash]
|
96
|
-
if body.inline
|
97
|
-
@hash = body.to_params
|
98
|
-
else
|
99
|
-
@hash = false
|
100
|
-
L.debug "failed to get params hash from #{c.last_effective_url}, take a look at my @doc for info; my object_id is #{object_id}"
|
101
|
-
@html = body; to_doc
|
102
|
-
end
|
103
|
-
|
104
|
-
else
|
105
|
-
@html = body.xml_to_utf
|
106
|
-
to_doc
|
107
|
-
if opts[:eval]
|
108
|
-
load_scripts opts[:load_scripts]
|
109
|
-
eval_js
|
110
|
-
end
|
111
|
-
end
|
112
|
-
elsif !(opts[:json] or opts[:hash])
|
113
|
-
@html = @curl_res.body
|
114
|
-
@failed = @curl_res.code
|
192
|
+
|
193
|
+
if retry?
|
194
|
+
c.retry!
|
195
|
+
return # callback will not proceed
|
115
196
|
end
|
116
|
-
|
197
|
+
|
198
|
+
L.debug "#{@loc.fullpath} -> #{@curl_res}"
|
199
|
+
parse(opts)
|
117
200
|
end
|
118
201
|
|
202
|
+
|
119
203
|
def eval_js(frame=nil)
|
120
204
|
eval_string "document.location = window.location = #{@loc.to_json};
|
121
205
|
document.URL = document.baseURI = document.documentURI = location.href;
|
@@ -149,14 +233,18 @@ module RHACK
|
|
149
233
|
end
|
150
234
|
end
|
151
235
|
|
152
|
-
def
|
153
|
-
@doc = @
|
236
|
+
def to_html
|
237
|
+
@doc = @body.to_html
|
238
|
+
end
|
239
|
+
|
240
|
+
def to_xml
|
241
|
+
@doc = @body.to_xml
|
154
242
|
end
|
155
243
|
|
156
244
|
def title(full=true)
|
157
|
-
if @
|
245
|
+
if @data.nil? and !@failed and @body.b
|
158
246
|
if full
|
159
|
-
|
247
|
+
to_html unless defined? @doc
|
160
248
|
if @doc.title.b
|
161
249
|
@title = @doc.title
|
162
250
|
else
|
@@ -257,14 +345,14 @@ module RHACK
|
|
257
345
|
end
|
258
346
|
end
|
259
347
|
|
260
|
-
def __at(xp) (@doc ||
|
348
|
+
def __at(xp) (@doc || to_html).at xp end
|
261
349
|
|
262
|
-
def __find(xp) (@doc ||
|
350
|
+
def __find(xp) (@doc || to_html).find xp end
|
263
351
|
|
264
352
|
public
|
265
353
|
|
266
354
|
def at(selector_or_node, options={})
|
267
|
-
if selector_or_node and preresult = selector_or_node.is_a?(XML::Node) ?
|
355
|
+
if selector_or_node and preresult = selector_or_node.is_a?(LibXML::XML::Node) ?
|
268
356
|
selector_or_node : __at(selector_or_node)
|
269
357
|
|
270
358
|
preresult = preprocess_search_result(preresult, options[:preprocess])
|
@@ -277,7 +365,7 @@ module RHACK
|
|
277
365
|
alias :first :at
|
278
366
|
|
279
367
|
def find(selector_or_nodes, options={}, &foreach)
|
280
|
-
preresult = selector_or_nodes.is_a?(XML::XPath::Object, Array) ?
|
368
|
+
preresult = selector_or_nodes.is_a?(LibXML::XML::XPath::Object, Array) ?
|
281
369
|
selector_or_nodes : __find(selector_or_nodes)
|
282
370
|
|
283
371
|
if preresult.size > 0
|
@@ -349,7 +437,7 @@ module RHACK
|
|
349
437
|
form = "[action=#{@loc.path.inspect}]" if form == :self
|
350
438
|
if form.is String
|
351
439
|
form_node = at form
|
352
|
-
raise XML::Error, "Can't find form by xpath `#{form}` on page #{inspect}" if !form_node or form_node.name != 'form'
|
440
|
+
raise LibXML::XML::Error, "Can't find form by xpath `#{form}` on page #{inspect}" if !form_node or form_node.name != 'form'
|
353
441
|
else form_node = form
|
354
442
|
end
|
355
443
|
hash = form_node.inputs_all.merge!(hash)
|
@@ -376,13 +464,13 @@ module RHACK
|
|
376
464
|
end
|
377
465
|
|
378
466
|
|
379
|
-
|
467
|
+
### DEPRECATED ###
|
380
468
|
|
381
469
|
# TODO: make into same form as #get_src and #map
|
382
470
|
def get_srcs(links='img')
|
383
471
|
begin
|
384
472
|
links = find(links).map {|e| e.src} if links.is String
|
385
|
-
rescue XML::Error
|
473
|
+
rescue LibXML::XML::Error
|
386
474
|
links = [links]
|
387
475
|
end
|
388
476
|
links.map {|link| expand_link link}.uniq
|
@@ -392,7 +480,7 @@ module RHACK
|
|
392
480
|
#def get_src(link='img')
|
393
481
|
# begin
|
394
482
|
# link = at(link) && at(link).src if link.is String
|
395
|
-
# rescue XML::Error; nil
|
483
|
+
# rescue LibXML::XML::Error; nil
|
396
484
|
# end
|
397
485
|
# expand_link link if link
|
398
486
|
#end
|
@@ -400,7 +488,7 @@ module RHACK
|
|
400
488
|
def get_links(links='a')
|
401
489
|
begin
|
402
490
|
links = find(links).map {|e| e.href}.b || find(links+'//a').map {|e| e.href} if links.is String
|
403
|
-
rescue XML::Error
|
491
|
+
rescue LibXML::XML::Error
|
404
492
|
links = [links]
|
405
493
|
end
|
406
494
|
links.map {|link| expand_link link}.uniq
|
@@ -421,22 +509,93 @@ module RHACK
|
|
421
509
|
end
|
422
510
|
|
423
511
|
end
|
512
|
+
|
513
|
+
### Pages with specific processing
|
514
|
+
|
515
|
+
class XmlPage < Page
|
516
|
+
|
517
|
+
# override this in a subclass
|
518
|
+
# MUST return self if successful
|
519
|
+
# MAY return false otherwise
|
520
|
+
def parse(opts={})
|
521
|
+
if failed?
|
522
|
+
failed!
|
523
|
+
else
|
524
|
+
parse_xml opts
|
525
|
+
end
|
526
|
+
self
|
527
|
+
end
|
528
|
+
|
529
|
+
end
|
530
|
+
|
531
|
+
|
532
|
+
class HtmlPage < Page
|
533
|
+
|
534
|
+
# override this in a subclass
|
535
|
+
# MUST return self if successful
|
536
|
+
# MAY return false otherwise
|
537
|
+
def parse(opts={})
|
538
|
+
if failed?
|
539
|
+
failed!
|
540
|
+
else
|
541
|
+
parse_html opts
|
542
|
+
end
|
543
|
+
self
|
544
|
+
end
|
545
|
+
|
546
|
+
end
|
547
|
+
|
548
|
+
|
549
|
+
class JsonPage < Page
|
550
|
+
|
551
|
+
# override this in a subclass
|
552
|
+
# MUST return self if successful
|
553
|
+
# MAY return false otherwise
|
554
|
+
def parse(opts={})
|
555
|
+
if failed?
|
556
|
+
failed!
|
557
|
+
else
|
558
|
+
parse_json opts
|
559
|
+
end
|
560
|
+
self
|
561
|
+
end
|
562
|
+
|
563
|
+
end
|
564
|
+
|
565
|
+
|
566
|
+
class HashPage < Page
|
567
|
+
|
568
|
+
# override this in a subclass
|
569
|
+
# MUST return self if successful
|
570
|
+
# MAY return false otherwise
|
571
|
+
def parse(opts={})
|
572
|
+
if failed?
|
573
|
+
failed!
|
574
|
+
else
|
575
|
+
parse_hash opts
|
576
|
+
end
|
577
|
+
self
|
578
|
+
end
|
579
|
+
|
580
|
+
end
|
424
581
|
|
582
|
+
### DEPRECATED ### Use native inheritance and override #retry instead
|
583
|
+
|
425
584
|
# using reprocessing of page in case of non-200 response:
|
426
585
|
# page_class = ReloadablePage do
|
427
586
|
# @res and @res.code != 200
|
428
587
|
# end
|
429
588
|
def ReloadablePage(&reload_condition)
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
589
|
+
Class.new Page do
|
590
|
+
define_method :process do |curl, opts|
|
591
|
+
super(curl, opts || {})
|
592
|
+
if curl.instance_eval &reload_condition
|
593
|
+
curl.retry!
|
594
|
+
nil # in case of reload_condition.call super's callback will not proceed
|
595
|
+
else self
|
596
|
+
end
|
437
597
|
end
|
438
598
|
end
|
439
|
-
rp
|
440
599
|
end
|
441
600
|
|
442
601
|
end
|
data/lib/rhack/scout.rb
CHANGED
@@ -46,9 +46,17 @@ module RHACK
|
|
46
46
|
@timeout = opts[:timeout] || @@timeout || 60
|
47
47
|
@post_proc = @get_proc = @head_proc = @put_proc = @delete_proc = Proc::NULL
|
48
48
|
update uri
|
49
|
+
|
49
50
|
@retry = opts[:retry] || {}
|
50
51
|
@retry = {@uri.host => @retry} if @retry.is Array
|
51
|
-
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup_curl
|
55
|
+
if loaded?
|
56
|
+
Curl.carier.remove @http
|
57
|
+
end
|
58
|
+
@http = Curl::Easy(@webproxy ? @proxy : @root)
|
59
|
+
@http.base = self
|
52
60
|
@http.cacert = @@cacert
|
53
61
|
end
|
54
62
|
|
@@ -66,8 +74,7 @@ module RHACK
|
|
66
74
|
if @http
|
67
75
|
@http.url = @webproxy ? @proxy : @root
|
68
76
|
else
|
69
|
-
|
70
|
-
@http.base = self
|
77
|
+
setup_curl
|
71
78
|
end
|
72
79
|
if @proxy
|
73
80
|
@http.proxy_url = @proxy*':' if !@webproxy
|
@@ -186,12 +193,23 @@ module RHACK
|
|
186
193
|
cks.map2 {|k, v| Cookie(k, v)}
|
187
194
|
end
|
188
195
|
|
189
|
-
def retry?(
|
190
|
-
#
|
191
|
-
|
192
|
-
return false if
|
193
|
-
|
194
|
-
|
196
|
+
def retry?(eclass)
|
197
|
+
# sites = ['0chan.ru', '2-ch.ru', 'www.nomer.org', 'nomer.org'].select_in('http://www.nomer.org') = ['www.nomer.org', 'nomer.org']
|
198
|
+
sites = (@@retry.keys + @retry.keys).select_in @root
|
199
|
+
return false if sites.empty?
|
200
|
+
errname = eclass.self_name
|
201
|
+
# retry = ['www.nomer.org', 'nomer.org'].any? {|www| {'nomer.org' => ['TimeoutError']}[www].include? 'TimeoutError'}
|
202
|
+
sites.any? {|site|
|
203
|
+
(@@retry[site] || []).include? errname or
|
204
|
+
(@retry[site] || []).include? errname
|
205
|
+
}
|
206
|
+
end
|
207
|
+
|
208
|
+
def retry!(path=@__path, headers=@__headers, not_redir=@__not_redir, relvl=@__relvl, callback=@__callback)
|
209
|
+
# all external params including post_body are still set
|
210
|
+
setup_curl # @http reload here
|
211
|
+
# and now we can set @http.on_complete back again
|
212
|
+
load(path, headers, not_redir, relvl, &callback)
|
195
213
|
end
|
196
214
|
|
197
215
|
def loaded?
|
@@ -209,10 +227,24 @@ module RHACK
|
|
209
227
|
end
|
210
228
|
rescue RuntimeError => e
|
211
229
|
e.message << ". Failed to load allready loaded? easy handler: Bad file descriptor" unless Curl::Err::CurlError === e
|
212
|
-
|
230
|
+
L.warn "#{e.inspect}: #{e.message}"
|
231
|
+
if loaded?
|
232
|
+
Curl.carier.remove @http
|
233
|
+
end
|
234
|
+
sleep 1
|
235
|
+
load!
|
236
|
+
#e.message << ". Failed to load allready loaded? easy handler: Bad file descriptor" unless Curl::Err::CurlError === e
|
237
|
+
#raise e
|
213
238
|
end
|
214
239
|
|
215
240
|
def load(path=@path, headers={}, not_redir=1, relvl=10, &callback)
|
241
|
+
# cache preprocessed data for one time for we can do #retry
|
242
|
+
@__path = path
|
243
|
+
@__headers = headers
|
244
|
+
@__not_redir = not_redir
|
245
|
+
@__relvl = relvl
|
246
|
+
@__callback = callback
|
247
|
+
|
216
248
|
@http.path = path = fix(path)
|
217
249
|
@http.headers = mkHeader(path).merge!(headers)
|
218
250
|
@http.timeout = @timeout
|
@@ -233,24 +265,18 @@ module RHACK
|
|
233
265
|
end
|
234
266
|
}
|
235
267
|
@http.on_failure {|c, e|
|
268
|
+
eclass = e[0]
|
236
269
|
@error = e
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
270
|
+
c.outdate!
|
271
|
+
# we must clean @http.on_complete, otherwise
|
272
|
+
# it would run right after this function and with broken data
|
273
|
+
@http.on_complete &Proc::NULL
|
274
|
+
if retry? eclass
|
275
|
+
L.debug "#{eclass} -> reloading scout"
|
276
|
+
retry!
|
242
277
|
else
|
243
|
-
|
244
|
-
if
|
245
|
-
L.debug "#{e[0]} -> reloading scout"
|
246
|
-
#load uri, headers, not_redir, relvl, &callback
|
247
|
-
load! # all params including post_body are still set
|
248
|
-
# DO they include `on_complete'?
|
249
|
-
else
|
250
|
-
@http.on_complete &Proc::NULL
|
251
|
-
L.debug "#{e[0]} -> not reloading scout"
|
252
|
-
raise *e if @raise_err
|
253
|
-
end
|
278
|
+
L.debug "#{eclass} -> not reloading scout"
|
279
|
+
raise *e if @raise_err
|
254
280
|
end
|
255
281
|
} if !@http.on_failure
|
256
282
|
|
data/lib/rhack/scout_squad.rb
CHANGED
@@ -15,12 +15,16 @@ module RHACK
|
|
15
15
|
if args[0].is Scout
|
16
16
|
s = args[0]
|
17
17
|
else
|
18
|
-
|
19
|
-
args.unshift ''
|
18
|
+
unless args[0].is String
|
20
19
|
if (opts = args[-1]).is Hash and (opts[:cp] || opts[:ck]).is Hash
|
21
20
|
L.warn "it's useless to setup cookies for untargeted squad!"
|
22
21
|
end
|
23
22
|
end
|
23
|
+
if !args[0]
|
24
|
+
args[0] = ''
|
25
|
+
elsif !args[0].is String
|
26
|
+
args.unshift ''
|
27
|
+
end
|
24
28
|
if args[1] and args[1][0].is Array
|
25
29
|
proxies = args[1]
|
26
30
|
args[1] = proxies.shift
|
@@ -43,7 +47,9 @@ module RHACK
|
|
43
47
|
end
|
44
48
|
|
45
49
|
def wait_for_available
|
50
|
+
#L.debug {"Curl.carier_thread = #{Curl.carier_thread}; Thread.current = #{Thread.current}"}
|
46
51
|
Curl.execute :unless_already
|
52
|
+
#L.debug {"Curl.carier_thread = #{Curl.carier_thread}; Thread.current = #{Thread.current}"}
|
47
53
|
# Carier.requests освобождаются ещё до колбека,
|
48
54
|
# но колбеки выполняются последовательно,
|
49
55
|
# поэтому здесь мы можем усыплять тред,
|
@@ -59,6 +65,7 @@ module RHACK
|
|
59
65
|
raise PickError if !b
|
60
66
|
# to_a because Array#reject returns object of this class
|
61
67
|
if scout = to_a.rand_by_available?
|
68
|
+
L.debug {"randomly picked an available scout##{scout.object_id}"}
|
62
69
|
scout
|
63
70
|
else
|
64
71
|
wait_for_available
|
@@ -69,6 +76,7 @@ module RHACK
|
|
69
76
|
def next
|
70
77
|
raise PickError if !b
|
71
78
|
if scout = to_a.find_available?
|
79
|
+
L.debug {"picked the next available scout##{scout.object_id}"}
|
72
80
|
scout
|
73
81
|
else
|
74
82
|
wait_for_available
|
data/lib/rhack/version.rb
CHANGED
data/rhack.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.add_runtime_dependency "activesupport"
|
20
20
|
#spec.add_runtime_dependency "redis"
|
21
|
-
spec.add_runtime_dependency "rmtools", ">= 2.3.
|
21
|
+
spec.add_runtime_dependency "rmtools", ">= 2.3.6"
|
22
22
|
spec.add_runtime_dependency "libxml-ruby"
|
23
23
|
|
24
24
|
spec.extensions << 'ext/curb/extconf.rb'
|