Просмотр исходного кода

Added mostvoice/mostdevoices feature

Morten Brix Pedersen 25 лет назад
Родитель
Сommit
310f0ffc0f
5 измененных файлов с 141 добавлено и 50 удалено
  1. 8 2
      docs/CONFIG-README
  2. 57 41
      lang.txt
  3. 1 0
      modules/Pisg.pm
  4. 61 0
      modules/Pisg/HTMLGenerator.pm
  5. 14 7
      modules/Pisg/Parser/Logfile.pm

+ 8 - 2
docs/CONFIG-README

@@ -74,8 +74,9 @@ You can also combine settings into one line such as:
 All the different options are listed below.
 
 Other examples:
-<set lang='EN' langfile='lang.txt'>
+<set lang='EN'>
 <set bgcolor="#dedeee" text="black" hbgcolor="#666699" hcolor="white" hicell="#BABADD" hicell2="#CCCCCC">
+<set show_voice="1" show_wpl="1">
 <set topichistory="3" timeoffset="+0">
 
 There is many options which can be set, here's a list of them all (not
@@ -96,7 +97,8 @@ outputfile          Outputted stats goes to this HTML file. Default 'index.html'
 maintainer          The maintainer or bot which makes the logfile.
 
 lang                Language to use (see lang.txt)
-                    EN | DE | DK | FR | ES | PL | PT | NO | NL | SE
+                    EN | DE | DK | FR | ES | PL | PT | NO | NL | SE | EE | IT
+                    HU | SI | FI 
 
 pagehead            Some 'page header' file which you want to include in top
                     of the output file.
@@ -165,6 +167,10 @@ show_mrn            1 or 0, this will enable or disable the "most
 show_mru            1 or 0, this will enable or disable the "most
                     referenced urls" list
 
+show_voices         1 or 0, this will enable or disable the voice statistics
+                    (those who got voice and those who voiced). Disabled by
+                    default.
+
 ignorewords         A space seperated list of words to ignore in 'most
                     referenced words'
 

+ 57 - 41
lang.txt

@@ -30,15 +30,23 @@ mostop1 = "<b>[:nick]</b> donated [:ops] ops in the channel..."
 mostop2 = "<b>[:nick]</b> was also very polite: [:ops] ops from [:him:her:]."
 mostop3 = "Strange, no op was given on [:channel]!"
 
+mostdeop1 = "<b>[:nick]</b> is the channel sheriff with [:deops] deops."
+mostdeop2 = "<b>[:nick]</b> deoped [:deops] users."
+mostdeop3 = "Wow, no op was taken on [:channel]!"
+
+mostvoice1 = "<b>[:nick]</b> donated [:voices] voices in the channel..."
+mostvoice2 = "<b>[:nick]</b> was also very polite: [:voices] voices from [:him:her:]."
+mostvoice3 = "Strange, no voices was given on [:channel]!"
+
+mostdevoice1 = "<b>[:nick]</b> is the channel sheriff with [:devoices] devoices."
+mostdevoice2 = "<b>[:nick]</b> devoiced [:devoices] users."
+mostdevoice3 = "Wow, no devoices was taken on [:channel]!"
+
 action1 = "<b>[:nick]</b> always lets us know what [:he:she:]'s doing: [:actions] actions!"
 action2 = "Also, <b>[:nick]</b> tells us what's up with [:actions] actions."
 action3 = "No actions in [:channel]!"
 actiontext = "<b>For example, like this:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> is the channel sheriff with [:deops] deops."
-mostdeop2 = "<b>[:nick]</b> deoped [:deops] users."
-mostdeop3 = "Wow, no op was taken on [:channel]!"
-
 question1 = "Is <b>[:nick]</b> stupid or just asking too many questions?  [:per]% lines contained a question!"
 question2 = "<b>[:nick]</b> didn't know that much either.  [:per]% of [:his:her:] lines were questions."
 question3 = "Nobody asked questions here; just geniuses in this channel?"
@@ -141,11 +149,6 @@ pagetitle3 = "During this [:days]-day reporting period, a total of <b>[:nicks]</
 
 ### German
 <lang name="DE">
-action1 = "<b>[:nick]</b> hält uns immer auf dem Laufenden was [:er:sie:] gerade macht: [:actions] Actions!"
-action2 = "Auch <b>[:nick]</b> verät uns was los ist: [:actions] Actions von [:ihm:ihr:]."
-action3 = "Keine Actions in [:channel] !"
-actiontext = "<b>Zum Beispiel so:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
-
 mostop1 = "<b>[:nick]</b> vergab [:ops] ops im Channel..."
 mostop2 = "<b>[:nick]</b> war auch sehr zuvorkommend: [:ops] von [:ihm:ihr:]."
 mostop3 = "Komisch, kein op wurde in [:channel] vergeben!"
@@ -154,6 +157,11 @@ mostdeop1 = "<b>[:nick]</b> ist die Channel-Polizei. [:Er:Sie:] hat [:deops] Use
 mostdeop2 = "<b>[:nick]</b> nahm [:deops] Usern das @ wieder weg."
 mostdeop3 = "Wow, niemand wurde deopped in [:channel]!"
 
+action1 = "<b>[:nick]</b> hält uns immer auf dem Laufenden was [:er:sie:] gerade macht: [:actions] Actions!"
+action2 = "Auch <b>[:nick]</b> verät uns was los ist: [:actions] Actions von [:ihm:ihr:]."
+action3 = "Keine Actions in [:channel] !"
+actiontext = "<b>Zum Beispiel so:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
+
 question1 = "<b>[:nick]</b> hat wohl in der Schule nicht gut aufgepasst... [:per]% [:seiner:ihrer:] Zeilen enthielten eine Frage!"
 question2 = "<b>[:nick]</b> weiss wohl auch nicht viel, [:per]% [:seiner:ihrer:] Zeilen waren Fragen."
 question3 = "Niemand hat hier was gefragt, sollte das etwa ein Channel voller Genies sein? ;)"
@@ -259,15 +267,23 @@ mostop1 = "<b>[:nick]</b> gav [:ops] op status i kanalen..."
 mostop2 = "<b>[:nick]</b> var også venlig at gi': [:ops] fra sig"
 mostop3 = "Underligt, ingen har fået op på [:channel] endnu!"
 
+mostdeop1 = "<b>[:nick]</b> holder orden på [:channel] med [:deops] deops..."
+mostdeop2 = "<b>[:nick]</b> deoppede [:deops] brugere"
+mostdeop3 = "Hmm, der var ingen som blev deopped på [:channel]!"
+
+mostvoice1 = "<b>[:nick]</b> gav [:voices] voice i kanalen..."
+mostvoice2 = "<b>[:nick]</b> var også venlig at gi': [:voices] fra sig"
+mostvoice3 = "Underligt, ingen har fået voice på [:channel] endnu!"
+
+mostdevoice1 = "<b>[:nick]</b> holder orden på [:channel] med [:devoices] -v's"
+mostdevoice2 = "<b>[:nick]</b> devoicede [:devoices] brugere"
+mostdevoice3 = "Hmm, der var ingen som blev devoiced på [:channel]!"
+
 action1 = "<b>[:nick]</b> bruger /me meget tit, ialt [:actions] gange!"
 action2 = "<b>[:nick]</b> fortæller os også hvad [:han:hun:] laver.. [:actions] /me's"
 action3 = "Ingen /me's i [:channel] !"
 actiontext = "<b>For eksempel sådan her:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> holder orden på [:channel] med [:deops] deops..."
-mostdeop2 = "<b>[:nick]</b> deoppede [:deops] brugere"
-mostdeop3 = "Hmm, der var ingen som blev deopped på [:channel]!"
-
 question1 = "<b>[:nick]</b> må være rimelig dum eller efterligner bare Spørge-Jørgen... [:per]% af [:hans:hendes:] linjer var spørgsmål!"
 question2 = "<b>[:nick]</b> var heller ingen Einstein, [:per]% af [:hans:hendes:] linjer var også spørgsmål"
 question3 = "Ingen spørgsmål på denne kanal. De må sørme være kloge!"
@@ -373,15 +389,15 @@ mostop1 = "<b>[:nick]</b> a donn
 mostop2 = "<b>[:nick]</b> est aussi très poli : [:ops] ops de sa part"
 mostop3 = "Etrange, aucun op n'a été donné sur [:channel]!"
 
