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

Big patch by the almighty Phil Gregory.
This creates two new modules and restructures a lot of things; all the
parsing code is now divided into modules, meaning we have a 'Logfile.pm' for
parsing normal logfiles, and we have some common functions in 'Common.pm'.

Morten Brix Pedersen 25 лет назад
Родитель
Сommit
a4611e29bf
6 измененных файлов с 794 добавлено и 611 удалено
  1. 66 0
      API
  2. 2 0
      CONFIG-README
  3. 51 51
      lang.txt
  4. 95 0
      modules/Pisg/Common.pm
  5. 389 0
      modules/Pisg/Logfile.pm
  6. 191 560
      pisg.pl

+ 66 - 0
API

@@ -0,0 +1,66 @@
+With the advent of the modules, an API becomes necessary.  This
+file is the place to document anything along those lines.
+
+The main parts of pisg operate by passing around a %stats hash.  That
+hash is pretty big:
+
+Key           Type   Index   Description
+--------------------------------------------------------------------------
+words         hash   <nick>  Number of words typed by given nick.
+wordcounts    hash   <word>  Number of times given word was used.
+wordnicks     hash   <word>  The last nick to use the given word.
+times         hash   <hour>  Number of lines typed in the channel during
+                             the given hour (0..23).
+lines         hash   <nick>  Number of lines typed by the given nick (both
+                             "normal" and action lines).
+line_times    hash   <nick>  $line_times{nick}[index]  index ranges from 
+                             0 to 3 and contains a count of the number of
+                             lines typed by that nick in the given time
+                             period.  Each index is a 6-hour block.
+                             (e.g. 3 is from 18:00 to 23:59.)
+monologues    hash   <nick>  Number of times the given nick had a
+                             monologue.
+sayings       hash   <nick>  Random normal line from the given nick.
+questions     hash   <nick>  Number of lines from the given nick that
+                             ended in question marks.
+shouts        hash   <nick>  Number of lines ending in exclamation points.
+allcaps       hash   <nick>  Number of lines in ALL CAPS.
+allcaplines   hash   <nick>  Random line containing ALL CAPS.
+foul          hash   <nick>  Number of lines containing foul words.
+smiles        hash   <nick>  Number of lines containing smiling faces.
+frowns        hash   <nick>  Number of lines containing sad faces.
+urlcounts     hash   <url>   Number of times each URL was mentioned.
+urlnicks      hash   <url>   Last nick to mention each URL.
+lengths       hash   <nick>  Total length of all lines from the given
+                             nick.
+actions       hash   <nick>  Number of actions.
+actionlines   hash   <nick>  Random action line.
+violence      hash   <nick>  Number of times the given nick attacked
+                             someone else.
+violencelines hash   <nick>  Random example of the given nick attacking
+                             someone.
+attacked      hash   <nick>  Number of times the given nick was attacked.
+attackedlines hash   <nick>  Ramdom example of the given nick being
+                             attacked.
+gaveops       hash   <nick>  Number of times the given nick granted ops.
+tookops       hash   <nick>  Number of times the given nick removed ops.
+kicked        hash   <nick>  Number of times the given nick kicked
+                             someone.
+gotkicked     hash   <nick>  Number of times the give nick was kicked.
+kicklines     hash   <nick>  Random example of the given nick being
+                             kicked.
+joins         hash   <nick>  Number of times the given nick joined the
+                             channel.
+topics        array          Each array element is a hash with the
+                             following indices:
+                               topic - The new channel topic.
+                               nick  - The person who set the topic.
+                               hour  - The hour in which the change took
+                                       place.
+                               min   - The minute in which the change took
+                                       place.
+days          scalar         Number of days the reporting period spanned.
+totallines    scalar         Total number of lines (normal, action, and
+                             third) seen in channel.
+processtime   scalar         String describing the time elapsed while
+                             processing this channel.

+ 2 - 0
CONFIG-README

@@ -82,6 +82,8 @@ casesensitive):
  * The most useful ones *
 
 channel              The name of your channel.
+logtype              The type of logs kept for your channel.  Currently only
+                     "Logfile" is supported.
 logfile              The exact filename of the logfile
 format               logfile format. see FORMATS file
 network              Network the channels is using.

+ 51 - 51
lang.txt

@@ -38,14 +38,14 @@ question1 = "Is <b>[:nick]</b> stupid or just asking too many questions?  [:per]
 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?"
 
-loud1 = "The loudest one was <b>[:nick]</b>, who yelled [:per]% of the time!"
-loud2 = "Another <i>old yeller</i> was <b>[:nick]</b>, who shouted [:per]% of the time!"
-loud3 = "Nobody shouted at all, wow."
+shout1 = "The loudest one was <b>[:nick]</b>, who yelled [:per]% of the time!"
+shout2 = "Another <i>old yeller</i> was <b>[:nick]</b>, who shouted [:per]% of the time!"
+shout3 = "Nobody shouted at all, wow."
 
