saber 0.0.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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:/