nanny 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ <item>
2
+ <title>The Office US S09E12 HDTV x264 LOL</title>
3
+ <link>http://torrentz.eu/419b8bf295303d977c97c07b8bd63349c181776e</link>
4
+ <guid>http://torrentz.eu/419b8bf295303d977c97c07b8bd63349c181776e</guid>
5
+ <pubDate>Fri, 25 Jan 2013 15:57:11 +0000</pubDate>
6
+ <category>tv video shows</category>
7
+ <description>Size: 163 MB Seeds: 12 Peers: 1 Hash: 419b8bf295303d977c97c07b8bd63349c181776e</description>
8
+ </item>
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nanny::MagnetURI do
4
+
5
+ it "takes an URI" do
6
+ Nanny::MagnetURI.new('foo').uri.should == 'foo'
7
+ end
8
+
9
+ describe "#hash" do
10
+ it "parses the hash from the URI" do
11
+ uri = Nanny::MagnetURI.new('magnet:?xt=urn:btih:f6c598d155e53f793d429582afaa160f2101b3fb&dn=The+Office+US+-+The+Complete+Season+8+HDTV&tr=udp%3A%2F%2Ftracker.1337x.org%3A80%2Fannounce&tr=http%3A%2F%2Ftracker.publicbt.com%2Fannounce&tr=http%3A%2F%2Fexodus.desync.com%2Fannounce')
12
+ uri.hash.should == 'f6c598d155e53f793d429582afaa160f2101b3fb'
13
+ end
14
+ end
15
+
16
+ end
17
+
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nanny::Search do
4
+
5
+ describe "#search_torrents" do
6
+ it "transforms each feed item into a torrent" do
7
+ doc = double('Nokogiri::XML')
8
+ doc.stub(:xpath).with(Nanny::Search::FEED_ITEMS_XPATH).and_return [ 'feed_item' ]
9
+ subject.stub(:document_for_query).with('my query').and_return doc
10
+ subject.stub(:torrent_from_item).with('feed_item').and_return 'torrent'
11
+ torrents = subject.search_torrents('my query')
12
+ torrents.should == [ 'torrent' ]
13
+ end
14
+ end
15
+
16
+ describe "#torrent_from_item" do
17
+ it "parses feed item into torrent" do
18
+ item_xml = dump_file('item.xml').read
19
+ torrent = subject.torrent_from_item Nokogiri::XML(item_xml)
20
+
21
+ torrent.should be_a Nanny::Torrent
22
+ torrent.title.should == 'The Office US S09E12 HDTV x264 LOL'
23
+ torrent.url.should == 'http://torrentz.eu/419b8bf295303d977c97c07b8bd63349c181776e'
24
+ torrent.size.should == 170917888
25
+ torrent.seeds.should == 12
26
+ torrent.peers.should == 1
27
+ torrent.hash.should == '419b8bf295303d977c97c07b8bd63349c181776e'
28
+ end
29
+ end
30
+
31
+ example do
32
+ VCR.use_cassette "search_torrents" do
33
+ torrents = subject.search_torrents "The Office Season 8"
34
+ torrents.should have(3).torrents
35
+ torrents.first.title.should == "The Office US The Complete Season 8 HDTV"
36
+ end
37
+ end
38
+
39
+ example do
40
+ VCR.use_cassette "complete integration" do
41
+ torrents = subject.search_torrents "The Office Season 8"
42
+ torrents.first.torrent_url.should == 'http://torcache.net/torrent/F6C598D155E53F793D429582AFAA160F2101B3FB.torrent'
43
+ end
44
+ end
45
+
46
+ end
47
+
@@ -0,0 +1,15 @@
1
+ root = File.expand_path('../../', __FILE__)
2
+ $LOAD_PATH.unshift(root) unless $LOAD_PATH.include?(root)
3
+
4
+ require 'vcr'
5
+ require 'nanny'
6
+
7
+ VCR.configure do |c|
8
+ c.cassette_library_dir = 'spec/cassettes'
9
+ c.hook_into :webmock
10
+ c.ignore_localhost = true
11
+ end
12
+
13
+ Dir[File.join("spec/support/**/*.rb")].each do |f|
14
+ require f
15
+ end
@@ -0,0 +1,29 @@
1
+ require 'psych'
2
+
3
+ module DumpHelpers
4
+ def dump_path(path)
5
+ File.join(File.dirname(__FILE__), "../dumps", path)
6
+ end
7
+
8
+ def dump_file(path)
9
+ File.new(dump_path(path))
10
+ end
11
+
12
+ def yaml_dump(path)
13
+ Psych.load(dump_file(path).read)
14
+ end
15
+
16
+ def write_dump(text, path)
17
+ File.open(dump_path(path), 'w') do |f|
18
+ f.write text
19
+ end
20
+ end
21
+
22
+ def write_yaml_dump(obj, path)
23
+ write_dump(Psych.dump(obj), path)
24
+ end
25
+ end
26
+
27
+ RSpec.configure do |c|
28
+ c.include DumpHelpers
29
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nanny::Torrent do
4
+
5
+ describe "#human_size" do
6
+ it "formats size" do
7
+ Nanny::Torrent.new(size: 0).human_size.should == "0B"
8
+ Nanny::Torrent.new(size: 5000).human_size.should == "4.9KB"
9
+ Nanny::Torrent.new(size: 5000000).human_size.should == "4.8MB"
10
+ Nanny::Torrent.new(size: 5000000000).human_size.should == "4.7GB"
11
+ end
12
+ end
13
+
14
+ describe "#torrent_url" do
15
+ it "returns Torcache URL" do
16
+ torrent = Nanny::Torrent.new
17
+ torrent.stub(:torcache_url).and_return('foo_url')
18
+ torrent.torrent_url.should == 'foo_url'
19
+ end
20
+ it "returns torrent url from trackers otherwise" do
21
+ torrent = Nanny::Torrent.new
22
+ torrent.stub(:torcache_url).and_raise(Nanny::Torrent::URLNotFound)
23
+ torrent.stub(:trackers_torrent_url).and_return('foo_url')
24
+ torrent.torrent_url.should == 'foo_url'
25
+ end
26
+ end
27
+
28
+ describe "#torcache_url" do
29
+ it "uses hash" do
30
+ Nanny::Torcache.stub(:url_for).with('foo').and_return('foo_url')
31
+ Nanny::Torrent.new(hash: 'foo').torcache_url.should == 'foo_url'
32
+ end
33
+ it "else uses trackers magnet" do
34
+ Nanny::Torcache.stub(:url_for).with('foo').and_raise(Nanny::Torcache::HashNotFound)
35
+ torrent = Nanny::Torrent.new(hash: 'foo')
36
+ torrent.stub(:trackers_torcache_url).and_return('bar_url')
37
+ torrent.torcache_url.should == 'bar_url'
38
+ end
39
+ end
40
+
41
+ describe "#trackers_torcache_url" do
42
+ it "returns the Torcache URL for the first tracker with a magnet link" do
43
+ failing_tracker = double('Tracker')
44
+ failing_tracker.stub(:magnet_uri).and_raise(Nanny::Tracker::MagnetNotFound)
45
+
46
+ tracker = double('Tracker')
47
+ tracker.stub(:magnet_uri).and_return(stub(hash: 'XXX'))
48
+
49
+ Nanny::Torcache.stub(:url_for).with('XXX').and_return('foo_url')
50
+
51
+ subject.stub(:trackers).and_return [ failing_tracker, tracker ]
52
+ subject.trackers_torcache_url.should == 'foo_url'
53
+ end
54
+
55
+ it "raises URLNotFound otherwise" do
56
+ subject.stub(:trackers).and_return []
57
+ lambda { subject.trackers_torcache_url }.should raise_error(Nanny::Torrent::URLNotFound)
58
+ end
59
+ end
60
+
61
+ describe "#trackers_torrent_url" do
62
+ it "returns the torrent URL for the first tracker" do
63
+ failing_tracker = double('Tracker')
64
+ failing_tracker.stub(:torrent_url).and_raise(Nanny::Tracker::TorrentNotFound)
65
+
66
+ tracker = double('Tracker')
67
+ tracker.stub(:torrent_url).and_return('foo_url')
68
+
69
+ subject.stub(:trackers).and_return [ failing_tracker, tracker ]
70
+ subject.trackers_torrent_url.should == 'foo_url'
71
+ end
72
+
73
+ it "raises URLNotFound otherwise" do
74
+ subject.stub(:trackers).and_return []
75
+ lambda { subject.trackers_torrent_url }.should raise_error(Nanny::Torrent::URLNotFound)
76
+ end
77
+ end
78
+
79
+ describe "#trackers" do
80
+ example do
81
+ VCR.use_cassette "trackers" do
82
+ torrent = Nanny::Torrent.new(url: 'http://torrentz.eu/f6c598d155e53f793d429582afaa160f2101b3fb')
83
+ torrent.should have(8).trackers
84
+ end
85
+ end
86
+ end
87
+
88
+ example do
89
+ VCR.use_cassette "complex_torrent_find" do
90
+ torrent = Nanny::Torrent.new(hash: 'a47987c83f1a23d3ff328f89d1f8023f214297a8', url: 'http://torrentz.eu/a47987c83f1a23d3ff328f89d1f8023f214297a8')
91
+ torrent.torrent_url.should == 'http://torrage.com/torrent/A47987C83F1A23D3FF328F89D1F8023F214297A8.torrent'
92
+ end
93
+ end
94
+
95
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Nanny::Tracker do
6
+
7
+ describe "#valid_url?" do
8
+ subject { Nanny::Tracker.new('http://google.it/foobar').valid_url?(url) }
9
+
10
+ context "torrent extension required" do
11
+ let(:url) { "foobar.html" }
12
+ it { should be_false }
13
+ end
14
+
15
+ context "valid URI required" do
16
+ let(:url) { "fòòbar.html" }
17
+ it { should be_false }
18
+ end
19
+
20
+ context "valid URI required" do
21
+ let(:url) { "foobar.torrent" }
22
+ it { should be_true }
23
+ end
24
+ end
25
+
26
+ describe "#to_absolute_uri" do
27
+ subject { Nanny::Tracker.new('http://google.it/foobar').to_absolute_url(url) }
28
+ context "absolute URIs are left unchanged" do
29
+ let(:url) { "http://foobar.com/foobar.html" }
30
+ it { should == url }
31
+ end
32
+ context "relative URI become absolute based on tracker page" do
33
+ let(:url) { "/bar.html" }
34
+ it { should == 'http://google.it/bar.html' }
35
+ end
36
+ context "urls not starting with a forward slash are not handled correctly", fixme: true do
37
+ let(:url) { "bar.html" }
38
+ it { should == 'http://google.it/bar.html' }
39
+ end
40
+ end
41
+
42
+ describe "#magnet_uri" do
43
+ it "raises MagnetNotFound if cannot download the tracker page" do
44
+ tracker = Nanny::Tracker.new('http://google.com')
45
+ tracker.stub(:tracker_doc).and_raise Nanny::Tracker::PageNotAvailable
46
+ lambda { tracker.magnet_uri }.should raise_error Nanny::Tracker::MagnetNotFound
47
+ end
48
+
49
+ example do
50
+ VCR.use_cassette "fenopy" do
51
+ tracker = Nanny::Tracker.new("http://fenopy.se/torrent/the+office+us+the+complete+season+8+hdtv/ODMxMzA4Mg")
52
+ tracker.magnet_uri.hash.should == "f6c598d155e53f793d429582afaa160f2101b3fb"
53
+ end
54
+ end
55
+
56
+ example do
57
+ VCR.use_cassette "extratorrent" do
58
+ tracker = Nanny::Tracker.new("http://extratorrent.com/torrent/2685289/The+Office+US+-+The+Complete+Season+8+HDTV.html")
59
+ tracker.magnet_uri.hash.should == "f6c598d155e53f793d429582afaa160f2101b3fb"
60
+ end
61
+ end
62
+
63
+ example do
64
+ VCR.use_cassette "google" do
65
+ tracker = Nanny::Tracker.new("http://google.com")
66
+ lambda { tracker.magnet_uri }.should raise_error Nanny::Tracker::MagnetNotFound
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#torrent_url" do
72
+ it "raises TorrentNotFound if cannot download the tracker page" do
73
+ tracker = Nanny::Tracker.new('http://google.com')
74
+ tracker.stub(:tracker_doc).and_raise Nanny::Tracker::PageNotAvailable
75
+ lambda { tracker.torrent_url }.should raise_error Nanny::Tracker::TorrentNotFound
76
+ end
77
+
78
+ example do
79
+ VCR.use_cassette "fenopy" do
80
+ tracker = Nanny::Tracker.new("http://fenopy.se/torrent/the+office+us+the+complete+season+8+hdtv/ODMxMzA4Mg")
81
+ tracker.torrent_url.should == "http://torcache.net/torrent/F6C598D155E53F793D429582AFAA160F2101B3FB.torrent"
82
+ end
83
+ end
84
+
85
+ example do
86
+ VCR.use_cassette "yourbittorrent" do
87
+ tracker = Nanny::Tracker.new("http://yourbittorrent.com/torrent/3433946/the-lincoln-lawyer-italian-dvdrip-blw.html")
88
+ tracker.torrent_url.should == "http://yourbittorrent.com/down/3433946.torrent"
89
+ end
90
+ end
91
+
92
+ example do
93
+ VCR.use_cassette "google" do
94
+ tracker = Nanny::Tracker.new("http://google.com")
95
+ lambda { tracker.torrent_url }.should raise_error Nanny::Tracker::TorrentNotFound
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#tracker_doc" do
101
+ it "returns a Nokogiri HTML of tracker URL" do
102
+ VCR.use_cassette "google" do
103
+ tracker = Nanny::Tracker.new("http://google.com")
104
+ tracker.tracker_doc.should be_a Nokogiri::HTML::Document
105
+ end
106
+ end
107
+ it "gives up if download takes more than 2 seconds" do
108
+ tracker = Nanny::Tracker.new("http://google.com")
109
+ Nanny::HTTPClient.stub(:get).and_return {
110
+ sleep 3
111
+ }
112
+ lambda { tracker.tracker_doc }.should raise_error Nanny::Tracker::PageNotAvailable
113
+ end
114
+ end
115
+
116
+ end
metadata ADDED
@@ -0,0 +1,220 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nanny
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Stefano Verna
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: addressable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: active_support
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: colored
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: trollop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: terminal-table
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: highline
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: ruby-progressbar
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Nanny helps you find valid Torrent links from CLI
140
+ email:
141
+ - stefano.verna@welaika.com
142
+ executables:
143
+ - nanny
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - .travis.yml
148
+ - Gemfile
149
+ - Gemfile.lock
150
+ - LICENSE.txt
151
+ - README.md
152
+ - Rakefile
153
+ - bin/nanny
154
+ - doc/cli.png
155
+ - lib/nanny.rb
156
+ - lib/nanny/attr_initializer.rb
157
+ - lib/nanny/cli.rb
158
+ - lib/nanny/http_client.rb
159
+ - lib/nanny/magnet_uri.rb
160
+ - lib/nanny/progress.rb
161
+ - lib/nanny/search.rb
162
+ - lib/nanny/torcache.rb
163
+ - lib/nanny/torrent.rb
164
+ - lib/nanny/tracker.rb
165
+ - lib/nanny/version.rb
166
+ - nanny.gemspec
167
+ - spec/cassettes/complete_integration.yml
168
+ - spec/cassettes/complex_torrent_find.yml
169
+ - spec/cassettes/extratorrent.yml
170
+ - spec/cassettes/fenopy.yml
171
+ - spec/cassettes/google.yml
172
+ - spec/cassettes/search_torrents.yml
173
+ - spec/cassettes/trackers.yml
174
+ - spec/cassettes/yourbittorrent.yml
175
+ - spec/dumps/item.xml
176
+ - spec/magnet_uri_spec.rb
177
+ - spec/search_spec.rb
178
+ - spec/spec_helper.rb
179
+ - spec/support/dump_helpers.rb
180
+ - spec/torrent_spec.rb
181
+ - spec/tracker_spec.rb
182
+ homepage: http://getmetorrents.com
183
+ licenses: []
184
+ metadata: {}
185
+ post_install_message:
186
+ rdoc_options: []
187
+ require_paths:
188
+ - lib
189
+ required_ruby_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - '>='
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ required_rubygems_version: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - '>='
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
+ requirements: []
200
+ rubyforge_project:
201
+ rubygems_version: 2.0.0
202
+ signing_key:
203
+ specification_version: 4
204
+ summary: Nanny scrapes torrent meta-search engines to find direct torrent links
205
+ test_files:
206
+ - spec/cassettes/complete_integration.yml
207
+ - spec/cassettes/complex_torrent_find.yml
208
+ - spec/cassettes/extratorrent.yml
209
+ - spec/cassettes/fenopy.yml
210
+ - spec/cassettes/google.yml
211
+ - spec/cassettes/search_torrents.yml
212
+ - spec/cassettes/trackers.yml
213
+ - spec/cassettes/yourbittorrent.yml
214
+ - spec/dumps/item.xml
215
+ - spec/magnet_uri_spec.rb
216
+ - spec/search_spec.rb
217
+ - spec/spec_helper.rb
218
+ - spec/support/dump_helpers.rb
219
+ - spec/torrent_spec.rb
220
+ - spec/tracker_spec.rb