-shout1 = "It seem that <b>[:nick]</b>'s shift-key is hanging:  [:per]% of the time [:he:she:] wrote UPPERCASE."
-shout2 = "<b>[:nick]</b> just forgot to deactivate [:his:her:] Caps-Lock.  [:He:She:] wrote UPPERCASE [:per]% of the time."
-shout3 = "Everybody had their shift-key under control.  :)"
-shouttext = "<b>For example, like this:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
+allcaps1 = "It seem that <b>[:nick]</b>'s shift-key is hanging:  [:per]% of the time [:he:she:] wrote UPPERCASE."
+allcaps2 = "<b>[:nick]</b> just forgot to deactivate [:his:her:] Caps-Lock.  [:He:She:] wrote UPPERCASE [:per]% of the time."
+allcaps3 = "Everybody had their shift-key under control.  :)"
+allcapstext = "<b>For example, like this:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
 
 violent1 = "<b>[:nick]</b> is a very aggresive person.  [:He:She:] attacked others <b>[:attacks]</b> times."
@@ -154,14 +154,14 @@ question1 = "<b>[:nick]</b> hat wohl in der Schule nicht gut aufgepasst... [:per
 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? ;)"
 
-loud1 = "Am lautesten war <b>[:nick]</b> der/die [:per]% der Zeit geschrien hat!"
-loud2 = "Ein anderer <i>Schreihals</i> war <b>[:nick]</b> [:der:die:] [:per]% der Zeit rumgeschrieen hat!"
-loud3 = "Niemand hat ein Ausrufungszeichen benutzt, wow... Zurückhaltende User im Channel ;)"
+shout1 = "Am lautesten war <b>[:nick]</b> der/die [:per]% der Zeit geschrien hat!"
+shout2 = "Ein anderer <i>Schreihals</i> war <b>[:nick]</b> [:der:die:] [:per]% der Zeit rumgeschrieen hat!"
+shout3 = "Niemand hat ein Ausrufungszeichen benutzt, wow... Zurückhaltende User im Channel ;)"
 
-shout1 = "Anscheinend klemmte die Shift-Taste von <b>[:nick]</b>, denn [:per]% der Zeit schrieb [:er:sie:] in GROSSBUCHSTABEN."
-shout2 = "<b>[:nick]</b> hat auch wohl vergessen CAPS-Lock auszuschalten, von [:ihm:ihr:] kamen [:per]% der Zeit GROSSBUCHSTABEN."
-shout3 = "Alle hatten ihre Shift-Taste gut unter kontrolle :)"
-shouttext = "<b>Zum Beispiel so:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
+allcaps1 = "Anscheinend klemmte die Shift-Taste von <b>[:nick]</b>, denn [:per]% der Zeit schrieb [:er:sie:] in GROSSBUCHSTABEN."
+allcaps2 = "<b>[:nick]</b> hat auch wohl vergessen CAPS-Lock auszuschalten, von [:ihm:ihr:] kamen [:per]% der Zeit GROSSBUCHSTABEN."
+allcaps3 = "Alle hatten ihre Shift-Taste gut unter kontrolle :)"
+allcapstext = "<b>Zum Beispiel so:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
 violent1 = "<b>[:nick]</b> ist etwas agressiv. [:Er:Sie:] schlug <b>[:attacks]</b> mal wild um sich herum."
 violent2 = "Auch <b>[:nick]</b> hat einige Probleme seine Agressionen unter Kontrolle zu halten, <b>[:attacks]</b> Schläge von [:ihm:ihr:]."
@@ -268,9 +268,9 @@ question1 = "<b>[:nick]</b> m
 question2 = "<b>[:nick]</b> var heller ingen Einstein, [:per]% af hans linjer var også spørgsmål"
 question3 = "Ingen spørgsmål på denne kanal. De må sørme være kloge!"
 
-loud1 = "Den mest larmende var <b>[:nick]</b>, som råbte [:per]% af tiden!"
-loud2 = "En anden skrigehals var <b>[:nick]</b>, som råbte [:per]% af tiden!"
-loud3 = "Der er ingen som råber. Leger de stilleleg?"
+shout1 = "Den mest larmende var <b>[:nick]</b>, som råbte [:per]% af tiden!"
+shout2 = "En anden skrigehals var <b>[:nick]</b>, som råbte [:per]% af tiden!"
+shout3 = "Der er ingen som råber. Leger de stilleleg?"
 
 gotkick1 = "<b>[:nick]</b> er ret upopulær, blev sparket ud [:kicks] gange!"
 gotkick2 = "<b>[:nick]</b> er heller ikke nogen Elvis, [:kicks] gange fik han sparket"
