addic7ed_downloader 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,90 @@
1
+ require 'httparty'
2
+ require 'nokogiri'
3
+
4
+ module Addic7edDownloader
5
+ class Search
6
+ BASE_URL = 'http://www.addic7ed.com'.freeze
7
+ DEFAULTS = {
8
+ lang: 'en',
9
+ tags: [],
10
+ path: './'
11
+ }.freeze
12
+
13
+ attr_accessor :showname, :season, :episode, :lang, :tags, :path
14
+
15
+ def initialize(showname, season, episode, options = {})
16
+ @showname = showname
17
+ @season = season.to_i
18
+ @episode = episode.to_i
19
+
20
+ opts = DEFAULTS.merge(options)
21
+ @lang, @tags, @path = opts.values_at(:lang, :tags, :path)
22
+ end
23
+
24
+ def results
25
+ @results ||= build_subtitles_list
26
+ end
27
+
28
+ def find_best_subtitle
29
+ return if results.empty?
30
+
31
+ # We can refine the search with tags
32
+ # Only version match
33
+ unless @tags.empty?
34
+ results.each do |subtitle|
35
+ return subtitle if @tags.include?(subtitle.version) && subtitle.completed?
36
+ end
37
+ end
38
+
39
+ # If no matches, return most downloaded
40
+ results.first
41
+ end
42
+
43
+ def download_best
44
+ download_subtitle(find_best_subtitle)
45
+ end
46
+
47
+ def download_subtitle(subtitle)
48
+ return unless subtitle
49
+
50
+ # Addic7ed needs the correct Referer to be set
51
+ response = HTTParty.get(
52
+ BASE_URL + subtitle.url,
53
+ headers: { 'Referer' => url, 'User-Agent' => USER_AGENTS.sample }
54
+ )
55
+
56
+ raise unless response.headers['content-type'].include? 'text/srt'
57
+
58
+ filename = response.headers['content-disposition'][/filename=\"(.+?)\"/, 1]
59
+ open(filename, 'w') { |f| f << response }
60
+
61
+ # return subtitle filename
62
+ filename
63
+ end
64
+
65
+ private
66
+
67
+ def page
68
+ @page ||= Nokogiri::HTML(HTTParty.get(url, headers: { 'User-Agent' => USER_AGENTS.sample }))
69
+ end
70
+
71
+ def url
72
+ @url ||= URI.encode("#{BASE_URL}/serie/#{@showname}/#{@season}/#{@episode}/#{LANGUAGES[@lang][:id]}")
73
+ end
74
+
75
+ def build_subtitles_list
76
+ # If it doesn't find the episode it redirects to the homepage
77
+ return [] if page.at('#containernews')
78
+
79
+ # If it doesn't find the subtitle it shows a message
80
+ return [] if page.at(%q(font:contains("Couldn't find any subs")))
81
+
82
+ # Create a list with results
83
+ subtitles = page.css('div#container95m').each_with_object([]) do |subtitle, list|
84
+ list << Addic7ed::Subtitle.new(subtitle) if subtitle.at('.NewsTitle')
85
+ end
86
+
87
+ subtitles.sort!.reverse!
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,12 @@
1
+ module Addic7edDownloader
2
+ module SearchFilename
3
+ def self.search(filename, options = {})
4
+ showname = filename[SHOWNAME_REGEXP, 1].strip
5
+ season = filename[SEASON_REGEXP, 1].to_i
6
+ episode = filename[EPISODE_REGEXP, 1].to_i
7
+ options[:tags] = filename[TAGS_REGEXP, 1].split(TAGS_FILTER_REGEXP)
8
+
9
+ Search.new(showname, season, episode, options)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Addic7edDownloader
2
+ module SearchString
3
+ def self.search(search_string, options = {})
4
+ showname = search_string[SHOWNAME_REGEXP, 1].strip
5
+ season = search_string[SEASON_REGEXP, 1].to_i
6
+ episode = search_string[EPISODE_REGEXP, 1].to_i
7
+ options[:tags] = options[:filename][TAGS_REGEXP, 1].split(TAGS_FILTER_REGEXP)
8
+
9
+ Search.new(showname, season, episode, options)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,54 @@
1
+ module Addic7edDownloader
2
+ class Subtitle
3
+ include Comparable
4
+ attr_accessor :version, :language, :url, :downloads, :notes
5
+
6
+ def initialize(nokogiri_fragment)
7
+ @version = nokogiri_fragment.at('.NewsTitle').text[/\AVersion (.*?),/, 1]
8
+ @language = nokogiri_fragment.at('.language').text.strip
9
+ @complete = nokogiri_fragment.at('table tr:nth-child(3) td:nth-child(4)').text.strip
10
+ @url = generate_download_url(nokogiri_fragment)
11
+ @notes = nokogiri_fragment.at('.newsDate').text.strip
12
+ @hi = nokogiri_fragment.css('.newsDate').last.children[1]['title'] == 'Hearing Impaired'
13
+ @downloads = nokogiri_fragment.css('.newsDate').last.text[/(\d+) Downloads/, 1].to_i
14
+ end
15
+
16
+ def to_s
17
+ str = "Version #{@version} (#{@language}): #{@complete} [#{@downloads} Downloads]"
18
+ str << " — #{@notes}" unless @notes.empty?
19
+ str
20
+ end
21
+
22
+ # We can sort by downloads number
23
+ def <=>(other)
24
+ @downloads <=> other.downloads
25
+ end
26
+
27
+ def completed?
28
+ # 'Completed' or '33.37% Completed'
29
+ @complete == 'Completed'
30
+ end
31
+
32
+ def hearing_impaired?
33
+ @hi
34
+ end
35
+
36
+ def works_with?(tag)
37
+ @notes[/works? with \"?([^\"\s]+)/i, 1].downcase.include? tag.downcase
38
+ end
39
+
40
+ private
41
+
42
+ def generate_download_url(nokogiri_fragment)
43
+ links = nokogiri_fragment.css('.buttonDownload')
44
+
45
+ case links.length
46
+ when 1
47
+ links[0]['href']
48
+ # If there are two download buttons, the second is the "most updated"
49
+ when 2
50
+ links[1]['href']
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,3 @@
1
+ module Addic7edDownloader
2
+ VERSION = '0.1.1'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,217 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: addic7ed_downloader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - David Marchante
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-05-08 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: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: highline
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: httparty
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.13'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '4.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '4.6'
111
+ - !ruby/object:Gem::Dependency
112
+ name: factory_girl
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.24'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.24'
139
+ - !ruby/object:Gem::Dependency
140
+ name: pry
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.10'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.10'
153
+ - !ruby/object:Gem::Dependency
154
+ name: pry-byebug
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '3.3'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '3.3'
167
+ description:
168
+ email:
169
+ - davidmarchan@gmail.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".gitignore"
175
+ - ".rspec"
176
+ - ".travis.yml"
177
+ - Gemfile
178
+ - Guardfile
179
+ - LICENSE.txt
180
+ - README.md
181
+ - Rakefile
182
+ - addic7ed_downloader.gemspec
183
+ - bin/console
184
+ - bin/setup
185
+ - lib/addic7ed_downloader.rb
186
+ - lib/addic7ed_downloader/common.rb
187
+ - lib/addic7ed_downloader/search.rb
188
+ - lib/addic7ed_downloader/search_filename.rb
189
+ - lib/addic7ed_downloader/search_string.rb
190
+ - lib/addic7ed_downloader/subtitle.rb
191
+ - lib/addic7ed_downloader/version.rb
192
+ homepage: https://github.com/iovis9/addic7ed_downloader
193
+ licenses:
194
+ - MIT
195
+ metadata: {}
196
+ post_install_message:
197
+ rdoc_options: []
198
+ require_paths:
199
+ - lib
200
+ required_ruby_version: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ version: '0'
205
+ required_rubygems_version: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
210
+ requirements: []
211
+ rubyforge_project:
212
+ rubygems_version: 2.6.4
213
+ signing_key:
214
+ specification_version: 4
215
+ summary: Search and download subtitles from Addic7ed.
216
+ test_files: []
217
+ has_rdoc: