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

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 *
  * The most useful ones *
 
 
 channel              The name of your channel.
 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
 logfile              The exact filename of the logfile
 format               logfile format. see FORMATS file
 format               logfile format. see FORMATS file
 network              Network the channels is using.
 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."
 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?"
 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."
 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."
 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? ;)"
 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."
 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:]."
 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"
 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!"
 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!"
 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"
 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"
 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 :-)"
 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."
 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)."
 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"
 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?"
 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!"
 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"
 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"
 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"
 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."
 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."
 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"
 question2 = "<b>[:nick]</b> rowniez nie wie zbyt wiele, [:per]% linii bylo pytaniami"
 question3 = "Nikt o nic nie pyta na kanale - czyzby sami geniusze?"
 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!"
 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"
 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."
 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?"
 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."
 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."
 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"
 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?"
 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!"
 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"
 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 ?"
 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?"
 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."
 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."
 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"
 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?"
 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."
 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."
 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


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