]> git.somenet.org - irc/bugbot.git/blob - BotModules/Karma.bm
GITOLITE.txt
[irc/bugbot.git] / BotModules / Karma.bm
1 # -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
2 ################################
3 # Karma Module                 #
4 ################################
5
6 package BotModules::Karma;
7 use vars qw(@ISA);
8 @ISA = qw(BotModules);
9 1;
10
11 # RegisterConfig - Called when initialised, should call registerVariables
12 sub RegisterConfig {
13     my $self = shift;
14     $self->SUPER::RegisterConfig(@_);
15     $self->registerVariables(
16       # [ name, save?, settable? ]
17       ['scores', 1, 1, {}], # nick => total karma.
18       ['privateScores', 1, 1, {}], # nick => nick karma nick karma...
19       ['secondsDelayRequired', 1, 1, 20],
20       ['_lastspoken', 0, 0, {}], # nick => nick => time
21     );
22 }
23
24 sub Help {
25     my $self = shift;
26     my ($event) = @_;
27     return {
28             '' => 'A karma tracker. If you have authenticated (using the \'auth\' command) then it will also keep track of your own setting of people\'s karma, as well as the total of everyone\'s settings. Use the \'rank\' command to find someone\'s karma rank.',
29             '++' => 'Increase someone\'s karma. Syntax: victim++',
30             '--' => 'Decrease someone\'s karma. Syntax: victim--',
31             'rank' => 'Find someone\'s karma level. Omit the victim\'s name to get a complete listing of everyone\'s karma (long). Syntax: \'rank victim\' or just \'rank\'',
32     };
33 }
34
35 sub Told {
36     my $self = shift;
37     my ($event, $message) = @_;
38     if ($message =~ /^(\S+)\+\+$/os) {
39         $self->ChangeKarma($event, $1, 1);
40     } elsif ($message =~ /^(\S+)\-\-$/os) {
41         $self->ChangeKarma($event, $1, -1);
42     } elsif ($message =~ /^\s*(?:karma\s+)?ranks?[?\s]*$/os) {
43         $self->ReportKarmaRanks($event, $1);
44     } elsif ($message =~ /^\s*karma(?:\s+rank)?\s+(\S+)[?\s]*$/os or
45              $message =~ /^\s*(?:karma\s+)?rank\s+(\S+)[?\s]*$/os) {
46         $self->ReportKarma($event, $1);
47     } else {
48         return $self->SUPER::Told(@_);
49     }
50     return 0; # dealt with it...
51 }
52
53 sub Heard {
54     my $self = shift;
55     my ($event, $message) = @_;
56     if ($message =~ /^(\S*[^-+\s])\+\+$/os) {
57         $self->ChangeKarma($event, $1, 1);
58     } elsif ($message =~ /^(\S*[^-+\s])\-\-$/os) {
59         $self->ChangeKarma($event, $1, -1);
60     } else {
61         return $self->SUPER::Told(@_);
62     }
63     return 0; # we've dealt with it, no need to do anything else.
64 }
65
66 sub ChangeKarma {
67     my $self = shift;
68     my ($event, $who, $delta) = @_;
69     $self->debug("$who += $delta requested");
70     if ((defined($self->{'_lastSpoken'}->{$event->{'user'}})) and
71         (defined($self->{'_lastSpoken'}->{$event->{'user'}}->{lc $who})) and
72         (($event->{'time'} - $self->{'_lastSpoken'}->{$event->{'user'}}->{lc $who}) <= $self->{'secondsDelayRequired'})) {
73         $self->{'_lastSpoken'}->{$event->{'user'}}->{lc $who} = $self->{'_lastSpoken'}->{$event->{'user'}}->{lc $who}+5;
74         my $delay = $self->{'secondsDelayRequired'} - ($event->{'time'} - $self->{'_lastSpoken'}->{$event->{'user'}}->{lc $who});
75         $self->directSay($event, "You will have to wait another $delay seconds before being able to change ${who}'s karma.");
76     } else {
77         if (not defined($self->{'_lastSpoken'}->{$event->{'user'}})) {
78             $self->{'_lastSpoken'}->{$event->{'user'}} = {};
79         }
80         $self->{'_lastSpoken'}->{$event->{'user'}}->{lc $who} = $event->{'time'};
81         if (lc $event->{'from'} eq lc $who) {
82             if ($delta > 0) {
83                 $delta = -$delta;
84             }
85         }
86         if ($event->{'channel'} ne '') {
87             $self->{'scores'}->{lc $who} += $delta;
88             if ($self->{'scores'}->{lc $who} == 0) {
89                 delete($self->{'scores'}->{lc $who});
90             }
91         }
92         my $nick = lc $event->{'userName'};
93         if ($nick) {
94             if (not defined($self->{"privateScores"}->{$nick})) {
95                 $self->{"privateScores"}->{$nick} = (lc($who) . ' ' . $delta);
96             } else {
97                 my %privateScores = split(' ', $self->{"privateScores"}->{$nick});
98                 $privateScores{lc $who} += $delta;
99                 if ($privateScores{lc $who} == 0) {
100                     delete($privateScores{lc $who});
101                 }
102                 my @privateScores = %privateScores;
103                 local $" = ' ';
104                 $self->{'privateScores'}->{$nick} = "@privateScores";
105             }
106         } elsif ($event->{'channel'} eq '') {
107             $self->say($event, 'For private stats, you need to authenticate. Use the \'newuser\' and \'auth\' commands.');
108         }
109         $self->saveConfig();
110     }
111 }
112
113 sub ReportKarma {
114     my $self = shift;
115     my ($event, $who) = @_;
116     if (not defined($self->{'scores'}->{lc $who})) {
117         $self->say($event, "$who has no karma.");
118     } else {
119         my $karma = $self->{'scores'}->{lc $who};
120         my @order = sort { $self->{'scores'}->{$b} <=> $self->{'scores'}->{$a} } keys(%{$self->{'scores'}});
121         my $rank = 0;
122         if (scalar(@order)) {
123             user: foreach my $user (@order) {
124                 $rank++;
125                 if (lc $user eq lc $who) {
126                     last user;
127                 }
128             }
129         }
130         $self->say($event, "$who has $karma points of karma (rank $rank).");
131     }
132     if ($event->{'channel'} eq '') {
133         $nick = lc $event->{'userName'};
134         if ($nick) {
135             if (not defined($self->{"privateScores"}->{$nick})) {
136                 $self->say($event, "You have not given anyone any karma.");
137             } else {
138                 my %privateScores = split(' ', $self->{"privateScores"}->{$nick});
139                 my $karma = $privateScores{lc $who};
140
141                 if (not defined($karma)) {
142                     $self->say($event, "You have not given $who any karma.");
143                 } else {
144                     $self->say($event, "You have given $who $karma points of karma.");
145                 }
146             }
147         } else {
148             $self->say($event, 'For private stats, you need to authenticate. Use the \'newuser\' and \'auth\' commands.');
149         }
150     }
151 }
152
153 sub ReportKarmaRanks {
154     my $self = shift;
155     my ($event) = @_;
156     my @order = sort { $self->{'scores'}->{$b} <=> $self->{'scores'}->{$a} } keys(%{$self->{'scores'}});
157     if (scalar(@order)) {
158         if ($event->{'channel'} ne '') {
159             my $top = $order[0];
160             my $score = $self->{'scores'}->{$top};
161             $self->say($event, "The person with the most karma is $top with $score points.");
162         }
163         $self->directSay($event, "Global rankings:");
164         $self->ReportKarmaRanksList($event, \@order, $self->{'scores'});
165     }
166     if ($event->{'channel'} eq '') {
167         $nick = lc $event->{'userName'};
168         if ($nick) {
169             if (defined($self->{"privateScores"}->{$nick})) {
170                 my %privateScores = split(' ', $self->{"privateScores"}->{$nick});
171                 @order = sort { $privateScores{$b} <=> $privateScores{$a} } keys(%privateScores);
172                 if (scalar(@order)) {
173                     $self->directSay($event, "Personal rankings:");
174                     $self->ReportKarmaRanksList($event, \@order, \%privateScores);
175                 } else {
176                     $self->say($event, "I seem to have lost track of the people to which you gave karma points.");
177                 }
178             } else {
179                 $self->say($event, "You have not given anyone karma.");
180             }
181         } else {
182             $self->say($event, 'For private stats, you need to authenticate. Use the \'newuser\' and \'auth\' commands.');
183         }
184     }
185 }
186
187 sub ReportKarmaRanksList {
188     my $self = shift;
189     my($event, $order, $scores) = @_;
190     my $rank = 1;
191     foreach my $entry (@$order) {
192         my $score = $scores->{$entry};
193         $self->directSay($event, "$rank. $entry ($score)");
194         $rank++;
195     }
196 }