# # Copyright Michael Orlitzky # # http://michael.orlitzky.com/ # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 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' # 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+)$/ def self.owns_url?(url) return url =~ VALID_REDTUBE_URL_REGEX 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) # This mess is actually the only directory out of # which they serve videos. return 'http://dl.redtube.com/_videos_t4vn23s9jc5498tgj49icfj4678/' + "#{video_dir}/#{file_name}" end 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) 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