+mostdeop1 = "<b>[:nick]</b> est le shérif avec [:deops] deops..."
+mostdeop2 = "<b>[:nick]</b> a deopé [:deops] utilisateurs"
+mostdeop3 = "Wow, aucun op n'a été retiré sur [:channel]!"
+
 action1 = "<b>[:nick]</b> aime bien faire savoir ce qu'[:il:elle:]fait, avec [:actions] actions!"
 action2 = "Egalement <b>[:nick]</b> qui n'est pas en reste avec [:actions] actions!"
 action3 = "Aucune action sur [:channel] !"
 actiontext = "<b>Exemple:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> est le shérif avec [:deops] deops..."
-mostdeop2 = "<b>[:nick]</b> a deopé [:deops] utilisateurs"
-mostdeop3 = "Wow, aucun op n'a été retiré sur [:channel]!"
-
 question1 = "<b>[:nick]</b> est soit stupide soit trop curieux... [:per]% de ses lignes contiennent une question!"
 question2 = "<b>[:nick]</b> n'en connait pas davantage, [:per]% de ses lignes étaient des questions"
 question3 = "Personne ne pose de question ici, tous des génies sur ce channel?"
@@ -939,15 +955,15 @@ mostop1 = "<b>[:nick]</b> gav [:ops] personer operat
 mostop2 = "<b>[:nick]</b> var också väldigt vänlig: [:ops] från [:honom:henne:]"
 mostop3 = "Underligt, inga personer fick operatörsstatus i [:channel]!"
 
+mostdeop1 = "<b>[:nick]</b> var kanalens sheriff och tog ifrån [:deops] personer deras operatörsstatus..."
+mostdeop2 = "<b>[:nick]</b> tog ifrån [:deops] användare sin operatörsstatus"
+mostdeop3 = "Wow, inga personer blev av med sin operatörsstatus i [:channel]!"
+
 action1 = "<b>[:nick]</b> berättar alltid för oss vad [:han:hon:] gör: [:actions] beskrivningar!"
 action2 = "Även <b>[:nick]</b> berättar vad som händer med [:actions] beskrivningar."
 action3 = "Inga beskrivningar i [:channel]!"
 actiontext = "<b>Till exempel, såhär:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> var kanalens sheriff och tog ifrån [:deops] personer deras operatörsstatus..."
-mostdeop2 = "<b>[:nick]</b> tog ifrån [:deops] användare sin operatörsstatus"
-mostdeop3 = "Wow, inga personer blev av med sin operatörsstatus i [:channel]!"
-
 question1 = "<b>[:nick]</b> är antingen dum eller ställer bara många frågor... [:per]% rader innehöll en fråga!"
 question2 = "<b>[:nick]</b> visste heller inte mycket, [:per]% av [:hans:hennes:] rader innehöll en fråga"
 question3 = "Ingen frågade någonting, bara genier i denna kanalen?"
@@ -1041,15 +1057,15 @@ mostop1 = "<b>[:nick]</b> jakeli kanavalla oppeja [:ops] kertaa..."
 mostop2 = "<b>[:nick]</b>kin oli tosi kohtelias: häneltä tippui oppeja [:ops] kertaa!"
 mostop3 = "Kummaa kyllä, [:channel]:lla ei opitettu ketään!"
 
+mostdeop1 = "<b>[:nick]</b> yritti olla pomo [:deops] deopilla..."
+mostdeop2 = "Pikkupomon tittelin saa <b>[:nick]</b>: deopittanut [:deops] kertaa..."
+mostdeop3 = "Huh huh! Ketään ei rangaistu [:channel]:lla!"
+
 action1 = "<b>[:nick]</b> halusi kaikkien tietävän mitä on tekemässä: [:actions] /me:tä!"
 action2 = "Myöskin <b>[:nick]</b>:ssa esiintyy itserakkautta: selitteli tekemisiään [:actions] kertaa..."
 action3 = "Ei yhtään toimintaa [:channel]:lla!"
 actiontext = "<b>Yksi esimerkki:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> yritti olla pomo [:deops] deopilla..."
