kat 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2169e0aa1bb57e770b1f18c28c7e303a1d873f91
4
- data.tar.gz: ef1a8c23da1ffbf1a178b82a1296bdbd98f42124
3
+ metadata.gz: a787a58459b2ef07e56e8ea0dcbd2303b88d1a2e
4
+ data.tar.gz: 8044118ce50282384b57378d82c117b633a1f372
5
5
  SHA512:
6
- metadata.gz: 63795bf527fc336114b525c5d0de19bab3cb5079c761fd8261383801a1cf204a2e6079cd54f3e9819ea2e464bb4c434785da21ace8b063cd34d29913f91270bc
7
- data.tar.gz: e6be7512cb382544a0614ec6dfce16bb713326412f72b25f877eaf71519b1eb9f47454d68a4691c19e5246594d33f52d69c4cc8a5164f60c819d117514fd08da
6
+ metadata.gz: 47b3095fe9256337fe71d7248d0f36d3cee42f78794d66da09bedea20bb8120efe9bed80bfa24f45469b7bf25361ee236155f4d36bab343b8b4691640aec14ce
7
+ data.tar.gz: 5bfe7bd174afabe76d089625bc35054da1be957781061932db125c1e6fa74fc84be2fc22b7e3323cc8570d6f1d9f3fd99496b6e8855d99f203834bea89820e47
data/README.md CHANGED
@@ -22,11 +22,11 @@ Or install it yourself as:
22
22
 
23
23
  ### Quick search
24
24
 
25
- Kat.search('game of thrones')
25
+ Kat.quick_search('game of thrones')
26
26
 
27
27
  ### Search for torrents
28
28
 
29
- kat = Kat.new('game of thrones', { :category => 'tv' })
29
+ kat = Kat.search('game of thrones', { :category => 'tv' })
30
30
  kat.search
31
31
 
32
32
  ### Specifying pages
data/kat.gemspec CHANGED
@@ -16,11 +16,12 @@ Gem::Specification.new do |s|
16
16
  s.description = 'A Ruby interface to Kickass Torrents'
17
17
 
18
18
  s.files = `git ls-files`.split $/
19
- s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f }
19
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename f }
20
20
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
21
- s.require_paths = [ 'lib' ]
21
+ s.require_paths = ['lib']
22
22
 
23
23
  s.add_runtime_dependency 'nokogiri', '~> 1.6'
24
24
  s.add_runtime_dependency 'highline', '~> 1.6'
25
25
  s.add_runtime_dependency 'trollop', '~> 2.0'
26
+ s.add_runtime_dependency 'andand', '~> 1.3'
26
27
  end
data/lib/kat/app.rb CHANGED
@@ -18,6 +18,7 @@ module Kat
18
18
 
19
19
  class App
20
20
  MIN_WIDTH = 80
21
+ CONFIG = File.join ENV['HOME'], '.katrc'
21
22
 
22
23
  # The current page number (0-based)
23
24
  attr_accessor :page
@@ -46,20 +47,22 @@ module Kat
46
47
  # Initialise the app's options
47
48
  #
48
49
  def init_options(args = nil)
49
- @options = {}
50
50
  @args = case args
51
51
  when nil then []
52
52
  when String then args.split
53
53
  else args
54
54
  end
55
55
 
56
- load_config
56
+ @options = load_config || {}
57
57
 
58
58
  Kat.options(@args).tap { |o|
59
59
  @options.merge!(o) { |k, ov, nv| o["#{ k }_given".intern] ? nv : ov }
60
60
  }
61
61
 
62
62
  Kat::Colour.colour = @options[:colour]
63
+ rescue NoMethodError => e
64
+ @options = {}
65
+ warn "Wrong config file format: #{ e }"
63
66
  end
64
67
 
65
68
  #
@@ -144,28 +147,26 @@ module Kat
144
147
  }
145
148
  ].map { |w| Thread.new { w.call } }.each(&:join)
146
149
 
147
- unless @kat.results[@page] && !@kat.error
148
- puts "\rNo results ".red
149
- puts @kat.error[:error] if @kat.error
150
- return false
151
- end
150
+ puts (res = format_results)
152
151
 
