rhack 1.3.8 → 1.4.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 +4 -4
- data/lib/rhack.rb +12 -4
- data/lib/rhack/clients.rb +1 -7
- data/lib/rhack/clients/base.rb +31 -11
- data/lib/rhack/clients/errors.rb +41 -0
- data/lib/rhack/dl.rb +1 -1
- data/lib/rhack/frame.rb +7 -1
- data/lib/rhack/js/johnson.rb +3 -3
- data/lib/rhack/page.rb +8 -8
- data/lib/rhack/scout.rb +20 -14
- data/lib/rhack/scout_squad.rb +3 -3
- data/lib/rhack/version.rb +1 -1
- metadata +11 -12
- data/lib/rhack/services.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a6f9fd958d14ef221d1f20ebb4217decff1a257
|
4
|
+
data.tar.gz: 9b0d6cdf7cbe66b9d0f7ee3fa155761af34584c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7905168e4924ff769eb900fe57105edefa41ed98605b9421b4e9a4c1185e5ad3ce50c94034652cae9a94418f1b6fbc0da4058b153903bc91805224ba134e9ef
|
7
|
+
data.tar.gz: 2574c36ae2d5eabd0721d9134d38645963fcec1f49495642084bf63a24d1bc116cfc508564bc3c11b8e78ef212a0bc9870d9e5de30e7b7962e487136358c9339
|
data/lib/rhack.rb
CHANGED
@@ -50,7 +50,7 @@ module RHACK
|
|
50
50
|
if uas = uas.desktop.to_s and File.file? uas
|
51
51
|
@@useragents = IO.read(uas)/"\n"
|
52
52
|
else
|
53
|
-
@@useragents = ['Mozilla/5.0 (
|
53
|
+
@@useragents = ['Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36']
|
54
54
|
end
|
55
55
|
|
56
56
|
class Scout
|
@@ -58,9 +58,9 @@ module RHACK
|
|
58
58
|
mattr_accessor :retry, :timeout
|
59
59
|
|
60
60
|
scout = RHACK.config.scout || {}
|
61
|
-
@@retry = scout.retry.
|
62
|
-
@@timeout = scout.timeout.
|
63
|
-
@@cacert = scout.cacert.
|
61
|
+
@@retry = scout.retry.presence || {}
|
62
|
+
@@timeout = scout.timeout.presence || 60
|
63
|
+
@@cacert = scout.cacert.presence ? File.expand_path(scout.cacert) : File.expand_path('../../config/cacert.pem', __FILE__)
|
64
64
|
end
|
65
65
|
|
66
66
|
end
|
@@ -89,5 +89,13 @@ require "rhack/scout_squad"
|
|
89
89
|
require "rhack/frame"
|
90
90
|
require "rhack/page"
|
91
91
|
if defined? Redis::Objects
|
92
|
+
# redis storage for namespaced cache, oauth data etc
|
92
93
|
require "rhack/storage"
|
93
94
|
end
|
95
|
+
|
96
|
+
module RHACK
|
97
|
+
# key feature
|
98
|
+
autoload :Client, 'rhack/clients'
|
99
|
+
# basic client for oauth
|
100
|
+
autoload :OAuthClient, 'rhack/clients/oauth'
|
101
|
+
end
|
data/lib/rhack/clients.rb
CHANGED
@@ -1,10 +1,4 @@
|
|
1
1
|
require 'rhack'
|
2
2
|
require 'rhack/clients/base'
|
3
3
|
require 'rhack/clients/storage'
|
4
|
-
require 'rhack/clients/
|
5
|
-
|
6
|
-
module RHACK
|
7
|
-
for name in [:Service, :ServiceError]
|
8
|
-
autoload name, 'rhack/clients/compatibility'
|
9
|
-
end
|
10
|
-
end
|
4
|
+
require 'rhack/clients/errors'
|
data/lib/rhack/clients/base.rb
CHANGED
@@ -1,29 +1,42 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
|
-
# TODO 1.0+: опция для клиента, чтобы это описание имело смысл, т.к. сейчас это ложь:
|
4
|
-
# Вызовам клиентов всегда следует ждут и возвращают обработанный ответ, если вызвваны без блока.
|
5
|
-
# В противном случае используется событийная модель и обработанный ответ передаётся в блок.
|
6
2
|
module RHACK
|
7
3
|
|
8
4
|
class Client
|
9
5
|
attr_reader :service
|
10
6
|
attr_accessor :f
|
11
7
|
class_attribute :frame_defaults, :instance_writer => false
|
8
|
+
class_attribute :scouts_initializers, :instance_writer => false
|
12
9
|
class_attribute :accounts, :instance_writer => false
|
13
10
|
class_attribute :routes, :instance_writer => false
|
14
11
|
class_attribute :rootpath, :instance_writer => false
|
15
12
|
|
16
13
|
self.frame_defaults = {}
|
14
|
+
self.scouts_initializers = []
|
17
15
|
self.accounts = {}
|
18
16
|
self.routes = {}
|
19
17
|
|
20
18
|
class << self
|
21
19
|
|
22
20
|
def inherited(child)
|
23
|
-
child.class_eval
|
21
|
+
child.class_eval do
|
24
22
|
include RHACK
|
25
23
|
__init__
|
26
|
-
|
24
|
+
|
25
|
+
# Proxying Rails router methods digging into the client namespace
|
26
|
+
if defined? ::Rails.application.routes.url_helpers
|
27
|
+
url_helpers = ::Rails.application.routes.url_helpers
|
28
|
+
routes_namespace = name.gsub(/::/, '').underscore.sub(/_client$/, '')
|
29
|
+
route_pattern = /^(.+_)?#{routes_namespace}_(.+)/
|
30
|
+
url_helpers.my_methods.each {|name|
|
31
|
+
if name.to_s[route_pattern]
|
32
|
+
full_route_name = $&
|
33
|
+
define_method "#$1#$2" do |*options|
|
34
|
+
url_helpers.send full_route_name, *options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
27
40
|
end
|
28
41
|
|
29
42
|
def method_missing(method, *args, &block)
|
@@ -55,8 +68,11 @@ module RHACK
|
|
55
68
|
end
|
56
69
|
|
57
70
|
# Set default Frame options
|
58
|
-
def frame(dict)
|
71
|
+
def frame(dict, &scout_initializer)
|
59
72
|
self.frame_defaults += dict
|
73
|
+
if scout_initializer
|
74
|
+
self.scouts_initializers << scout_initializer
|
75
|
+
end
|
60
76
|
end
|
61
77
|
|
62
78
|
# Set usable accounts
|
@@ -78,6 +94,13 @@ module RHACK
|
|
78
94
|
if self.class.const_defined? :Result
|
79
95
|
opts[:result] = self.class::Result
|
80
96
|
end
|
97
|
+
if scouts_initializers = self.scouts_initializers.presence
|
98
|
+
opts[:on_scout_initialize] ||= lambda {|scout|
|
99
|
+
scouts_initializers.each {|initializer|
|
100
|
+
initializer.call scout
|
101
|
+
}
|
102
|
+
}
|
103
|
+
end
|
81
104
|
@f = Frame(rootpath || route(service) || route(:login), opts)
|
82
105
|
end
|
83
106
|
end
|
@@ -120,7 +143,7 @@ module RHACK
|
|
120
143
|
def route(name, interpolation=nil)
|
121
144
|
if url = routes[name]
|
122
145
|
if interpolation
|
123
|
-
url %= interpolation
|
146
|
+
url %= interpolation.symbolize_keys
|
124
147
|
end
|
125
148
|
if url !~ /^\w+:/
|
126
149
|
url = File.join rootpath, url
|
@@ -129,8 +152,6 @@ module RHACK
|
|
129
152
|
end
|
130
153
|
end
|
131
154
|
alias :url :route
|
132
|
-
# URI is deprecated # backward compatibility
|
133
|
-
alias :URI :route
|
134
155
|
|
135
156
|
def account(name)
|
136
157
|
accounts[name]
|
@@ -138,5 +159,4 @@ module RHACK
|
|
138
159
|
|
139
160
|
end
|
140
161
|
|
141
|
-
class ClientError < Exception; end
|
142
162
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RHACK
|
2
|
+
|
3
|
+
# Abstraction, don't use it.
|
4
|
+
class BasicError < StandardError
|
5
|
+
# keep here debugful data
|
6
|
+
attr_accessor :details
|
7
|
+
|
8
|
+
# # Usage ...
|
9
|
+
# # ... without :details keyword, as usual:
|
10
|
+
# raise ServerError, 'an error has occured'
|
11
|
+
# # ... with :details keyword
|
12
|
+
# raise ServerError.new 'an error has occured', details: @curl_res
|
13
|
+
# # ... if you also want to set custom backtrace
|
14
|
+
# raise ServerError.new('an error has occured', details: @curl_res), backtrace_array
|
15
|
+
def initialize(message, *opts) # details: nil
|
16
|
+
@details = opts.extract_options![:details]
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
# The client couldn't connect and yet we don't know whose this fault is,
|
23
|
+
# e.g. domain lookup error or timeout.
|
24
|
+
class ConnectionError < BasicError; end
|
25
|
+
|
26
|
+
# The client successfully connected to the server
|
27
|
+
# but it returned an improper, non-descriptive response,
|
28
|
+
# e.g. 500 status, empty body, etc.
|
29
|
+
class ServerError < BasicError; end
|
30
|
+
|
31
|
+
# The client successfully connected to the server
|
32
|
+
# but server didn't accept a request and returned a descriptive exception,
|
33
|
+
# e.g. 406 status, body with only "error" key, etc.
|
34
|
+
class RequestError < BasicError; end
|
35
|
+
|
36
|
+
# The client successfully connected to the server,
|
37
|
+
# the server accept a request but we failed to process a response,
|
38
|
+
# e.g. because of an unexpected response structure
|
39
|
+
class ClientError < BasicError; end
|
40
|
+
|
41
|
+
end
|
data/lib/rhack/dl.rb
CHANGED
data/lib/rhack/frame.rb
CHANGED
@@ -25,6 +25,8 @@ module RHACK
|
|
25
25
|
alias options opts
|
26
26
|
@@cache = {}
|
27
27
|
|
28
|
+
# Opts passed to Scout:
|
29
|
+
# :ck / :cp, :raise, :timeout, :retry, :redir
|
28
30
|
def initialize *args
|
29
31
|
#args << 10 unless args[-1].is Fixnum
|
30
32
|
#args.insert -2, {} unless args[-2].is Hash
|
@@ -44,6 +46,10 @@ module RHACK
|
|
44
46
|
@static = false
|
45
47
|
end
|
46
48
|
@ss = ScoutSquad @loc.href, @opts, scouts_count
|
49
|
+
# for low-level settings that are not implemented explicitly
|
50
|
+
if @opts[:on_scout_initialize].present?
|
51
|
+
each &@opts[:on_scout_initialize]
|
52
|
+
end
|
47
53
|
end
|
48
54
|
|
49
55
|
def update_loc url
|
@@ -256,7 +262,7 @@ module RHACK
|
|
256
262
|
order = [del ? :loadDelete : :loadGet, url]
|
257
263
|
end
|
258
264
|
end
|
259
|
-
if
|
265
|
+
if order.blank? and orders.blank?
|
260
266
|
raise ArgumentError, "failed to run blank request#{'s' if many}, params was
|
261
267
|
(#{args.inspect[1..-2]})"
|
262
268
|
end
|
data/lib/rhack/js/johnson.rb
CHANGED
@@ -20,7 +20,7 @@ module Johnson
|
|
20
20
|
class << self
|
21
21
|
|
22
22
|
def runtime_set?(opts)
|
23
|
-
|
23
|
+
opts[:eval].blank? or (@@browser and @@browser.thread_id == Curl.carier_thread.object_id)
|
24
24
|
end
|
25
25
|
|
26
26
|
# CarierThread breaks if Multi has no work && CarierThread
|
@@ -36,9 +36,9 @@ module Johnson
|
|
36
36
|
unless runtime_set? opts
|
37
37
|
if Curl.status
|
38
38
|
Curl.recall
|
39
|
-
|
39
|
+
L.debug 'recalled'
|
40
40
|
end
|
41
|
-
if opts[:thread_safe].
|
41
|
+
if opts[:thread_safe].present?
|
42
42
|
@@browser = new_browser(opts[:jq])
|
43
43
|
L.debug "#@@browser initialized in #{Thread.current}\nmain: #{Thread.main}; carier: #{Curl.carier_thread}"
|
44
44
|
else
|
data/lib/rhack/page.rb
CHANGED
@@ -49,7 +49,7 @@ module RHACK
|
|
49
49
|
if obj.is Curl::Easy or obj.kinda Scout
|
50
50
|
c = obj.kinda(Scout) ? obj.http : obj
|
51
51
|
# just (c, loc) would pass to #process opts variable that returns '' on any key
|
52
|
-
process(c, loc.
|
52
|
+
process(c, loc.presence || {})
|
53
53
|
else
|
54
54
|
@body = obj
|
55
55
|
@loc = loc
|
@@ -57,7 +57,7 @@ module RHACK
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def empty?
|
60
|
-
!@data &&
|
60
|
+
!@data && @body.blank?
|
61
61
|
end
|
62
62
|
|
63
63
|
def size
|
@@ -215,10 +215,10 @@ module RHACK
|
|
215
215
|
document.domain = location.host;"
|
216
216
|
find("script").each {|n|
|
217
217
|
L.debug n.text.strip
|
218
|
-
if text = n.text.strip.
|
218
|
+
if text = n.text.strip.presence
|
219
219
|
js[:write_output] = ''
|
220
220
|
eval_string text
|
221
|
-
if res = js[:write_output].
|
221
|
+
if res = js[:write_output].presence then n.after res end
|
222
222
|
n.remove!
|
223
223
|
elsif frame and n.src
|
224
224
|
eval_string frame.get_cached expand_link n.src
|
@@ -251,10 +251,10 @@ module RHACK
|
|
251
251
|
end
|
252
252
|
|
253
253
|
def title(full=true)
|
254
|
-
if @data.nil? and !@failed and @body.
|
254
|
+
if @data.nil? and !@failed and @body.present?
|
255
255
|
if full
|
256
256
|
to_html unless defined? @doc
|
257
|
-
if @doc.title.
|
257
|
+
if @doc.title.present?
|
258
258
|
@title = @doc.title
|
259
259
|
else
|
260
260
|
@title = @loc.href
|
@@ -454,7 +454,7 @@ module RHACK
|
|
454
454
|
if form_node['method'].downcase == 'post'
|
455
455
|
[hash, form_node.enctype =~ /multipart/, action, opts]
|
456
456
|
else
|
457
|
-
action = "#{action}#{action['?'] ? '&' : '?'}#{hash.urlencode}" if hash.
|
457
|
+
action = "#{action}#{action['?'] ? '&' : '?'}#{hash.urlencode}" if hash.present?
|
458
458
|
[action, opts]
|
459
459
|
end
|
460
460
|
end
|
@@ -496,7 +496,7 @@ module RHACK
|
|
496
496
|
|
497
497
|
def get_links(links='a')
|
498
498
|
begin
|
499
|
-
links = find(links).map {|e| e.href}.
|
499
|
+
links = find(links).map {|e| e.href}.presence || find(links+'//a').map {|e| e.href} if links.is String
|
500
500
|
rescue LibXML::XML::Error
|
501
501
|
links = [links]
|
502
502
|
end
|
data/lib/rhack/scout.rb
CHANGED
@@ -193,7 +193,7 @@ module RHACK
|
|
193
193
|
when Curl::Response
|
194
194
|
ck = res['cookies']
|
195
195
|
end
|
196
|
-
return if
|
196
|
+
return if ck.blank?
|
197
197
|
ck.each {|c| Cookie(c, self)}
|
198
198
|
end
|
199
199
|
|
@@ -253,12 +253,15 @@ module RHACK
|
|
253
253
|
retry!
|
254
254
|
else
|
255
255
|
L.debug "#{curl_err} -> not reloading scout"
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
256
|
+
begin
|
257
|
+
raise @error if @raise_err
|
258
|
+
#raise *@error if @raise_err # old
|
259
|
+
yield if block_given?
|
260
|
+
ensure
|
261
|
+
# Now, we assume that data of this @http have been copied or will not be used anymore,
|
262
|
+
# thus the scout can be reused.
|
263
|
+
@busy = false
|
264
|
+
end
|
262
265
|
end
|
263
266
|
end
|
264
267
|
|
@@ -302,14 +305,17 @@ module RHACK
|
|
302
305
|
process_cookies res if @cookies_enabled
|
303
306
|
# We cannot just cancel on_complete in on_redirect block,
|
304
307
|
# because loadGet should (and will) immediately reset on_complete back.
|
305
|
-
if res.code.in(300..399) and
|
308
|
+
if res.code.in(300..399) and not_redir.blank? and (relvl -= 1) > -1 and loc = res.hash.location
|
306
309
|
loadGet(loc, headers: headers, relvl: relvl, redir: true, &callback)
|
307
310
|
else
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
311
|
+
begin
|
312
|
+
yield @http if block_given?
|
313
|
+
ensure
|
314
|
+
# Now, we assume that data of this @http have been copied or will not be used anymore,
|
315
|
+
# thus the scout can be reused.
|
316
|
+
@busy = false
|
317
|
+
@http.on_failure &Proc::NULL
|
318
|
+
end
|
313
319
|
end
|
314
320
|
}
|
315
321
|
# Curl::Err::* (TCP/IP level) exception callback.
|
@@ -353,7 +359,7 @@ module RHACK
|
|
353
359
|
unless hash.is Hash # not parameterized
|
354
360
|
opts[:headers] = opts[:headers].reverse_merge 'Content-Type' => 'application/octet-stream'
|
355
361
|
end
|
356
|
-
mkBody hash, multipart.
|
362
|
+
mkBody hash, multipart.present?
|
357
363
|
@last_method = :post
|
358
364
|
if block_given?
|
359
365
|
@post_proc = callback
|
data/lib/rhack/scout_squad.rb
CHANGED
@@ -62,7 +62,7 @@ module RHACK
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def rand
|
65
|
-
raise PickError if
|
65
|
+
raise PickError if empty?
|
66
66
|
# to_a because Array#reject returns object of this class
|
67
67
|
if scout = to_a.rand_by_available?
|
68
68
|
L.debug {"randomly picked an available scout##{scout.object_id}"}
|
@@ -74,7 +74,7 @@ module RHACK
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def next
|
77
|
-
raise PickError if
|
77
|
+
raise PickError if empty?
|
78
78
|
if scout = to_a.find_available?
|
79
79
|
L.debug {"picked the next available scout##{scout.object_id}"}
|
80
80
|
scout
|
@@ -86,7 +86,7 @@ module RHACK
|
|
86
86
|
|
87
87
|
def to_s
|
88
88
|
str = '<#ScoutSquad @ '
|
89
|
-
if
|
89
|
+
if any?
|
90
90
|
if first.webproxy
|
91
91
|
str << "#{first.proxy} ~ "
|
92
92
|
elsif first.proxy
|
data/lib/rhack/version.rb
CHANGED
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rhack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Baev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rmtools
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '2.4'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.4'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: libxml-ruby
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '2.7'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.7'
|
41
41
|
description: 'RHACK is Ruby Http ACcess Kit: curl-based web-client framework created
|
@@ -49,7 +49,7 @@ extensions:
|
|
49
49
|
- ext/curb/extconf.rb
|
50
50
|
extra_rdoc_files: []
|
51
51
|
files:
|
52
|
-
- .gitignore
|
52
|
+
- ".gitignore"
|
53
53
|
- CURB-LICENSE
|
54
54
|
- Gemfile
|
55
55
|
- LICENSE
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- lib/rhack/clients.rb
|
92
92
|
- lib/rhack/clients/base.rb
|
93
93
|
- lib/rhack/clients/compatibility.rb
|
94
|
+
- lib/rhack/clients/errors.rb
|
94
95
|
- lib/rhack/clients/examples.rb
|
95
96
|
- lib/rhack/clients/oauth.rb
|
96
97
|
- lib/rhack/clients/storage.rb
|
@@ -116,7 +117,6 @@ files:
|
|
116
117
|
- lib/rhack/proxy/list.rb
|
117
118
|
- lib/rhack/scout.rb
|
118
119
|
- lib/rhack/scout_squad.rb
|
119
|
-
- lib/rhack/services.rb
|
120
120
|
- lib/rhack/storage.rb
|
121
121
|
- lib/rhack/version.rb
|
122
122
|
- lib/rhack_in.rb
|
@@ -134,19 +134,18 @@ require_paths:
|
|
134
134
|
- lib
|
135
135
|
required_ruby_version: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
|
-
- -
|
137
|
+
- - ">="
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '0'
|
140
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
|
-
- -
|
142
|
+
- - ">="
|
143
143
|
- !ruby/object:Gem::Version
|
144
144
|
version: '0'
|
145
145
|
requirements: []
|
146
146
|
rubyforge_project:
|
147
|
-
rubygems_version: 2.
|
147
|
+
rubygems_version: 2.2.2
|
148
148
|
signing_key:
|
149
149
|
specification_version: 4
|
150
150
|
summary: Curl-based web-client framework created for developing web-scrapers/bots
|
151
151
|
test_files: []
|
152
|
-
has_rdoc:
|
data/lib/rhack/services.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'rhack/clients'
|