# GNU General Public License for more details.
#
# http://www.fsf.org/licensing/licenses/gpl.html
-#
-#
-# NOTE:
-#
-# All credit belongs to whomever reverse-engineered the Redtube
-# Flash applet in the first place. I took the algorithm from this
-# script:
-#
-# http://userscripts.org/scripts/review/8691
-#
-# and merely cleaned it up a bit while porting it to Ruby.
-#
-# The Redtube class needs the extra string methods..
-require 'src/string'
require 'src/website'
+require 'cgi'
+
-# This class handles the algorithm magic needed to get
-# the URL from a Redtube video id.
class Redtube < Website
VALID_REDTUBE_URL_REGEX = /^(http:\/\/)?(www\.)?redtube\.com\/(\d+)$/
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()
- # First, parse the video ID out of the URL.
- video_id = parse_video_id()
-
- padded_id = video_id.to_s.pad_left('0', 7)
-
- video_dir = self.get_video_dir(video_id)
- file_name = self.get_file_name(padded_id)
-
page_data = self.get_page_data(@url)
-
- # As far as I know, the MP4s don't work yet.
- # So just default to the FLV.
- top_secret_hash = parse_hash_flv(page_data)
-
- return 'http://dl.redtube.com/' +
- self.get_root_server_dir() +
- "/#{video_dir}/#{file_name}" +
- top_secret_hash
- end
-
-
- def get_video_filename()
- # Mildly redundant.
- video_id = parse_video_id()
- padded_id = video_id.to_s.pad_left('0', 7)
-
- return self.get_file_name(padded_id)
+ return self.parse_hashlink(page_data)
end
protected;
- VIDEO_FILE_EXTENSION = '.flv'
-
def parse_video_id()
return /\d+/.match(@url)[0]
end
+ def parse_hashlink(page_data)
+ hashlink_regex = /hashlink=([^"]+)"/
- def parse_hash_flv(page_data)
- # Hashes are generated for both flv/mp4 and are delivered
- # along with the video page. We need to stick them back on
- # the end of the final video URL, or else it doesn't work.
- hash_flv_regex = /&hash_flv=(\/.*?)&/
-
- matches = hash_flv_regex.match(page_data)
+ matches = hashlink_regex.match(page_data)
if matches.nil?
- raise StandardError.new("Couldn't parse the hash_flv variable.")
+ raise StandardError.new("Could not parse the 'hashlink' Flash variable.")
end
- return matches[1]
- end
-
-
- def get_root_server_dir()
- # They hard code this shit into the SWF file.
- return '467f9bca32b1989277b48582944f325afa3374'
+ # The hashlink variable /is/ the video URL, but it's encoded.
+ return CGI::unescape(matches[1])
end
- # Not sure what they're thinking with this one.
- def get_video_dir(video_id)
- return (video_id.to_f / 1000.0).floor.to_s.pad_left('0', 7)
- end
-
-
- # The first part of the algorithmic magic. Multiply each
- # digit of the padded video id by the index of the
- # following digit, and sum them up.
- def int_magic(padded_video_id)
- ret = 0
-
- 0.upto(6) do |a|
- ret += padded_video_id[a,1].to_i * (a+1)
- end
-
- return ret
- end
-
-
- # Part 2 of the magic. Sum the digits of the result
- # of the first magic.
- def more_magic(file_string)
- magic = self.int_magic(file_string).to_s
-
- ret = 0
-
- 0.upto(magic.length - 1) do |a|
- ret += magic[a,1].to_i
- end
-
- return ret
- end
-
-
- # Complete fricking mystery
- def get_file_name(file_string)
- map = ['R', '1', '5', '3', '4', '2', 'O', '7', 'K', '9', 'H', 'B', 'C', 'D', 'X', 'F', 'G', 'A', 'I', 'J', '8', 'L', 'M', 'Z', '6', 'P', 'Q', '0', 'S', 'T', 'U', 'V', 'W', 'E', 'Y', 'N']
-
- # The stupid variable names I copied from the
- # source script. Considering myself disclaimed.
- my_int = self.more_magic(file_string)
- new_char = '0' + my_int.to_s
-
- if my_int >= 10 then
- new_char = my_int.to_s
- end
-
- file_name = map[file_string[3] - 48 + my_int + 3]
- file_name += new_char[1,1]
- file_name += map[file_string[0] - 48 + my_int + 2]
- file_name += map[file_string[2] - 48 + my_int + 1]
- file_name += map[file_string[5] - 48 + my_int + 6]
- file_name += map[file_string[1] - 48 + my_int + 5]
- file_name += new_char[0,1]
- file_name += map[file_string[4] - 48 + my_int + 7]
- file_name += map[file_string[6] - 48 + my_int + 4]
- file_name += VIDEO_FILE_EXTENSION
-
- return file_name
- end
-
-
end