Added a factory method to the website class which creates the appropriate subclass based on the URL given to it.
Added a get_video_filename method to the website class.
Made two Website methods abstract via NotImplementedError, get_video_url and owns_url?.
Created a default implementation of get_video_filename in the Website class.
Made the site URL member data of the Website class.
Fixed a bug in the URL handling for Youtube.
Added output stating the filename for the download.
Replaced all code in the classes/tests to accommodate the other changes.
Kernel.exit(EXIT_NO_URL)
end
- # Check the URL against each website's class.
- # The class will know whether or not the URL
- # "belongs" to its website.
-
- site = nil
-
- Website.subclasses.each do |w|
- if w.owns_url?(ARGV[0])
- site = w.new()
- break
- end
- end
+ # Factory method.
+ site = Website.create(ARGV[0])
if site.nil?
puts 'Invalid URL.'
exit(EXIT_INVALID_URL)
end
- video_url = site.get_video_url(ARGV[0])
+ video_url = site.get_video_url()
if video_url.nil?
puts 'Error retrieving video URL.'
video_uri = URI.parse(video_url)
uu = UriUtilities.new()
-
- # Here, we start out with a default file name and
- # extension. If UriUtilities can parse a sane filename
- # out of the URL, we'll use that. Otherwise, we fall
- # back to the default.
- outfile_name = 'default.ext'
-
- if not uu.get_filename(video_uri).nil?
- outfile_name = uu.get_filename(video_uri)
- else
- puts "We couldn't determine the video's filename. Falling back to the default, #{outfile_name}."
- end
-
-
- if File.exists?(outfile_name)
- puts "Error: output file already exists. Please remove #{outfile_name}, and try again."
+ if File.exists?(site.get_video_filename())
+ puts "Error: output file already exists. Please remove #{site.get_video_filename()}, and try again."
Kernel.exit(EXIT_OUTPUT_FILE_ALREADY_EXISTS)
end
# any (predictable) exceptions.
begin
puts "Fetching #{video_url}"
- uu.download_with_progress_bar(video_uri, outfile_name)
+ puts "Saving as #{site.get_video_filename()}."
+ puts ""
+ uu.download_with_progress_bar(video_uri, site.get_video_filename())
rescue Errno::ECONNREFUSED => e
puts 'The connection to the server (to download the video file) was refused. Check your connection, and try again later.'
Kernel.exit(EXIT_CONNECTION_REFUSED)
Kernel.exit(EXIT_HTTP_ERROR)
end
+ # Write an empty line at the end for aesthetic reasons.
+ puts ""
+
Kernel.exit(EXIT_SUCCESS)
end
-1) Refactor the download file naming procedure so that it's the
- responsibility of the website (sub)class.
-
-2) Possibly generalize the http retrieval process (get_page_data et
+1) Possibly generalize the http retrieval process (get_page_data et
al) into a Website method.
# for trouble.
class UriUtilities
- # Get the filename portion of a given URI.
- # Return nil if there is no filename portion.
- def get_filename(uri)
- return uri.path.split('/').last
- end
-
-
# Download the given URI object to <outfile_name>.
# Should use the progress_proc parameter to show
# a progress bar using the Ruby/ProgressBar library.
# We wrap the whole thing in a begin/rescue so that
# we can clean up afterwards in case of an error.
begin
- open(outfile_name, 'wb') do |outfile|
+ File.open(outfile_name, 'wb') do |outfile|
pbar = nil
uri.open(:content_length_proc => lambda {|content_length|
if content_length && (0 < content_length)
# We use this to loop through every "website" in an
# attempt to determine to which site a URL belongs.
class Website
+
+ protected;
+
+ @url = nil
+
+
def self.inherited(subclass)
if superclass.respond_to? :inherited
superclass.inherited(subclass)
@subclasses << subclass
end
- def self.subclasses
- @subclasses
+
+ public;
+
+ def initialize(url)
+ @url = url
end
- # This should be overridden in any class that wants
- # to claim ownership of a URL.
+
+ def self.create(url)
+ # Factory method returning an instance of
+ # the appropriate subclass.
+
+ # Check the URL against each website's class.
+ # The class will know whether or not the URL
+ # "belongs" to its website.
+ @subclasses.each do |w|
+ if w.owns_url?(url)
+ return w.new(url)
+ end
+ end
+
+ # If nothing matched, we don't return an instance
+ # of anything.
+ return nil
+ end
+
+
+ # Abstract definition. Each subclass of Website
+ # should support it on its own.
def self.owns_url?(url)
- return false
+ raise NotImplementedError
end
- # Same here. We want to default to nil unless overridden.
- def get_video_url(url)
- return nil
+
+ # Same here. Abstract.
+ def get_video_url()
+ raise NotImplementedError
+ end
+
+
+ # The website class should be responsible for determining the
+ # video's filename. By default, we can take the last component
+ # of the video URL, but in some cases, subclasses will want
+ # to override this behavior.
+ def get_video_filename()
+ # Use whatever comes after the final front slash.
+ return get_video_url().split('/').pop()
end
+
end
return url =~ VALID_HOWCAST_URL_REGEX
end
-
- def get_video_url(url)
+
+ def parse_video_id()
# This regex just pulls out the video id
id_regex = /\/(\d+)-/
- matches = id_regex.match(url)
+ matches = id_regex.match(@url)
if matches.nil?
raise StandardError.new('The URL is a valid Howcast URL, but does not match on the digit portion of the regex. Since the digit portion is a subset of the "valid" regex, this should never occur.')
end
+
+ return matches[1]
+ end
- video_id = matches[1]
+
+ def get_video_url()
+ video_id = parse_video_id()
+
return "http://media.howcast.com/system/videos/#{video_id}/#{video_id}.flv"
end
-
+
end
end
- def get_video_url(url)
- page_data = self.get_page_data(url)
+ def get_video_url()
+ page_data = self.get_page_data(@url)
video_url = self.parse_video_url(page_data)
return video_url
end
# The only public method. This calls the other parts
# of the algorithm and, with any luck, we wind up with
# the URL to the video.
- def get_video_url(url)
+ def get_video_url()
# First, parse the video ID out of the URL.
- video_id = /\d+/.match(url)[0]
+ video_id = parse_video_id()
padded_id = video_id.to_s.pad_left('0', 7)
protected
VIDEO_FILE_EXTENSION = '.flv'
+
+ def parse_video_id()
+ return /\d+/.match(@url)[0]
+ end
+
# Not sure what they're thinking with this one.
def get_video_dir(video_id)
end
- def get_video_url(url)
+ def get_video_url()
# First, figure out the video id from the URL.
# Then, use the video id to construct the video details URL.
# Get the video details page, and parse the redirect
# id from the redirect, but for now we're going to rely
# on our HTTP library to follow the redirect for us and
# save us a step.
- video_id = parse_video_id(url)
+ video_id = self.parse_video_id()
details_url = "http://www.veoh.com/rest/video/#{video_id}/details"
details_data = get_page_data(details_url)
redirect_url = parse_redirect_url(details_data)
- # Being slightly explicit about what we're doing here...
- video_url = redirect_url
-
- return video_url
+ # We trust our HTTP library to do the right thing here.
+ return redirect_url
end
+
+ def get_video_filename()
+ return (self.parse_video_id() + '.flv')
+ end
protected;
- def parse_video_id(url)
+ def parse_video_id()
video_id_regex = /[[:alnum:]]+$/
- matches = video_id_regex.match(url)
+ matches = video_id_regex.match(@url)
video_id = matches[0] if not matches.nil?
return video_id
def get_page_data(url)
uri = URI.parse(url)
-
+
response = Net::HTTP.start(uri.host, uri.port) do |http|
http.get(uri.path)
end
end
- def get_video_url(url)
+ def get_video_url()
# First, figure out the video id from the URL.
# Then, use the video id to construct the video details URL.
# Get the video details page, and parse the resulting XML for
# the junk we need to construct the video URL. Note that the file
# URL given in the XML is *not* valid.
- video_id = parse_video_id(url)
+ video_id = self.parse_video_id()
details_url = "http://www.vimeo.com/moogaloop/load/clip:#{video_id}/local"
details_data = get_page_data(details_url)
return video_url
end
+
+ def get_video_filename()
+ # The default behavior is no good here, use the video
+ # id with an extension tacked onto it.
+ return (self.parse_video_id() + '.flv')
+ end
+
protected;
- def parse_video_id(url)
+ def parse_video_id()
video_id = nil
# First, try to get the video id from the end of the URL.
video_id_regex = /\/(\d+)$/
- matches = video_id_regex.match(url)
+ matches = video_id_regex.match(@url)
if matches.nil?
# If that didn't work, the URL must be of the clip_id= form.
video_id_regex = /clip_id\=(\d+)/
- matches = video_id_regex.match(url)
+ matches = video_id_regex.match(@url)
video_id = matches[1] if not (matches.nil? || matches.length < 1)
else
video_id = matches[1] if not (matches.nil? || matches.length < 1)
class Youporn < Website
- VALID_YOUPORN_URL_REGEX = /^(http:\/\/)?(www\.)?youporn\.com\/watch\/(\d+)$/
+ VALID_YOUPORN_URL_REGEX = /^(http:\/\/)?(www\.)?youporn\.com\/watch\/(\d+)(\/.*)?$/
def self.owns_url?(url)
return url =~ VALID_YOUPORN_URL_REGEX
end
- def get_video_url(url)
- page_data = self.get_page_data(url)
+ def get_video_url()
+ page_data = self.get_page_data(@url)
video_url = self.parse_video_url(page_data)
return video_url
end
response = Net::HTTP.start(uri.host, uri.port) do |http|
# Bypass the stupid age verification.
form_data = 'user_choice=Enter'
- http.post(uri.path, form_data, self.get_headers(url))
+ http.post(uri.path, form_data, self.get_headers())
end
return response.body
end
# Build the header hash from the URL we're requesting.
- def get_headers(url)
- headers = { 'Referer' => url }
+ def get_headers()
+ headers = { 'Referer' => @url,
+ 'Content-Type' => 'application/x-www-form-urlencoded' }
end
class Youtube < Website
- VALID_YOUTUBE_URL_REGEX = /^(http:\/\/)?(www\.)?youtube\.com\/((watch\?v=)|(v\/))[[:alnum:]]+(\&.*)?\#?$/
+ VALID_YOUTUBE_URL_REGEX = /^(http:\/\/)?(www\.)?youtube\.com\/((watch\?v=)|(v\/))[a-z0-9_\-]+(\&.*)?\#?$/i
def self.owns_url?(url)
return url =~ VALID_YOUTUBE_URL_REGEX
end
- def get_video_url(url)
- video_id = self.parse_video_id(url)
+ def get_video_url()
+ video_id = self.parse_video_id()
# The video's URL (the "page data" URL) may be different from the
# URL that was passed to the program. We support the /v/video_id
return video_url
end
+
+ def get_video_filename()
+ return (self.parse_video_id() + '.flv')
+ end
+
protected;
# Get the video id from the URL. Should be relatively easy,
# unless Youtube supports some URL formats of which I'm unaware.
- def parse_video_id(url)
+ def parse_video_id()
# Return nil if we get no matches below.
video_id = nil
# them one at a time. The only tricky situation is when
# parameters like "&hl=en" are tacked on to the end.
# We'll call /watch?v=video_id the "first form."
- first_form_video_id_regex = /v=([[:alnum:]]+)$/
- first_form_matches = first_form_video_id_regex.match(url)
+ first_form_video_id_regex = /v=([0-9a-z_\-]+)/i
+ first_form_matches = first_form_video_id_regex.match(@url)
return first_form_matches[1] if not (first_form_matches.nil? ||
first_form_matches.length < 2)
# First form didn't work? Try the second.
- second_form_video_id_regex = /\/v\/([[:alnum:]]+)/
- second_form_matches = second_form_video_id_regex.match(url)
+ second_form_video_id_regex = /\/v\/([0-9a-z_\-]+)/i
+ second_form_matches = second_form_video_id_regex.match(@url)
video_id = second_form_matches[1] if not (second_form_matches.nil? ||
second_form_matches.length < 2)
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ \r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ \r
+\r
+<videos offset="0" items="1" numItems="1" title="" guid="6520470f-6730-403a-8f80-a800fb4239f8" >\r
+\r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ \r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+\r
+\r
+ \r
+ \r
+ \r
+ \r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ \r
+ \r
+\r
+ \r
+ \r
+\r
+ \r
+ \r
+\r
+ \r
+ \r
+\r
+ \r
+ \r
+\r
+ \r
+ \r
+\r
+\r
+\r
+\r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+<video videoId="15795090"\r
+ uploadToken=""\r
+ permalinkId="v15795090Z6mZAbSq"\r
+ extension=".mov"\r
+ length="1 min 33 sec"\r
+ size="18605143"\r
+ releaseHash=""\r
+ tags="health aetna magic johnson aging life@50 basketball"\r
+ tagsCommaSeparated=" health, aetna, magic johnson, aging, life@50, basketball"\r
+ previewHash="3f8044ce2538155c55af5c036cd96ba82a83ddb5"\r
+ fullPreviewHashPath="http://content.veoh.com/flash/f/2/v15795090Z6mZAbSq/3f8044ce2538155c55af5c036cd96ba82a83ddb5.flv?ct=ff4914d2e699e8ad04a69102faaab6ce82b7704998890f69" \r
+ fullPreviewToken=""\r
+ previewHashLow="52d2992ab57d6a53044cd2e0675d386dcd477003"\r
+ fullPreviewHashLowPath="http://content.veoh.com/flash/p/2/v15795090Z6mZAbSq/3f8044ce2538155c55af5c036cd96ba82a83ddb5.flv?ct=2de922866d56e92db1797cecff28f7c13f192be0a1e1e014" \r
+ fullPreviewTokenLow=""\r
+ highResImage="media-v15795090Z6mZAbSq1220545508.jpeg"\r
+ fullHighResImagePath="http://ll-images.veoh.com/image.out?imageId=media-v15795090Z6mZAbSq1220545508.jpeg"\r
+ medResImage="media-v15795090Z6mZAbSq1220545508.jpeg"\r
+ fullMedResImagePath="http://ll-images.veoh.com/image.out?imageId=media-v15795090Z6mZAbSq1220545508.jpeg"\r
+ username="MJenterprises"\r
+ views="546"\r
+ rating="5.0"\r
+ numRatingVotes="1"\r
+ description="Magic Johnson discusses turning 50 years old and living a healthy lifestyle."\r
+ title="Magic Johnson On Healthy Living"\r
+ dateAdded="2008-08-29 06:44:00"\r
+ age="1 week ago"\r
+ primaryCollectionPermalink=""\r
+ primaryCollectionTitle=""\r
+ primaryCollectionThumb=""\r
+ allowEmbedding="true"\r
+ premium="false"\r
+ paidContent="false" \r
+ \r
+ \r
+ portable="false" \r
+ ipodLink="" \r
+ showStreamingAd="1"\r
+ showCompanionAd="false"\r
+ \r
+ \r
+ houseAdDetailsUrl=""\r
+ houseAdPlacement="-1"\r
+ geoRestrictions=""\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+ flashHash=""\r
+ flashExtension=""\r
+ flashPieceHashFile="http://p-cache.veoh.com/cache/veoh/.veoh"\r
+ flashUrlRoot="http://p-cache.veoh.com/cache"\r
+ \r
+ originalHash="d569b9d5efdd2d5efa541b2f7d36d2c6d693aaa4"\r
+ origExtension=".mov" \r
+ originalPieceHashFile="http://p-cache.veoh.com/cache/veoh/d569b9d5efdd2d5efa541b2f7d36d2c6d693aaa4.veoh"\r
+ originalUrlRoot="http://p-cache.veoh.com/cache"\r
+ \r
+ \r
+ contentRating="1"\r
+ \r
+\r
+ \r
+ \r
+ \r
+ licenseId=""\r
+ licenseName=""\r
+ licenseType=""\r
+ licenseExpires=""\r
+ licensePrice=""\r
+ licenseDuration=""\r
+ licenseTimeUnits=""\r
+ \r
+ \r
+ \r
+ \r
+ aowPublisherName=""\r
+ aowPermalink=""\r
+ aowEmbedCode=""\r
+ aowGuideVideoId=""\r
+ \r
+ \r
+ isExternalMedia="false"\r
+ isDotComPlayable="true"\r
+ isTvPlayable="true"\r
+>\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+ <categories>\r
+ \r
+ <category></category>\r
+ \r
+ <category></category>\r
+ \r
+ <category></category>\r
+ \r
+ </categories>\r
+ \r
+\r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+</video>\r
+\r
+ \r
+</videos>\r
+ \r
+ \r
+ \r
+ \r
+\r
class InfoqRemoteTest < Test::Unit::TestCase
def test_get_page_data
- iq = Infoq.new()
+ iq = Infoq.new('http://www.infoq.com/interviews/jim-weirich-discusses-rake')
+ expected_result = 'http://flv.thruhere.net/interviews/JimWeirich.flv'
+ actual_result = iq.get_video_url()
+ assert_equal(expected_result, actual_result)
+ end
- # We can't rely on the fixture here, because Infoq might
- # change their page layout. Instead, check that we can actually
- # find the base64 regex (containing the FLV URL).
- page_data = iq.send('get_page_data', 'http://www.infoq.com/interviews/jim-weirich-discusses-rake')
-
- test_result = iq.get_video_url(page_data)
- assert_equal('http://flv.thruhere.net/interviews/JimWeirich.flv', test_result)
+
+ def test_superclass_get_filename_works
+ iq = Infoq.new('http://www.infoq.com/interviews/jim-weirich-discusses-rake')
+ expected_result = 'JimWeirich.flv'
+ actual_result = iq.get_video_filename()
+ assert_equal(expected_result, actual_result)
end
-
+
end
def test_parse_video_url
- iq = Infoq.new()
+ iq = Infoq.new(nil)
page_data = nil
def test_get_video_url
- rt = Redtube.new()
-
- test_result = rt.get_video_url('http://www.redtube.com/6807')
- assert_equal("http://dl.redtube.com/_videos_t4vn23s9jc5498tgj49icfj4678/0000006/X57OBH08G.flv", test_result)
+ rt = Redtube.new('http://www.redtube.com/6807')
+ expected_result = 'http://dl.redtube.com/_videos_t4vn23s9jc5498tgj49icfj4678/0000006/X57OBH08G.flv'
+ actual_result = rt.get_video_url()
+ assert_equal(expected_result, actual_result)
end
+
+ def test_get_video_filename
+ rt = Redtube.new('http://www.redtube.com/6807')
+ # I don't know where they get these filenames from, but whatever.
+ expected_result = 'X57OBH08G.flv'
+ actual_result = rt.get_video_filename()
+ assert_equal(expected_result, actual_result)
+ end
end
class UriUtilitiesTest < Test::Unit::TestCase
- def test_filename
- uu = UriUtilities.new()
- example_uri = 'http://www.example.com/whatever.avi'
- uri = URI.parse(example_uri)
- assert_equal('whatever.avi', uu.get_filename(uri))
- end
-
-
- def test_no_filename_results_in_nil
- uu = UriUtilities.new()
- example_uri = 'http://www.example.com'
- uri = URI.parse(example_uri)
- assert(uu.get_filename(uri).nil?)
- end
-
-
- def test_no_filename_with_trailing_slash_results_in_nil
- uu = UriUtilities.new()
- example_uri = 'http://www.example.com/'
- uri = URI.parse(example_uri)
- assert(uu.get_filename(uri).nil?)
- end
-
-
def test_system_call_exception_on_connection_refused
uu = UriUtilities.new()
class VeohTest < Test::Unit::TestCase
def test_parse_video_id
- v = Veoh.new
- video_id = v.send('parse_video_id', 'http://www.veoh.com/videos/v801204yMZ8BWcC')
+ v = Veoh.new('http://www.veoh.com/videos/v801204yMZ8BWcC')
+ video_id = v.send('parse_video_id')
assert_equal('v801204yMZ8BWcC', video_id)
end
+
+ def test_parse_second_video_id
+ v = Veoh.new('http://www.veoh.com/videos/v15795090Z6mZAbSq')
+ video_id = v.send('parse_video_id')
+ assert_equal('v15795090Z6mZAbSq', video_id)
+ end
+
def test_parse_redirect_url
- v = Veoh.new
+ v = Veoh.new(nil)
details_data = nil
assert_equal(expected_result, actual_result)
end
+
+
+ def test_second_parse_redirect_url
+ v = Veoh.new(nil)
+
+ details_data = nil
+
+ File.open('test/fixtures/veoh/details_data-v15795090Z6mZAbSq.xml') do |f|
+ details_data = f.read
+ end
+
+ actual_result = v.send('parse_redirect_url', details_data)
+ expected_result = 'http://content.veoh.com/flash/f/2/v15795090Z6mZAbSq/3f8044ce2538155c55af5c036cd96ba82a83ddb5.flv?ct=ff4914d2e699e8ad04a69102faaab6ce82b7704998890f69'
+
+ assert_equal(expected_result, actual_result)
+ end
+
def test_owns_veoh_urls
assert(Veoh.owns_url?('http://www.veoh.com/videos/v801204yMZ8BWcC'))
+ assert(Veoh.owns_url?('http://www.veoh.com/videos/v15795090Z6mZAbSq'))
end
end
class VimeoTest < Test::Unit::TestCase
def test_parse_standard_video_id
- v = Vimeo.new
+ v = Vimeo.new('http://www.vimeo.com/1561578')
# First form, with the id at the end.
- video_id = v.send('parse_video_id', 'http://www.vimeo.com/1561578')
+ video_id = v.send('parse_video_id')
assert_equal('1561578', video_id)
end
def test_parse_swf_video_id
- v = Vimeo.new
+ v = Vimeo.new('http://www.vimeo.com/moogaloop.swf?clip_id=1561578&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1')
# Second, clip_id= form.
- video_id = v.send('parse_video_id', 'http://www.vimeo.com/moogaloop.swf?clip_id=1561578&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1')
+ video_id = v.send('parse_video_id')
assert_equal('1561578', video_id)
end
def test_parse_request_signature
- v = Vimeo.new
+ v = Vimeo.new(nil)
details_data = nil
def test_parse_request_signature_expires
- v = Vimeo.new
+ v = Vimeo.new(nil)
details_data = nil
def test_parse_quality
- v = Vimeo.new
+ v = Vimeo.new(nil)
details_data = nil
class WebsiteTest < Test::Unit::TestCase
- def test_doesnt_own_misc_urls
- Website.subclasses.each do |w|
- assert(!w.owns_url?('6807'))
- assert(!w.owns_url?('www'))
- assert(!w.owns_url?('http'))
+ def test_nobody_owns_misc_urls
+ assert_nil(Website.create('6807'))
+ assert_nil(Website.create('www'))
+ assert_nil(Website.create('http'))
+ end
+
+
+ def test_owns_url_must_be_implemented
+ assert_raise NotImplementedError do
+ Website.owns_url?('http://www.example.com/')
+ end
+ end
+
+
+ def test_get_video_url_must_be_implemented
+ w = Website.new(nil)
+ assert_raise NotImplementedError do
+ w.get_video_url()
end
end
+
+ def test_youtube_url_returns_youtube_instance
+ yt = Website.create('http://www.youtube.com/watch?v=83-hlYMH1XE&feature=dir')
+ assert_instance_of(Youtube, yt)
+ end
+
end
class YoupornRemoteTest < Test::Unit::TestCase
def test_get_page_data
- yp = Youporn.new()
-
- # We can't rely on the fixture here, because Youporn might
- # change their page layout. Instead, check that we can actually
- # find the FLV URL on this page.
- page_data = yp.send('get_page_data', 'http://www.youporn.com/watch/65778')
-
- test_result = yp.get_video_url(page_data)
- assert_equal('http://download.youporn.com/download/112911/flv/65778_moaning_mom_fucked_at_night.flv', test_result)
+ yp = Youporn.new('http://www.youporn.com/watch/65778')
+ expected_result = 'http://download.youporn.com/download/112911/flv/65778_moaning_mom_fucked_at_night.flv'
+ actual_result = yp.get_video_url()
+ assert_equal(expected_result, actual_result)
end
end
class YoupornTest < Test::Unit::TestCase
+ def test_owns_youporn_urls
+ assert(Youporn.owns_url?('http://www.youporn.com/watch/65778'))
+ assert(Youporn.owns_url?('http://www.youporn.com/watch/61637/amateursoffie-fuckingagain-andtakinglo-ad/'))
+ end
+
+
def test_parse_video_url
- yp = Youporn.new()
+ yp = Youporn.new(nil)
page_data = nil
assert(Youtube.owns_url?('http://www.youtube.com/watch?v=K9iDMcmm0tE'))
assert(Youtube.owns_url?('http://www.youtube.com/watch?v=K9iDMcmm0tE#'))
assert(Youtube.owns_url?('http://www.youtube.com/v/K9iDMcmm0tE'))
+ assert(Youtube.owns_url?('http://www.youtube.com/watch?v=83-hlYMH1XE'))
+ assert(Youtube.owns_url?('http://www.youtube.com/watch?v=83-hlYMH1XE&feature=dir'))
end
def test_parse_video_id
- yt = Youtube.new()
+ yt = Youtube.new('http://www.youtube.com/watch?v=SudixyugiX4')
expected_result = 'SudixyugiX4'
- actual_result = yt.send('parse_video_id', 'http://www.youtube.com/watch?v=SudixyugiX4')
+ actual_result = yt.send('parse_video_id')
assert_equal(expected_result, actual_result)
end
def test_parse_video_id_again
- yt = Youtube.new()
+ yt = Youtube.new('http://www.youtube.com/watch?v=K9iDMcmm0tE')
expected_result = 'K9iDMcmm0tE'
- actual_result = yt.send('parse_video_id', 'http://www.youtube.com/watch?v=K9iDMcmm0tE')
+ actual_result = yt.send('parse_video_id')
assert_equal(expected_result, actual_result)
end
-
+
def test_parse_t_parameter
- yt = Youtube.new()
+ yt = Youtube.new(nil)
page_data = nil
# This was failing once because my regex missed a hyphen.
# I modified the regex to match anything between the pair
# of quotes, so it should now catch the hyphen and underscore.
- yt = Youtube.new()
+ yt = Youtube.new(nil)
page_data = nil
actual_result = yt.send('parse_t_parameter', page_data)
assert_equal(expected_result, actual_result)
end
+
+
+ def test_get_video_filename
+ yt = Youtube.new('http://www.youtube.com/watch?v=SudixyugiX4')
+ expected_result = 'SudixyugiX4.flv'
+ actual_result = yt.get_video_filename()
+ assert_equal(expected_result, actual_result)
+ end
+
+
+ def test_get_video_filename_again
+ yt = Youtube.new('http://www.youtube.com/watch?v=K9iDMcmm0tE')
+ expected_result = 'K9iDMcmm0tE.flv'
+ actual_result = yt.get_video_filename()
+ assert_equal(expected_result, actual_result)
+ end
+
+
+ def test_get_troublesome_video_filename_first_form
+ # This non-alphanumeric video id was causing
+ # get_video_filename to barf.
+ yt = Youtube.new('http://www.youtube.com/watch?v=83-hlYMH1XE&feature=dir')
+ expected_result = '83-hlYMH1XE.flv'
+ actual_result = yt.get_video_filename()
+ assert_equal(expected_result, actual_result)
+ end
+
+
+ def test_get_troublesome_video_filename_second_form
+ yt = Youtube.new('http://www.youtube.com/v/83-hlYMH1XE&feature=dir')
+ expected_result = '83-hlYMH1XE.flv'
+ actual_result = yt.get_video_filename()
+ assert_equal(expected_result, actual_result)
+ end
end