3 # whatever-dl, a script to download online (web-based) videos.
5 # Copyright Michael Orlitzky
7 # http://michael.orlitzky.com/
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # http://www.fsf.org/licensing/licenses/gpl.html
22 # We need Pathname to get the real filesystem path
23 # of this script (and not, for example, the path of
24 # a symlink which points to it.
27 # And getoptlong to check for our one option, --continue.
30 # This bit of magic adds the parent directory (the
31 # project root) to the list of ruby load paths.
32 # Thus, our require statements will work regardless of
33 # how or from where the script was run.
34 executable
= Pathname
.new(__FILE__
).realpath
.to_s
35 $
: << File
.dirname(executable
) +
'/../'
37 # Load our config file.
38 require 'bin/configuration'
40 # And the downloaders...
41 require 'src/downloader'
43 # The Dir.glob that's coming up doesn't use the
44 # Ruby library path so we need to tell it where to
46 websites_pattern
= File
.dirname(executable
) +
'/../src/websites/*.rb'
48 # All of the website classes are located in one
49 # directory, so we can 'require' them automatically.
50 Dir
.glob(websites_pattern
).each
do |r
|
58 EXIT_COULDNT_GET_VIDEO_URL
= 3
60 EXIT_ERROR_READING_FROM_VIDEO_URL
= 5
61 EXIT_CONNECTION_REFUSED
= 6
63 EXIT_ACCESS_DENIED
= 8
68 Usage: whatever-dl [options] <url>
71 -c, --continue Continue downloading a previously-attempted file.
77 # Only actually do something if this script was called
78 # directly (i.e. not from the tests).
79 if (__FILE__
== $0) then
81 options
= { :continue => false }
83 # Parse the command-line options into the options hash.
84 opts
= GetoptLong
.new(["--continue", "-c", GetoptLong
::NO_ARGUMENT],
85 ["--help", "-h", GetoptLong
::NO_ARGUMENT])
87 opts
.each
do |opt
, arg
|
91 Kernel
.exit(EXIT_SUCCESS
)
93 options
[:continue] = true
97 # Warn about nonsensical options.
98 if options
[:continue] and not (Configuration
::DOWNLOAD_METHOD == :wget)
99 puts
'WARNING: The --continue flag does nothing unless DOWNLOAD_METHOD is :wget.'
102 # Note that GetoptLong steals its arguments from ARGV, so we don't need
103 # to take optional arguments into account when figuring out whether or not
104 # we were passed a URL.
105 if (ARGV.length
< 1) then
106 # If the user didn't give us a URL, yell
109 Kernel
.exit(EXIT_NO_URL
)
113 site
= Website
.create(ARGV[0])
117 exit(EXIT_INVALID_URL
)
120 video_url
= site
.get_video_url()
123 puts
'Error retrieving video URL.'
124 exit(EXIT_COULDNT_GET_VIDEO_URL
)
127 # The Downloader class is a factory; it should decide
128 # which subclass we get.
129 downloader
= Downloader
.create(Configuration
::DOWNLOAD_METHOD)
131 # Attempt to download the file, and rescue and report
132 # any (predictable) exceptions. The wget downloader will
133 # naturally not report any of these, since it will die in
136 downloader
.download(video_url
,
137 site
.get_video_filename(),
138 continue
=options
[:continue])
139 rescue Errno
::ECONNREFUSED => e
140 puts
'The connection to the server (to download the video file) was refused. Check your connection, and try again later.'
141 Kernel
.exit(EXIT_CONNECTION_REFUSED
)
142 rescue Errno
::EACCES => e
143 puts
"Access denied. Check that you have write permission to the output file/directory. Details: #{e.message}."
144 rescue OpenURI
::HTTPError => e
145 puts
"An HTTP error occurred while downloading the video file: #{e.message}."
146 Kernel
.exit(EXIT_HTTP_ERROR
)
148 puts
"Input/Output Error: #{e.message}"
149 Kernel
.exit(EXIT_IO_ERROR
)
152 # Write an empty line at the end for aesthetic reasons.
155 Kernel
.exit(EXIT_SUCCESS
)