p3-eztv 0.0.7

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8ab92a3ca25bec774bd2a32f97959abcb970c134
4
+ data.tar.gz: f12a355129da5d3f8a09c077103190bf71704c12
5
+ SHA512:
6
+ metadata.gz: eaad6c86a40a0c63d484a3da0fabd2a54a6c1ece7915d399ccd7484a7593b372f8fcb6af32682347ae084fdd0df4d3d5da7e5e48b0e6124ba99adfa5e00408cd
7
+ data.tar.gz: 61f1fa16b72a608c19d0f460840e98a9ce824470498b256fe4339b8eb7d469920d97328d4c4867c8c217548deef8f6d0d2ae05505c8e8919058ba4b266d9ac9d
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in p3-eztv.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Damir Svrtan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,68 @@
1
+ # P3::Eztv
2
+ [![Gem Version](https://badge.fury.io/rb/p3-eztv.svg)](http://badge.fury.io/rb/p3-eztv)
3
+
4
+ EZTV Search API: Parses EZTV.ag's HTML as they do not have a clean REST API
5
+
6
+ ## Installation
7
+
8
+ $ gem install p3-eztv
9
+
10
+ ## Usage
11
+
12
+ Fetch a series and get all the magnet links:
13
+ ```ruby
14
+ require 'p3-eztv'
15
+
16
+ white_collar = P3::Eztv::Series.new("white collar")
17
+
18
+ white_collar.episodes.each do |episode|
19
+ puts episode.magnet_link
20
+ end
21
+ ```
22
+
23
+ Get all regular torrent download links from S01E01:
24
+
25
+ ```ruby
26
+ white_collar.episode(1,1).links
27
+ # ["//torrent.zoink.it/White.Collar.S01E01.Pilot.HDTV.XviD-FQM.[eztv].torrent",
28
+ # "http://www.mininova.org/tor/3077342",
29
+ # "http://www.bt-chat.com/download.php?info_hash=e0e74306adca549be19b147b5ee14bde1b99bb1d"]
30
+ ```
31
+
32
+ Get number of seasons or number of episodes per season:
33
+ ```ruby
34
+ puts "Number of seasons: #{white_collar.seasons.count}"
35
+ # Number of seasons: 5
36
+ puts "Number of episodes in season 1: #{white_collar.season(1).count}"
37
+ # Number of episodes in season 1: 13
38
+ ```
39
+
40
+ Get the last episode of the latest season in S01E01 format:
41
+ ```ruby
42
+ white_collar.episodes.last.s01e01_format
43
+ # S05E13
44
+ ```
45
+
46
+ Fetch an episode in S01E01 format:
47
+ ```ruby
48
+ white_collar.get('S03E05')
49
+ # P3::Eztv::Episode.new
50
+ ```
51
+ There will be an error raised if you browsed for a non existing series:
52
+ ```ruby
53
+ nonny = P3::Eztv::Series.new("nonny")
54
+ begin
55
+ nonny.episodes
56
+ rescue P3::Eztv::SeriesNotFoundError => e
57
+ puts e.message
58
+ # "Unable to find 'nonny' on https://eztv.it."
59
+ end
60
+ ```
61
+
62
+ ## Contributing
63
+
64
+ 1. Fork it.
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create new Pull Request
@@ -0,0 +1,128 @@
1
+ require 'httparty'
2
+ require 'nokogiri'
3
+ require 'uri'
4
+
5
+ module P3
6
+ module Eztv
7
+ SE_FORMAT = /S(\d{1,2})E(\d{1,2})/
8
+ X_FORMAT = /(\d{1,2})x(\d{1,2})/
9
+
10
+ class SeriesNotFoundError < StandardError
11
+ def initialize(series)
12
+ msg = "Unable to find '#{series.name}' on https://eztv.ag."
13
+ super(msg)
14
+ end
15
+ end
16
+
17
+ class Series
18
+ include HTTParty
19
+ attr_reader :name
20
+ EPISODES_XPATH = '//*[@id="header_holder"]/table[5]'
21
+
22
+ base_uri 'http://eztv.ag'
23
+
24
+ def initialize(name)
25
+ @name = URI::escape( name )
26
+ end
27
+
28
+ def high_def!
29
+ @name = "#{@name}%20720p"
30
+ end
31
+
32
+ def episodes
33
+ @episodes ||= EpisodeFactory.create( fetch_episodes() )
34
+ end
35
+
36
+ def episode(season, episode_number)
37
+ episodes().find do |episode|
38
+ episode.season == season and episode.episode_number == episode_number
39
+ end
40
+ end
41
+
42
+ def get(s01e01_format)
43
+ season_episode_match_data = s01e01_format.match( SE_FORMAT )
44
+ season = season_episode_match_data[1].to_i
45
+ episode_number = season_episode_match_data[2].to_i
46
+ return episode(season, episode_number)
47
+ end
48
+
49
+ def season(season)
50
+ episodes().find_all {|episode| episode.season == season }
51
+ end
52
+
53
+ def seasons
54
+ episodes().sort.group_by {|episode| episode.season }
55
+ end
56
+
57
+ private
58
+
59
+ def fetch_episodes
60
+
61
+ # 'get' method comes from httparty
62
+ result = Series::get("/search/#{name}")
63
+
64
+ document = Nokogiri::HTML(result)
65
+
66
+ episodes_array = document.xpath( EPISODES_XPATH )
67
+
68
+ episodes_array = episodes_array.children
69
+ episodes_array = episodes_array.select{ | episode | episode.attributes['class'].to_s == 'forum_header_border' }
70
+
71
+ raise SeriesNotFoundError.new(self) if episodes_array.empty?
72
+
73
+ return episodes_array
74
+ end
75
+ end
76
+
77
+ module EpisodeFactory
78
+ def self.create( episodes_array )
79
+ episodes = []
80
+ episodes_array.reverse.collect do |episode|
81
+ begin
82
+ # Episode will throw if it can't parse
83
+ episodes << Episode.new( episode )
84
+ rescue
85
+ end
86
+ end
87
+ return episodes.uniq
88
+ end
89
+ end
90
+
91
+ class Episode
92
+ attr_accessor :season, :episode_number, :links, :magnet_link, :raw_title
93
+
94
+ def initialize(episode_node)
95
+ set_season_and_episode_number(episode_node)
96
+ set_links(episode_node)
97
+ end
98
+
99
+ def s01e01_format
100
+ @s01e01_format ||= "S#{season.to_s.rjust(2,'0')}E#{episode_number.to_s.rjust(2,'0')}"
101
+ end
102
+
103
+ def eql?(other)
104
+ other.hash == self.hash
105
+ end
106
+
107
+ def hash
108
+ [episode_number, season].hash
109
+ end
110
+
111
+ private
112
+
113
+ def set_season_and_episode_number(episode_node)
114
+ @raw_title = episode_node.css('td.forum_thread_post a.epinfo').first.inner_text
115
+ season_episode_match_data = @raw_title.match( SE_FORMAT ) || @raw_title.match( X_FORMAT )
116
+ raise unless season_episode_match_data
117
+ @season = season_episode_match_data[1].to_i
118
+ @episode_number = season_episode_match_data[2].to_i
119
+ end
120
+
121
+ def set_links(episode_node)
122
+ links_data = episode_node.css('td.forum_thread_post')[2]
123
+ @magnet_link = links_data.css('a.magnet').first.attributes['href'].value
124
+ @links = links_data.css('a')[2..-1].map {|a_element| a_element['href'] }
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "p3-eztv"
7
+ spec.version = "0.0.7"
8
+ spec.authors = ["Damir Svrtan", "Poul Hornsleth"]
9
+ spec.email = ["poulh@umich.edu"]
10
+ spec.summary = "EZTV Search API"
11
+ spec.description = "Parses EZTV.ag's HTML as they do not have a clean REST API"
12
+ spec.homepage = "https://github.com/poulh/p3-eztv"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_runtime_dependency "nokogiri", "~> 1.6.8.1"
20
+ spec.add_runtime_dependency "httparty", "~> 0.13.7"
21
+
22
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: p3-eztv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Damir Svrtan
8
+ - Poul Hornsleth
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-02-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 1.6.8.1
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 1.6.8.1
28
+ - !ruby/object:Gem::Dependency
29
+ name: httparty
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 0.13.7
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: 0.13.7
42
+ description: Parses EZTV.ag's HTML as they do not have a clean REST API
43
+ email:
44
+ - poulh@umich.edu
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - .gitignore
50
+ - .travis.yml
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - lib/p3-eztv.rb
55
+ - p3-eztv.gemspec
56
+ homepage: https://github.com/poulh/p3-eztv
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.0.14.1
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: EZTV Search API
80
+ test_files: []