Class: Suby::Downloader

Inherits:
Object
  • Object
show all
Defined in:
lib/suby/downloader.rb

Direct Known Subclasses

Addic7ed, OpenSubtitles, TVSubtitles

Defined Under Namespace

Classes: Addic7ed, OpenSubtitles, TVSubtitles

Constant Summary collapse

DOWNLOADERS =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, *args) ⇒ Downloader

Returns a new instance of Downloader.



17
18
19
20
21
22
23
24
# File 'lib/suby/downloader.rb', line 17

def initialize(file, *args)
  @file = file
  @lang = (args.last || 'en').to_sym
  @video_data = FilenameParser.parse(file)
  if video_data[:type] == :tvshow
    @show, @season, @episode = video_data.values_at(:show, :season, :episode)
  end
end

Instance Attribute Details

#episodeObject (readonly)

Returns the value of attribute episode.



15
16
17
# File 'lib/suby/downloader.rb', line 15

def episode
  @episode
end

#fileObject (readonly)

Returns the value of attribute file.



15
16
17
# File 'lib/suby/downloader.rb', line 15

def file
  @file
end

#langObject (readonly)

Returns the value of attribute lang.



15
16
17
# File 'lib/suby/downloader.rb', line 15

def lang
  @lang
end

#seasonObject (readonly)

Returns the value of attribute season.



15
16
17
# File 'lib/suby/downloader.rb', line 15

def season
  @season
end

#showObject (readonly)

Returns the value of attribute show.



15
16
17
# File 'lib/suby/downloader.rb', line 15

def show
  @show
end

#video_dataObject (readonly)

Returns the value of attribute video_data.



15
16
17
# File 'lib/suby/downloader.rb', line 15

def video_data
  @video_data
end

Class Method Details

.inherited(downloader) ⇒ Object



11
12
13
# File 'lib/suby/downloader.rb', line 11

def self.inherited(downloader)
  DOWNLOADERS << downloader
end

Instance Method Details

#convert_to_utf8_from_latin1(content) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/suby/downloader.rb', line 146

def convert_to_utf8_from_latin1(content)
  if content.valid_encoding?
    content
  else
    enc = content.encoding
    if content.force_encoding("ISO-8859-1").valid_encoding?
      yield if block_given?
      content.encode("UTF-8")
    else
      # restore original encoding
      subtitles.force_encoding(enc)
    end
  end
end

#downloadObject



81
82
83
84
85
86
87
88
89
# File 'lib/suby/downloader.rb', line 81

def download
  begin
    extract download_url
  rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EINVAL,
      Errno::ECONNRESET, EOFError, RuntimeError, Net::HTTPBadResponse,
      Net::HTTPHeaderSyntaxError, Net::ProtocolError => error
    raise Suby::DownloaderError, error.message
  end
end

#encode(subtitles) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
# File 'lib/suby/downloader.rb', line 165

def encode(subtitles)
  if @lang == :fr
    convert_to_utf8_from_latin1(subtitles) do
      def self.success_message
        "#{super} (transcoded from ISO-8859-1)"
      end
    end
  else
    subtitles
  end
end

#extract(url_or_response) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/suby/downloader.rb', line 99

def extract(url_or_response)
  contents = subtitles(url_or_response)
  http.finish
  format = self.class::FORMAT
  case format
  when :file
    # nothing special to do
  when :gz
    begin
      gz = Zlib::GzipReader.new(StringIO.new(contents))
      contents = gz.read
    ensure
      gz.close if gz
    end
  when :zip
    TEMP_ARCHIVE.write contents
    Suby.extract_sub_from_archive(TEMP_ARCHIVE, format, TEMP_SUBTITLES)
    contents = TEMP_SUBTITLES.read
  else
    raise "unknown subtitles format: #{format}"
  end
  sub_name(contents).write encode contents
end

#find_nfo_fileObject



142
143
144
# File 'lib/suby/downloader.rb', line 142

def find_nfo_file
  @file.dir.children.find { |file| file.ext == "nfo" }
end

#get(path, initheader = {}, parse_response = true) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/suby/downloader.rb', line 44

def get(path, initheader = {}, parse_response = true)
  if host = URI.parse(path).host and host != self.class::SITE
    raise DownloaderError, "Cross-Origin request not supported yet (#{host})"
  end
  response = http.get(path, initheader)
  if parse_response
    unless Net::HTTPSuccess === response
      raise DownloaderError, "Invalid response for #{path}: #{response}"
    end
    response.body
  else
    response
  end
end

#get_redirection(path, initheader = {}) ⇒ Object



70
71
72
73
74
75
76
77
78
79
# File 'lib/suby/downloader.rb', line 70

def get_redirection(path, initheader = {})
  response = http.get(path, initheader)
  location = response['Location']
  unless (Net::HTTPFound === response or
          Net::HTTPSuccess === response) and location
    raise DownloaderError, "Invalid response for #{path}: " +
          "#{response}: location: #{location.inspect}, #{response.body}"
  end
  location
end

#httpObject



34
35
36
# File 'lib/suby/downloader.rb', line 34

def http
  @http ||= Net::HTTP.new(self.class::SITE).start
end

#imdbidObject



135
136
137
138
139
140
# File 'lib/suby/downloader.rb', line 135

def imdbid
  @imdbid ||= begin
    nfo_file = find_nfo_file
    convert_to_utf8_from_latin1(nfo_file.read)[%r!imdb\.[^/]+/title/tt(\d+)!i, 1] if nfo_file
  end
end

#post(path, data = {}, initheader = {}) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/suby/downloader.rb', line 59

def post(path, data = {}, initheader = {})
  post = Net::HTTP::Post.new(path, initheader)
  post.form_data = data
  response = http.request(post)
  unless Net::HTTPSuccess === response
    raise DownloaderError, "Invalid response for #{path}(#{data}): " +
                           response.inspect
  end
  response.body
end

#sub_extension(contents) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/suby/downloader.rb', line 127

def sub_extension(contents)
  if contents[0..10] =~ /1\r?\n/
    'srt'
  else
    'sub'
  end
end

#sub_name(contents) ⇒ Object



123
124
125
# File 'lib/suby/downloader.rb', line 123

def sub_name(contents)
  file.sub_ext sub_extension(contents)
end

#subtitles(url_or_response = download_url) ⇒ Object



91
92
93
94
95
96
97
# File 'lib/suby/downloader.rb', line 91

def subtitles(url_or_response = download_url)
  if Net::HTTPSuccess === url_or_response
    url_or_response.body
  else
    get(url_or_response)
  end
end

#success_messageObject



161
162
163
# File 'lib/suby/downloader.rb', line 161

def success_message
  "Found"
end

#support_video_type?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/suby/downloader.rb', line 26

def support_video_type?
  self.class::SUBTITLE_TYPES.include? video_data[:type]
end

#to_sObject



30
31
32
# File 'lib/suby/downloader.rb', line 30

def to_s
  self.class.name.sub(/^.+::/, '')
end

#xmlrpcObject



38
39
40
41
42
# File 'lib/suby/downloader.rb', line 38

def xmlrpc
  @xmlrpc ||= XMLRPC::Client.new(self.class::XMLRPC_HOST, self.class::XMLRPC_PATH).tap do |xmlrpc|
    xmlrpc.http_header_extra = { 'accept-encoding' => 'identity' } if RbConfig::CONFIG['MAJOR'] == '2'
  end
end