@@ -306,10 +306,10 @@ sad1 = "<b>[:nick]</b> er meget ked af det for tiden, [:per]% af linjerne havde
 sad2 = "<b>[:nick]</b> er også en trist person, som græd [:per]% af tiden"
 sad3 = "Ingen er kede af det på [:channel]! Sikke en glad kanal :-)"
 
-shout1 = "Ser ud til at <b>[:nick]</b> har en voldsom trang til at råbe konstant, [:per]% af de gange han skrev var med stort" 
-shout2 = "<b>[:nick]</b> glemte vidst at Caps-Lock var slået til, [:per]% af de gange han skrev var med stort"
-shout3 = "Ser ud til at alle har deres shift under kontrol :)"
-shouttext = "<b>For eksempel sådan her: </b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
+allcaps1 = "Ser ud til at <b>[:nick]</b> har en voldsom trang til at råbe konstant, [:per]% af de gange han skrev var med stort" 
+allcaps2 = "<b>[:nick]</b> glemte vidst at Caps-Lock var slået til, [:per]% af de gange han skrev var med stort"
+allcaps3 = "Ser ud til at alle har deres shift under kontrol :)"
+allcapstext = "<b>For eksempel sådan her: </b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:line]"
 
 violent1 = "<b>[:nick]</b> er en meget aggresiv person, han delte <b>[:attacks]</b> slaps ud."
 violent2 = "<b>[:nick]</b> er ude af kontrol. Han/Hun slog andre folk <b>[:attacks]</b> gang(e)."
@@ -387,9 +387,9 @@ question1 = "<b>[:nick]</b> est soit stupide soit trop curieux... [:per]% de ses
 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?"
 
-loud1 = "Le plus bruyant est <b>[:nick]</b> qui gueule [:per]% du temps!"
-loud2 = "Un autre <i>vieux raleur</i> est <b>[:nick]</b> qui braille [:per]% du temps!"
-loud3 = "Personne ne s'exclame ici, wow."
+shout1 = "Le plus bruyant est <b>[:nick]</b> qui gueule [:per]% du temps!"
+shout2 = "Un autre <i>vieux raleur</i> est <b>[:nick]</b> qui braille [:per]% du temps!"
+shout3 = "Personne ne s'exclame ici, wow."
 
 gotkick1 = "<b>[:nick]</b> n'est pas trés populaire, kické [:kicks] fois!"
 gotkick2 = "<b>[:nick]</b> n'a pas d'ami non plus, [:kicks] kicks reçus"
@@ -465,13 +465,13 @@ question1 = "<b>[:nick]</b> necesitaba m
 question2 = "<b>[:nick]</b> tampoco se entera de mucho, el [:per]% de sus lineas son preguntas"
 question3 = "Nadie hace preguntas aquí, esto parece un canal de genios"
 
-loud1 = "Me parece que <b>[:nick]</b> está algo exaltado/a. Escribe con exclamaciones el [:per]% del tiempo!"
-loud2 = "A <b>[:nick]</b> tambien le gusta afirmar con rotundidad lo que dice. Escribe con exclamaciones el [:per]% del tiempo!"
-loud3 = "Nadie ha escrito frases con exclamaciones."
+shout1 = "Me parece que <b>[:nick]</b> está algo exaltado/a. Escribe con exclamaciones el [:per]% del tiempo!"
+shout2 = "A <b>[:nick]</b> tambien le gusta afirmar con rotundidad lo que dice. Escribe con exclamaciones el [:per]% del tiempo!"
+shout3 = "Nadie ha escrito frases con exclamaciones."
 
-shout1 = "A <b>[:nick]</b> se le ha atascado el bloqueo de mayusculas, el [:per]% del tiempo escribe CON ESTE ESTILO TAN PECULIAR"
-shout2 = "<b>[:nick]</b> debe tener vicio con la tecla shift, el [:per]% del tiempo hace lo mismo"
-shout3 = "Todo el mundo tiene su tecla shift bajo control :)"
+allcaps1 = "A <b>[:nick]</b> se le ha atascado el bloqueo de mayusculas, el [:per]% del tiempo escribe CON ESTE ESTILO TAN PECULIAR"
+allcaps2 = "<b>[:nick]</b> debe tener vicio con la tecla shift, el [:per]% del tiempo hace lo mismo"
+allcaps3 = "Todo el mundo tiene su tecla shift bajo control :)"
 
 violent1 = "<b>[:nick]</b> es el más agresivo del canal, ha repartido tortas <b>[:attacks]</b> veces."
 violent2 = "<b>[:nick]</b> tiene la mano floja. Ha repartido tortas <b>[:attacks]</b> veces."
@@ -567,9 +567,9 @@ question1 = "<b>[:nick]</b> jest glupi albo zadaje wiele pytan... [:per]% linii
 question2 = "<b>[:nick]</b> rowniez nie wie zbyt wiele, [:per]% linii bylo pytaniami"
 question3 = "Nikt o nic nie pyta na kanale - czyzby sami geniusze?"
 
