leecher 0.1.0 → 0.2.1
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.
- 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
|