saber 0.0.7 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +18 -8
- data/Gemfile.lock +72 -33
- data/Guardfile +4 -0
- data/README.md +192 -52
- data/Rakefile +46 -0
- data/bin/1saber +5 -3
- data/bin/saber +4 -0
- data/bin/saber.bib +3 -0
- data/bin/saber.what +3 -0
- data/extconf.rb +4 -1
- data/lib/saber.rb +7 -13
- data/lib/saber/autofetcher.rb +8 -0
- data/lib/saber/autofetcher/client.rb +66 -0
- data/lib/saber/autofetcher/server.rb +78 -0
- data/lib/saber/cli.rb +65 -26
- data/lib/saber/{downloader.rb → fetcher.rb} +9 -11
- data/lib/saber/mechanize_ext.rb +136 -0
- data/lib/saber/rc.rb +3 -21
- data/lib/saber/task.rb +26 -11
- data/lib/saber/task/base.rb +18 -0
- data/lib/saber/task/clean.rb +18 -0
- data/lib/saber/task/generate.rb +38 -0
- data/lib/saber/task/make.rb +44 -0
- data/lib/saber/task/send.rb +21 -0
- data/lib/saber/task/upload.rb +37 -0
- data/lib/saber/tracker.rb +28 -0
- data/lib/saber/tracker/base.rb +115 -2
- data/lib/saber/tracker/bb.rb +244 -0
- data/lib/saber/tracker/bib.rb +225 -0
- data/lib/saber/tracker/ptp.rb +100 -0
- data/lib/saber/tracker/what.rb +55 -7
- data/lib/saber/ui.rb +65 -22
- data/lib/saber/version.rb +1 -1
- data/rutorrent/init.js +8 -9
- data/rutorrent/plugin.info +1 -1
- data/saber.gemspec +14 -10
- data/spec/data/_saber/.gitkeep +0 -0
- data/spec/saber/downloader_spec.rb +5 -2
- data/spec/saber/task_spec.rb +16 -0
- data/spec/saber/tracker/bib_spec.rb +24 -0
- data/spec/spec_helper.rb +25 -0
- data/templates/_saberrc +36 -0
- data/templates/bb/anime.yml +6 -0
- data/templates/bb/application.yml +7 -0
- data/templates/bb/audiobook.yml +12 -0
- data/templates/bb/comic.yml +7 -0
- data/templates/bb/documentary.yml +26 -0
- data/templates/bb/ebook.yml +8 -0
- data/templates/bb/elearning_video.yml +7 -0
- data/templates/bb/game_console.yml +6 -0
- data/templates/bb/game_pc.yml +6 -0
- data/templates/bb/magazine.yml +6 -0
- data/templates/bb/misc.yml +6 -0
- data/templates/bb/movie.yml +26 -0
- data/templates/bb/music.yml +21 -0
- data/templates/bb/tv.yml +6 -0
- data/templates/bib/application.yml +9 -0
- data/templates/bib/article.yml +18 -0
- data/templates/bib/audiobook.yml +17 -0
- data/templates/bib/comic.yml +22 -0
- data/templates/bib/ebook.yml +20 -0
- data/templates/bib/journal.yml +18 -0
- data/templates/bib/magazine.yml +18 -0
- data/templates/ptp/movie.yml +63 -0
- data/templates/ptp/movie_add.yml +35 -0
- data/templates/what/ebook.yml +6 -0
- data/templates/what/music.yml +2 -0
- data/templates/what/music_add.yml +2 -0
- metadata +182 -26
- data/doc/Development.md +0 -3
- data/lib/saber/client.rb +0 -58
- data/lib/saber/server.rb +0 -70
- data/saber.watchr +0 -23
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
PROJECT = "saber"
|
2
|
+
|
3
|
+
namespace :test do
|
4
|
+
desc "Run all specs on multiple ruby versions (requires rvm)"
|
5
|
+
task :portability do
|
6
|
+
require "yaml"
|
7
|
+
travis_options = YAML::load_file(File.expand_path("../.travis.yml", __FILE__))
|
8
|
+
travis_options["rvm"].each do |version|
|
9
|
+
system <<-BASH
|
10
|
+
bash -c 'source ~/.rvm/scripts/rvm;
|
11
|
+
rvm #{version};
|
12
|
+
ruby_version_string_size=`ruby -v | wc -m`
|
13
|
+
echo;
|
14
|
+
for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done
|
15
|
+
echo;
|
16
|
+
echo "`ruby -v`";
|
17
|
+
for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done
|
18
|
+
echo;
|
19
|
+
bundle install;
|
20
|
+
bundle exec rspec spec 2>&1;'
|
21
|
+
BASH
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "rewrite gemspec with add_dependency from Gemfile"
|
27
|
+
task :gemspec do
|
28
|
+
require "bundler"
|
29
|
+
gemspec = "#{PROJECT}.gemspec"
|
30
|
+
|
31
|
+
deps = Bundler.definition.dependencies.find_all{|v|
|
32
|
+
v.groups.include? :default
|
33
|
+
}
|
34
|
+
|
35
|
+
deps = deps.map {|dep|
|
36
|
+
list = [dep.name] + dep.requirements_list
|
37
|
+
"\ts.add_dependency #{list.map(&:inspect).join(', ')}\n"
|
38
|
+
}
|
39
|
+
|
40
|
+
lines = File.read(gemspec).lines.to_a
|
41
|
+
idx = lines.find_index{|v| v =~ /s\.add_dependency/} || -2
|
42
|
+
lines.delete_if{|v| v =~ /s\.add_dependency/}
|
43
|
+
lines.insert(idx, *deps)
|
44
|
+
|
45
|
+
File.write(gemspec, lines.join(""))
|
46
|
+
end
|
data/bin/1saber
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
dir = File.expand_path("../..", File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__)
|
4
|
+
libdir = File.join(dir, "lib"); $:.unshift(libdir) unless $:.include?(libdir)
|
5
|
+
ENV["BUNDLE_GEMFILE"] = File.join(dir, "Gemfile")
|
5
6
|
|
6
|
-
|
7
|
+
require "bundler/setup"
|
8
|
+
load File.join(dir, "bin/saber")
|
data/bin/saber
CHANGED
data/bin/saber.bib
ADDED
data/bin/saber.what
ADDED
data/extconf.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
require "fileutils"
|
3
3
|
require "mkmf"
|
4
4
|
|
5
|
-
|
5
|
+
bindir = File.expand_path("../bin", __FILE__)
|
6
|
+
|
7
|
+
FileUtils.install File.join(bindir, "saber-drb_add"), Gem.bindir
|
8
|
+
FileUtils.install File.join(bindir, "saber.bib"), Gem.bindir
|
6
9
|
|
7
10
|
create_makefile("saber")
|
data/lib/saber.rb
CHANGED
@@ -1,27 +1,21 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require "pd"
|
3
2
|
require "pa"
|
4
3
|
require "optimism"
|
5
|
-
require "
|
6
|
-
|
7
|
-
Retort::Service.configure do |c|
|
8
|
-
c.url = "http://localhost/RPC2"
|
9
|
-
end
|
4
|
+
require "active_support/core_ext/module/attribute_accessors"
|
5
|
+
require "active_support/concern"
|
10
6
|
|
11
7
|
module Saber
|
12
8
|
autoload :VERSION, "saber/version"
|
13
9
|
autoload :CLI, "saber/cli"
|
14
10
|
autoload :UI, "saber/ui"
|
15
11
|
autoload :Task, "saber/task"
|
16
|
-
autoload :
|
17
|
-
autoload :
|
18
|
-
autoload :
|
19
|
-
autoload :DRbServer, "saber/server"
|
20
|
-
autoload :DRbClient, "saber/client"
|
12
|
+
autoload :Fetcher, "saber/fetcher"
|
13
|
+
autoload :AutoFetcher, "saber/autofetcher"
|
14
|
+
autoload :Tracker, "saber/tracker"
|
21
15
|
|
22
16
|
Error = Class.new Exception
|
23
17
|
FatalError = Class.new Exception
|
24
|
-
Rc = Optimism.require "saber/rc", "
|
18
|
+
Rc = Optimism.require "saber/rc", "~/.saberrc"
|
25
19
|
|
26
20
|
class << self
|
27
21
|
attr_accessor :ui
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "tagen/xmpp4r"
|
2
|
+
require "xmpp4r/client"
|
3
|
+
require "drb"
|
4
|
+
|
5
|
+
module Saber
|
6
|
+
module AutoFetcher
|
7
|
+
class Client
|
8
|
+
class << self
|
9
|
+
def start
|
10
|
+
client = Client.new
|
11
|
+
|
12
|
+
client.start
|
13
|
+
|
14
|
+
Thread.list.each{|v| v.join}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :client, :fetcher
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@client = Jabber::Client.new(Jabber::JID.new(Rc.client.xmpp.jid))
|
22
|
+
@fetcher = Fetcher.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def start
|
26
|
+
client.connect Rc.client.xmpp.host, Rc.client.xmpp.port
|
27
|
+
client.auth Rc.client.xmpp.password
|
28
|
+
|
29
|
+
at_exit do
|
30
|
+
client.send Jabber::Presence.new.set_type(:unavaliable)
|
31
|
+
end
|
32
|
+
|
33
|
+
client.add_message_callback { |msg|
|
34
|
+
if msg.from.bare == Rc.server.xmpp.jid
|
35
|
+
files = msg.body.split("\n")
|
36
|
+
Saber.ui.debug "RECV #{files}"
|
37
|
+
fetcher.add *files
|
38
|
+
end
|
39
|
+
}
|
40
|
+
|
41
|
+
client.send Jabber::Iq.new_rosterget
|
42
|
+
client.send Jabber::Presence.new.set_type(:avaliable)
|
43
|
+
Saber.ui.say ">> Connected to xmpp with #{Rc.client.xmpp.jid}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def stop
|
47
|
+
@client.close!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class DRbClient
|
52
|
+
attr_reader :server
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
DRb.start_service
|
56
|
+
@server = DRbObject.new_with_uri(Rc.drb_uri)
|
57
|
+
Saber.ui.say ">> DRbClient connected to #{Rc.drb_uri}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def add(*names)
|
61
|
+
Saber.ui.say "ADD #{names}"
|
62
|
+
server.add(*names)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "tagen/xmpp4r"
|
2
|
+
require "xmpp4r/client"
|
3
|
+
require "drb"
|
4
|
+
|
5
|
+
module Saber
|
6
|
+
module AutoFetcher
|
7
|
+
class Server
|
8
|
+
def self.start
|
9
|
+
s = Server.new
|
10
|
+
DRbServer.start(s)
|
11
|
+
s.start
|
12
|
+
|
13
|
+
Thread.list.each {|v| v.join}
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :client
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@client = Jabber::Client.new(Jabber::JID.new(Rc.server.xmpp.jid))
|
20
|
+
end
|
21
|
+
|
22
|
+
def start
|
23
|
+
client.connect Rc.server.xmpp.host, Rc.server.xmpp.port
|
24
|
+
client.auth Rc.server.xmpp.password
|
25
|
+
|
26
|
+
at_exit do
|
27
|
+
client.send Jabber::Presence.new.set_type(:unavaliable)
|
28
|
+
end
|
29
|
+
|
30
|
+
client.send Jabber::Iq.new_rosterget
|
31
|
+
client.send Jabber::Presence.new.set_type(:avaliable)
|
32
|
+
|
33
|
+
Saber.ui.say ">> Connected to xmpp with #{Rc.server.xmpp.jid}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def send(files)
|
37
|
+
Saber.ui.debug "SEND #{files.join("\n")}"
|
38
|
+
#client.send Jabber::Presence.new
|
39
|
+
client.send Jabber::Message.new(Rc.client.xmpp.jid, files.join("\n")).set_type(:chat)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class DRbServer
|
44
|
+
class << self
|
45
|
+
def start(saber_server)
|
46
|
+
DRbServer.new(saber_server).start
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
attr_reader :saber_server
|
51
|
+
|
52
|
+
# @params [Server] server
|
53
|
+
def initialize(saber_server)
|
54
|
+
@saber_server = saber_server
|
55
|
+
end
|
56
|
+
|
57
|
+
def start
|
58
|
+
DRb.start_service Rc.drb_uri, self
|
59
|
+
Saber.ui.say ">> DRbSever listening on #{Rc.drb_uri}"
|
60
|
+
end
|
61
|
+
|
62
|
+
# drb. add a complete torrent.
|
63
|
+
def add(*names)
|
64
|
+
Saber.ui.debug "DRbServer-ADD #{names.inspect}"
|
65
|
+
files = build_files(*names)
|
66
|
+
|
67
|
+
saber_server.send(files)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# ["filea", "foo/filea", "foo/fileb"]
|
73
|
+
def build_files(*names)
|
74
|
+
Pa.ls2_r(*names, :base_dir => Rc.p.remote_download, :file => true, :include => true) { |p,abs| not Pa.directory?(abs) }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/saber/cli.rb
CHANGED
@@ -1,60 +1,99 @@
|
|
1
1
|
require "thor"
|
2
|
-
require "drb"
|
3
2
|
|
4
3
|
module Saber
|
5
4
|
class CLI < Thor
|
6
5
|
include Thor::Actions
|
7
6
|
|
8
|
-
class_option "no-color",
|
9
|
-
class_option "verbose",
|
10
|
-
class_option "log",
|
7
|
+
class_option "no-color", banner: "Disable colorization in output", type: :boolean
|
8
|
+
class_option "verbose", aliases: "-V", banner: "Enable verbose output mode", type: :boolean
|
9
|
+
class_option "log", banner: "Log file", type: :string
|
10
|
+
class_option "force", aliases: "-f", banner: "Fore writing even if file exists", type: :boolean
|
11
|
+
class_option "tracker", aliases: "-t", banner: "tracker name", type: :string
|
11
12
|
|
12
13
|
attr_reader :o
|
13
14
|
|
14
15
|
def initialize(*)
|
15
16
|
super
|
16
17
|
o = @o = options.dup
|
17
|
-
|
18
|
-
Saber.ui =
|
18
|
+
|
19
|
+
Saber.ui = if o["log"] then
|
20
|
+
require "logger"
|
21
|
+
UI::Logger.new(::Logger.new(o["log"]))
|
22
|
+
else
|
23
|
+
the_shell = (options["no-color"] ? Thor::Shell::Basic.new : shell)
|
24
|
+
UI::Shell.new(the_shell)
|
25
|
+
end
|
26
|
+
|
19
27
|
Saber.ui.debug! if o["verbose"]
|
28
|
+
|
29
|
+
# Initialize environment in first time
|
30
|
+
unless Rc.p.home.exists?
|
31
|
+
Pa.mkdir Rc.p.home
|
32
|
+
end
|
20
33
|
end
|
21
34
|
|
22
35
|
desc "clean", "clean up files doesn't in rtorrent client"
|
23
36
|
def clean
|
24
|
-
|
25
|
-
end
|
37
|
+
require "saber/task/clean"
|
26
38
|
|
27
|
-
|
28
|
-
def add(*names)
|
29
|
-
Downloader.new.add_names(*names)
|
39
|
+
Task["clean"].invoke(:clean, [], o)
|
30
40
|
end
|
31
41
|
|
32
42
|
desc "server", "start saber-server daemon"
|
33
43
|
def server
|
34
|
-
|
35
|
-
o["log"] ||= "/var/log/saber-server.log"
|
36
|
-
|
37
|
-
$log = Logger.new options["verbose"] ? STDOUT : o["log"]
|
38
|
-
Server.start
|
44
|
+
AutoFetcher::Server.start
|
39
45
|
end
|
40
46
|
|
41
47
|
desc "client", "start saber-client daemon"
|
42
48
|
def client
|
43
|
-
|
44
|
-
o["log"] ||= "/var/log/saber-client.log"
|
45
|
-
|
46
|
-
$log = Logger.new options["verbose"] ? STDOUT : o["log"]
|
47
|
-
Client.start
|
49
|
+
AutoFetcher::Client.start
|
48
50
|
end
|
49
51
|
|
50
|
-
desc "drb_add <
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
desc "drb_add [options] <id,...> <label>", "add a file to saber-server daemon via drb."
|
53
|
+
def drb_add(ids_str, label="")
|
54
|
+
return if label != "saber"
|
55
|
+
|
56
|
+
require "drb"
|
57
|
+
require "retort"
|
58
|
+
Retort::Service.configure { |c| c.url = Rc.scgi_server }
|
54
59
|
|
55
60
|
names = ids_str.split(",").map{|v| Retort::Torrent.action("name", v)}
|
56
61
|
|
57
|
-
DRbClient.new.add(*names)
|
62
|
+
AutoFetcher::DRbClient.new.add(*names)
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "upload [options] <torrent_file/file ...>", "[make a torrent file and] upoad a torrent file to the site"
|
66
|
+
def upload(*files)
|
67
|
+
require "saber/task/upload"
|
68
|
+
|
69
|
+
Task["upload"].invoke(:upload, [options["tracker"] || ENV["SABER_TRACKER"], *files], o)
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "generate [options] <type> <filename> [arg ...]", %~generate a meta data file (alias: "g")~
|
73
|
+
def generate(type, filename, *args)
|
74
|
+
require "saber/task/generate"
|
75
|
+
|
76
|
+
Task["generate"].invoke(:generate, [options["tracker"] || ENV["SABER_TRACKER"], type, filename, *args], o)
|
77
|
+
end
|
78
|
+
map "g" => "generate"
|
79
|
+
|
80
|
+
desc "fetch [options] <file ..>", "fetch files from seedbox."
|
81
|
+
def fetch(*names)
|
82
|
+
Fetcher.new.add_names(*names)
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "send1 <src ..> <dest>", "send files to seedbox"
|
86
|
+
def send1(*names)
|
87
|
+
require "saber/task/send"
|
88
|
+
|
89
|
+
Task["send"].invoke(:send1, names, o)
|
90
|
+
end
|
91
|
+
|
92
|
+
desc "make [options] <file ..>", "make a torent file and send it to local and/or remote watch directory"
|
93
|
+
def make(*files)
|
94
|
+
require "saber/task/make"
|
95
|
+
|
96
|
+
Task["make"].invoke(:make, [options["tracker"] || ENV["SABER_TRACKER"], *files], o)
|
58
97
|
end
|
59
98
|
end
|
60
99
|
end
|
@@ -2,35 +2,33 @@ require "xmlrpc/client"
|
|
2
2
|
require "net/ssh"
|
3
3
|
|
4
4
|
module Saber
|
5
|
-
class
|
6
|
-
|
7
|
-
|
5
|
+
class Fetcher
|
6
|
+
|
7
|
+
def add_names(*names)
|
8
|
+
files = retrive_files(*names)
|
9
|
+
add(*files)
|
8
10
|
end
|
9
11
|
|
10
12
|
def aria2_add(uris, o={}, &blk)
|
13
|
+
@aria2 = XMLRPC::Client.new2(Rc.aria2.rpc)
|
11
14
|
@aria2.call("aria2.addUri", uris, o, &blk)
|
12
15
|
end
|
13
16
|
|
14
17
|
def add(*files)
|
15
18
|
files.each { |file|
|
16
19
|
uri = "#{Rc.server.ftp}/#{file}"
|
17
|
-
gid = aria2_add([uri], :dir => Pa.dir2("#{Rc.p.
|
18
|
-
|
20
|
+
gid = aria2_add([uri], :dir => Pa.dir2("#{Rc.p.fetcher_download}/#{file}"))
|
21
|
+
Saber.ui.debug "DOWNLOAD #{gid} #{uri}"
|
19
22
|
}
|
20
23
|
end
|
21
24
|
|
22
|
-
def add_names(*names)
|
23
|
-
files = retrive_files(*names)
|
24
|
-
add(*files)
|
25
|
-
end
|
26
|
-
|
27
25
|
private
|
28
26
|
|
29
27
|
def retrive_files(*names)
|
30
28
|
files = []
|
31
29
|
Net::SSH.start(Rc.server.host, Rc.server.user) do |s|
|
32
30
|
name = "'#{names.join("' '")}'"
|
33
|
-
cmd = "cd #{Rc.
|
31
|
+
cmd = "cd #{Rc.p.remote_download} && find #{name} -type f"
|
34
32
|
|
35
33
|
rst = s.exec!(cmd)
|
36
34
|
if rst =~ /^find: `|^cd:cd:/
|