-mostdeop2 = "Pikkupomon tittelin saa <b>[:nick]</b>: deopittanut [:deops] kertaa..."
-mostdeop3 = "Huh huh! Ketään ei rangaistu [:channel]:lla!"
-
 question1 = "Onko <b>[:nick]</b> vähän tyhmä vai muuten kyselee liikaa?  [:per]% hänen kirjoittamista riveistään olivat kysymyksiä!"
 question2 = "Ei tuo <b>[:nick]</b>:kaan mitään tiedä... [:per]% hänen sanomisistaan olivat kysymiksiä..."
 question3 = "Kukaan ei kysellyt mitään! Onko tämä kanava täynnä neroja?"
@@ -1156,15 +1172,15 @@ mostop1 = "<b>[:nick]</b> je [:podaril:podarila:] [:ops] opov na kanalu..."
 mostop2 = "<b>[:nick]</b> je [:bil:bila:] tudi zelo [:radodaren:radodarna:]. [:ops] opov od [:njega:nje:]."
 mostop3 = "Cudno, nikomur ni bil dan op na [:channel]!"
 
+mostdeop1 = "<b>[:nick]</b> je [:bil:bila:] serif tega kanala z [:deops] deopi."
+mostdeop2 = "<b>[:nick]</b> je [:odvzel:odvzela:] op [:deops] uporabnikom kanala."
+mostdeop3 = "Wooo...nikomu ni bil odvzet op na kanalu [:channel]!"
+
 action1 = "<b>[:nick]</b> nam je vedno [:povedal:povedala:] kaj pocne: [:actions] dejanj!"
 action2 = "Tudi <b>[:nick]</b> nam je vedno [:povedal:povedala:] kaj se je dogajalo z [:njim:njo:], [:actions] dejanj."
 action3 = "Nobenih dejanj na kanalu [:channel]!"
 actiontext = "<b>Najbolj izstopa primer:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> je [:bil:bila:] serif tega kanala z [:deops] deopi."
-mostdeop2 = "<b>[:nick]</b> je [:odvzel:odvzela:] op [:deops] uporabnikom kanala."
-mostdeop3 = "Wooo...nikomu ni bil odvzet op na kanalu [:channel]!"
-
 question1 = "Je <b>[:nick]</b> res najbolj [:neumen:neumna:] na tem kanalu ali samo sprasuje veliko vprasanj? [:per]% [:njegovih:njenih:] vrstic so bila vprasanja!"
 question2 = "<b>[:nick]</b> ni [:imel:imela:] pojma o nicemer.  [:per]% [:njegovih:njenih:] vrstic so bila vprasanja."
 question3 = "Nihce ni nic vprasal na tem kanalu; ocitno so sami geniji na tem kanalu?"
@@ -1272,15 +1288,15 @@ mostop1 = "<b>[:nick]</b> [:ops] opot adott a csatin..."
 mostop2 = "<b>[:nick]</b> szinten nagylelku: [:ops] opot adomanyozott."
 mostop3 = "Erdekes, senki nem kapott opot a [:channel] csatin!"
 
+mostdeop1 = "<b>[:nick]</b> volt a csati rendore, [:deops] alkalommal deopolt."
+mostdeop2 = "<b>[:nick]</b> deopolt [:deops] emberket."
+mostdeop3 = "Hu, nem vettek el egy opot sem a [:channel]-n!"
+
 action1 = "<b>[:nick]</b> mindig tudatja velunk mit csinal: [:actions] akciot nyomott!"
 action2 = "A masodik <b>[:nick]</b>, aki [:actions] alkalommal mondta el, mi a helyzet vele."
 action3 = "Semmi ekson nem volt a [:channel]-n!"
 actiontext = "<b>Peldaul:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> volt a csati rendore, [:deops] alkalommal deopolt."
-mostdeop2 = "<b>[:nick]</b> deopolt [:deops] emberket."
-mostdeop3 = "Hu, nem vettek el egy opot sem a [:channel]-n!"
-
 question1 = "<b>[:nick]</b> kerdez a legtobbet, a sorainak a [:per]%-a tartalmazott kerdest."
 question2 = "<b>[:nick]</b> se tud sokkal tobbet. O [:per]%-ban tett fel kerdeseket."
 question3 = "Senki sem kerdezett a csatin - csak zsenik jarnak ide? <B>( Nem muxik :( )</B>"