153
- puts format_results
152
+ if res.size > 1
153
+ case (answer = prompt)
154
+ when 'i' then @show_info = !@show_info
155
+ when 'n' then @page += 1 if next?
156
+ when 'p' then @page -= 1 if prev?
157
+ when 'q' then return false
158
+ else
159
+ if (1..@kat.results[@page].size).include? (answer = answer.to_i)
160
+ print "\nDownloading".yellow <<
161
+ ": #{ @kat.results[@page][answer - 1][:title] }... "
162
+ puts download @kat.results[@page][answer - 1]
163
+ end
164
+ end
154
165
 
155
- case (answer = prompt)
156
- when 'i' then @show_info = !@show_info
157
- when 'n' then @page += 1 if next?
158
- when 'p' then @page -= 1 if prev?
159
- when 'q' then return false
166
+ true
160
167
  else
161
- if (1..@kat.results[@page].size).include? (answer = answer.to_i)
162
- print "\nDownloading".yellow <<
163
- ": #{ @kat.results[@page][answer - 1][:title] }... "
164
- puts download @kat.results[@page][answer - 1]
165
- end
168
+ false
166
169
  end
167
-
168
- true
169
170
  end
170
171
 
171
172
  #
@@ -195,6 +196,12 @@ module Kat
195
196
  def format_results
196
197
  main_width = @window_width - (!hide_info? || @show_info ? 42 : 4)
197
198
 
199
+ if @kat.error
200
+ return ["\rConnection failed".red]
201
+ elsif !@kat.results[@page]
202
+ return ["\rNo results ".red]
203
+ end
204
+
198
205
  buf = ["\r%-#{ main_width + 5 }s#{ ' Size Age Seeds Leeches' if !hide_info? || @show_info }" %
199
206
  "Page #{ page + 1 } of #{ @kat.pages }", nil].yellow!
200
207
 
@@ -242,7 +249,9 @@ module Kat
242
249
  # Download the torrent to either the output directory or the working directory
243
250
  #
244
251
  def download(torrent)
245
- uri = URI(URI::encode torrent[:download])
252
+ return [:failed, 'no download link available'].red unless torrent[:download]
253
+
254
+ uri = URI(URI.encode torrent[:download])
246
255
  uri.query = nil
247
256
  file = "#{ @options[:output] || '.' }/" <<
248
257
  "#{ torrent[:title].tr(' ', ?.).gsub(/[^a-z0-9()_.-]/i, '') }.torrent"
@@ -259,16 +268,14 @@ module Kat
259
268
  end
260
269
 
261
270
  #
262
- # Load options from ~/.katrc if it exists
271
+ # Load options from CONFIG if it exists
263
272
  #
264
273
  def load_config
265
- config = File.join(ENV['HOME'], '.katrc')
266
-
267
- @options = (symbolise = -> h {
274
+ (symbolise = -> h {
268
275
  Hash === h ? Hash[h.map { |k, v| [k.intern, symbolise[v]] }] : h
269
- })[YAML.load_file config] if File.readable? config
276
+ })[YAML.load_file CONFIG] if File.readable? CONFIG
270
277
  rescue => e
271
- warn "Failed to load #{config}: #{e}"
278
+ warn "Failed to load #{ CONFIG }: #{ e }"
272
279
  end
273
280
 
274
281
  end
data/lib/kat/field_map.rb CHANGED
@@ -1,122 +1,33 @@
1
- require 'yaml'
2
-
3
1
  module Kat
4
2
 
