AutoNZB 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +25 -0
- data/LICENSE +20 -0
- data/README.markdown +44 -0
- data/Rakefile +69 -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,69 @@
|
|
1
|
+
# # Rakefile
|
2
|
+
# require 'rubygems'
|
3
|
+
# require 'rake'
|
4
|
+
# require 'echoe'
|
5
|
+
#
|
6
|
+
# Echoe.new('autonzb', '0.5.4') do |p|
|
7
|
+
# p.description = "Ruby tool to automatically download x264 HD nzb movies files from newzleech.com & nzbs.org"
|
8
|
+
# p.url = "http://github.com/pirate/autonzb"
|
9
|
+
# p.author = "Pirate"
|
10
|
+
# p.email = "pirate.2061@gmail.com"
|
11
|
+
# p.ignore_pattern = ["tmp/*", "script/*"]
|
12
|
+
# p.executable_pattern = "bin/autonzb"
|
13
|
+
# p.runtime_dependencies = ["hpricot", "optiflag", 'rubyzip', 'htmlentities']
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'rake'
|
21
|
+
|
22
|
+
begin
|
23
|
+
require 'jeweler'
|
24
|
+
Jeweler::Tasks.new do |gem|
|
25
|
+
gem.name = "AutoNZB"
|
26
|
+
gem.summary = "Automatically download x264 HD nzb movies files."
|
27
|
+
gem.description = "Ruby tool to automatically download x264 HD nzb movies files from newzleech.com & nzbs.org"
|
28
|
+
gem.email = "pirate.2061@gmail.com"
|
29
|
+
gem.homepage = "http://github.com/pirate/autonzb"
|
30
|
+
gem.authors = ["Pirate"]
|
31
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
32
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
33
|
+
# gem.ignore_pattern = ["tmp/*", "script/*"]
|
34
|
+
gem.add_dependency "hpricot"
|
35
|
+
gem.add_dependency "optiflag"
|
36
|
+
gem.add_dependency "rubyzip"
|
37
|
+
gem.add_dependency "htmlentities"
|
38
|
+
gem.default_executable = "bin/autonzb"
|
39
|
+
end
|
40
|
+
Jeweler::GemcutterTasks.new
|
41
|
+
rescue LoadError
|
42
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'spec/rake/spectask'
|
46
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
47
|
+
spec.libs << 'lib' << 'spec'
|
48
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
49
|
+
end
|
50
|
+
|
51
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
52
|
+
spec.libs << 'lib' << 'spec'
|
53
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
54
|
+
spec.rcov = true
|
55
|
+
end
|
56
|
+
|
57
|
+
task :spec => :check_dependencies
|
58
|
+
|
59
|
+
task :default => :spec
|
60
|
+
|
61
|
+
require 'rake/rdoctask'
|
62
|
+
Rake::RDocTask.new do |rdoc|
|
63
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
64
|
+
|
65
|
+
rdoc.rdoc_dir = 'rdoc'
|
66
|
+
rdoc.title = "test-gem #{version}"
|
67
|
+
rdoc.rdoc_files.include('README*')
|
68
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
69
|
+
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
|