]> gitweb.michael.orlitzky.com - dead/whatever-dl.git/blob - src/websites/redtube.rb
9ecdceccd7d1575a0167d3d84738a048b10fba3a
[dead/whatever-dl.git] / src / websites / redtube.rb
1 #
2 # Copyright Michael Orlitzky
3 #
4 # http://michael.orlitzky.com/
5 #
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.
10 #
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.
15 #
16 # http://www.fsf.org/licensing/licenses/gpl.html
17 #
18 #
19 # NOTE:
20 #
21 # All credit belongs to whomever reverse-engineered the Redtube
22 # Flash applet in the first place. I took the algorithm from this
23 # script:
24 #
25 # http://userscripts.org/scripts/review/8691
26 #
27 # and merely cleaned it up a bit while porting it to Ruby.
28 #
29
30 # The Redtube class needs the extra string methods..
31 require 'src/string'
32 require 'src/website'
33
34 # This class handles the algorithm magic needed to get
35 # the URL from a Redtube video id.
36 class Redtube < Website
37
38 VALID_REDTUBE_URL_REGEX = /^(http:\/\/)?(www\.)?redtube\.com\/(\d+)$/
39
40 def self.owns_url?(url)
41 return url =~ VALID_REDTUBE_URL_REGEX
42 end
43
44
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.
48 def get_video_url(url)
49 # First, parse the video ID out of the URL.
50 video_id = /\d+/.match(url)[0]
51
52 padded_id = video_id.to_s.pad_left('0', 7)
53
54 video_dir = self.get_video_dir(video_id)
55 file_name = self.get_file_name(padded_id)
56
57 # This mess is actually the only directory out of
58 # which they serve videos.
59 return 'http://dl.redtube.com/_videos_t4vn23s9jc5498tgj49icfj4678/' +
60 "#{video_dir}/#{file_name}"
61 end
62
63
64 protected
65
66 VIDEO_FILE_EXTENSION = '.flv'
67
68 # Not sure what they're thinking with this one.
69 def get_video_dir(video_id)
70 return (video_id.to_f / 1000.0).floor.to_s.pad_left('0', 7)
71 end
72
73
74 # The first part of the algorithmic magic. Multiply each
75 # digit of the padded video id by the index of the
76 # following digit, and sum them up.
77 def int_magic(padded_video_id)
78 ret = 0
79
80 0.upto(6) do |a|
81 ret += padded_video_id[a,1].to_i * (a+1)
82 end
83
84 return ret
85 end
86
87
88 # Part 2 of the magic. Sum the digits of the result
89 # of the first magic.
90 def more_magic(file_string)
91 magic = self.int_magic(file_string).to_s
92
93 ret = 0
94
95 0.upto(magic.length - 1) do |a|
96 ret += magic[a,1].to_i
97 end
98
99 return ret
100 end
101
102
103 # Complete fricking mystery
104 def get_file_name(file_string)
105 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']
106
107 # The stupid variable names I copied from the
108 # source script. Considering myself disclaimed.
109 my_int = self.more_magic(file_string)
110 new_char = '0' + my_int.to_s
111
112 if my_int >= 10 then
113 new_char = my_int.to_s
114 end
115
116 file_name = map[file_string[3] - 48 + my_int + 3]
117 file_name += new_char[1,1]
118 file_name += map[file_string[0] - 48 + my_int + 2]
119 file_name += map[file_string[2] - 48 + my_int + 1]
120 file_name += map[file_string[5] - 48 + my_int + 6]
121 file_name += map[file_string[1] - 48 + my_int + 5]
122 file_name += new_char[0,1]
123 file_name += map[file_string[4] - 48 + my_int + 7]
124 file_name += map[file_string[6] - 48 + my_int + 4]
125 file_name += VIDEO_FILE_EXTENSION
126
127 return file_name
128 end
129
130 end