File Coverage

blib/lib/Bot/Cobalt/Plugin/Extras/Karma.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Bot::Cobalt::Plugin::Extras::Karma;
2             $Bot::Cobalt::Plugin::Extras::Karma::VERSION = '0.021001';
3             ## simple karma++/-- tracking
4              
5 1     1   746 use Carp;
  1         1  
  1         51  
6 1     1   4 use strictures 2;
  1         5  
  1         40  
7              
8 1     1   151 use Object::Pluggable::Constants qw/ :ALL /;
  1         1  
  1         83  
9              
10 1     1   3 use Bot::Cobalt;
  1         1  
  1         4  
11 1     1   644 use Bot::Cobalt::DB;
  0            
  0            
12              
13             use List::Objects::WithUtils;
14              
15             use File::Spec;
16              
17             use IRC::Utils qw/decode_irc/;
18              
19             sub new { bless +{ Cache => hash }, shift }
20              
21             sub _cache { shift->{Cache} }
22             sub _set_cache { $_[0]->{Cache} = ($_[1] || confess "Expected a param") }
23              
24             sub Cobalt_register {
25             my ($self, $core) = splice @_, 0, 2;
26            
27             my $dbpath = File::Spec->catfile( $core->var, 'karma.db' );
28            
29             $self->{karmadb} = Bot::Cobalt::DB->new(
30             file => $dbpath,
31             );
32              
33             $self->{karma_regex} = qr/^(\S+)(\+{2}|\-{2})$/;
34              
35             register( $self, 'SERVER',
36             qw/
37             public_msg
38             public_cmd_karma
39             public_cmd_topkarma
40             public_cmd_resetkarma
41            
42             karmaplug_sync_db
43             /
44             );
45              
46             $core->timer_set( 5,
47             { Event => 'karmaplug_sync_db' },
48             'KARMAPLUG_SYNC_DB',
49             );
50              
51             logger->info("Registered");
52              
53             PLUGIN_EAT_NONE
54             }
55              
56             sub Cobalt_unregister {
57             my ($self, $core) = splice @_, 0, 2;
58             logger->debug("Calling _sync");
59             $self->_sync();
60             logger->info("Unregistered");
61             PLUGIN_EAT_NONE
62             }
63              
64              
65             sub _sync {
66             my ($self) = @_;
67             return unless keys %{ $self->_cache };
68            
69             my $db = $self->{karmadb};
70             unless ($db->dbopen) {
71             logger->error("dbopen failure for karmadb in _sync");
72             return
73             }
74            
75             for my $karma_for (keys %{ $self->_cache }) {
76             my $current = $self->_cache->{$karma_for};
77             $current ?
78             $db->put($karma_for, $current)
79             : $db->del($karma_for);
80             delete $self->_cache->{$karma_for};
81             }
82              
83             $db->dbclose;
84             1
85             }
86              
87             sub _get {
88             my ($self, $karma_for) = @_;
89            
90             return $self->_cache->{$karma_for}
91             if exists $self->_cache->{$karma_for};
92            
93             my $db = $self->{karmadb};
94             unless ($db->dbopen) {
95             logger->error("dbopen failure for karmadb in _get");
96             return
97             }
98             my $current = $db->get($karma_for) || 0;
99             $db->dbclose;
100              
101             $current
102             }
103              
104             sub Bot_karmaplug_sync_db {
105             my ($self, $core) = splice @_, 0, 2;
106            
107             $self->_sync();
108             $core->timer_set( 5,
109             { Event => 'karmaplug_sync_db' },
110             'KARMAPLUG_SYNC_DB',
111             );
112              
113             PLUGIN_EAT_NONE
114             }
115              
116             sub Bot_public_msg {
117             my ($self, $core) = splice @_, 0, 2;
118             my $msg = ${$_[0]};
119             return PLUGIN_EAT_NONE if $msg->highlight
120             or $msg->cmd;
121             my $context = $msg->context;
122              
123             my $first_word = $msg->message_array->[0] // return PLUGIN_EAT_NONE;
124             $first_word = decode_irc($first_word);
125              
126             if ($first_word =~ $self->{karma_regex}) {
127             my ($karma_for, $karma) = (lc($1), $2);
128             my $current = $self->_get($karma_for);
129             if ($karma eq '--') {
130             --$current;
131             } elsif ($karma eq '++') {
132             ++$current;
133             }
134              
135             $self->_cache->{$karma_for} = $current;
136             }
137              
138             PLUGIN_EAT_NONE
139             }
140              
141             sub Bot_public_cmd_resetkarma {
142             my ($self, $core) = splice @_, 0, 2;
143             my $msg = ${$_[0]};
144             my $context = $msg->context;
145             my $nick = $msg->src_nick;
146             my $usr_lev = $core->auth->level($context, $nick)
147             || return PLUGIN_EAT_ALL;
148              
149             my $pcfg = $core->get_plugin_cfg($self);
150             my $req_lev = $pcfg->{LevelRequired} || 9999;
151             return PLUGIN_EAT_ALL unless $usr_lev >= $req_lev;
152              
153             my $channel = $msg->target;
154              
155             my $karma_for = lc($msg->message_array->[0] || return PLUGIN_EAT_ALL);
156             $karma_for = decode_irc($karma_for);
157              
158             unless ( $self->_get($karma_for) ) {
159             broadcast( 'message', $context, $channel,
160             "${nick}: that item has no karma to clear",
161             );
162             return PLUGIN_EAT_ALL
163             }
164            
165             $self->_cache->{$karma_for} = 0;
166             logger->debug("Calling explicit _sync for cmd_resetkarma");
167             $self->_sync;
168              
169             logger->info("Cleared karma for '$karma_for' per '$nick' on $context");
170             broadcast( 'message', $context, $channel, "Cleared karma for $karma_for" );
171            
172             PLUGIN_EAT_ALL
173             }
174              
175             sub Bot_public_cmd_karma {
176             my ($self, $core) = splice @_, 0, 2;
177             my $msg = ${$_[0]};
178             my $context = $msg->context;
179             my $channel = $msg->target;
180              
181             my $karma_for = $msg->message_array->[0];
182             $karma_for = lc($karma_for || $msg->src_nick);
183             $karma_for = decode_irc($karma_for);
184              
185             my $resp;
186             if ( my $karma = $self->_get($karma_for) ) {
187             $resp = "Karma for $karma_for: $karma";
188             } else {
189             $resp = "$karma_for currently has no karma, good or bad.";
190             }
191              
192             broadcast( 'message', $context, $channel, $resp );
193              
194             PLUGIN_EAT_ALL
195             }
196              
197             sub Bot_public_cmd_topkarma {
198             my ($self, $core) = splice @_, 0, 2;
199             my $msg = ${ $_[0] };
200             my $context = $msg->context;
201             my $channel = $msg->target;
202              
203             if ($self->{cached_top} && time - $self->{cached_top}->[0] < 300) {
204             broadcast( 'message', $context, $channel, $self->{cached_top}->[1] );
205             return PLUGIN_EAT_NONE
206             }
207              
208             my $db = $self->{karmadb};
209             unless ($db->dbopen) {
210             logger->error("dbopen failure for karmadb in cmd_topkarma");
211             broadcast( 'message', $context, $channel, 'karmadb open failure' );
212             return PLUGIN_EAT_ALL
213             }
214             my $karma = hash(%{ $db->dbdump('HASH') });
215             $db->dbclose;
216             $karma->set(%{ $self->_cache }) if keys %{ $self->_cache };
217             # some common junk data:
218             $karma->delete('<', '-', '<-', '<--');
219             my $sorted = $karma->kv_sort(sub { $karma->get($a) <=> $karma->get($b) });
220             my $bottom = $sorted->sliced(0..4)->grep(sub { defined });
221             my $top = $sorted
222             ->sliced( ($sorted->end - 4) .. $sorted->end )
223             ->grep(sub { defined });
224              
225             my $str = '[ top -> ';
226             for my $pair ($top->reverse->all) {
227             my ($item, $karma) = @$pair;
228             $str .= "'${item}':${karma} ";
229             }
230             $str .= ']; [ bottom -> ';
231             for my $pair ($bottom->all) {
232             my ($item, $karma) = @$pair;
233             $str .= "'${item}':${karma} ";
234             }
235             $str .= ']';
236              
237             $self->{cached_top} = [ time, $str ];
238              
239             broadcast( 'message', $context, $channel, $str );
240             PLUGIN_EAT_ALL
241             }
242              
243              
244             1;
245             __END__