root/trunk/plagger/lib/Plagger/Plugin/CustomFeed/YouTube.pm

Revision 1411 (checked in by mizzy, 14 years ago)

add test for CustomFeed?::YouTube?
CustomFeed?::YouTube?: fix the way of extracting description

Line 
1 package Plagger::Plugin::CustomFeed::YouTube;
2 use strict;
3 use warnings;
4 use base qw( Plagger::Plugin );
5
6 use Plagger::Enclosure;
7 use Plagger::UserAgent;
8
9 sub register {
10     my($self, $context) = @_;
11     $context->register_hook(
12         $self,
13         'subscription.load' => \&load,
14     );
15 }
16
17 sub load {
18     my($self, $context) = @_;
19     my $feed = Plagger::Feed->new;
20     $feed->aggregator(sub { $self->aggregate(@_) });
21     $context->subscription->add($feed);
22 }
23
24 sub aggregate {
25     my($self, $context, $args) = @_;
26
27     my $q = $self->conf->{query};
28     $q =~ s/\s/\+/g;
29
30     my $file = $self->cache->path_to('youtube_search_result.html');
31
32     $context->log( info => 'Getting YouTube search results for ' . $self->conf->{query} );
33
34     my $ua = Plagger::UserAgent->new;
35
36     my $feed = Plagger::Feed->new;
37     $feed->type('youtubesearch');
38     $feed->title('YouTube Search - ' . $self->conf->{query});
39
40     my $page = $self->conf->{page} || 1;
41     my $sort = $self->conf->{sort} || 'video_date_uploaded';
42     for ( 1 .. $page ){
43         my $res = $ua->mirror("http://youtube.com/results?search_type=search_videos&search_query=$q&search_sort=$sort&search_category=0&page=$_" => $file);
44
45         if($res->is_error){
46             $context->log( error => $res->status_line );
47             return;
48         }
49
50         open my $fh, "<:encoding(utf-8)", $file
51             or return $context->log(error => "$file: $!");
52
53         my (@videos, $data, $title_flag, $tag_flag);
54         while (<$fh>) {
55             # get title
56             m!<div class="vtitle">!
57                 and $title_flag = 1;
58             m!<a href="/watch\?v=([^"]+)">(.+)</a>!
59                 and do {
60                     if($title_flag){
61                         $data->{title} = $2;
62                         $data->{id} = $1;
63                         $title_flag = 0;
64                     }
65                 };
66             m!<img src="(http://[\w-]*static\d+(.[\w-]+)?\.youtube.com/[^">]+/[12].jpg)" class="vimg120" />!
67                 and $data->{image}->{url} = $1;
68             m!<div class="vdesc">!
69                 and $data->{description} = <$fh>;
70             m!<div class="vtagLabel">Tags:</div>!
71                 and $tag_flag = 1;
72             m!(<a href="/results\?search_type=.*)!
73                 and do {
74                     if($tag_flag){
75                         $data->{tags} = $1;
76                         $tag_flag = 0;
77                     }
78                 };
79             m!profile\?user=([^"]+)!
80                 and do {
81                     $context->log( info => 'Got ' . $data->{title});
82                     $data->{author} = $1;
83                     my $entry = Plagger::Entry->new;
84                     $entry->title($data->{title});
85                     $entry->link('http://youtube.com/watch?v=' . $data->{id});
86                     $entry->icon({
87                         url    => $data->{image}->{url},
88                         #width  => $data->{image}->{width},
89                         #height => $data->{image}->{height},
90                     });
91                     $entry->summary($data->{description});
92                     $entry->body($data->{description});
93                     $entry->author($data->{author});
94
95                     # tags
96                     while( $data->{tags} =~ /<a href="\/results\?search_type=[^"]+" class="dg">([^<]+)<\/a>/gms){
97                         $entry->add_tag($1);
98                     }
99
100                     # enclosure
101                     my $video_url = $self->cache->get_callback(
102                         "item-" . $entry->link, sub {
103                             my $res = $ua->fetch($entry->link);
104                             if ($res->is_error){
105                                 $context->log( error => $res->status_line );
106                                 return;
107                             }
108                             my $url;
109                             if ($res->content =~ /&t=([^&]+)/gms){
110                                 $url = 'http://youtube.com/get_video?video_id=' . $data->{id} . "&t=$1";
111                             }
112                             return $url;
113                         },
114                         '24 hours',
115                     );
116
117                     if ($video_url) {
118                         my $video_id = ( $video_url =~ /video_id=(\w+)/ )[0];
119
120                         my $enclosure = Plagger::Enclosure->new;
121                         $enclosure->url( URI->new($video_url) );
122                         $enclosure->type('video/x-flv');
123                         $enclosure->filename("$video_id.flv");
124                         $entry->add_enclosure($enclosure);
125                     }
126
127                     $feed->add_entry($entry);
128                     $data = {};
129             };
130         }
131     }
132
133     $context->update->add($feed);
134 }
135
136 1;
137 __END__
138
139 =head1 NAME
140
141 Plagger::Plugin::CustomFeed::YouTube - Get YouTube search result or rss
142
143 =head1 SYNOPSIS
144
145   - module: CustomFeed::YouTube
146     config:
147       query: Twenty Four
148       sort: video_date_uploaded
149       page: 5
150
151 =head1 DESCRIPTION
152
153 This plugin fetches the result of YouTube search or the rss of a specified tag.
154
155 =head1 CONFIG
156
157 =over 4
158
159 =item query
160
161 Specify search query.
162
163 =item sort
164
165 Set sort condition. Available condisions are below. Default is video_date_uploaded.
166
167   relevance
168   video_date_uploaded
169   video_view_count
170   video_avg_rating
171
172 =item page
173
174 Number of pages of search result you get. Default is 1.
175
176 =back
177
178 =head1 AUTHOR
179
180 Gosuke Miyashita
181
182 =head1 SEE ALSO
183
184 L<Plagger>
185
186 =cut
187
Note: See TracBrowser for help on using the browser.