2 # Copyright Michael Orlitzky
4 # http://michael.orlitzky.com/
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # http://www.fsf.org/licensing/licenses/gpl.html
21 # All credit belongs to whomever reverse-engineered the Redtube
22 # Flash applet in the first place. I took the algorithm from this
25 # http://userscripts.org/scripts/review/8691
27 # and merely cleaned it up a bit while porting it to Ruby.
30 # The Redtube class needs the extra string methods..
34 # This class handles the algorithm magic needed to get
35 # the URL from a Redtube video id.
36 class Redtube
< Website
38 VALID_REDTUBE_URL_REGEX
= /^(http:\/\
/)?(www\.)?redtube\.com\/(\d+
)$/
40 def self.owns_url
?(url
)
41 return url
=~ VALID_REDTUBE_URL_REGEX
45 # The only public method. This calls the other parts
46 # of the algorithm and, with any luck, we wind up with
47 # the URL to the video.
49 # First, parse the video ID out of the URL.
50 video_id
= parse_video_id()
52 padded_id
= video_id
.to_s
.pad_left('0', 7)
54 video_dir
= self.get_video_dir(video_id
)
55 file_name
= self.get_file_name(padded_id
)
57 page_data
= self.get_page_data(@url)
59 # As far as I know, the MP4s don't work yet.
60 # So just default to the FLV.
61 top_secret_hash
= parse_hash_flv(page_data
)
63 return 'http://dl.redtube.com/' +
64 self.get_root_server_dir() +
65 "/#{video_dir}/#{file_name}" +
70 def get_video_filename()
72 video_id
= parse_video_id()
73 padded_id
= video_id
.to_s
.pad_left('0', 7)
75 return self.get_file_name(padded_id
)
81 VIDEO_FILE_EXTENSION
= '.flv'
84 return /\d+/.match(@url)[0]
89 def parse_hash_flv(page_data
)
90 # Hashes are generated for both flv/mp4 and are delivered
91 # along with the video page. We need to stick them back on
92 # the end of the final video URL, or else it doesn't work.
93 hash_flv_regex
= /&hash_flv=(\/.*?)&/
95 matches
= hash_flv_regex
.match(page_data
)
98 raise StandardError
.new("Couldn't parse the hash_flv variable.")
105 def get_root_server_dir()
106 # They hard code this shit into the SWF file.
107 return '467f9bca32b1989277b48582944f325afa3374'
110 # Not sure what they're thinking with this one.
111 def get_video_dir(video_id
)
112 return (video_id
.to_f
/ 1000.0).floor
.to_s
.pad_left('0', 7)
116 # The first part of the algorithmic magic. Multiply each
117 # digit of the padded video id by the index of the
118 # following digit, and sum them up.
119 def int_magic(padded_video_id
)
123 ret +
= padded_video_id
[a
,1].to_i
* (a+
1)
130 # Part 2 of the magic. Sum the digits of the result
131 # of the first magic.
132 def more_magic(file_string
)
133 magic
= self.int_magic(file_string
).to_s
137 0.upto(magic
.length
- 1) do |a
|
138 ret +
= magic
[a
,1].to_i
145 # Complete fricking mystery
146 def get_file_name(file_string
)
147 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']
149 # The stupid variable names I copied from the
150 # source script. Considering myself disclaimed.
151 my_int
= self.more_magic(file_string
)
152 new_char
= '0' + my_int
.to_s
155 new_char
= my_int
.to_s
158 file_name
= map
[file_string
[3] - 48 + my_int +
3]
159 file_name +
= new_char
[1,1]
160 file_name +
= map
[file_string
[0] - 48 + my_int +
2]
161 file_name +
= map
[file_string
[2] - 48 + my_int +
1]
162 file_name +
= map
[file_string
[5] - 48 + my_int +
6]
163 file_name +
= map
[file_string
[1] - 48 + my_int +
5]
164 file_name +
= new_char
[0,1]
165 file_name +
= map
[file_string
[4] - 48 + my_int +
7]
166 file_name +
= map
[file_string
[6] - 48 + my_int +
4]
167 file_name +
= VIDEO_FILE_EXTENSION