-loud1 = "Najglosniejszym okazal/a sie <b>[:nick]</b> krzyczac przez [:per]% czasu!"
-loud2 = "Kolejnym krzykaczem byl <b>[:nick]</b> ktory wrzeszczal przez [:per]% czasu!"
-loud3 = "Nikt nic nie wykrzykiwal na kanale, wow."
+shout1 = "Najglosniejszym okazal/a sie <b>[:nick]</b> krzyczac przez [:per]% czasu!"
+shout2 = "Kolejnym krzykaczem byl <b>[:nick]</b> ktory wrzeszczal przez [:per]% czasu!"
+shout3 = "Nikt nic nie wykrzykiwal na kanale, wow."
 
 gotkick1 = "<b>[:nick]</b> nie zalapal o co chodzilo operatorom za pierwszym razem i zostal wykopany [:kicks] razy!"
 gotkick2 = "<b>[:nick]</b> nie jest tu chyba zbyt lubiany - wylatywal [:kicks] razy"
@@ -645,9 +645,9 @@ question1 = "<b>[:nick]</b> er sikkert dum, hvis ikke bare litt nysgjerrig. [:pe
 question2 = "<b>[:nick]</b> skjønner heller ikke mye, [:per]% av hans/hennes linjer ser mistenkelig ut som spørsmål."
 question3 = "Ingen stilte noen spørsmål, er det bare glupinger her?"
 
-loud1 = "Den mest bråkete var såklart <b>[:nick]</b> som ropte [:per]% av tiden."
-loud2 = "En annen <i>bråkemaker</i> var <b>[:nick]</b> som ropte [:per]% av tiden."
-loud3 = "Finnes det ikke bråkemakere her? Kjekt."
+shout1 = "Den mest bråkete var såklart <b>[:nick]</b> som ropte [:per]% av tiden."
+shout2 = "En annen <i>bråkemaker</i> var <b>[:nick]</b> som ropte [:per]% av tiden."
+shout3 = "Finnes det ikke bråkemakere her? Kjekt."
 
 gotkick1 = "<b>[:nick]</b> ble kastet ut [:kicks] ganger og var neppe særlig populær."
 gotkick2 = "<b>[:nick]</b> stiller seg som en god nr 2, [:kicks] kicks er notert."
@@ -723,9 +723,9 @@ question1 = "<b>[:nick]</b> necessitava mais horas de estudo quando crian
 question2 = "<b>[:nick]</b> tampouco é muito inteligente, [:per]% de suas linhas são perguntas"
 question3 = "Ninguém fez perguntas aqui, apenas gênios neste canal?"
 
-loud1 = "A pessoa que mais gritou foi: <b>[:nick]</b> que escreve com exclamações em [:per]% do tempo!"
-loud2 = "Quem não fica atrás é <b>[:nick]</b>, que gritou [:per]% do tempo!"
-loud3 = "Ninguém escreveu frases exclamativas."
+shout1 = "A pessoa que mais gritou foi: <b>[:nick]</b> que escreve com exclamações em [:per]% do tempo!"
+shout2 = "Quem não fica atrás é <b>[:nick]</b>, que gritou [:per]% do tempo!"
+shout3 = "Ninguém escreveu frases exclamativas."
 
 gotkick1 = "<b>[:nick]</b> não tem sido muito popular, levou chute [:kicks] vezes!"
 gotkick2 = "<b>[:nick]</b> também tem sido odiado, [:kicks] foram recebidos"
@@ -800,13 +800,13 @@ question1 = "<b>[:nick]</b> is gewoon stom of verzint de vragen waar hij/zij bij
 question2 = "<b>[:nick]</b> is bijna net zo stom/blond en weet ook weinig, [:per]% van zijn/haar regels eindigde ook met ?"
 question3 = "Niemand vroeg wat hiero denken zeker allemaal dat ze slim zijn ~NOT?"
 
-loud1 = "Lelijk Schreeuwmonster was <b>[:nick]</b>, en schreeuwde [:per]% tijdens zijn/haar aanwezigheid!"
-loud2 = "Ook een <i>grote smoel </i> heeft <b>[:nick]</b> die schreeuwde  [:per]% tijdens het tijdbestek van zijn/haar aanwezigheid!"
-loud3 = "Hmm niet veel geschreeuw hiero, stil zooitje zeg."
+shout1 = "Lelijk Schreeuwmonster was <b>[:nick]</b>, en schreeuwde [:per]% tijdens zijn/haar aanwezigheid!"
+shout2 = "Ook een <i>grote smoel </i> heeft <b>[:nick]</b> die schreeuwde  [:per]% tijdens het tijdbestek van zijn/haar aanwezigheid!"
+shout3 = "Hmm niet veel geschreeuw hiero, stil zooitje zeg."
 