5
- FIELD_MAP = (symbolise = -> h {
6
- case h
7
- when Hash then Hash[h.map { |k, v| [k.to_sym, k == 'desc' ? v : symbolise[v]] }]
8
- when String then h.to_sym
9
- else h
10
- end
11
- })[YAML.load(<<-FIELD_MAP
12
- ---
13
- exact:
14
- type: string
15
- desc: Exact phrase
16
-
17
- or:
18
- type: string
19
- desc: Optional words
20
- multi: true
21
-
22
- without:
23
- type: string
24
- desc: Without this word
25
- multi: true
26
-
27
- sort:
28
- type: string
29
- desc: Sort field (size, files, added, seeds, leeches)
30
-
31
- asc:
32
- desc: Ascending sort order (descending is default)
33
-
34
- category:
35
- select: categories
36
- type: string
37
- desc: Category
38
- short: c
39
-
40
- added:
41
- select: times
42
- sort: time_add
43
- type: string
44
- desc: Age of the torrent
45
- id: age
46
- short: a
47
-
48
- size:
49
- sort: size
50
-
51
- user:
52
- input: true
53
- type: string
54
- desc: Uploader
55
-
56
- files:
57
- input: true
58
- sort: files_count
59
- type: int
60
- desc: Number of files
61
-
62
- imdb:
63
- input: true
64
- type: int
65
- desc: IMDB ID
66
-
67
- seeds:
68
- input: true
69
- sort: seeders
70
- type: int
71
- desc: Min no of seeders
72
- short: s
73
-
74
- leeches:
75
- sort: leechers
76
-
77
- season:
78
- input: true
79
- type: int
80
- desc: Television season
81
-
82
- episode:
83
- input: true
84
- type: int
85
- desc: Television episode
86
- short: e
3
+ FIELD_MAP = {
4
+ exact: { type: :string, desc: 'Exact phrase' },
5
+ or: { type: :string, desc: 'Optional words', multi: true },
6
+ without: { type: :string, desc: 'Without this word', multi: true },
87
7
 
88
- language:
89
- select: languages
90
- type: int
91
- desc: Language
92
- id: lang_id
8
+ sort: { type: :string, desc: 'Sort field (size, files, added, seeds, leeches)' },
9
+ asc: { desc: 'Ascending sort order (descending is default)' },
93
10
 
94
- platform:
95
- select: platforms
96
- type: int
97
- desc: Game platform
98
- id: platform_id
11
+ category: { type: :string, desc: 'Category', select: :categories, short: :c },
12
+ added: { type: :string, desc: 'Age of the torrent', select: :times, short: :a, sort: :time_add, id: :age },
13
+ size: { sort: :size },
99
14
 
100
- safe:
101
- check: true
102
- desc: Family safe filter
103
- short: none
15
+ user: { type: :string, desc: 'Uploader', input: true },
16
+ files: { type: :int, desc: 'Number of files', input: true, sort: :files_count },
17
+ imdb: { type: :int, desc: 'IMDB ID', input: true },
18
+ seeds: { type: :int, desc: 'Min no of seeders', input: true, sort: :seeders, short: :s },
19
+ leeches: { sort: :leechers },
20
+ season: { type: :int, desc: 'Television season', input: true },
21
+ episode: { type: :int, desc: 'Television episode', input: true, short: :e },
104
22
 
105
- verified:
106
- check: true
107
- desc: Verified torrent
108
- short: none
23
+ language: { type: :int, desc: 'Language', select: :languages, id: :lang_id },
24
+ platform: { type: :int, desc: 'Game platform', select: :platforms, id: :platform_id },
109
25
 
110
- output:
111
- type: string
112
- desc: Directory to save torrents in
113
- short: o
26
+ safe: { desc: 'Family safe filter', check: true, short: :none},
27
+ verified: { desc: 'Verified torrent', check: true, short: :none },
114
28
 
115
- colour:
116
- type: boolean
117
- desc: Output with colour
118
- short: none
119
- FIELD_MAP
120
- )].freeze
29
+ output: { type: :string, desc: 'Directory to save torrents in', short: :o },
30
+ colour: { desc: 'Output with colour', short: :none }
31
+ }.freeze
121
32
 
122
33
  end
data/lib/kat/search.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/field_map'
2
2
  require 'nokogiri'
3
3
  require 'net/http'
4
+ require 'andand'
4
5
 
5
6
  module Kat
6
7
 
@@ -197,10 +198,10 @@ module Kat
197
198
  doc = Nokogiri::HTML(res.body)
198
199
 
