File Coverage

blib/lib/Bot/Cobalt/Plugin/YouTube.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Bot::Cobalt::Plugin::YouTube;
2             our $VERSION = '0.003000';
3              
4 1     1   26365 use Bot::Cobalt;
  0            
  0            
5             use Bot::Cobalt::Common;
6              
7             use strictures 1;
8              
9             use HTML::TokeParser;
10              
11             use HTTP::Request;
12              
13             use URI::Escape;
14              
15             sub REGEX () { 0 }
16              
17             sub new {
18             bless [
19             qr{(youtu\.be|youtube\.com)/(\S+)}, ## ->[REGEX]
20             ], shift
21             }
22              
23             sub Cobalt_register {
24             my ($self, $core) = @_;
25              
26             register( $self, 'SERVER', qw/
27             public_msg
28             ctcp_action
29             youtube_plug_resp_recv
30             / );
31              
32             logger->info("YouTube plugin registered ($VERSION)");
33              
34             PLUGIN_EAT_NONE
35             }
36              
37             sub Cobalt_unregister {
38             my ($self, $core) = @_;
39              
40             logger->info("YouTube plugin unregistered.");
41              
42             PLUGIN_EAT_NONE
43             }
44              
45             sub _create_yt_link {
46             my ($self, $base, $id) = @_;
47              
48             "http://www.youtube.com/"
49             . ($base eq "youtu.be" ? "watch?v=" : "")
50             . uri_escape($id)
51             }
52              
53             sub _issue_yt_request {
54             my ($self, $msg, $base, $id) = @_;
55              
56             unless (core()->Provided->{www_request}) {
57             logger->warn(
58             "We appear to be missing Bot::Cobalt::Plugin::WWW; ",
59             "it may not be possible to issue async HTTP requests."
60             );
61             }
62              
63             my $chcfg = core->get_channels_cfg( $msg->context );
64             my $this_chcfg = $chcfg->{ $msg->channel } // {};
65             return if $this_chcfg->{no_yt_retrieve};
66              
67             my $req_url = $self->_create_yt_link($base, $id);
68              
69             logger->debug("dispatching request to $req_url");
70              
71             broadcast( 'www_request',
72             HTTP::Request->new( GET => $req_url ),
73             'youtube_plug_resp_recv',
74             [ $req_url, $msg ],
75             );
76              
77             1
78             }
79              
80             sub Bot_public_msg {
81             my ($self, $core) = splice @_, 0, 2;
82             my $msg = ${ $_[0] };
83              
84             my ($base, $id) = $msg->stripped =~ $self->[REGEX] ;
85              
86             if ($base && defined $id) {
87             $self->_issue_yt_request($msg, $base, $id)
88             }
89              
90             PLUGIN_EAT_NONE
91             }
92              
93             sub Bot_ctcp_action {
94             my ($self, $core) = splice @_, 0, 2;
95             my $msg = ${ $_[0] };
96              
97             return PLUGIN_EAT_NONE unless $msg->channel;
98              
99             my ($base, $id) = $msg->stripped =~ $self->[REGEX];
100              
101             if ($base && defined $id) {
102             $self->_issue_yt_request($msg, $base, $id)
103             }
104              
105             PLUGIN_EAT_NONE
106             }
107              
108             sub Bot_youtube_plug_resp_recv {
109             my ($self, $core) = splice @_, 0, 2;
110              
111             my $response = ${ $_[1] };
112             my $args = ${ $_[2] };
113             my ($req_url, $msg) = @$args;
114              
115             logger->debug("youtube_plug_resp_recv for $req_url");
116              
117             return PLUGIN_EAT_ALL unless $response->is_success;
118              
119             my $content = $response->decoded_content;
120              
121             my $html = HTML::TokeParser->new( \$content );
122              
123             my ($title, $short_url);
124              
125             TAG: while (my $tok = $html->get_tag('meta', 'link') ) {
126             my $args = ref $tok->[1] eq 'HASH' ? $tok->[1] : next TAG ;
127              
128             if (defined $args->{name} && $args->{name} eq 'title') {
129             $title = $args->{content}
130             }
131              
132             if (defined $args->{rel} && $args->{rel} eq 'shortlink') {
133             $short_url = $args->{href}
134             }
135              
136             if (defined $title && defined $short_url) {
137             last TAG
138             }
139             }
140              
141             if (defined $title && $short_url) {
142             my $irc_resp =
143             color('bold', 'YouTube:')
144             . " $title ( $short_url )" ;
145              
146             broadcast( 'message',
147             $msg->context,
148             $msg->channel,
149             $irc_resp
150             );
151             } else {
152             logger->warn("Failed YouTube info retrieval for $req_url");
153             }
154              
155             PLUGIN_EAT_ALL
156             }
157              
158             1;
159              
160             =pod
161              
162             =head1 NAME
163              
164             Bot::Cobalt::Plugin::YouTube - YouTube plugin for Bot::Cobalt
165              
166             =head1 SYNOPSIS
167              
168             !plugin load YT Bot::Cobalt::Plugin::YouTube
169              
170             =head1 DESCRIPTION
171              
172             A L plugin.
173              
174             Retrieves YouTube links pasted to an IRC channel and reports titles
175             (as well as shorter urls) to IRC.
176              
177             Operates on both 'youtube.com' and 'youtu.be' links.
178              
179             Disregards channels with a 'no_yt_retrieve' flag enabled.
180              
181             =head1 AUTHOR
182              
183             Jon Portnoy
184              
185             =cut