-shout1 = "Het lijkt dat  <b>[:nick]</b>'s zijn/haar shift-key kapot is,met een cabs percentage van [:per]% "
-shout2 = "<b>[:nick]</b> is ff vergetuh ze Caps-Lock uit te zettuh, [:per]% CAPS"
-shout3 = "Iedereen had het hoofdletter gebruik onder de knie :)"
+allcaps1 = "Het lijkt dat  <b>[:nick]</b>'s zijn/haar shift-key kapot is,met een cabs percentage van [:per]% "
+allcaps2 = "<b>[:nick]</b> is ff vergetuh ze Caps-Lock uit te zettuh, [:per]% CAPS"
+allcaps3 = "Iedereen had het hoofdletter gebruik onder de knie :)"
 
 violent1 = "<b>[:nick]</b> is een agressief persoon, die veel in het rond slaat wel <b>[:attacks]</b> keer."
 violent2 = "<b>[:nick]</b> ze pilltjes helpen niet. Hij/zij sloeg <b>[:attacks]</b> keer."
@@ -896,13 +896,13 @@ question1 = "<b>[:nick]</b> 
 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?"
 
-loud1 = "Skrikigast var <b>[:nick]</b> som skrek [:per]% av tiden!"
-loud2 = "En annan <i>skrikhals</i> var <b>[:nick]</b> som skrek [:per]% av tiden!"
-loud3 = "Ingen använde utropstecknet, wow."
+shout1 = "Skrikigast var <b>[:nick]</b> som skrek [:per]% av tiden!"
+shout2 = "En annan <i>skrikhals</i> var <b>[:nick]</b> som skrek [:per]% av tiden!"
+shout3 = "Ingen använde utropstecknet, wow."
 
-shout1 = "Det verkar som <b>[:nick]</b> har en hängande shift-tangent, [:per]% av tiden skrev han/hon i VERSALER"
-shout2 = "<b>[:nick]</b> glömde att deaktivera sin CapsLock-tangent, [:per]% av det han/hon skrev var VERSALER"
-shout3 = "Alla hade sin shift-tangent under kontroll :)"
+allcaps1 = "Det verkar som <b>[:nick]</b> har en hängande shift-tangent, [:per]% av tiden skrev han/hon i VERSALER"
+allcaps2 = "<b>[:nick]</b> glömde att deaktivera sin CapsLock-tangent, [:per]% av det han/hon skrev var VERSALER"
+allcaps3 = "Alla hade sin shift-tangent under kontroll :)"
 
 violent1 = "<b>[:nick]</b> är en väldigt aggressiv person, som använde handflatan <b>[:attacks]</b> gånger."
 violent2 = "<b>[:nick]</b> kunde inte kontrollera sina aggressioner. Han/Hon slogs <b>[:attacks]</b> gånger med sin handflata."

+ 95 - 0
modules/Pisg/Common.pm