199
200
  @results[page] = doc.css('td.torrentnameCell').map { |node|
200
- { path: node.css('a.normalgrey').first.attributes['href'].value,
201
+ { path: node.css('a.normalgrey').first.andand.attr('href'),
201
202
  title: node.css('a.normalgrey').text,
202
- magnet: node.css('a.imagnet').first.attributes['href'].value,
203
- download: node.css('a.idownload').last.attributes['href'].value,
203
+ magnet: node.css('a.imagnet').first.andand.attr('href'),
204
+ download: node.css('a.idownload').last.andand.attr('href'),
204
205
  size: (node = node.next_element).text,
205
206
  files: (node = node.next_element).text.to_i,
206
207
  age: (node = node.next_element).text,
data/lib/kat/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Kat
2
2
  NAME = 'Kickass Torrents Search'
3
- VERSION = '2.0.0'
3
+ VERSION = '2.0.1'
4
4
  MALEVOLENT_DICTATOR_FOR_LIFE = 'Fission Xuiptz'
5
5
  AUTHOR = MALEVOLENT_DICTATOR_FOR_LIFE
6
6
  VERSION_STR = "#{NAME} #{VERSION} (c) 2013 #{MALEVOLENT_DICTATOR_FOR_LIFE}"
data/test/kat/test_app.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'minitest/autorun'
2
2
  require File.dirname(__FILE__) + '/../../lib/kat/app'
3
3
 
4
- app = Kat::App.new %w(predator -c movies -o .)
4
+ app = Kat::App.new %w(aliens -c movies -o .)
5
5
  app.kat.go(1).go(app.kat.pages - 1)
6
6
 
7
7
  describe Kat::App do
@@ -14,7 +14,7 @@ describe Kat::App do
14
14
  end
15
15
 
16
16
  it 're-initialises options' do
17
- k = Kat::App.new %w(predator)
17
+ k = Kat::App.new %w(aliens)
18
18
  k.init_options %w(bible -c books)
19
19
  k.options.must_be_instance_of Hash
20
20
  k.options[:category].must_equal 'books'
@@ -42,11 +42,13 @@ describe Kat::App do
42
42
 
43
43
  prev?.must_equal true
44
44
  next?.wont_equal true
45
+ # Skip the test if there's no results. We really only want to test in ideal
46
+ # network conditions and no results here are an indication that's not the case
45
47
  validation_regex.must_equal(
46
48
  /^([pq]|[1-#{ [9, n].min }]#{
47
- "|1[0-#{ [9, n - 10].min }]" if n > 9
48
- }#{ "|2[0-#{ n - 20 }]" if n > 19 })$/
49
- )
49
+ "|1[0-#{ [9, n - 10].min }]" if n > 9
50
+ }#{ "|2[0-#{ n - 20 }]" if n > 19 })$/
51
+ ) if n > 0
50
52
 
51
53
  @page = 0
52
54
  }
@@ -83,6 +85,7 @@ describe Kat::App do
83
85
 
84
86
  it 'formats a list of torrents' do
85
87
  Kat::Colour.colour = false
88
+
86
89
  app.instance_exec {
87
90
  set_window_width
88
91
  list = format_results
@@ -90,8 +93,10 @@ describe Kat::App do
90
93
  list.must_be_instance_of Array
91
94
  list.wont_be_empty
92
95
 
93
- list.size.must_equal kat.results[0].size + 3
94
- 2.upto(list.size - 2) { |i|
96
+ list[1].must_be_nil
97
+ list.last.must_be_nil
98
+
99
+ (2..list.size - 2).each { |i|
95
100
  list[i].must_match /^(\s[1-9]|[12][0-9])\. .*/
96
101
  }
97
102
  }
@@ -99,6 +104,7 @@ describe Kat::App do
99
104
 
100
105
  it 'downloads data from a URL' do
101
106
  Kat::Colour.colour = false
107
+
102
108
  app.instance_exec {
103
109
  s = 'foobar'
104
110
  result = download({ download: 'http://google.com', title: s })
@@ -110,6 +116,7 @@ describe Kat::App do
110
116
 
111
117
  it 'returns an error message when a download fails' do
112
118
  Kat::Colour.colour = false
119
+
113
120
  app.instance_exec {
114
121
  result = download({ download: 'http://foo.bar', title: 'foobar' })
115
122
  result.must_be_instance_of Array
@@ -23,6 +23,8 @@ describe Kat::Colour do
23
23
  end
24
24
 
25
25
  it 'colours strings' do
26
+ Kat::Colour.colour = true
27
+
26
28
  colours.each_with_index { |c, i|
27
29
  str = 'foobar'
28
30
  result = "\e[0;#{ 30 + i }mfoobar\e[0m"
@@ -55,6 +57,8 @@ describe Kat::Colour do
55
57
  end
56
58
 
57
59
  it 'colours symbols' do
60
+ Kat::Colour.colour = true
61
+
58
62
  colours.each_with_index { |c, i|
59
63
  sym = :foobar
60
64
  result = "\e[0;#{ 30 + i }mfoobar\e[0m"
@@ -85,6 +89,8 @@ describe Kat::Colour do
85
89
  end
86
90
 
87
91
  it 'colours arrays of strings and symbols' do
92
+ Kat::Colour.colour = true
93
+
88
94
  colours.each_with_index { |c, i|
89
95
  s = ['foobar', :foobar, nil, ['foobar', :foobar, nil]]
90
96
  t = ['foobar', :foobar, nil, ['foobar', :foobar, nil]]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kat
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fission Xuiptz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-18 00:00:00.000000000 Z
11
+ date: 2014-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: andand
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
55
69
  description: A Ruby interface to Kickass Torrents
56
70
  email: fissionxuiptz@softwaremojo.com
57
71
  executables:
@@ -76,7 +90,6 @@ files:
76
90
  - lib/kat/version.rb
77
91
  - test/kat/test_app.rb
78
92
  - test/kat/test_colour.rb
79
- - test/kat/test_field_map.rb
80
93
  - test/kat/test_options.rb
81
94
  - test/kat/test_search.rb
82
95
  homepage: http://github.com/fissionxuiptz/kat
@@ -99,13 +112,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
112
  version: '0'
100
113
  requirements: []
101
114
  rubyforge_project:
102
- rubygems_version: 2.0.3
115
+ rubygems_version: 2.0.14
103
116
  signing_key:
104
117
  specification_version: 4
105
118
  summary: Kickass Torrents Interface
106
119
  test_files:
107
120
  - test/kat/test_app.rb
108
121
  - test/kat/test_colour.rb
109
- - test/kat/test_field_map.rb
110
122
  - test/kat/test_options.rb
111
123
  - test/kat/test_search.rb
@@ -1,46 +0,0 @@
1
- require 'minitest/autorun'
2
- require File.dirname(__FILE__) + '/../../lib/kat/field_map'
3
-
4
- describe Kat do
5
- describe 'field map' do
6
- let(:f) { Kat::FIELD_MAP }
7
-
8
- it 'is a hash' do
9
- f.must_be_instance_of Hash
10
- end
11
-
12
- it 'has symbolised keys' do
13
- f.keys.wont_be_empty
14
- f.keys.each { |key|
15
- key.must_be_instance_of Symbol
16
- }
17
- end
18
-
19
- it 'has a hash for values' do
20
- f.values.wont_be_empty
21
- f.values.each { |value|
22
- value.must_be_instance_of Hash
23
- }
24
- end
25
-
26
- it 'has symbolised keys in each value' do
27
- f.values.each { |value|
28
- value.keys.wont_be_empty
29
- value.keys.each { |key|
30
- key.must_be_instance_of Symbol
31
- case key
32
- when :desc
33
- value[key].must_be_instance_of String
34
- when :multi, :check, :input
35
- value[key].must_equal true
36
- when :short
37
- value[key].must_be_instance_of Symbol
38
- value[key].must_match /\A([a-z]|none)\Z/
39
- else
40
- value[key].must_be_instance_of Symbol
41
- end
42
- }
43
- }
44
- end
45
- end
46
- end