File Coverage

blib/lib/Bot/Cobalt/Plugin/Twitter.pm
Criterion Covered Total %
statement 28 111 25.2
branch 0 24 0.0
condition 0 8 0.0
subroutine 10 20 50.0
pod 3 11 27.2
total 41 174 23.5


line stmt bran cond sub pod time code
1             package Bot::Cobalt::Plugin::Twitter;
2             # ABSTRACT: Bot::Cobalt plugin for automatic tweeting
3             $Bot::Cobalt::Plugin::Twitter::VERSION = '0.002';
4 1     1   48987 use strict;
  1         3  
  1         23  
5 1     1   5 use warnings;
  1         2  
  1         20  
6              
7 1     1   381 use Bot::Cobalt;
  1         8328  
  1         5  
8 1     1   1292 use Bot::Cobalt::Common;
  1         190059  
  1         6  
9              
10 1     1   9019 use HTML::Entities qw(decode_entities);
  1         4745  
  1         69  
11 1     1   482 use Mojo::UserAgent;
  1         250165  
  1         9  
12 1     1   420 use Net::Twitter;
  1         1011940  
  1         39  
13 1     1   567 use Text::Unidecode qw(unidecode);
  1         1056  
  1         59  
14 1     1   390 use URI::Find::Simple qw(list_uris);
  1         2519  
  1         926  
