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