leecher 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/leecher +3 -1
- data/config/client.yml +3 -3
- data/leecher.gemspec +1 -0
- data/lib/leecher/client.rb +45 -16
- data/lib/leecher/version.rb +1 -1
- data/spec/client_spec.rb +25 -5
- metadata +18 -4
data/bin/leecher
CHANGED
@@ -62,7 +62,6 @@ module Leecher
|
|
62
62
|
[
|
63
63
|
[:username, "your username on the website?", :required],
|
64
64
|
[:password, ".. and the password for that user?", :password],
|
65
|
-
[:log_fn, "filename to log to:", File.join(@config_dirname, "log")],
|
66
65
|
[:host, "where does the amqp queue live?", "nzb.trim.za.net"],
|
67
66
|
[:aria2_bin, "which aria2 must I use?", %x{which aria2c}.strip()],
|
68
67
|
[:aria2_dir, "what whould you like your default download directory to be?", Dir.pwd],
|
@@ -172,6 +171,9 @@ module Leecher
|
|
172
171
|
raise log.fatal("First fork failed") if (pid = Kernel.fork()) == -1
|
173
172
|
Kernel.exit!(RC_OK) unless pid.nil?
|
174
173
|
Process.setsid()
|
174
|
+
File.open(File.join(@config_dirname, "pid"), "w") do |f|
|
175
|
+
f.puts(Process.pid)
|
176
|
+
end
|
175
177
|
Dir.chdir(config[:chdir]) if config.has_key? :chdir
|
176
178
|
File.umask(config[:umask]) if config.has_key? :umask
|
177
179
|
[
|
data/config/client.yml
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
:metalink_queue_name: metalink
|
4
4
|
:log:
|
5
5
|
:level: :info
|
6
|
-
:filename: <%=
|
6
|
+
:filename: <%= File.join(config_dirname, "leecher.log") %>
|
7
7
|
:bunny_opts:
|
8
8
|
:host: <%= host %>
|
9
9
|
:port: 5672
|
@@ -12,8 +12,8 @@
|
|
12
12
|
:pass: <%= password %>
|
13
13
|
:ssl: false
|
14
14
|
:verify_ssl: false
|
15
|
-
:logfile:
|
16
|
-
:
|
15
|
+
:logfile: <%= File.join(config_dirname, "bunny.log") %>
|
16
|
+
:logging: false
|
17
17
|
:frame_max: 131072
|
18
18
|
:channel_max: 0
|
19
19
|
:heartbeat: 300
|
data/leecher.gemspec
CHANGED
data/lib/leecher/client.rb
CHANGED
@@ -4,7 +4,8 @@ module Leecher
|
|
4
4
|
|
5
5
|
require "bunny"
|
6
6
|
require "leecher/shellout"
|
7
|
-
require
|
7
|
+
require "xmlrpc/client"
|
8
|
+
require "yajl"
|
8
9
|
|
9
10
|
include Leecher::Shellout
|
10
11
|
|
@@ -50,7 +51,6 @@ module Leecher
|
|
50
51
|
|
51
52
|
def run()
|
52
53
|
@bunny = make_bunny(self.bunny_opts)
|
53
|
-
@bunny.start()
|
54
54
|
|
55
55
|
@graceful_shutdown = false
|
56
56
|
@dont_kill_me = false
|
@@ -94,7 +94,6 @@ module Leecher
|
|
94
94
|
# Start again.
|
95
95
|
log.debug("Reconnecting to rabbitmq")
|
96
96
|
@bunny = make_bunny(self.bunny_opts)
|
97
|
-
@bunny.start()
|
98
97
|
rescue Exception => e
|
99
98
|
log.error([e.class.name, e.message].join(": "))
|
100
99
|
e.backtrace.each do |line|
|
@@ -105,7 +104,10 @@ module Leecher
|
|
105
104
|
end
|
106
105
|
|
107
106
|
def make_bunny(bunny_opts)
|
108
|
-
Bunny.new(bunny_opts)
|
107
|
+
b = Bunny.new(bunny_opts)
|
108
|
+
b.start()
|
109
|
+
b.qos()
|
110
|
+
b
|
109
111
|
end
|
110
112
|
|
111
113
|
def get_queue(bunny, *queue_joinable_name)
|
@@ -119,25 +121,51 @@ module Leecher
|
|
119
121
|
|
120
122
|
next_queue_message(q) do |msg|
|
121
123
|
@dont_kill_me = true
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
#FIXME is it possible something can go wrong but not throw an exception?
|
124
|
+
|
125
|
+
# FIXME: is it possible something can go wrong but not throw an exception?
|
126
126
|
begin
|
127
|
-
|
128
|
-
|
129
|
-
|
127
|
+
uris, options = Yajl::Parser.parse(msg)
|
128
|
+
call_aria(uris, options)
|
129
|
+
true
|
130
130
|
rescue Exception => e
|
131
131
|
log.error("Failed to add uri to aria2c: #{e.message}")
|
132
|
-
|
132
|
+
false
|
133
|
+
ensure
|
134
|
+
@dont_kill_me = false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def call_aria(uris, options)
|
140
|
+
rewrite_aria_dir_opt(options)
|
141
|
+
log.info("Will call aria2.addUri(#{uris.inspect()}, #{options.inspect()})")
|
142
|
+
status = call_rpc("aria2.addUri", uris, options)
|
143
|
+
log.info("Added uri to aria with gid: #{status}")
|
144
|
+
end
|
145
|
+
|
146
|
+
def rewrite_aria_dir_opt(options)
|
147
|
+
# Attempt to rewrite +dir+ to a relative path
|
148
|
+
if (dir = options.delete("dir"))
|
149
|
+
begin
|
150
|
+
global_opts = call_rpc("aria2.getGlobalOption")
|
151
|
+
global_dir = global_opts.delete("dir")
|
152
|
+
options["dir"] = File.join(global_dir, dir)
|
153
|
+
rescue Exception => e
|
154
|
+
log.error("Couldn't get aria2 global options")
|
133
155
|
end
|
134
156
|
end
|
135
|
-
ensure
|
136
|
-
@dont_kill_me = false
|
137
157
|
end
|
138
158
|
|
139
159
|
def next_queue_message(q, &block)
|
140
|
-
|
160
|
+
# +:timeout+: Sometimes it happens that our connection is stale (e.g. DSL
|
161
|
+
# drops and comes back) but the connection never drops. Rabbitmq
|
162
|
+
# kicks us off after 15 min. Thus, use a timeout of 15 minutes
|
163
|
+
# so that, if lightning strikes, worst case is we're 15 minutes
|
164
|
+
# behind.
|
165
|
+
# +:ack+: Acks are sent by +queue.ack+, which is sent via the
|
166
|
+
# subscribe block automatically if the option is turned on.
|
167
|
+
q.subscribe(:timeout => 900,
|
168
|
+
:ack => true) do |msg|
|
141
169
|
payload = msg[:payload]
|
142
170
|
case payload
|
143
171
|
when :queue_empty
|
@@ -169,6 +197,7 @@ module Leecher
|
|
169
197
|
raise e
|
170
198
|
else
|
171
199
|
retried = true
|
200
|
+
log.debug("It appears aria isn't running. Attempting to start it up by calling: #{make_aria_exec}")
|
172
201
|
shellout(make_aria_exec, nil, nil, nil)
|
173
202
|
sleep 10
|
174
203
|
retry
|
@@ -186,7 +215,7 @@ module Leecher
|
|
186
215
|
end
|
187
216
|
|
188
217
|
def make_aria_exec
|
189
|
-
args = aria2_opts[:args]
|
218
|
+
args = aria2_opts[:args].dup
|
190
219
|
|
191
220
|
if aria2_opts.has_key?(:config)
|
192
221
|
args.push([
|
data/lib/leecher/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -27,7 +27,7 @@ describe Leecher::Client do
|
|
27
27
|
@c.metalink_queue_name.should == "metalink"
|
28
28
|
end
|
29
29
|
|
30
|
-
|
30
|
+
context "next_queue_message" do
|
31
31
|
|
32
32
|
it "should only return when something is on the queue" do
|
33
33
|
bunny = double("bunny")
|
@@ -40,7 +40,7 @@ describe Leecher::Client do
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
|
43
|
+
context "drain_metalink_queue" do
|
44
44
|
|
45
45
|
before do
|
46
46
|
@q = double("q")
|
@@ -51,10 +51,13 @@ describe Leecher::Client do
|
|
51
51
|
|
52
52
|
|
53
53
|
it "should rpc to aria2" do
|
54
|
+
uris = ["http://some/url"]
|
55
|
+
options = {}
|
54
56
|
@c.stub(:next_queue_message).
|
55
|
-
and_yield(
|
57
|
+
and_yield(Yajl::Encoder.encode([uris, options]))
|
56
58
|
rpc_server = double("rpc_server")
|
57
|
-
rpc_server.
|
59
|
+
rpc_server.should_receive(:call).
|
60
|
+
with("aria2.addUri", uris, options).
|
58
61
|
and_return(true)
|
59
62
|
@c.stub(:rpc_server).
|
60
63
|
and_return(rpc_server)
|
@@ -63,7 +66,7 @@ describe Leecher::Client do
|
|
63
66
|
|
64
67
|
it "should return according to the success of the rpc" do
|
65
68
|
@c.stub(:next_queue_message).
|
66
|
-
and_yield(
|
69
|
+
and_yield(Yajl::Encoder.encode([[], {}]))
|
67
70
|
rpc_server = double("rpc_server")
|
68
71
|
@c.stub(:rpc_server).
|
69
72
|
and_return(rpc_server)
|
@@ -74,5 +77,22 @@ describe Leecher::Client do
|
|
74
77
|
and_raise(RuntimeError)
|
75
78
|
@c.drain_metalink_queue(@q).should be_false
|
76
79
|
end
|
80
|
+
|
81
|
+
it "should rewrite the dir option" do
|
82
|
+
uris = ["http://some/url"]
|
83
|
+
options = { "dir" => "foo" }
|
84
|
+
@c.stub(:next_queue_message).
|
85
|
+
and_yield(Yajl::Encoder.encode([uris, options]))
|
86
|
+
rpc_server = double("rpc_server")
|
87
|
+
rpc_server.should_receive(:call).
|
88
|
+
with("aria2.getGlobalOption").
|
89
|
+
and_return({"dir" => "/tmp"})
|
90
|
+
rpc_server.should_receive(:call).
|
91
|
+
with("aria2.addUri", uris, {"dir" => "/tmp/foo"}).
|
92
|
+
and_return(true)
|
93
|
+
@c.stub(:rpc_server).
|
94
|
+
and_return(rpc_server)
|
95
|
+
@c.drain_metalink_queue(@q).should be_true
|
96
|
+
end
|
77
97
|
end
|
78
98
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leecher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 2
|
8
9
|
- 1
|
9
|
-
|
10
|
-
version: 0.1.0
|
10
|
+
version: 0.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Marc Bowes
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-26 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -60,6 +60,20 @@ dependencies:
|
|
60
60
|
version: "0"
|
61
61
|
type: :runtime
|
62
62
|
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: yajl-ruby
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
63
77
|
description: A server populates a queue, this client downloads those files
|
64
78
|
email:
|
65
79
|
- marcbowes+leecher@gmail.com
|