15              
16             my $status_rx = qr/twitter\.com\/\w+\/status\/(\d+)/;
17              
18 1     1 0 182 sub new { bless {}, shift }
19 0     0 0   sub twitter { shift->{twitter} }
20              
21 0     0 1   sub tweet_topics { shift->{tweet_topics} }
22 0     0 1   sub tweet_links { shift->{tweet_links} }
23 0     0 1   sub retweet_tweets { shift->{retweet_tweets} }
24 0     0 0   sub ua { shift->{useragent} }
25              
26             sub Cobalt_register {
27 0     0 0   my $self = shift;
28 0           my $core = shift;
29 0           my $conf = $core->get_plugin_cfg($self);
30              
31 0   0       $self->{tweet_topics} = $conf->{tweet_topics} // 1;
32 0           $self->{tweet_links} = $conf->{tweet_links};
33 0           $self->{retweet_tweets} = $conf->{retweet_tweets};
34 0           $self->{useragent} = Mojo::UserAgent->new;
35              
36 0           eval {
37             $self->{twitter} = Net::Twitter->new(
38             traits => [ qw(API::RESTv1_1 RetryOnError) ],
39             consumer_key => $conf->{consumer_key},
40             consumer_secret => $conf->{consumer_secret},
41             access_token => $conf->{access_token},
42             access_token_secret => $conf->{access_token_secret},
43 0           ssl => 1,
44             );
45             };
46              
47 0 0         if (my $err = $@) {
48 0           logger->warn("Unable to create Net::Twitter object: $err");
49             }
50              
51 0           register( $self, 'SERVER', qw(public_msg public_cmd_tweet topic_changed) );
52 0           logger->info("Registered, commands: !tweet");
53              
54 0           return PLUGIN_EAT_NONE;
55             }
56              
57             sub Cobalt_unregister {
58 0     0 0   my $self = shift;
59 0           my $core = shift;
60              
61 0           logger->info("Unregistered");
62            
63 0           return PLUGIN_EAT_NONE;
64             }
65              
66             sub Bot_topic_changed {
67 0     0 0   my $self = shift;
68 0           my $core = shift;
69 0           my $topic = ${ shift() };
  0            
70              
71 0 0         return PLUGIN_EAT_NONE if not $self->tweet_topics;
72              
73 0           my $new_topic = $topic->stripped;
74 0           my $status = substr($new_topic, 0, 139);
75              
76 0           $self->twitter->update($status);
77              
78 0           return PLUGIN_EAT_NONE;
79             }
80              
81             sub Bot_public_cmd_tweet {
82 0     0 0   my $self = shift;
83 0           my $core = shift;
84 0           my $msg = ${ shift() };
  0            
85              
86 0           my $context = $msg->context;
87 0           my $channel = $msg->target;
88 0           my $nick = $msg->src_nick;
89              
90 0           my @split = split(/ /, $msg->stripped);
91              
92 0           shift @split; # shift off the command
93              
94 0           my $status = substr( join(' ', @split), 0, 139);
95              
96 0           $self->twitter->update($status);
97              
98 0           return PLUGIN_EAT_ALL;
99             }
100              
101             sub Bot_public_msg {
102 0     0 0   my $self = shift;
103 0           my $core = shift;
104 0           my $msg = ${ shift() };
  0            
105              
106 0 0 0       return PLUGIN_EAT_NONE unless $self->tweet_links or $self->retweet_tweets;
107              
108 0           my $context = $msg->context;
109 0           my $channel = $msg->target;
110              
111 0           foreach my $uri ( list_uris($msg->message) ) {
112 0 0         next if not $uri;
113              
114 0 0         if ($uri =~ $status_rx) {
    0          
115 0           my $id = $1;
116 0 0         if ($self->retweet_tweets) {
117 0           eval { $self->twitter->retweet($id) };
  0            
118 0 0         if (my $err = $@) {
119 0           logger->warn(
120             "Failed to retweet [$id] - " . $err->twitter_error_text,
121             );
122             }
123             }
124            
125 0           my $tweet = $self->twitter->show_status($id);
126 0           my $text = $tweet->{text};
127 0           my $name = $tweet->{user}->{name};
128 0           my $sname = $tweet->{user}->{screen_name};
129 0           my $user = sprintf '%s (@%s)', $name, $sname;
130            
131 0           $text = unidecode(decode_entities($text));
132 0           my @lines = split /\n/, $text;
133              
134 0 0         if (@lines == 1) {
135 0           broadcast( 'message', $context, $channel, "$user - $lines[0]" );
136             }
137             else {
138 0           broadcast( 'message', $context, $channel, $user );
139             broadcast( 'message', $context, $channel, " - $_" )
140 0           foreach @lines;
141             }
142 0           return PLUGIN_EAT_ALL;
143             }
144             elsif ($self->tweet_links) {
145 0           my $title = $self->ua->get($uri)->result->dom->at('title')->text;
146 0   0       my $uni = unidecode($title) || $title;
147 0           my $short = substr($uni, 0, 100);
148            
149 0 0         next if not $title;
150              
151             # my $title = decode_entities(
152             # $ua->get($uri)->result->dom->at('title')->text
153             # ) or next;
154            
155 0 0         if (length($short) < length($uni)) {
156 0           $short = "$short...";
157             }
158              
159 0           eval { $self->twitter->update("$short - $uri") };
  0            
160              
161 0 0         if (my $err = $@) {
162 0           logger->warn(
163             "Failed to tweet URL [$uri]: " . $err->twitter_error_text,
164             );
165             }
166             }
167             }
168 0           return PLUGIN_EAT_NONE;
169             }
170              
171             1;
172              
173             __END__
174              
175             =pod
176              
177             =encoding UTF-8
178              
179             =head1 NAME
180              
181             Bot::Cobalt::Plugin::Twitter - Bot::Cobalt plugin for automatic tweeting
182              
183             =head1 VERSION
184              
185             version 0.002
186              
187             =head1 SYNOPSIS
188              
189             ## In plugins.conf
190             Twitter:
191             Module: Bot::Cobalt::Plugin::Twitter
192             Config: plugins/twitter.conf
193             Opts:
194             retweet_tweets: 0
195             tweet_links: 0
196             tweet_topics: 1
197              
198             ## In plugins/twitter.conf
199             ---
200             consumer_key: <twitter consumer key>
201             consumer_secret: <twitter consumer secret>
202             access_token: <twitter access token>
203             access_token_secret: <twitter access token secret>
204              
205             =head1 DESCRIPTION
206              
207             A L<Bot::Cobalt> plugin.
208              
209             This plugin will display the contents of a tweet that is linked in a channel.
210             Additionally, it does a handful of twitter-related functions.
211              
212             =over 4
213              
214             =item tweet_links (default: off)
215              
216             Whenever a link is tweeted, tweet it (with title).
217              
218             =item retweet_tweets (default: off)
219              
220             Whenever a tweet is linked, retweet it.
221              
222             =item tweet_topics (default: on)
223              
224             Whenever a topic changes, tweet it.
225              
226             =item !tweet
227              
228             Finally a command, !tweet that will tweet the message you provide it.
229              
230             =back
231              
232             =head1 AUTHOR
233              
234             Scott Miller <scott.j.miller@gmail.com>
235              
236             =head1 COPYRIGHT AND LICENSE
237              
238             This software is copyright (c) 2017 by Scott Miller.
239              
240             This is free software; you can redistribute it and/or modify it under
241             the same terms as the Perl 5 programming language system itself.
242              
243             =cut