@@ -0,0 +1,95 @@
+package Pisg::Common;
+
+use Exporter;
+@ISA = ('Exporter');
+@EXPORT = qw(add_alias add_aliaswild add_ignore is_ignored find_alias match_url match_email);
+
+use strict;
+$^W = 1;
+
+my (%aliases, %aliaswilds, @ignored);
+
+# add_alias assumes that the first argument is the true nick and the second is
+# the alias, but will accomidate other arrangements if necessary.
+sub add_alias {
+    my ($nick, $alias) = @_;
+    my $lcnick  = lc($nick);
+    my $lcalias = lc($alias);
+
+    if (not defined $aliases{$lcnick} and not defined $aliases{$lcalias}) {
+        $aliases{$lcnick}  = $nick;
+        $aliases{$lcalias} = $nick;
+    } elsif (defined $aliases{$lcnick} and not defined $aliases{$lcalias}) {
+        $aliases{$lcalias} = $aliases{$lcnick};
+    } elsif (not defined $aliases{$lcnick} and defined $aliases{$lcalias}) {
+        $aliases{$lcnick} = $aliases{$lcalias};
+    } else { # Both are defined.
+        # If both point to the same nick, all is well.  Otherwise, redefine
+        # the alias's alias.
+        if ($aliases{$lcnick} ne $aliases{$lcalias}) {
+            $aliases{$lcalias} = $aliases{$lcnick};
+        }
+    }
+    #$debug->("Alias added: $alias -> $aliases{$lcalias}");
+}
+
+sub add_aliaswild {
+    my ($nick, $alias) = @_;
+    my $lcnick  = lc($nick);
+    my $lcalias = lc($alias);
+
+    if (not defined $aliases{$lcnick}) {
+        $aliases{$lcnick}  = $nick;
+    }
+    $aliaswilds{$lcalias} = $nick;
+    #$debug->("Aliaswild added: $alias -> $aliaswilds{$lcalias}");
+}
+
+sub add_ignore {
+    my ($nick) = @_;
+    push @ignored, find_alias($nick);
+}
+
+sub is_ignored {
+    my ($nick) = @_;
+    my $realnick = find_alias($nick);
+    return grep /^\Q$realnick\E$/, @ignored;
+}
+
+sub find_alias {
+    my $nick = shift;
+    my $lcnick = lc($nick);
+
+    if ($aliases{$lcnick}) {
+        return $aliases{$lcnick};
+    } else {
+        foreach (keys %aliaswilds) {
+            if ($nick =~ /^$_$/i) {
+                add_alias($aliaswilds{$_}, $lcnick);
+                return $aliaswilds{$_};
+            }
+        }
+    }
+    add_alias($nick, $nick);
+    return $nick;
+}
+
+sub match_url {
+    my ($str) = @_;
+
+    if ($str =~ /(http|https|ftp|telnet|news)(:\/\/[-a-zA-Z0-9_]+\.[-a-zA-Z0-9.,_~=:;&@%?#\/+]+)/) {
+        return "$1$2";
+    }
+    return undef;
+}
+
+sub match_email {
+    my ($str) = @_;
+
+    if ($str =~ /([-a-zA-Z0-9._]+@[-a-zA-Z0-9_]+\.[-a-zA-Z0-9._]+)/) {
+        return $1;
+    }
+    return undef;
+}
+
+1;

+ 389 - 0
modules/Pisg/Logfile.pm

@@ -0,0 +1,389 @@
+package Pisg::Logfile;
+
+use strict;
+$^W = 1;
+
+my ($conf, $debug, $parser);
+
+sub new {
+    # The sole argument is the config hash
+    my $self = shift;
+    $conf = shift;
+    $debug = shift;
+
+    # Load the Common module from wherever it's configured to be.
+    push @INC, $conf->{modules_dir};
+    require Pisg::Common;
+    Pisg::Common->import();
+
+    # Pick our parser.
+    $parser = choose_log_format($conf->{format});
+
+    return bless {};
+}
+
+# The function to choose which module to use.
+sub choose_log_format {
+    my $format = shift;
+    my $parser = undef;
+    $debug->("Loading module for log format $format");
+    eval <<_END;
+use lib '$conf->{modules_dir}';
+use Pisg::Parser::$format;
+\$parser = new Pisg::Parser::$format(\$debug);
+_END
+    if ($@) {
+    print STDERR "Could not load parser for '$format': $@\n";
+    return undef;
+}
+return $parser;
+}
+
+sub analyze {
+    my (%stats, %lines);
+
+    if (defined $parser) {
+        my $starttime = time();
+
+        if ($conf->{logdir}) {
+            # Run through all files in dir
+            parse_dir(\%stats, \%lines);
+        } else {
+            # Run through the whole logfile
+            my %state = (linecount  => 0,
+            lastnick   => "",
+            monocount  => 0,
+            lastnormal => "",
+            oldtime    => 24);
+            parse_file(\%stats, \%lines, $conf->{logfile}, \%state);
+        }
+
+        pick_random_lines(\%stats, \%lines);
+
+        my ($sec,$min,$hour) = gmtime(time() - $starttime);
+        $stats{processtime} =
+        sprintf("%02d hours, %02d minutes and %02d seconds", $hour, $min,
+        $sec);
+        print "Channel analyzed succesfully in $stats{processtime} on ",
+        scalar localtime(time()), "\n";;
+
+        return \%stats;
+
+    } else {
+        print STDERR "Skipping channel '$conf->{channel}' due to lack of parser.\n";
+        return undef
+    }
+
+    # Shouldn't get here.
+    return undef;
+}
+
+sub parse_dir {
+    my ($stats, $lines) = @_;
+
+    # Add trailing slash when it's not there..
+    $conf->{logdir} =~ s/([^\/])$/$1\//;
+
+    print "Going into $conf->{logdir} and parsing all files there...\n\n";
+    my @filesarray;
+    opendir(LOGDIR, $conf->{logdir}) or
+    die("Can't opendir $conf->{logdir}: $!");
+    @filesarray = grep {
+        /^[^\.]/ && /^$conf->{prefix}/ && -f "$conf->{logdir}/$_"
+    } readdir(LOGDIR) or
+    die("No files in \"$conf->{logdir}\" matched prefix \"$conf->{prefix}\"");
+    closedir(LOGDIR);
+
+    my %state = (lastnick   => "",
+    monocount  => 0,
+    oldtime    => 24);
+    foreach my $file (sort @filesarray) {
+        $file = $conf->{logdir} . $file;
+        parse_file($stats, $lines, $file, \%state);
+    }
+}
+
+# This parses the file...
+sub parse_file {
+    my ($stats, $lines, $file, $state) = @_;
+
+    print "Analyzing log($file) in '$conf->{format}' format...\n";
+
+    if ($file =~ /.bz2?$/ && -f $file) {
+        open (LOGFILE, "bunzip2 -c $file |") or
+        die("$0: Unable to open logfile($file): $!\n");
+    } elsif ($file =~ /.gz$/ && -f $file) {
+        open (LOGFILE, "gunzip -c $file |") or
+        die("$0: Unable to open logfile($file): $!\n");
+    } else {
+        open (LOGFILE, $file) or
+        die("$0: Unable to open logfile($file): $!\n");
+    }
+
+    my $linecount = 0;
+    my $lastnormal = "";
+    my $repeated;
+
+    while(my $line = <LOGFILE>) {
+        $line = strip_mirccodes($line);
+        $linecount++;
+
+        my $hashref;
+
+        # Match normal lines.
+        if ($hashref = $parser->normalline($line, $linecount)) {
+
+            if (defined $hashref->{repeated}) {
+                $repeated = $hashref->{repeated};
+            } else {
+                $repeated = 0;
+            }
+
+            my ($hour, $nick, $saying, $i);
+
+            for ($i = 0; $i <= $repeated; $i++) {
+
+                if ($i > 0) {
+                    $hashref = $parser->normalline($lastnormal, $linecount);
+                    #Increment number of lines for repeated lines
+                    $linecount++;
+                }
+
+                $hour   = $hashref->{hour};
+                $nick   = find_alias($hashref->{nick});
+                $saying = $hashref->{saying};
+
+                if ($hour < $state->{oldtime}) { $stats->{days}++ }
+                $state->{oldtime} = $hour;
+
+                unless (is_ignored($nick)) {
+                    $stats->{totallines}++;
+
+                    # Timestamp collecting
+                    $stats->{times}{$hour}++;
+
+                    $stats->{lines}{$nick}++;
+                    $stats->{line_times}{$nick}[int($hour/6)]++;
+
+                    # Count up monologues
+                    if ($state->{lastnick} eq $nick) {
+                        $state->{monocount}++;
+
+                        if ($state->{monocount} == 5) {
+                            $stats->{monologues}{$nick}++;
+                        }
+                    } else {
+                        $state->{monocount} = 0;
+                    }
+                    $state->{lastnick} = $nick;
+
+                    my $len = length($saying);
+                    if ($len > $conf->{minquote} && $len < $conf->{maxquote}) {
+                        push @{ $lines->{sayings}{$nick} }, $saying;
+                    }
+                    $stats->{lengths}{$nick} += $len;
+
+                    $stats->{questions}{$nick}++
+                    if ($saying =~ /\?/);
+
+                    $stats->{shouts}{$nick}++
+                    if ($saying =~ /!/);
+
+                    if ($saying !~ /[a-z]/ && $saying =~ /[A-Z]/) {
+                        $stats->{allcaps}{$nick}++;
+                        push @{ $lines->{allcaplines}{$nick} }, $line;
+                    }
+
+                    $stats->{foul}{$nick}++
+                    if ($saying =~ /$conf->{foul}/i);
+
+                    # Who smiles the most?
+                    # A regex matching al lot of smilies
+                    $stats->{smiles}{$nick}++
+                    if ($saying =~ /[8;:=][ ^-o]?[)pPD}\]>]/);
+
+                    if ($saying =~ /[8;:=][ ^-]?[\(\[\\\/{]/ and
+                    $saying !~ /\w+:\/\//) {
+                        $stats->{frowns}{$nick}++;
+                    }
+
+                    if (my $url = match_url($saying)) {
+                        $stats->{urlcounts}{$url}++;
+                        $stats->{urlnicks}{$url} = $nick;
+                    }
+
+                    parse_words($stats, $saying, $nick);
+                }
+            }
+            $lastnormal = $line;
+            $repeated = 0;
+        }
+
+        # Match action lines.
+        elsif ($hashref = $parser->actionline($line, $linecount)) {
+            $stats->{totallines}++;
+
+            my ($hour, $nick, $saying);
+
+            $hour   = $hashref->{hour};
+            $nick   = find_alias($hashref->{nick});
+            $saying = $hashref->{saying};
+
+            if ($hour < $state->{oldtime}) { $stats->{days}++ }
+            $state->{oldtime} = $hour;
+
+            unless (is_ignored($nick)) {
+                # Timestamp collecting
+                $stats->{times}{$hour}++;
+
+                $stats->{actions}{$nick}++;
+                push @{ $lines->{actionlines}{$nick} }, $line;
+                $stats->{lines}{$nick}++;
+                $stats->{line_times}{$nick}[int($hour/6)]++;
+
+                if ($saying =~ /^($conf->{violent}) (\S+)/) {
+                    my $victim = find_alias($2);
+                    $stats->{violence}{$nick}++;
+                    $stats->{attacked}{$victim}++;
+                    push @{ $lines->{violencelines}{$nick} }, $line;
+                    push @{ $lines->{attackedlines}{$victim} }, $line;
+                }
+
+
+                my $len = length($saying);
+                $stats->{lengths}{$nick} += $len;
+
+                parse_words($stats, $saying, $nick);
+            }
+        }
+
+        # Match *** lines.
+        elsif (($hashref = $parser->thirdline($line, $linecount)) and
+        $hashref->{nick}) {
+            $stats->{totallines}++;
+
+            my ($hour, $min, $nick, $kicker, $newtopic, $newmode, $newjoin);
+            my ($newnick);
+
+            $hour     = $hashref->{hour};
+            $min      = $hashref->{min};
+            $nick     = find_alias($hashref->{nick});
+            $kicker   = find_alias($hashref->{kicker})
+            if ($hashref->{kicker});
+            $newtopic = $hashref->{newtopic};
+            $newmode  = $hashref->{newmode};
+            $newjoin  = $hashref->{newjoin};
+            $newnick  = $hashref->{newnick};
+
+            if ($hour < $state->{oldtime}) { $stats->{days}++ }
+            $state->{oldtime} = $hour;
+
+            unless (is_ignored($nick)) {
+                # Timestamp collecting
+                $stats->{times}{$hour}++;
+
+                if (defined($kicker)) {
+                    $stats->{kicked}{$kicker}++;
+                    $stats->{gotkicked}{$nick}++;
+                    push @{ $lines->{kicklines}{$nick} }, $line;
+
+                } elsif (defined($newtopic)) {
+                    unless ($newtopic eq '') {
+                        my $tcount;
+                        if (defined $stats->{topics}) {
+                            $tcount = @{ $stats->{topics} };
+                        } else {
+                            $tcount = 0;
+                        }
+                        $stats->{topics}[$tcount]{topic} = $newtopic;
+                        $stats->{topics}[$tcount]{nick}  = $nick;
+                        $stats->{topics}[$tcount]{hour}  = $hour;
+                        $stats->{topics}[$tcount]{min}   = $min;
+                    }
+
+                } elsif (defined($newmode)) {
+                    my @opchange = opchanges($newmode);
+                    $stats->{gaveops}{$nick} += $opchange[0] if $opchange[0];
+                    $stats->{tookops}{$nick} += $opchange[1] if $opchange[1];
+
+                } elsif (defined($newjoin)) {
+                    $stats->{joins}{$nick}++;
+
+                } elsif (defined($newnick) and ($conf->{nicktracking} == 1)) {
+                    add_alias($nick, $newnick);
+                }
+            }
+        }
+    }
+
+    close(LOGFILE);
+
+    print "Finished analyzing log, $stats->{days} days total.\n";
+}
+
+sub opchanges {
+    my (@ops, $plus);
+    foreach (split(//, $_[0])) {
+        if ($_ eq "o") {
+            $ops[$plus]++;
+        } elsif ($_ eq "+") {
+            $plus = 0;
+        } elsif ($_ eq "-") {
+            $plus = 1;
+        }
+    }
+
+    return @ops;
+}
+
+sub parse_words {
+    my ($stats, $saying, $nick) = @_;
+
+    foreach my $word (split(/[\s,!?.:;)(\"]+/, $saying)) {
+        $stats->{words}{$nick}++;
+        # remove uninteresting words
+        next unless (length($word) >= $conf->{wordlength});
+        next if ($conf->{ignoreword}{$word});
+
+        # ignore contractions
+        next if ($word =~ m/'..?$/);#'
+
+        # Also ignore stuff from URLs.
+        next if ($word =~ m{https?|^//});
+
+        $stats->{wordcounts}{$word}++;
+        $stats->{wordnicks}{$word} = $nick;
+    }
+}
+
+sub pick_random_lines {
+    my ($stats, $lines) = @_;
+
+    foreach my $key (keys %{ $lines }) {
+        foreach my $nick (keys %{ $lines->{$key} }) {
+            $stats->{$key}{$nick} = 
+            @{ $lines->{$key}{$nick} }[rand@{ $lines->{$key}{$nick} }];
+        }
+    }
+}
+
+sub strip_mirccodes {
+    my $line = shift;
+
+    my $boldcode = chr(2);
+    my $colorcode = chr(3);
+    my $plaincode = chr(15);
+    my $reversecode = chr(22);
+    my $underlinecode = chr(31);
+
+    # Strip mIRC color codes
+    $line =~ s/$colorcode\d{1,2},\d{1,2}//go;
+    $line =~ s/$colorcode\d{0,2}//go;
+    # Strip mIRC bold, plain, reverse and underline codes
+    $line =~ s/[$boldcode$underlinecode$reversecode$plaincode]//go;
+
+    return $line;
+}
+
+
+1;

Разница между файлами не показана из-за своего большого размера
+ 191 - 560
pisg.pl


Некоторые файлы не были показаны из-за большого количества измененных файлов