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

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

CustomFeed?::YouTube?: encode query if no_decode_utf8 is not set and a little refactoring.

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