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

Revision 1947 (checked in by mizzy, 1 year ago)

CustomFeed?::YouTube?: strip HTML tags from the title.

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="vSnippetTitle">!
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->{title} =~ s/<[^>]+>//g;
75                         $data->{id} = $1;
76                         $title_flag = 0;
77                     }
78                 };
79             # get image url
80             m!<img src="(http://img.youtube.com/[^">]+/[12].jpg)" border="0" class="vimg120" />!
81                 and $data->{image}->{url} = $1;
82             # get description
83             m!<div class="vdesc">!
84                 and do {
85                     <$fh>;
86                     $data->{description} = <$fh>;
87                 };
88             # get tags
89             m!<div class="vtagLabel">Tags:</div>!
90                 and $tag_flag = 1;
91             m!(<a href="/results\?search_query=.*)!
92                 and do {
93                     if($tag_flag){
94                         $data->{tags} = $1;
95                         $tag_flag = 0;
96                     }
97                 };
98             # get author
99             m!From:</span> <a[^>]+href="/user/[^>]+">([^<]+)</a>!
100                 and $data->{author} = $1;
101             m/<!-- end vEntry -->/
102                 and do {
103                     $context->log( info => 'Got ' . $data->{title});
104                     my $entry = Plagger::Entry->new;
105                     $entry->title($data->{title});
106                     $entry->link('http://youtube.com/watch?v=' . $data->{id});
107                     $entry->icon({
108                         url    => $data->{image}->{url},
109                         #width  => $data->{image}->{width},
110                         #height => $data->{image}->{height},
111                     });
112                     $entry->summary($data->{description});
113                     $entry->body($data->{description});
114                     $entry->author($data->{author});
115
116                     # tags
117                     while( $data->{tags} =~ /<a href="\/results\?search_query=[^"]+" class="dg">([^<]+)<\/a>/gms){
118                         $entry->add_tag($1);
119                     }
120
121                     # enclosure
122                     my $video_url = $self->cache->get_callback(
123                         "item-" . $entry->link, sub {
124                             my $res = $ua->fetch($entry->link);
125                             if ($res->is_error){
126                                 $context->log( error => $res->status );
127                                 return;
128                             }
129                             my $url;
130                             if ($res->content =~ /&t=([^&]+)/gms){
131                                 $url = 'http://youtube.com/get_video?video_id=' . $data->{id} . "&t=$1";
132                             }
133                             return $url;
134                         },
135                         '24 hours',
136                     );
137
138                     if ($video_url) {
139                         my $video_id = ( $video_url =~ /video_id=(\w+)/ )[0];
140                         my $enclosure = Plagger::Enclosure->new;
141                         $enclosure->url( URI->new($video_url) );
142                         $enclosure->type('video/x-flv');
143                         $enclosure->filename("$video_id.flv");
144                         $entry->add_enclosure($enclosure);
145                     }
146
147                     $feed->add_entry($entry);
148                     $data = {};
149             };
150         }
151     }
152
153     $context->update->add($feed);
154 }
155
156 1;
157 __END__
158
159 =head1 NAME
160
161 Plagger::Plugin::CustomFeed::YouTube - Get YouTube search result or rss
162
163 =head1 SYNOPSIS
164
165   - module: CustomFeed::YouTube
166     config:
167       query: Twenty Four
168       sort: video_date_uploaded
169       page: 5
170
171 =head1 DESCRIPTION
172
173 This plugin fetches the result of YouTube search or the rss of a specified tag.
174
175 =head1 CONFIG
176
177 =over 4
178
179 =item query
180
181 Specify search query.
182
183 =item sort
184
185 Set sort condition. Available conditions are below. Default is video_date_uploaded.
186
187   relevance
188   video_date_uploaded
189   video_view_count
190   video_avg_rating
191
192 =item page
193
194 Number of pages of search result you get. Default is 1.
195
196 =back
197
198 =head1 AUTHOR
199
200 Gosuke Miyashita
201
202 =head1 SEE ALSO
203
204 L<Plagger>
205
206 =cut
Note: See TracBrowser for help on using the browser.