@@ -1387,15 +1403,15 @@ mostop1 = "K
 mostop2 = "<b>[:nick]</b> ei tahtnud sitem olla ja andis [:ops] opi."
 mostop3 = "Imelik, aga kanalil [:channel] ei andnud keegi kellegile opi!"
 
+mostdeop1 = "<b>[:nick]</b> mõtles, et on kõva kutt ja võttis [:deops]-lt kasutajalt op staatuse ära."
+mostdeop2 = "<b>[:nick]</b> deopis [:deops] kasutajat."
+mostdeop3 = "Ohoh, päris karm kanal see [:channel], keegi ei võtnud kelleltki opi ära!"
+
 action1 = "<b>[:nick]</b> tahtis, et kõik teaksid, mida ta teeb: kokku [:actions] tegevust!"
 action2 = "Kusjuures, <b>[:nick]</b> tahtis ka, et kõik teaksid tema tegevusest: kokku [:actions] tegevust."
 action3 = "Mitte yhtegi tegevuse kirjeldus selle perioodi jooksul!"
 actiontext = "<b>Näiteks:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> mõtles, et on kõva kutt ja võttis [:deops]-lt kasutajalt op staatuse ära."
-mostdeop2 = "<b>[:nick]</b> deopis [:deops] kasutajat."
-mostdeop3 = "Ohoh, päris karm kanal see [:channel], keegi ei võtnud kelleltki opi ära!"
-
 question1 = "Tundub, et <b>[:nick]</b> on mingi eriti loll tegelane või esitab ta lihtsalt liiga palju küsimusi?: [:per]% tema kirjutatud ridadest olid küsimused"
 question2 = "<b>[:nick]</b> ei teadnud ka kuigi palju: [:per]% tema kirjutatud ridadest olid küsimused."
 question3 = "Keegi ei esitanud küsimusi, tundub et siin kanalis käivad ainult targad inimesed"
@@ -1500,15 +1516,15 @@ mostop1 = "<b>[:nick]</b> ha oppato [:ops] persone..."
 mostop2 = "Anche <b>[:nick]</b> e' stato gentile: [:ops] persone sono state oppate da [:him:her:]."
 mostop3 = "Strano, nessuno e' stato oppato su [:channel]!"
 
+mostdeop1 = "<b>[:nick]</b> e' lo sceriffo del canale con [:deops] deop."
+mostdeop2 = "<b>[:nick]</b> ha deoppato [:deops] persone."
+mostdeop3 = "Wow, nessuno e' stato deoppato su [:channel]!"
+
 action1 = "<b>[:nick]</b> vuole sempre farci sapere cosa sta facendo: [:actions] actions!"
 action2 = "Inoltre, <b>[:nick]</b> ci spiffera [:actions] actions."
 action3 = "No actions in [:channel]!"
 actiontext = "<b>Ad esempio:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
-mostdeop1 = "<b>[:nick]</b> e' lo sceriffo del canale con [:deops] deop."
-mostdeop2 = "<b>[:nick]</b> ha deoppato [:deops] persone."
-mostdeop3 = "Wow, nessuno e' stato deoppato su [:channel]!"
-
 question1 = "Ma <b>[:nick]</b> e' stupido o semplicemente fa troppe domande?  [:per]% linee contengono una domanda!"
 question2 = "<b>[:nick]</b> non era meglio.  [:per]% di linee erano domande."
 question3 = "Nessuno ha posto una domanda nel canale, tutti geni?"

+ 1 - 0
modules/Pisg.pm

@@ -172,6 +172,7 @@ sub get_default_config_settings
         show_muw => 1,
         show_mrn => 1,
         show_mru => 1,
+        show_voices => 0,
 
         # Less important things
 

+ 61 - 0
modules/Pisg/HTMLGenerator.pm

@@ -94,6 +94,7 @@ sub create_html
         $self->_gotkicks();
         $self->_mostkicks();
         $self->_mostop();
