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.
Files changed (76) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +4 -0
  3. data/CHANGELOG.md +3 -0
  4. data/Gemfile +18 -8
  5. data/Gemfile.lock +72 -33
  6. data/Guardfile +4 -0
  7. data/README.md +192 -52
  8. data/Rakefile +46 -0
  9. data/bin/1saber +5 -3
  10. data/bin/saber +4 -0
  11. data/bin/saber.bib +3 -0
  12. data/bin/saber.what +3 -0
  13. data/extconf.rb +4 -1
  14. data/lib/saber.rb +7 -13
  15. data/lib/saber/autofetcher.rb +8 -0
  16. data/lib/saber/autofetcher/client.rb +66 -0
  17. data/lib/saber/autofetcher/server.rb +78 -0
  18. data/lib/saber/cli.rb +65 -26
  19. data/lib/saber/{downloader.rb → fetcher.rb} +9 -11
  20. data/lib/saber/mechanize_ext.rb +136 -0
  21. data/lib/saber/rc.rb +3 -21
  22. data/lib/saber/task.rb +26 -11
  23. data/lib/saber/task/base.rb +18 -0
  24. data/lib/saber/task/clean.rb +18 -0
  25. data/lib/saber/task/generate.rb +38 -0
  26. data/lib/saber/task/make.rb +44 -0
  27. data/lib/saber/task/send.rb +21 -0
  28. data/lib/saber/task/upload.rb +37 -0
  29. data/lib/saber/tracker.rb +28 -0
  30. data/lib/saber/tracker/base.rb +115 -2
  31. data/lib/saber/tracker/bb.rb +244 -0
  32. data/lib/saber/tracker/bib.rb +225 -0
  33. data/lib/saber/tracker/ptp.rb +100 -0
  34. data/lib/saber/tracker/what.rb +55 -7
  35. data/lib/saber/ui.rb +65 -22
  36. data/lib/saber/version.rb +1 -1
  37. data/rutorrent/init.js +8 -9
  38. data/rutorrent/plugin.info +1 -1
  39. data/saber.gemspec +14 -10
  40. data/spec/data/_saber/.gitkeep +0 -0
  41. data/spec/saber/downloader_spec.rb +5 -2
  42. data/spec/saber/task_spec.rb +16 -0
  43. data/spec/saber/tracker/bib_spec.rb +24 -0
  44. data/spec/spec_helper.rb +25 -0
  45. data/templates/_saberrc +36 -0
  46. data/templates/bb/anime.yml +6 -0
  47. data/templates/bb/application.yml +7 -0
  48. data/templates/bb/audiobook.yml +12 -0
  49. data/templates/bb/comic.yml +7 -0
  50. data/templates/bb/documentary.yml +26 -0
  51. data/templates/bb/ebook.yml +8 -0
  52. data/templates/bb/elearning_video.yml +7 -0
  53. data/templates/bb/game_console.yml +6 -0
  54. data/templates/bb/game_pc.yml +6 -0
  55. data/templates/bb/magazine.yml +6 -0
  56. data/templates/bb/misc.yml +6 -0
  57. data/templates/bb/movie.yml +26 -0
  58. data/templates/bb/music.yml +21 -0
  59. data/templates/bb/tv.yml +6 -0
  60. data/templates/bib/application.yml +9 -0
  61. data/templates/bib/article.yml +18 -0
  62. data/templates/bib/audiobook.yml +17 -0
  63. data/templates/bib/comic.yml +22 -0
  64. data/templates/bib/ebook.yml +20 -0
  65. data/templates/bib/journal.yml +18 -0
  66. data/templates/bib/magazine.yml +18 -0
  67. data/templates/ptp/movie.yml +63 -0
  68. data/templates/ptp/movie_add.yml +35 -0
  69. data/templates/what/ebook.yml +6 -0
  70. data/templates/what/music.yml +2 -0
  71. data/templates/what/music_add.yml +2 -0
  72. metadata +182 -26
  73. data/doc/Development.md +0 -3
  74. data/lib/saber/client.rb +0 -58
  75. data/lib/saber/server.rb +0 -70
  76. data/saber.watchr +0 -23
@@ -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
- ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
4
- require "bundler/setup"
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
- load File.expand_path("../saber", __FILE__)
7
+ require "bundler/setup"
8
+ load File.join(dir, "bin/saber")
data/bin/saber CHANGED
@@ -7,6 +7,10 @@ rescue Saber::Error => e
7
7
  Saber.ui.error e.message
8
8
  Saber.ui.debug e.backtrace.join("\n")
9
9
  exit 1
10
+ rescue Interrupt => e
11
+ Saber.ui.error "\nQuitting..."
12
+ Saber.ui.debug e.backtrace.join("\n")
13
+ exit 1
10
14
  rescue Exception => e
11
15
  raise e
12
16
  exit 1
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ SABER_TRACKER=bib saber $*
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ SABER_TRACKER=what saber $*
data/extconf.rb CHANGED
@@ -2,6 +2,9 @@
2
2
  require "fileutils"
3
3
  require "mkmf"
4
4
 
5
- FileUtils.install File.expand_path("../bin/saber-drb_add", __FILE__), Gem.bindir
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")
@@ -1,27 +1,21 @@
1
- libdir = File.dirname(__FILE__); $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
2
-
1
+ require "pd"
3
2
  require "pa"
4
3
  require "optimism"
5
- require "retort"
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 :Downloader, "saber/downloader"
17
- autoload :Server, "saber/server"
18
- autoload :Client, "saber/client"
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", "/etc/saber"
18
+ Rc = Optimism.require "saber/rc", "~/.saberrc"
25
19
 
26
20
  class << self
27
21
  attr_accessor :ui
@@ -0,0 +1,8 @@
1
+ module Saber
2
+ module AutoFetcher
3
+ autoload :Server, "saber/autofetcher/server"
4
+ autoload :Client, "saber/autofetcher/client"
5
+ autoload :DRbServer, "saber/autofetcher/server"
6
+ autoload :DRbClient, "saber/autofetcher/client"
7
+ end
8
+ end
@@ -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
@@ -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", :type => :boolean, :banner => "Disable colorization in output"
9
- class_option "verbose", :aliases => "-V", :type => :boolean, :banner => "Enable verbose output mode"
10
- class_option "log", :banner => "log file", :type => :string
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
- the_shell = (options["no-color"] ? Thor::Shell::Basic.new : shell)
18
- Saber.ui = UI::Shell.new(the_shell)
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
- Task.clean
25
- end
37
+ require "saber/task/clean"
26
38
 
27
- desc "add <file ..>", "begin download file or directory via aria2 daemon."
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
- require "logger"
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
- require "logger"
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 <ids> [label]", "add a file to saber-server daemon via drb"
51
- # drb_add "id1,id2", "foo"
52
- def drb_add(ids_str, label=Rc.label)
53
- return if label != Rc.label
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 Downloader
6
- def initialize
7
- @aria2 = XMLRPC::Client.new2(Rc.aria2.rpc)
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.download}/#{file}"))
18
- $log.debug "\nDOWNLOAD #{gid} #{uri}"
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.server.download.p} && find #{name} -type f"
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:/