saber 0.0.7 → 1.0.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.
- 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:/
|