]> gitweb.michael.orlitzky.com - dead/whatever-dl.git/blob - src/websites/redtube.rb
Made the output filename the responsibility of the website subclass.
[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()
49 # First, parse the video ID out of the URL.
50 video_id = parse_video_id()
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 def parse_video_id()
69 return /\d+/.match(@url)[0]
70 end
71
72
73 # Not sure what they're thinking with this one.
74 def get_video_dir(video_id)
75 return (video_id.to_f / 1000.0).floor.to_s.pad_left('0', 7)
76 end
77
78
79 # The first part of the algorithmic magic. Multiply each
80 # digit of the padded video id by the index of the
81 # following digit, and sum them up.
82 def int_magic(padded_video_id)
83 ret = 0
84
85 0.upto(6) do |a|
86 ret += padded_video_id[a,1].to_i * (a+1)
87 end
88
89 return ret
90 end
91
92
93 # Part 2 of the magic. Sum the digits of the result
94 # of the first magic.
95 def more_magic(file_string)
96 magic = self.int_magic(file_string).to_s
97
98 ret = 0
99
100 0.upto(magic.length - 1) do |a|
101 ret += magic[a,1].to_i
102 end
103
104 return ret
105 end
106
107
108 # Complete fricking mystery
109 def get_file_name(file_string)
110 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']
111
112 # The stupid variable names I copied from the
113 # source script. Considering myself disclaimed.
114 my_int = self.more_magic(file_string)
115 new_char = '0' + my_int.to_s
116
117 if my_int >= 10 then
118 new_char = my_int.to_s
119 end
120
121 file_name = map[file_string[3] - 48 + my_int + 3]
122 file_name += new_char[1,1]
123 file_name += map[file_string[0] - 48 + my_int + 2]
124 file_name += map[file_string[2] - 48 + my_int + 1]
125 file_name += map[file_string[5] - 48 + my_int + 6]
126 file_name += map[file_string[1] - 48 + my_int + 5]
127 file_name += new_char[0,1]
128 file_name += map[file_string[4] - 48 + my_int + 7]
129 file_name += map[file_string[6] - 48 + my_int + 4]
130 file_name += VIDEO_FILE_EXTENSION
131
132 return file_name
133 end
134
135 end