fix quoting in AsyncWgetFileGetter again
[videosite.git] / videosite / DailyMotionGrabber.pm
1 # Grabber for dailymotion.com
2 #
3 # (c) 2007 by Ralf Ertzinger <ralf@camperquake.de>
4 # licensed under GNU GPL v2
5
6 package videosite::DailyMotionGrabber;
7
8 use videosite::GrabberBase;
9 @ISA = qw(videosite::GrabberBase);
10
11 use HTML::TokeParser;
12 use videosite::JSArrayParser;
13 use Data::Dumper;
14
15 use strict;
16
17 sub new {
18     my $class = shift;
19     my $self = $class->SUPER::new(
20         NAME => 'dailymotion',
21         _SELFTESTURL => 'http://www.dailymotion.com/video/xylv6u_moon-duo-sleepwalker_music',
22         _SELFTESTTITLE => 'Moon Duo - Sleepwalker',
23         PATTERNS => ['(http://(?:[-a-zA-Z0-9_.]+\.)*dailymotion.com/(?:[^/]+/)*video/([-a-zA-Z0-9_]+))'],
24         @_,
25     );
26
27     return bless($self, $class);
28 }
29
30 sub _parse {
31     my $self = shift;
32     my $url = shift;
33     my $pattern = shift;
34     my $content;
35     my $metadata = {};
36     my $p;
37     my @accum;
38     my @text;
39     my $e;
40
41     $url =~ m|$pattern|;
42     $url = $1;
43
44     $metadata->{'URL'} = $url;
45     $metadata->{'ID'} = $2;
46     $metadata->{'TYPE'} = 'video';
47     $metadata->{'SOURCE'} = $self->{'NAME'};
48     $metadata->{'TITLE'} = undef;
49     $metadata->{'DLURL'} = undef;
50
51     unless(defined($content = $self->simple_get(sprintf('http://www.dailymotion.com/video/%s', $2)))) {
52         $self->error('Could not download %s', $url);
53         return undef;
54     }
55
56     $p = HTML::TokeParser->new(\$content);
57
58     # Look for the title in the meta tags
59     while ($e = $p->get_tag('meta', 'script')) {
60         if ('meta' eq $e->[0]) {
61             if (exists($e->[1]->{'property'}) && ('og:title' eq $e->[1]->{'property'})) {
62                 $metadata->{'TITLE'} = $e->[1]->{'content'};
63             }
64         } elsif ('script' eq $e->[0]) {
65             my $c = $p->get_text();
66
67             $self->debug("Found script: %s", $c);
68
69             if ($c =~ m|flashvars = (.+);$|m) {
70                 my $flashvars = $1;
71                 my $jsp = videosite::JSArrayParser->new();
72                 my $l;
73                 my $s;
74                 my $sequence;
75
76                 $self->debug("Found flashvars: %s", $flashvars);
77
78                 $self->debug("Using %s to parse", ref($jsp));
79                 $flashvars = $jsp->parse($flashvars);
80                 $self->debug("Parsed flashvars: %s", Dumper($flashvars));
81
82                 $sequence = $flashvars->{'sequence'};
83                 $sequence =~ s/%(..)/chr(hex($1))/ge;
84
85                 $self->debug("Decoded sequence: %s", $sequence);
86                 $sequence =  $jsp->parse($sequence);
87
88                 unless(defined($sequence)) {
89                     $self->error("Found sequence, but could not parse");
90                     return undef;
91                 } else {
92                     $self->debug("Parsed sequence: %s", Dumper($sequence));
93
94                     $l = $self->_fetch_layer($sequence->{'sequence'}, "root/layerList", "background/sequenceList", "main/layerList", "video/param");
95                     unless(defined($l)) {
96                         $self->error("Could not find video layer");
97                         return undef;
98                     }
99
100                     # Found video section
101                     if (exists($l->{'hd1080URL'})) {
102                         $metadata->{'DLURL'} = $l->{'hd1080URL'};
103                     } elsif (exists($l->{'hd720URL'})) {
104                         $metadata->{'DLURL'} = $l->{'hd720URL'};
105                     } elsif (exists($l->{'hqURL'})) {
106                         $metadata->{'DLURL'} = $l->{'hqURL'};
107                     } elsif (exists($l->{'sdURL'})) {
108                         $metadata->{'DLURL'} = $l->{'sdURL'};
109                     } elsif (exists($l->{'ldURL'})) {
110                         $metadata->{'DLURL'} = $l->{'ldURL'};
111                     } else {
112                         $self->error("Video section found, but no URLs");
113                         return undef;
114                     }
115                 }
116             }
117         }
118     }
119
120     unless(defined($metadata->{'DLURL'}) && defined($metadata->{'TITLE'})) {
121         $self->error('Could not determine download URL');
122         return undef;
123     }
124
125     return $metadata;
126 }
127
128 sub _fetch_layer {
129     my $self = shift;
130     my $sequence = shift;
131     my $point = shift;
132     my $next;
133     my @points = @_;
134     my $l;
135
136     $self->debug("Looking for %s in %s", $point, Dumper($sequence));
137
138     unless(defined($point)) {
139         $self->debug("Reached last point");
140         return $sequence;
141     }
142     ($point, $next) = split(/\//, $point, 2);
143
144     foreach (@{$sequence}) {
145         if (exists($_->{'name'}) and ($_->{'name'} eq $point)) {
146             if (exists($_->{$next})) {
147                 $self->debug("Using %s in %s", $next, $point);
148                 return $self->_fetch_layer($_->{$next}, @points);
149             } else {
150                 $self->debug("%s found, but no %s", $point, $next);
151                 return undef;
152             }
153
154         }
155     }
156
157     $self->debug("Could not find entry named %s", $point);
158     return undef;
159 }
160
161 1;