kat 2.0.0 → 2.0.1

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.
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