autonzb 0.5.4
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 +25 -0
- data/LICENSE +20 -0
- data/README.markdown +44 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/asset/failure.png +0 -0
- data/autonzb.gemspec +73 -0
- data/lib/imdb.rb +80 -0
- data/lib/inspector.rb +215 -0
- data/lib/movie.rb +209 -0
- data/lib/sites/newzleech/nfo.rb +35 -0
- data/lib/sites/newzleech/nzb.rb +100 -0
- data/lib/sites/nzbs/mechanize_hack.rb +41 -0
- data/lib/sites/nzbs/nfo.rb +36 -0
- data/lib/sites/nzbs/nzb.rb +120 -0
- data/spec/autonzb_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- metadata +121 -0
data/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## MAC OS
|
|
2
|
+
.DS_Store
|
|
3
|
+
|
|
4
|
+
## TEXTMATE
|
|
5
|
+
*.tmproj
|
|
6
|
+
tmtags
|
|
7
|
+
|
|
8
|
+
## EMACS
|
|
9
|
+
*~
|
|
10
|
+
\#*
|
|
11
|
+
.\#*
|
|
12
|
+
|
|
13
|
+
## VIM
|
|
14
|
+
*.swp
|
|
15
|
+
|
|
16
|
+
## PROJECT::GENERAL
|
|
17
|
+
coverage
|
|
18
|
+
rdoc
|
|
19
|
+
pkg
|
|
20
|
+
|
|
21
|
+
## PROJECT::SPECIFIC
|
|
22
|
+
autonzb
|
|
23
|
+
pkg
|
|
24
|
+
manifest
|
|
25
|
+
tasks
|
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2009 Pirate
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# AutoNZB
|
|
2
|
+
|
|
3
|
+
Ruby tool to automatically download x264 HD nzb movies files from newzleech.com
|
|
4
|
+
Currently only english and french subtitles are supported, but it's super easy to add your own language.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
sudo gem install pirate-autonzb --source http://gems.github.com
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
In your terminal:
|
|
13
|
+
|
|
14
|
+
autonzb -d /path/of/download/nzb/directory
|
|
15
|
+
|
|
16
|
+
Will download new x264 HD movies nzb from newzleech.com, with imdb score >= 7.0, year >= 1950 and nzb age <= 160 days
|
|
17
|
+
|
|
18
|
+
autonzb -d /path/of/download/nzb/directory -backup /path/of/backuped/already/downloaded/nzb
|
|
19
|
+
|
|
20
|
+
-backup option it's very useful to prevent useless re-download of nzb already downloaded
|
|
21
|
+
|
|
22
|
+
autonzb -d /path/of/download/nzb/directory -movies /path/with/already/downloaded/movies -age 1 -imdb 7.5 -year 1980 -srt fr,en
|
|
23
|
+
|
|
24
|
+
Will download only new nzb of the day with imdb score >= 7.5, year >= 1980 and subtitles french or english (and unknown srt).
|
|
25
|
+
The -movies setting prevents already owned movies to be re-downloaded (only if the owned movie is 'better' than the new release),
|
|
26
|
+
movies folder need to follow the name convention (especially {imdb_id})
|
|
27
|
+
|
|
28
|
+
more details with:
|
|
29
|
+
|
|
30
|
+
autonzb -h
|
|
31
|
+
|
|
32
|
+
## Folder Name Convention
|
|
33
|
+
|
|
34
|
+
AutoNZB use (and needs if you want to use -movies options) specific folders name for your movies:
|
|
35
|
+
|
|
36
|
+
name of the movie (year) tag(s) format source sound encoding lang {imdb_id} [srt(s)]
|
|
37
|
+
|
|
38
|
+
Burn After Reading (2008) PROPER 1080p BluRay DTS x264 {tt0887883} [fr,en]
|
|
39
|
+
Le Fabuleux Destin d'Amelie Poulain (2001) 720p BluRay x264 FRENCH {tt0211915} [en]
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
## Copyright
|
|
43
|
+
|
|
44
|
+
Copyright (c) 2009 Pirate. See LICENSE for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'jeweler'
|
|
6
|
+
Jeweler::Tasks.new do |gem|
|
|
7
|
+
gem.name = "autonzb"
|
|
8
|
+
gem.summary = "Automatically download x264 HD nzb movies files."
|
|
9
|
+
gem.description = "Ruby tool to automatically download x264 HD nzb movies files from newzleech.com & nzbs.org"
|
|
10
|
+
gem.email = "pirate.2061@gmail.com"
|
|
11
|
+
gem.homepage = "http://github.com/pirate/autonzb"
|
|
12
|
+
gem.authors = ["Pirate"]
|
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
15
|
+
# gem.ignore_pattern = ["tmp/*", "script/*"]
|
|
16
|
+
gem.add_dependency "hpricot"
|
|
17
|
+
gem.add_dependency "optiflag"
|
|
18
|
+
gem.add_dependency "rubyzip"
|
|
19
|
+
gem.add_dependency "htmlentities"
|
|
20
|
+
gem.default_executable = "bin/autonzb"
|
|
21
|
+
end
|
|
22
|
+
Jeweler::GemcutterTasks.new
|
|
23
|
+
rescue LoadError
|
|
24
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
require 'spec/rake/spectask'
|
|
28
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
|
30
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
34
|
+
spec.libs << 'lib' << 'spec'
|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
36
|
+
spec.rcov = true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
task :spec => :check_dependencies
|
|
40
|
+
|
|
41
|
+
task :default => :spec
|
|
42
|
+
|
|
43
|
+
require 'rake/rdoctask'
|
|
44
|
+
Rake::RDocTask.new do |rdoc|
|
|
45
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
|
46
|
+
|
|
47
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
48
|
+
rdoc.title = "test-gem #{version}"
|
|
49
|
+
rdoc.rdoc_files.include('README*')
|
|
50
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
51
|
+
end
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.4
|
data/asset/failure.png
ADDED
|
Binary file
|
data/autonzb.gemspec
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Generated by jeweler
|
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
|
4
|
+
# -*- encoding: utf-8 -*-
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = %q{autonzb}
|
|
8
|
+
s.version = "0.5.4"
|
|
9
|
+
|
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
|
+
s.authors = ["Pirate"]
|
|
12
|
+
s.date = %q{2009-11-01}
|
|
13
|
+
s.default_executable = %q{bin/autonzb}
|
|
14
|
+
s.description = %q{Ruby tool to automatically download x264 HD nzb movies files from newzleech.com & nzbs.org}
|
|
15
|
+
s.email = %q{pirate.2061@gmail.com}
|
|
16
|
+
s.executables = ["autonzb"]
|
|
17
|
+
s.extra_rdoc_files = [
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"README.markdown"
|
|
20
|
+
]
|
|
21
|
+
s.files = [
|
|
22
|
+
".gitignore",
|
|
23
|
+
"README.markdown",
|
|
24
|
+
"Rakefile",
|
|
25
|
+
"VERSION",
|
|
26
|
+
"asset/failure.png",
|
|
27
|
+
"autonzb.gemspec",
|
|
28
|
+
"bin/autonzb",
|
|
29
|
+
"lib/imdb.rb",
|
|
30
|
+
"lib/inspector.rb",
|
|
31
|
+
"lib/movie.rb",
|
|
32
|
+
"lib/sites/newzleech/nfo.rb",
|
|
33
|
+
"lib/sites/newzleech/nzb.rb",
|
|
34
|
+
"lib/sites/nzbs/mechanize_hack.rb",
|
|
35
|
+
"lib/sites/nzbs/nfo.rb",
|
|
36
|
+
"lib/sites/nzbs/nzb.rb"
|
|
37
|
+
]
|
|
38
|
+
s.homepage = %q{http://github.com/pirate/autonzb}
|
|
39
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
40
|
+
s.require_paths = ["lib"]
|
|
41
|
+
s.rubygems_version = %q{1.3.5}
|
|
42
|
+
s.summary = %q{Automatically download x264 HD nzb movies files.}
|
|
43
|
+
s.test_files = [
|
|
44
|
+
"spec/autonzb_spec.rb",
|
|
45
|
+
"spec/spec_helper.rb"
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
if s.respond_to? :specification_version then
|
|
49
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
50
|
+
s.specification_version = 3
|
|
51
|
+
|
|
52
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
53
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
|
54
|
+
s.add_runtime_dependency(%q<hpricot>, [">= 0"])
|
|
55
|
+
s.add_runtime_dependency(%q<optiflag>, [">= 0"])
|
|
56
|
+
s.add_runtime_dependency(%q<rubyzip>, [">= 0"])
|
|
57
|
+
s.add_runtime_dependency(%q<htmlentities>, [">= 0"])
|
|
58
|
+
else
|
|
59
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
|
60
|
+
s.add_dependency(%q<hpricot>, [">= 0"])
|
|
61
|
+
s.add_dependency(%q<optiflag>, [">= 0"])
|
|
62
|
+
s.add_dependency(%q<rubyzip>, [">= 0"])
|
|
63
|
+
s.add_dependency(%q<htmlentities>, [">= 0"])
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
|
67
|
+
s.add_dependency(%q<hpricot>, [">= 0"])
|
|
68
|
+
s.add_dependency(%q<optiflag>, [">= 0"])
|
|
69
|
+
s.add_dependency(%q<rubyzip>, [">= 0"])
|
|
70
|
+
s.add_dependency(%q<htmlentities>, [">= 0"])
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
data/lib/imdb.rb
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'cgi'
|
|
2
|
+
require 'hpricot'
|
|
3
|
+
require 'open-uri'
|
|
4
|
+
require 'htmlentities'
|
|
5
|
+
|
|
6
|
+
class IMDB
|
|
7
|
+
|
|
8
|
+
attr_accessor :link, :doc, :id
|
|
9
|
+
|
|
10
|
+
def initialize(name, year = nil, link = nil)
|
|
11
|
+
# $stdout.print 'i'
|
|
12
|
+
@try = 3
|
|
13
|
+
@name, @year, @link = name, year, link
|
|
14
|
+
@coder = HTMLEntities.new
|
|
15
|
+
set_doc
|
|
16
|
+
set_id
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def score
|
|
20
|
+
if @doc && score_text = @doc.search("div.meta b").first
|
|
21
|
+
score_text.inner_html.match(/(.*)\/10/)[1].to_f
|
|
22
|
+
else
|
|
23
|
+
0
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def year
|
|
28
|
+
@doc ? @doc.search("title").inner_html.match(/\s\(([0-9]{4})/)[1].to_i : @year.to_i
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def name
|
|
32
|
+
$KCODE = 'utf-8'
|
|
33
|
+
@doc ? @coder.decode(@doc.search("title").inner_html.match(/(.*)\s\(/u)[1]) : @name
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def set_doc
|
|
39
|
+
if @link
|
|
40
|
+
@doc = Hpricot(open(@link.gsub(/\/\s*$/,'')))
|
|
41
|
+
@id = @link.match(/tt[0-9]+/)[0]
|
|
42
|
+
else
|
|
43
|
+
query = "#{@name} (#{@year})"
|
|
44
|
+
search_url = "http://www.imdb.com/find?q=#{CGI::escape(query)}"
|
|
45
|
+
doc = Hpricot(open(search_url))
|
|
46
|
+
case doc.search("title").inner_html
|
|
47
|
+
when "IMDb Title Search", "IMDb Search" # search result page
|
|
48
|
+
if !doc.search("b[text()*='Media from'] a").empty?
|
|
49
|
+
imdb_id = doc.search("b[text()*='Media from'] a").first[:href]
|
|
50
|
+
movie_url = "http://www.imdb.com#{imdb_id}"
|
|
51
|
+
elsif !doc.search("td[@valign='top'] a[@href^='/title/tt']").empty?
|
|
52
|
+
imdb_id = doc.search("td[@valign='top'] a[@href^='/title/tt']").first[:href]
|
|
53
|
+
movie_url = "http://www.imdb.com#{imdb_id}"
|
|
54
|
+
else
|
|
55
|
+
movie_url = nil
|
|
56
|
+
end
|
|
57
|
+
if movie_url
|
|
58
|
+
@doc = Hpricot(open(movie_url))
|
|
59
|
+
@id = movie_url.match(/tt[0-9]+/)[0]
|
|
60
|
+
end
|
|
61
|
+
else # direct in movie page
|
|
62
|
+
@doc = doc
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
rescue
|
|
66
|
+
if @try > 0
|
|
67
|
+
@try -= 1
|
|
68
|
+
$stdout.print '*'
|
|
69
|
+
sleep 2
|
|
70
|
+
set_doc #retry
|
|
71
|
+
else
|
|
72
|
+
@doc = nil
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def set_id
|
|
77
|
+
@id ||= doc.search("a[@href*='/title/tt']").first[:href].match(/tt[0-9]+/)[0] if doc
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
data/lib/inspector.rb
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'movie')
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'sites', 'newzleech', 'nzb')
|
|
3
|
+
require File.join(File.dirname(__FILE__), 'sites', 'nzbs', 'nzb')
|
|
4
|
+
|
|
5
|
+
class Inspector
|
|
6
|
+
|
|
7
|
+
attr_accessor :download_path, :backup_path, :movies, :nzbs
|
|
8
|
+
|
|
9
|
+
def initialize(download_path, options = {})
|
|
10
|
+
@download_path = download_path.gsub(/\/$/,'')
|
|
11
|
+
@paths = options[:movie_paths] ? options[:movie_paths].split(',').map { |p| p.gsub(/\/$/,'') } : []
|
|
12
|
+
@options = options
|
|
13
|
+
@options[:srt] = @options[:srt] ? (@options[:srt].split(',') - ["unknown"] + ['unknown']).uniq : nil
|
|
14
|
+
@options[:imdb_score] = @options[:imdb_score] ? @options[:imdb_score].to_f : 7.0
|
|
15
|
+
@options[:year] = @options[:year] ? @options[:year].to_i : 1950
|
|
16
|
+
|
|
17
|
+
@movies = []
|
|
18
|
+
initialize_movies
|
|
19
|
+
|
|
20
|
+
if @options[:backup_path]
|
|
21
|
+
@backup_path = @options[:backup_path].gsub(/\/$/,'')
|
|
22
|
+
@nzbs = []
|
|
23
|
+
initialize_nzbs
|
|
24
|
+
@movies = @nzbs + @movies
|
|
25
|
+
load_age_from_yaml
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
$stdout.print "Movie criteria: imdb score >= #{@options[:imdb_score]}, year >= #{@options[:year]}#{" and srt [#{@options[:srt].join(',')}]" if @options[:srt]}\n"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def search_and_download
|
|
32
|
+
if @options[:login] && @options[:pass]
|
|
33
|
+
site = Nzbs::NZB.new(@options)
|
|
34
|
+
parse_nzbs(site)
|
|
35
|
+
end
|
|
36
|
+
site = Newzleech::NZB.new(@options)
|
|
37
|
+
parse_nzbs(site)
|
|
38
|
+
|
|
39
|
+
if backup_path
|
|
40
|
+
keep_only_best_nzbs
|
|
41
|
+
set_age_on_yaml
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def parse_nzbs(site)
|
|
46
|
+
site.nzbs.each do |movie|
|
|
47
|
+
$stdout.print "#{movie.dirname}, imdb score: #{movie.score}, age: #{movie.age} day(s)\n"
|
|
48
|
+
if need?(movie)
|
|
49
|
+
$stdout.print " => DOWNLOAD: #{movie.name} (#{movie.year})\n"
|
|
50
|
+
download(site, movie)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
$stdout.print "No nzb found, maybe change -age or -page setting\n" if site.nzbs.empty?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def download(site, movie)
|
|
57
|
+
Tempfile.open("movie.nzb") do |tempfile|
|
|
58
|
+
tempfile.write(site.download(movie)) # download nzb
|
|
59
|
+
tempfile.close
|
|
60
|
+
File.copy(tempfile.path, "#{backup_path}/#{movie.dirname}.nzb") if backup_path
|
|
61
|
+
File.move(tempfile.path, "#{download_path}/#{movie.dirname}.nzb")
|
|
62
|
+
end
|
|
63
|
+
@movies << movie
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def need?(movie, movies = @movies, not_validate = false, log = true)
|
|
67
|
+
if not_validate || valid?(movie)
|
|
68
|
+
$stdout.print " => movie has required criteria " if log
|
|
69
|
+
if m = movies.detect { |m| m == movie }
|
|
70
|
+
$stdout.print "but is already owned " if log
|
|
71
|
+
if srt_score(movie) > srt_score(m)
|
|
72
|
+
$stdout.print "but new movie has better subtitle: [#{movie.srt.join(',')}]\n" if log
|
|
73
|
+
true
|
|
74
|
+
elsif srt_score(movie) == srt_score(m)
|
|
75
|
+
if format_score(movie) > format_score(m)
|
|
76
|
+
$stdout.print "but new movie has better format: #{movie.format}\n" if log
|
|
77
|
+
true
|
|
78
|
+
elsif format_score(movie) == format_score(m)
|
|
79
|
+
if source_score(movie) > source_score(m)
|
|
80
|
+
$stdout.print "but new movie has better source: #{movie.source}\n" if log
|
|
81
|
+
true
|
|
82
|
+
elsif source_score(movie) == source_score(m)
|
|
83
|
+
if sound_score(movie) > sound_score(m)
|
|
84
|
+
$stdout.print "but new movie has better sound: #{movie.sound}\n" if log
|
|
85
|
+
true
|
|
86
|
+
else
|
|
87
|
+
$stdout.print "with same srt, format, source and sound\n" if log
|
|
88
|
+
false
|
|
89
|
+
end
|
|
90
|
+
else
|
|
91
|
+
$stdout.print "with same srt, format and better source: #{m.source}\n" if log
|
|
92
|
+
false
|
|
93
|
+
end
|
|
94
|
+
else
|
|
95
|
+
$stdout.print "with same srt and better format: #{m.format}\n" if log
|
|
96
|
+
false
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
$stdout.print "with better subtitle: [#{m.srt.join(',')}]\n" if log
|
|
100
|
+
false
|
|
101
|
+
end
|
|
102
|
+
else
|
|
103
|
+
$stdout.print "and is not already owned\n" if log
|
|
104
|
+
true
|
|
105
|
+
end
|
|
106
|
+
else
|
|
107
|
+
$stdout.print " => movie doesn't have required criteria\n" if log
|
|
108
|
+
false
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def self.growl(title, msg, pri = 0)
|
|
113
|
+
system("/usr/local/bin/growlnotify -w -n autonzb --image #{File.dirname(__FILE__) + "/../asset/failure.png"} -p #{pri} -m #{msg.inspect} #{title} &")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
def initialize_movies
|
|
119
|
+
@paths.each do |path|
|
|
120
|
+
old_movies_size = @movies.size
|
|
121
|
+
base_dir = clean_dir(Dir.new(path))
|
|
122
|
+
base_dir.each do |movie|
|
|
123
|
+
movie_path = "#{path}/#{movie}"
|
|
124
|
+
@movies << Movie.new(movie, :path => movie_path) if File.directory?(movie_path)
|
|
125
|
+
end
|
|
126
|
+
$stdout.print "Found #{@movies.size - old_movies_size} movie(s) in #{path}\n"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def initialize_nzbs
|
|
131
|
+
base_dir = clean_dir(Dir.new(@backup_path))
|
|
132
|
+
base_dir.each do |nzb|
|
|
133
|
+
nzb_path = "#{@backup_path}/#{nzb}"
|
|
134
|
+
@nzbs << Movie.new(nzb, :path => nzb_path) if File.extname(nzb_path) == '.nzb'
|
|
135
|
+
end
|
|
136
|
+
$stdout.print "Found #{@nzbs.size} backuped nzb(s) in #{@backup_path}\n"
|
|
137
|
+
rescue => e
|
|
138
|
+
$stdout.print "Problem with backup nzb: #{e}\n"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def clean_dir(dir)
|
|
142
|
+
dir.select { |e| !["..", ".", ".DS_Store", ".com.apple.timemachine.supported", "Icon\r"].include?(e) }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def valid?(movie)
|
|
146
|
+
(@options[:srt].nil? || (((@options[:srt] - movie.srt).size < @options[:srt].size)) || movie.lang == 'FRENCH') &&
|
|
147
|
+
movie.year != nil && movie.year >= @options[:year] &&
|
|
148
|
+
movie.score != nil && movie.score >= @options[:imdb_score]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def srt_score(movie)
|
|
152
|
+
if @options[:srt]
|
|
153
|
+
srts = @options[:srt].reverse
|
|
154
|
+
movie.srt.inject(-1) do |score, srt|
|
|
155
|
+
s = (i = srts.index(srt)) ? i : -1
|
|
156
|
+
score = s if s > score
|
|
157
|
+
score
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
0
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def format_score(movie)
|
|
165
|
+
case movie.format
|
|
166
|
+
when '1080p'; 2
|
|
167
|
+
when '720p'; 1
|
|
168
|
+
else; 0
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def source_score(movie)
|
|
173
|
+
case movie.format
|
|
174
|
+
when 'BluRay'; 4
|
|
175
|
+
when 'HDDVD'; 3
|
|
176
|
+
when 'HDTV'; 2
|
|
177
|
+
when 'DVD'; 1
|
|
178
|
+
else; 0
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def sound_score(movie)
|
|
183
|
+
movie.format == 'DTS' ? 1 : 0
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def keep_only_best_nzbs
|
|
187
|
+
size = 0
|
|
188
|
+
@nzbs.each do |nzb|
|
|
189
|
+
nzbs = @nzbs.select { |item| item.path != nzb.path }
|
|
190
|
+
unless need?(nzb, nzbs, true, false)
|
|
191
|
+
File.delete(nzb.path)
|
|
192
|
+
size += 1
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
if size > 0
|
|
196
|
+
$stdout.print "#########################################################################\n"
|
|
197
|
+
$stdout.print "Deleted #{size} useless backuped nzb(s) (keep only the best nzb by movie)\n"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def load_age_from_yaml
|
|
202
|
+
yml_file = "#{backup_path}/options.yml"
|
|
203
|
+
yml_options = File.exist?(yml_file) ? YAML.load_file(yml_file) : {}
|
|
204
|
+
if yml_age = yml_options['age']
|
|
205
|
+
age = sprintf("%.1f", ((Time.now.tv_sec - yml_age.to_i) / 60.0 / 60.0 / 24.0)).to_f
|
|
206
|
+
@options[:age] = age if age > 0
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def set_age_on_yaml
|
|
211
|
+
yml_file = "#{backup_path}/options.yml"
|
|
212
|
+
File.open(yml_file, "w") { |f| f.write(({ 'age' => Time.now.tv_sec }).to_yaml) }
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
end
|
data/lib/movie.rb
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'imdb')
|
|
2
|
+
|
|
3
|
+
class Movie
|
|
4
|
+
include Comparable
|
|
5
|
+
|
|
6
|
+
attr_accessor :path, :name, :format, :source, :sound, :encoding, :year, :srt, :lang, :score, :tags, :age,
|
|
7
|
+
:imdb_link, :imdb_id, :nzb_link, :nfo
|
|
8
|
+
|
|
9
|
+
def initialize(raw_name, attributes = {})
|
|
10
|
+
@raw_name = raw_name.gsub(/\.|\_/,' ')
|
|
11
|
+
attributes.each { |k,v| self.send("#{k}=", v) }
|
|
12
|
+
@srt, @tags = [], []
|
|
13
|
+
|
|
14
|
+
# for info set with nzbs title
|
|
15
|
+
if name && year && score
|
|
16
|
+
@info_get_from_title = true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
set_name
|
|
20
|
+
set_year
|
|
21
|
+
set_format
|
|
22
|
+
set_source
|
|
23
|
+
set_sound
|
|
24
|
+
set_srt
|
|
25
|
+
set_lang
|
|
26
|
+
set_encoding
|
|
27
|
+
set_tags
|
|
28
|
+
|
|
29
|
+
set_imdb_id
|
|
30
|
+
set_data_from_imdb unless path || @info_get_from_title
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def score
|
|
34
|
+
@score ||= imdb.score
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def dirname
|
|
38
|
+
"#{name} (#{year}) #{tags.join(' ')} #{format} #{source} #{sound} #{encoding} #{lang} {#{imdb_id}} [#{srt.join(',')}]".gsub(/\s+|\//,' ')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def <=>(other_movie)
|
|
42
|
+
if imdb_id && other_movie.imdb_id
|
|
43
|
+
imdb_id <=> other_movie.imdb_id
|
|
44
|
+
else
|
|
45
|
+
"#{name} #{year}".downcase <=> "#{other_movie.name} #{other_movie.year}".downcase
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def imdb
|
|
52
|
+
@imdb ||= IMDB.new(name, year, imdb_link)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def imdb_link
|
|
56
|
+
@imdb_link || (imdb_id && "http://imdb.com/title/#{imdb_id}")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def set_imdb_id
|
|
60
|
+
if imdb_link
|
|
61
|
+
@imdb_id = imdb_link.match(/tt[0-9]+/)[0]
|
|
62
|
+
elsif matched = @raw_name.match(/\{(tt[0-9]+)\}/)
|
|
63
|
+
@imdb_id = matched[1]
|
|
64
|
+
elsif imdb
|
|
65
|
+
@imdb_id = imdb.id
|
|
66
|
+
add_imdb_id_to_file if path
|
|
67
|
+
else
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def set_name
|
|
73
|
+
if name.nil?
|
|
74
|
+
raw_name = @raw_name.gsub(/\(|\)|\[|\]|\{|\}|\//, ' ')
|
|
75
|
+
if matched = raw_name.match(/(.*)(19[0-9]{2}|20[0-9]{2})[^p]/)
|
|
76
|
+
@name = matched[1]
|
|
77
|
+
elsif matched = raw_name.match(/(.*)1080p/i)
|
|
78
|
+
@name = matched[1]
|
|
79
|
+
elsif matched = raw_name.match(/(.*)720p/i)
|
|
80
|
+
@name = matched[1]
|
|
81
|
+
else
|
|
82
|
+
@name = ''
|
|
83
|
+
end
|
|
84
|
+
@name.gsub!(/REPACK|LIMITED|UNRATED|PROPER|REPOST|Directors\sCut/iu,'')
|
|
85
|
+
@name.gsub!(/^\s+|\s+$/u,'')
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def set_year
|
|
90
|
+
if year.nil?
|
|
91
|
+
if matched = @raw_name.match(/19[0-9]{2}|20[0-9]{2}/)
|
|
92
|
+
@year = matched[0].to_i
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def set_format
|
|
98
|
+
@format = case @raw_name
|
|
99
|
+
when /1080p/i
|
|
100
|
+
'1080p'
|
|
101
|
+
when /720p/i
|
|
102
|
+
'720p'
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def set_encoding
|
|
107
|
+
@encoding = case @raw_name
|
|
108
|
+
when /x264/i
|
|
109
|
+
'x264'
|
|
110
|
+
when /VC1/i
|
|
111
|
+
'VC1'
|
|
112
|
+
when /PS3/i
|
|
113
|
+
'PS3'
|
|
114
|
+
when /divx/i
|
|
115
|
+
'DIVX'
|
|
116
|
+
when /xvid/i
|
|
117
|
+
'XVID'
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def set_source
|
|
122
|
+
@source = case @raw_name
|
|
123
|
+
when /Blu\s?Ray|Blu-Ray|BDRip/i
|
|
124
|
+
'BluRay'
|
|
125
|
+
when /HDDVD/i
|
|
126
|
+
'HDDVD'
|
|
127
|
+
when /HDTV/i
|
|
128
|
+
'HDTV'
|
|
129
|
+
when /DVD/i
|
|
130
|
+
'DVD'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def set_sound
|
|
135
|
+
@sound = case @raw_name
|
|
136
|
+
when /DTS/i
|
|
137
|
+
'DTS'
|
|
138
|
+
when /AC3/i
|
|
139
|
+
'AC3'
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def set_srt
|
|
144
|
+
if nfo
|
|
145
|
+
@srt = nfo.srt
|
|
146
|
+
elsif matched = @raw_name.match(/\[(.*)\]/)
|
|
147
|
+
srts = matched[1].split(',')
|
|
148
|
+
if srts.empty?
|
|
149
|
+
@srt << 'none'
|
|
150
|
+
else
|
|
151
|
+
srts.each { |srt| @srt << srt }
|
|
152
|
+
end
|
|
153
|
+
else
|
|
154
|
+
@srt << 'unknown'
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def set_lang
|
|
159
|
+
@lang = case @raw_name
|
|
160
|
+
when /FRENCH/i
|
|
161
|
+
'FRENCH'
|
|
162
|
+
when /GERMAN/i
|
|
163
|
+
'GERMAN'
|
|
164
|
+
when /DANISH/i
|
|
165
|
+
'DANISH'
|
|
166
|
+
when /NORDIC/i
|
|
167
|
+
'NORDIC'
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def set_tags
|
|
172
|
+
@tags << 'REPACK' if @raw_name =~ /REPACK/i
|
|
173
|
+
@tags << 'LIMITED' if @raw_name =~ /LIMITED/i
|
|
174
|
+
@tags << 'UNRATED' if @raw_name =~ /UNRATED/i
|
|
175
|
+
@tags << 'PROPER' if @raw_name =~ /PROPER/i
|
|
176
|
+
@tags << 'REPOST' if @raw_name =~ /REPOST/i
|
|
177
|
+
@tags << 'OUTDATED' if @raw_name =~ /OUTDATED/i
|
|
178
|
+
@tags << 'Directors Cut' if @raw_name =~ /Directors\sCut|DirCut/i
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def set_data_from_imdb
|
|
182
|
+
@name = imdb.name
|
|
183
|
+
imdb_year = imdb.year
|
|
184
|
+
if !imdb_year.nil? && imdb_year != 0
|
|
185
|
+
@year = imdb_year
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def add_imdb_id_to_file
|
|
190
|
+
dir_name = File.dirname(path)
|
|
191
|
+
if File.directory?(path)
|
|
192
|
+
base_name = File.basename(path)
|
|
193
|
+
ext_name = ''
|
|
194
|
+
else
|
|
195
|
+
ext_name = path.include?('.nzb') ? '.nzb' : File.extname(path)
|
|
196
|
+
base_name = File.basename(path, ext_name)
|
|
197
|
+
end
|
|
198
|
+
if matched = base_name.match(/^(.*)\s(\[{1}.*\]{1})$/)
|
|
199
|
+
base_name_without_srts = matched[1]
|
|
200
|
+
srts = matched[2]
|
|
201
|
+
new_base_name = "#{base_name_without_srts} {#{imdb_id}} #{srts}#{ext_name}"
|
|
202
|
+
else
|
|
203
|
+
new_base_name = "#{base_name} {#{imdb_id}}#{ext_name}"
|
|
204
|
+
end
|
|
205
|
+
File.rename(path, "#{dir_name}/#{new_base_name}")
|
|
206
|
+
$stdout.print "Added {#{imdb_id}} (imdb id) => #{dir_name}/#{new_base_name}\n"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'open-uri'
|
|
2
|
+
|
|
3
|
+
module Newzleech
|
|
4
|
+
class Nfo
|
|
5
|
+
|
|
6
|
+
attr_accessor :srt, :imdb_link
|
|
7
|
+
|
|
8
|
+
def initialize(url)
|
|
9
|
+
@nfo = open(url.gsub(/\/$/,'')).read
|
|
10
|
+
@srt = []
|
|
11
|
+
|
|
12
|
+
parse_nfo
|
|
13
|
+
@srt.uniq!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
# searching for subtitles languages info & imdb link
|
|
19
|
+
def parse_nfo
|
|
20
|
+
@nfo.split(/\n/).each do |line|
|
|
21
|
+
case line
|
|
22
|
+
when /subtitle|sub/i
|
|
23
|
+
@srt << 'fr' if line =~ /fr|fre|french/i
|
|
24
|
+
@srt << 'en' if line =~ /en|eng|english/i
|
|
25
|
+
# TODO add more language parsing here
|
|
26
|
+
@srt << 'none' if line =~ /none/i
|
|
27
|
+
when /imdb\.com\/title\//
|
|
28
|
+
@imdb_link = (matched = line.match(/imdb.com\/title\/(tt[0-9]+)/)) && "http://imdb.com/title/#{matched[1]}"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
@srt << 'unknown' if @srt.empty?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'open-uri'
|
|
2
|
+
require 'hpricot'
|
|
3
|
+
require 'zip/zip'
|
|
4
|
+
|
|
5
|
+
require File.join(File.dirname(__FILE__), 'nfo')
|
|
6
|
+
|
|
7
|
+
module Newzleech
|
|
8
|
+
class NZB
|
|
9
|
+
|
|
10
|
+
URL = 'http://www.newzleech.com'
|
|
11
|
+
DAYS_BY_PAGE = 1.7
|
|
12
|
+
|
|
13
|
+
attr_accessor :nzbs
|
|
14
|
+
|
|
15
|
+
def initialize(options = {})
|
|
16
|
+
@options = options
|
|
17
|
+
@options[:age] ||= 160
|
|
18
|
+
@options[:pages] ||= ((@options[:age].to_f + DAYS_BY_PAGE) / DAYS_BY_PAGE).ceil
|
|
19
|
+
|
|
20
|
+
@nzb_urls = []
|
|
21
|
+
@nzbs = []
|
|
22
|
+
|
|
23
|
+
(1..(@options[:pages].to_i)).each do |page|
|
|
24
|
+
@nzb_urls << "#{URL}?group=143&minage=&age=160&min=4000&max=max&q=&m=search&adv=1&offset=#{(page.to_i - 1) * 60}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
parse_newzleech
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def download(movie)
|
|
31
|
+
open(movie.nzb_link).read
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def parse_newzleech
|
|
37
|
+
$stdout.print "Parsing #{URL} for new x264 HD nzb movies, with age <= #{@options[:age]}, in last #{@options[:pages]} page(s)\n"
|
|
38
|
+
@nzb_urls.each do |url|
|
|
39
|
+
doc = Hpricot(open(url))
|
|
40
|
+
doc.search("table.contentt").each do |table|
|
|
41
|
+
raw_name = raw_name(table)
|
|
42
|
+
if nfo_link = nfo_link(table)
|
|
43
|
+
nfo = Nfo.new(nfo_link)
|
|
44
|
+
imdb_link = nfo.imdb_link
|
|
45
|
+
else
|
|
46
|
+
imdb_link = imdb_link(table)
|
|
47
|
+
end
|
|
48
|
+
if raw_name && (imdb_link || (raw_name = find_clean_nzb_name(raw_name))) && raw_name.include?('x264')
|
|
49
|
+
age = parse_age(table.search("td.age").first.inner_html) # get age of the nzb
|
|
50
|
+
if age <= @options[:age].to_f
|
|
51
|
+
raw_name = clean_raw_name(raw_name)
|
|
52
|
+
movie = Movie.new(raw_name, :nfo => nfo, :imdb_link => imdb_link, :nzb_link => nzb_link(table), :age => age)
|
|
53
|
+
@nzbs << movie
|
|
54
|
+
|
|
55
|
+
$stdout.print '.'
|
|
56
|
+
$stdout.flush
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
$stdout.print "\n"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def clean_raw_name(raw_name)
|
|
65
|
+
(find_clean_nzb_name(raw_name) || raw_name).strip
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def find_clean_nzb_name(raw_name)
|
|
69
|
+
if matched = raw_name.match(/^\[[0-9]*\]-\[.*\]-\[(.*)\]-/)
|
|
70
|
+
matched[1]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def raw_name(table)
|
|
75
|
+
(a = table.search("td.subject a[@href^='?p=']").first) && a.inner_html
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def nfo_link(table)
|
|
79
|
+
(nfo = table.search("td.subject a[@href^='nfo.php?id=']").first) && "#{URL}/#{nfo[:href]}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def imdb_link(table)
|
|
83
|
+
(imdb = table.search("td.subject a[@href^='http://anonym.to/?http://www.imdb.com']").first) && imdb[:href].match(/\?(.*)/)[1]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def nzb_link(table)
|
|
87
|
+
(nzb = table.search("td.get a[@href^='?m=gen&dl=1']").first) && "#{URL}/#{nzb[:href]}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def parse_age(string)
|
|
91
|
+
case string
|
|
92
|
+
when /h/i
|
|
93
|
+
((string.to_f / 24) * 10).to_i / 10.0
|
|
94
|
+
when /d/i
|
|
95
|
+
string.to_f
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module WWW
|
|
2
|
+
class Mechanize
|
|
3
|
+
class Chain
|
|
4
|
+
class ResponseReader
|
|
5
|
+
include WWW::Handler
|
|
6
|
+
|
|
7
|
+
def initialize(response)
|
|
8
|
+
@response = response
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def handle(ctx, params)
|
|
12
|
+
params[:response] = @response
|
|
13
|
+
body = StringIO.new
|
|
14
|
+
total = 0
|
|
15
|
+
@response.read_body { |part|
|
|
16
|
+
total += part.length
|
|
17
|
+
body.write(part)
|
|
18
|
+
Mechanize.log.debug("Read #{total} bytes") if Mechanize.log
|
|
19
|
+
}
|
|
20
|
+
body.rewind
|
|
21
|
+
|
|
22
|
+
res_klass = Net::HTTPResponse::CODE_TO_OBJ[@response.code.to_s]
|
|
23
|
+
raise ResponseCodeError.new(@response) unless res_klass
|
|
24
|
+
|
|
25
|
+
# Net::HTTP ignores EOFError if Content-length is given, so we emulate it here.
|
|
26
|
+
# unless res_klass <= Net::HTTPRedirection
|
|
27
|
+
# raise EOFError if (!params[:request].is_a?(Net::HTTP::Head)) && @response.content_length() && @response.content_length() != total
|
|
28
|
+
# end
|
|
29
|
+
|
|
30
|
+
@response.each_header { |k,v|
|
|
31
|
+
Mechanize.log.debug("response-header: #{ k } => #{ v }")
|
|
32
|
+
} if Mechanize.log
|
|
33
|
+
|
|
34
|
+
params[:response_body] = body
|
|
35
|
+
params[:res_klass] = res_klass
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'open-uri'
|
|
2
|
+
|
|
3
|
+
module Nzbs
|
|
4
|
+
class Nfo
|
|
5
|
+
|
|
6
|
+
attr_accessor :srt, :imdb_link
|
|
7
|
+
|
|
8
|
+
def initialize(agent, url)
|
|
9
|
+
@page = agent.get(url.gsub(/\/$/,''))
|
|
10
|
+
@srt = []
|
|
11
|
+
|
|
12
|
+
parse_nfo
|
|
13
|
+
@srt.uniq!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
# searching for subtitles languages info & imdb link
|
|
19
|
+
def parse_nfo
|
|
20
|
+
pre = @page.search('pre.nfo')
|
|
21
|
+
pre.to_s.split(/\n/).each do |line|
|
|
22
|
+
case line
|
|
23
|
+
when /subtitle|sub/i
|
|
24
|
+
@srt << 'fr' if line =~ /fr|fre|french/i
|
|
25
|
+
@srt << 'en' if line =~ /en|eng|english/i
|
|
26
|
+
# TODO add more language parsing here
|
|
27
|
+
@srt << 'none' if line =~ /none/i
|
|
28
|
+
when /imdb\.com\/title\//
|
|
29
|
+
@imdb_link = (matched = line.match(/imdb.com\/title\/(tt[0-9]+)/)) && "http://imdb.com/title/#{matched[1]}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
@srt << 'unknown' if @srt.empty?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'open-uri'
|
|
2
|
+
require 'hpricot'
|
|
3
|
+
require 'zip/zip'
|
|
4
|
+
require 'mechanize'
|
|
5
|
+
|
|
6
|
+
require File.join(File.dirname(__FILE__), 'nfo')
|
|
7
|
+
require File.join(File.dirname(__FILE__), 'mechanize_hack')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module Nzbs
|
|
11
|
+
class NZB
|
|
12
|
+
|
|
13
|
+
URL = 'http://www.nzbs.org'
|
|
14
|
+
DAYS_BY_PAGE = 5
|
|
15
|
+
|
|
16
|
+
attr_accessor :nzbs, :agent
|
|
17
|
+
|
|
18
|
+
def initialize(options = {})
|
|
19
|
+
@options = options
|
|
20
|
+
@options[:age] ||= DAYS_BY_PAGE
|
|
21
|
+
@options[:pages] ||= ((@options[:age].to_f + DAYS_BY_PAGE) / DAYS_BY_PAGE).ceil
|
|
22
|
+
|
|
23
|
+
@nzb_urls = []
|
|
24
|
+
@nzbs = []
|
|
25
|
+
|
|
26
|
+
(1..(@options[:pages].to_i)).each do |page|
|
|
27
|
+
@nzb_urls << "#{URL}/index.php?action=browse&catid=4&page=#{(page)}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
login
|
|
31
|
+
parse_nzbs
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def download(movie)
|
|
35
|
+
@agent.get_file(movie.nzb_link)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def login
|
|
41
|
+
@agent = WWW::Mechanize.new
|
|
42
|
+
page = @agent.get "#{URL}/index.php?action=browse&catid=4"
|
|
43
|
+
|
|
44
|
+
form = page.forms[1]
|
|
45
|
+
form.username = @options[:login]
|
|
46
|
+
form.password = @options[:pass]
|
|
47
|
+
|
|
48
|
+
@agent.submit form
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def parse_nzbs
|
|
52
|
+
$stdout.print "Parsing #{URL} for new x264 HD nzb movies, with age <= #{@options[:age]}, in last #{@options[:pages]} page(s)\n"
|
|
53
|
+
@nzb_urls.each do |url|
|
|
54
|
+
page = @agent.get url
|
|
55
|
+
page.search("#nzbtable tr").each do |tr|
|
|
56
|
+
if raw_name = raw_name(tr)
|
|
57
|
+
if (age = age(tr)) <= @options[:age].to_f
|
|
58
|
+
if nfo_link = nfo_link(tr)
|
|
59
|
+
@nfo = Nfo.new(@agent, nfo_link(tr))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
name, year, score = get_info_from_imdb_title(tr)
|
|
63
|
+
movie = Movie.new(raw_name, :name => name,
|
|
64
|
+
:year => year,
|
|
65
|
+
:score => score,
|
|
66
|
+
:imdb_link => imdb_link(tr),
|
|
67
|
+
:nzb_link => nzb_link(tr, page),
|
|
68
|
+
:age => age,
|
|
69
|
+
:nfo => @nfo)
|
|
70
|
+
@nzbs << movie
|
|
71
|
+
|
|
72
|
+
$stdout.print '.'
|
|
73
|
+
$stdout.flush
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
$stdout.print "\n"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def raw_name(tr)
|
|
82
|
+
(a = tr.search("a.nzb").first) && a.inner_html
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def age(tr)
|
|
86
|
+
age_text = (td = tr.search("td[@align='right']").first) && td.inner_html
|
|
87
|
+
if age_text && age_text.include?("days ago")
|
|
88
|
+
@last_age = age_text.to_f
|
|
89
|
+
else
|
|
90
|
+
$stdout.print "AGE NOT FOUND"
|
|
91
|
+
end
|
|
92
|
+
@last_age
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def nfo_link(tr)
|
|
96
|
+
(a = tr.search("small a[@href$='#nfo']").first) && a[:href]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def get_info_from_imdb_title(tr)
|
|
100
|
+
title = (a = tr.search("small a.viewimdb").first) && a[:title]
|
|
101
|
+
if title
|
|
102
|
+
if matched = title.match(/^(.*)\s\(([0-9]{4}).*\s\((.*)\/10\)/)
|
|
103
|
+
name = matched[1]
|
|
104
|
+
year = matched[2]
|
|
105
|
+
score = matched[3]
|
|
106
|
+
return name, year.to_i, score.to_f
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def imdb_link(tr)
|
|
112
|
+
(a = tr.search("small a.viewimdb").first) && a[:href].match(/^http:\/\/anonym.to\/\?(.*)/)[1]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def nzb_link(tr, page)
|
|
116
|
+
(a = tr.search("a.dlnzb").first) && "#{URL}/#{a[:href]}"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: autonzb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.5.4
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Pirate
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-11-01 00:00:00 +01:00
|
|
13
|
+
default_executable: bin/autonzb
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: rspec
|
|
17
|
+
type: :development
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: 1.2.9
|
|
24
|
+
version:
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: hpricot
|
|
27
|
+
type: :runtime
|
|
28
|
+
version_requirement:
|
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: "0"
|
|
34
|
+
version:
|
|
35
|
+
- !ruby/object:Gem::Dependency
|
|
36
|
+
name: optiflag
|
|
37
|
+
type: :runtime
|
|
38
|
+
version_requirement:
|
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: "0"
|
|
44
|
+
version:
|
|
45
|
+
- !ruby/object:Gem::Dependency
|
|
46
|
+
name: rubyzip
|
|
47
|
+
type: :runtime
|
|
48
|
+
version_requirement:
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: "0"
|
|
54
|
+
version:
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: htmlentities
|
|
57
|
+
type: :runtime
|
|
58
|
+
version_requirement:
|
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: "0"
|
|
64
|
+
version:
|
|
65
|
+
description: Ruby tool to automatically download x264 HD nzb movies files from newzleech.com & nzbs.org
|
|
66
|
+
email: pirate.2061@gmail.com
|
|
67
|
+
executables:
|
|
68
|
+
- autonzb
|
|
69
|
+
extensions: []
|
|
70
|
+
|
|
71
|
+
extra_rdoc_files:
|
|
72
|
+
- LICENSE
|
|
73
|
+
- README.markdown
|
|
74
|
+
files:
|
|
75
|
+
- .gitignore
|
|
76
|
+
- README.markdown
|
|
77
|
+
- Rakefile
|
|
78
|
+
- VERSION
|
|
79
|
+
- asset/failure.png
|
|
80
|
+
- autonzb.gemspec
|
|
81
|
+
- bin/autonzb
|
|
82
|
+
- lib/imdb.rb
|
|
83
|
+
- lib/inspector.rb
|
|
84
|
+
- lib/movie.rb
|
|
85
|
+
- lib/sites/newzleech/nfo.rb
|
|
86
|
+
- lib/sites/newzleech/nzb.rb
|
|
87
|
+
- lib/sites/nzbs/mechanize_hack.rb
|
|
88
|
+
- lib/sites/nzbs/nfo.rb
|
|
89
|
+
- lib/sites/nzbs/nzb.rb
|
|
90
|
+
- LICENSE
|
|
91
|
+
has_rdoc: true
|
|
92
|
+
homepage: http://github.com/pirate/autonzb
|
|
93
|
+
licenses: []
|
|
94
|
+
|
|
95
|
+
post_install_message:
|
|
96
|
+
rdoc_options:
|
|
97
|
+
- --charset=UTF-8
|
|
98
|
+
require_paths:
|
|
99
|
+
- lib
|
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: "0"
|
|
105
|
+
version:
|
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: "0"
|
|
111
|
+
version:
|
|
112
|
+
requirements: []
|
|
113
|
+
|
|
114
|
+
rubyforge_project:
|
|
115
|
+
rubygems_version: 1.3.5
|
|
116
|
+
signing_key:
|
|
117
|
+
specification_version: 3
|
|
118
|
+
summary: Automatically download x264 HD nzb movies files.
|
|
119
|
+
test_files:
|
|
120
|
+
- spec/autonzb_spec.rb
|
|
121
|
+
- spec/spec_helper.rb
|