File Coverage

blib/lib/Bot/Cobalt/Plugin/Twitter.pm
Criterion Covered Total %
statement 28 114 24.5
branch 0 28 0.0
condition 0 13 0.0
subroutine 10 21 47.6
pod 4 12 33.3
total 42 188 22.3


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.004';
4 1     1   19126 use strict;
  1         4  
  1         34  
5 1     1   6 use warnings;
  1         3  
  1         32  
6              
7 1     1   532 use Bot::Cobalt;
  1         12128  
  1         7  
8 1     1   2083 use Bot::Cobalt::Common;
  1         237575  
  1         6  
9              
10 1     1   10966 use HTML::Entities qw(decode_entities);
  1         5493  
  1         94  
11 1     1   1053 use Mojo::UserAgent;
  1         266696  
  1         8  
12 1     1   508 use Twitter::API;
  1         114283  
  1         48  
13 1     1   681 use Text::Unidecode qw(unidecode);
  1         1399  
  1         96  
14 1     1   488 use URI::Find::Simple qw(list_uris);
  1         3352  
  1         1151  
15              
16             my $status_rx = qr/twitter\.com\/\w+\/status\/(\d+)/;
17              
18 1     1 0 82 sub new { bless {}, shift }
19 0     0 0   sub twitter { shift->{twitter} }
20              
21 0     0 1   sub display_tweets { shift->{display_tweets} }
22 0     0 1   sub tweet_topics { shift->{tweet_topics} }
23 0     0 1   sub tweet_links { shift->{tweet_links} }
24 0     0 1   sub retweet_tweets { shift->{retweet_tweets} }
25 0     0 0   sub ua { shift->{useragent} }
26              
27             sub Cobalt_register {
28 0     0 0   my $self = shift;
29 0           my $core = shift;
30 0           my $conf = $core->get_plugin_cfg($self);
31              
32 0   0       $self->{display_tweets} = $conf->{display_tweets} // 1;
33 0   0       $self->{tweet_topics} = $conf->{tweet_topics} // 1;
34 0           $self->{tweet_links} = $conf->{tweet_links};
35 0           $self->{retweet_tweets} = $conf->{retweet_tweets};
36 0           $self->{useragent} = Mojo::UserAgent->new;
37              
38 0           eval {
39             $self->{twitter} = Twitter::API->new_with_traits(
40             traits => 'Enchilada',
41             consumer_key => $conf->{consumer_key},
42             consumer_secret => $conf->{consumer_secret},
43             access_token => $conf->{access_token},
44             access_token_secret => $conf->{access_token_secret},
45 0           );
46             };
47              
48 0 0         if (my $err = $@) {
49 0           logger->warn("Unable to create Twitter::API object: $err");
50             }
51              
52 0           register( $self, 'SERVER', qw(public_msg public_cmd_tweet topic_changed) );
53 0           logger->info("Registered, commands: !tweet");
54              
55 0           return PLUGIN_EAT_NONE;
56             }
57              
58             sub Cobalt_unregister {
59 0     0 0   my $self = shift;
60 0           my $core = shift;
61              
62 0           logger->info("Unregistered");
63            
64 0           return PLUGIN_EAT_NONE;
65             }
66              
67             sub Bot_topic_changed {
68 0     0 0   my $self = shift;
69 0           my $core = shift;
70 0           my $topic = ${ shift() };
  0            
71              
72 0 0         return PLUGIN_EAT_NONE if not $self->tweet_topics;
73              
74 0           my $new_topic = $topic->stripped;
75 0           my $status = substr($new_topic, 0, 139);
76              
77 0           $self->twitter->update($status);
78              
79 0           return PLUGIN_EAT_NONE;
80             }
81              
82             sub Bot_public_cmd_tweet {
83 0     0 0   my $self = shift;
84 0           my $core = shift;
85 0           my $msg = ${ shift() };
  0            
86              
87 0           my $context = $msg->context;
88 0           my $channel = $msg->target;
89 0           my $nick = $msg->src_nick;
90              
91 0           my @split = split(/ /, $msg->stripped);
92              
93 0           shift @split; # shift off the command
94              
95 0           my $status = substr( join(' ', @split), 0, 139);
96              
97 0           $self->twitter->update($status);
98              
99 0           return PLUGIN_EAT_ALL;
100             }
101              
102             sub Bot_public_msg {
103 0     0 0   my $self = shift;
104 0           my $core = shift;
105 0           my $msg = ${ shift() };
  0            
106              
107 0 0 0       return PLUGIN_EAT_NONE
      0        
108             unless $self->display_tweets or $self->tweet_links or $self->retweet_tweets;
109              
110 0           my $context = $msg->context;
111 0           my $channel = $msg->target;
112              
113 0           foreach my $uri ( list_uris($msg->message) ) {
114 0 0         next if not $uri;
115              
116 0 0         if ($uri =~ $status_rx) {
    0          
117 0           my $id = $1;
118 0 0         if ($self->retweet_tweets) {
119 0           eval { $self->twitter->retweet($id) };
  0            
120 0 0         if (my $err = $@) {
121 0           logger->warn(
122             "Failed to retweet [$id] - " . $err->twitter_error_text,
123             );
124             }
125             }
126            
127 0 0         if ($self->display_tweets) {
128 0           my $tweet = $self->twitter->show_status($id, { tweet_mode => 'extended' });
129 0 0         my $text = $tweet->{truncated} ? $tweet->{text} : $tweet->{full_text};
130 0           my $name = $tweet->{user}->{name};
131 0           my $sname = $tweet->{user}->{screen_name};
132 0           my $user = sprintf '%s (@%s)', $name, $sname;
133            
134 0           $text = unidecode(decode_entities($text));
135 0           my @lines = split /\n/, $text;
136              
137 0 0         if (@lines == 1) {
138 0           broadcast( 'message', $context, $channel, "$user - $lines[0]" );
139             }
140             else {
141 0           broadcast( 'message', $context, $channel, $user );
142             broadcast( 'message', $context, $channel, " - $_" )
143 0           foreach @lines;
144             }
145 0           return PLUGIN_EAT_ALL;
146             }
147             }
148             elsif ($self->tweet_links) {
149 0           my $title = $self->ua->get($uri)->result->dom->at('title')->text;
150 0   0       my $uni = unidecode($title) || $title;
151 0           my $short = substr($uni, 0, 100);
152            
153 0 0         next if not $title;
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.004
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             display_tweets: 1
195             retweet_tweets: 0
196             tweet_links: 0
197             tweet_topics: 1
198              
199             ## In plugins/twitter.conf
200             ---
201             consumer_key: <twitter consumer key>
202             consumer_secret: <twitter consumer secret>
203             access_token: <twitter access token>
204             access_token_secret: <twitter access token secret>
205              
206             =head1 DESCRIPTION
207              
208             A L<Bot::Cobalt> plugin.
209              
210             This plugin will display the contents of a tweet that is linked in a channel.
211             Additionally, it does a handful of twitter-related functions.
212              
213             =over 4
214              
215             =item display_tweets (default: on)
216              
217             Whenever a twitter status link is said in chat, look it up and display it.
218              
219             =item tweet_links (default: off)
220              
221             Whenever a link is tweeted, tweet it (with title).
222              
223             =item retweet_tweets (default: off)
224              
225             Whenever a tweet is linked, retweet it.
226              
227             =item tweet_topics (default: on)
228              
229             Whenever a topic changes, tweet it.
230              
231             =item !tweet
232              
233             Finally a command, !tweet that will tweet the message you provide it.
234              
235             =back
236              
237             =head1 AUTHOR
238              
239             Scott Miller <scott.j.miller@gmail.com>
240              
241             =head1 COPYRIGHT AND LICENSE
242              
243             This software is copyright (c) 2017 by Scott Miller.
244              
245             This is free software; you can redistribute it and/or modify it under
246             the same terms as the Perl 5 programming language system itself.
247              
248             =cut