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

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

CustomFeed?::YouTube?: Oops.Deleted debug code.

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