Change new() function in plugins to avoid having to call _prepare_parameters() in...
[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::Parser;
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         PATTERNS => ['(http://(?:[-a-zA-Z0-9_.]+\.)*dailymotion.com/(?:[^/]+/)*video/([-a-zA-Z0-9_]+))'],
22     );
23
24     return bless($self, $class);
25 }
26
27 sub _parse {
28     my $self = shift;
29     my $url = shift;
30     my $pattern = shift;
31     my $content;
32     my $metadata = {};
33     my $p = HTML::Parser->new(api_version => 3);
34     my @accum;
35     my @text;
36     my $e;
37
38     $url =~ m|$pattern|;
39     $url = $1;
40
41     $metadata->{'URL'} = $url;
42     $metadata->{'ID'} = $2;
43     $metadata->{'TYPE'} = 'video';
44     $metadata->{'SOURCE'} = $self->{'NAME'};
45     $metadata->{'TITLE'} = undef;
46     $metadata->{'DLURL'} = undef;
47
48     unless(defined($content = $self->simple_get(sprintf('http://www.dailymotion.com/video/%s', $2)))) {
49         $self->error('Could not download %s', $url);
50         return undef;
51     }
52
53     $p->handler(start => \@accum, "tagname, attr");
54     $p->handler(text => \@text, "text");
55     $p->report_tags(qw(meta script));
56     $p->utf8_mode(1);
57     $p->parse($content);
58
59     # Look for the title in the meta tags
60     foreach $e (@accum) {
61         if ('meta' eq $e->[0]) {
62             if ('title' eq $e->[1]->{'name'}) {
63                 $metadata->{'TITLE'} = $e->[1]->{'content'};
64                 $metadata->{'TITLE'} =~ s/^Dailymotion\s+-\s+//;
65                 $metadata->{'TITLE'} =~ s/(?:\s+-\s+.*)?$//;
66             }
67         }
68     }
69
70     # Look for the download URL
71     foreach $e (@text) {
72         if ($e->[0] =~ m|\.addVariable\("sequence",\s*"([^\"]+)"|) {
73             my $sequence = $1;
74             my $jsp = videosite::JSArrayParser->new();
75             my $l;
76             my $s;
77
78             $sequence =~ s/%(..)/chr(hex($1))/ge;
79             $self->debug("Found sequence: %s", $sequence);
80
81             $self->debug("Using %s to parse", ref($jsp));
82             $sequence = $jsp->parse($sequence);
83             $self->debug(Dumper($sequence));
84
85             unless(defined($sequence)) {
86                 $self->error("Found sequence, but could not parse");
87                 return undef;
88             } else {
89                 $self->debug("Parsed sequence: %s", Dumper($sequence));
90
91                 $l = $self->_fetch_layer($sequence, "root/layerList", "background/sequenceList", "main/layerList", "video/param");
92                 unless(defined($l)) {
93                     $self->error("Could not find video layer");
94                     return undef;
95                 }
96
97                 # Found video section
98                 if (exists($l->{'videoPluginParameters'}->{'hdURL'})) {
99                     $metadata->{'DLURL'} = $l->{'videoPluginParameters'}->{'hdURL'};
100                 } elsif (exists($l->{'videoPluginParameters'}->{'hqURL'})) {
101                     $metadata->{'DLURL'} = $l->{'videoPluginParameters'}->{'hqURL'};
102                 } elsif (exists($l->{'videoPluginParameters'}->{'hqURL'})) {
103                     $metadata->{'DLURL'} = $l->{'videoPluginParameters'}->{'sdURL'};
104                 } else {
105                     $self->error("Video section found, but no URLs");
106                     return undef;
107                 }
108             }
109         }
110     }
111
112     unless(defined($metadata->{'DLURL'}) && defined($metadata->{'TITLE'})) {
113         $self->error('Could not determine download URL');
114         return undef;
115     }
116
117     return $metadata;
118 }
119
120 sub _fetch_layer {
121     my $self = shift;
122     my $sequence = shift;
123     my $point = shift;
124     my $next;
125     my @points = @_;
126     my $l;
127
128     $self->debug("Looking for %s in %s", $point, Dumper($sequence));
129
130     unless(defined($point)) {
131         $self->debug("Reached last point");
132         return $sequence;
133     }
134     ($point, $next) = split(/\//, $point, 2);
135
136     foreach (@{$sequence}) {
137         if (exists($_->{'name'}) and ($_->{'name'} eq $point)) {
138             if (exists($_->{$next})) {
139                 $self->debug("Using %s in %s", $next, $point);
140                 return $self->_fetch_layer($_->{$next}, @points);
141             } else {
142                 $self->debug("%s found, but no %s", $point, $next);
143                 return undef;
144             }
145
146         }
147     }
148
149     $self->debug("Could not find entry named %s", $point);
150     return undef;
151 }
152
153 1;