+        $self->_mostvoice() if $self->{cfg}->{show_voice};
         $self->_mostactions();
         $self->_mostmonologues();
         $self->_mostjoins();
@@ -1076,6 +1077,66 @@ sub _mostop
     }
 }
 
+sub _mostvoice
+{
+    my $self = shift;
+
+    my @voice   = sort { $self->{stats}->{gavevoice}{$b} <=> $self->{stats}->{gavevoice}{$a} }
+                     keys %{ $self->{stats}->{gavevoice} };
+    my @devoice = sort { $self->{stats}->{tookvoice}{$b} <=> $self->{stats}->{tookvoice}{$a} }
+                     keys %{ $self->{stats}->{tookvoice} };
+
+    if (@voice) {
+        my %hash = (
+            nick => $voice[0],
+            voices  => $self->{stats}->{gavevoice}{$voice[0]}
+        );
+
+        my $text = $self->_template_text('mostvoice1', %hash);
+
+        _html("<tr><td bgcolor=\"$self->{cfg}->{hicell}\">$text");
+
+        if (@voice >= 2) {
+            my %hash = (
+                nick => $voice[1],
+                voices  => $self->{stats}->{gavevoice}{$voice[1]}
+            );
+
+            my $text = $self->_template_text('mostvoice2', %hash);
+            _html("<br><span class=\"small\">$text</span>");
+        }
+        _html("</td></tr>");
+    } else {
+        my $text = $self->_template_text('mostvoice3');
+        _html("<tr><td bgcolor=\"$self->{cfg}->{hicell}\">$text</td></tr>");
+    }
+
+    if (@devoice) {
+        my %hash = (
+            nick  => $devoice[0],
+            devoices => $self->{stats}->{tookvoice}{$devoice[0]}
+        );
+        my $text = $self->_template_text('mostdevoice1', %hash);
+
+        _html("<tr><td bgcolor=\"$self->{cfg}->{hicell}\">$text");
+
+        if (@devoice >= 2) {
+            my %hash = (
+                nick  => $devoice[1],
+                devoices => $self->{stats}->{tookvoice}{$devoice[1]}
+            );
+            my $text = $self->_template_text('mostdevoice2', %hash);
+
+            _html("<br><span class=\"small\">$text</span>");
+        }
+        _html("</td></tr>");
+    } else {
+        my $text = $self->_template_text('mostdevoice3');
+        _html("<tr><td bgcolor=\"$self->{cfg}->{hicell}\">$text");
+    }
+
+}
+
 sub _mostactions
 {
     # The person who did the most /me's

+ 14 - 7
modules/Pisg/Parser/Logfile.pm

@@ -339,9 +339,7 @@ sub _parse_file
                     }
 
                 } elsif (defined($newmode)) {
-                    my @opchange = _opchanges($newmode);
-                    $stats->{gaveops}{$nick} += $opchange[0] if $opchange[0];
-                    $stats->{tookops}{$nick} += $opchange[1] if $opchange[1];
+                    _modechanges($stats, $newmode, $nick);
 
                 } elsif (defined($newjoin)) {
                     $stats->{joins}{$nick}++;
@@ -359,20 +357,29 @@ sub _parse_file
         unless ($self->{cfg}->{silent});
 }
 
-sub _opchanges
+sub _modechanges
 {
-    my (@ops, $plus);
-    foreach (split(//, $_[0])) {
+    my $stats = shift;
+    my $newmode = shift;
+    my $nick = shift;
+
+    my (@voice, @ops, $plus);
+    foreach (split(//, $newmode)) {
         if ($_ eq "o") {
             $ops[$plus]++;
+        } elsif ($_ eq "v") {
+            $voice[$plus]++;
         } elsif ($_ eq "+") {
             $plus = 0;
         } elsif ($_ eq "-") {
             $plus = 1;
         }
     }
+    $stats->{gaveops}{$nick} += $ops[0] if $ops[0];
+    $stats->{tookops}{$nick} += $ops[1] if $ops[1];
+    $stats->{gavevoice}{$nick} += $voice[0] if $voice[0];
+    $stats->{tookvoice}{$nick} += $voice[1] if $voice[1];
 
-    return @ops;
 }
 
 sub _parse_words