X-Git-Url: http://royale.zerezo.com/git/?p=irssistats;a=blobdiff_plain;f=irssistats.c;h=ae6b2a80e23275dd1a2bbced737cf680634532f6;hp=c528da3db66045cd51970a984de21ddf07e4e318;hb=363a540f2233a72f1dccd300f93514d009e2053b;hpb=8d70a2e0456b158f3ca70636b4920e9aff08830a diff --git a/irssistats.c b/irssistats.c index c528da3..ae6b2a8 100644 --- a/irssistats.c +++ b/irssistats.c @@ -1,12 +1,14 @@ -/* Usage: cat /path/to/file.log | ./irssistats channel maintainer language theme > /path/to/file.html */ +/* Usage: irssistats [/path/to/file.conf] */ +#include #include #include #include #include +#include /* Config */ -#define MAXUSERS 5000 +#define MAXUSERS 10000 #define MAXNICKLENGTH 50 #define MAXLINELENGTH 2000 #define MAXQUOTELENGTH 100 @@ -18,8 +20,8 @@ #define MINWORDLENGTH 5 /* irssistats */ -#define VERSION "0.3" -#define URL "http://royale.zerezo.com/programmation/irssistats/" +#define VERSION "0.5" +#define URL "http://royale.zerezo.com/irssistats/" /* Counters */ #define D_SMILE 0 @@ -39,13 +41,13 @@ char *counters[NBCOUNTERS]={"C_SMILE","C_FROWN","C_EXCLAM","C_QUESTION","C_ME","C_TOPIC","C_MODE","C_KICK","C_KICKED","C_URL","C_JOIN","C_NICK","C_MONOLOGUE"}; /* Languages */ -#define NBLANGUAGES 2 +#define NBLANGUAGES 8 #define NBKEYS 38 char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and abbreviation */ { { /* English language */ { "English", "en" }, - { "HEADER", "Statistics for #%s by %s" }, + { "HEADER", "Statistics for %s by %s" }, { "LEGEND", "Legend" }, { "LASTDAYS", "Lastdays statistics" }, { "TOPHOURS", "Hourly statistics" }, @@ -68,7 +70,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "OCCURRENCES", "occurrences" }, { "BIGNUMBERS", "Some big numbers..." }, { "NUMBERS", "numbers" }, - { "TIME", "%d lines parsed in %d seconds" }, + { "TIME", "%d lines (%d days) parsed in %d seconds" }, { "FOOTER", "Statistics generated by" }, { "C_SMILE", "is often happy :)" }, { "C_FROWN", "is often sad :(" }, @@ -85,8 +87,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "C_MONOLOGUE", "speaks a lot of monologues" } }, { /* French language */ - { "Français", "fr" }, - { "HEADER", "Statistiques de #%s par %s" }, + { "French", "fr" }, + { "HEADER", "Statistiques de %s par %s" }, { "LEGEND", "Légende" }, { "LASTDAYS", "Statistiques des derniers jours" }, { "TOPHOURS", "Statistiques horaires" }, @@ -97,7 +99,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "AVGLETTERS", "lettres/lignes" }, { "HOURS", "heures" }, { "QUOTE", "message aléatoire" }, - { "TOPUSERSTIME", "Personnes les plus actives par période de la journée" }, + { "TOPUSERSTIME", "Personnes les plus actives par période de la journée" }, { "RANDTOPICS", "Quelques topics" }, { "CHANGEDBY", "changé par" }, { "NEWTOPIC", "nouveau topic" }, @@ -109,7 +111,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "OCCURRENCES", "occurrences" }, { "BIGNUMBERS", "Quelques grands nombres..." }, { "NUMBERS", "nombres" }, - { "TIME", "%d lignes traitées en %d secondes" }, + { "TIME", "%d lignes (%d jours) traitées en %d secondes" }, { "FOOTER", "Statistiques générées par" }, { "C_SMILE", "est souvent heureux :)" }, { "C_FROWN", "est souvent triste :(" }, @@ -124,102 +126,285 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "C_JOIN", "ne sait pas s'il doit rester ou partir" }, { "C_NICK", "change souvent de nick" }, { "C_MONOLOGUE", "parle beaucoup de monologues" } - } -}; - -int language; - -char *L(char *key) -{ - int i; - for (i=1;i<=NBKEYS;i++) if (strcmp(key,keys[language][i][0])==0) return(keys[language][i][1]); - fprintf(stderr,"unknown language key: %s\n",key); - return(""); -} - -/* Themes */ -#define NBTHEMES 5 -#define NBCOLORS 9 -char *colors[NBTHEMES][NBCOLORS+1][2]= /* first key used for theme name/description and abbreviation */ -{ - { /* Default theme */ - { "White background", "default" }, - { "BGCOLOR", "#FFFFFF" }, - { "TEXT", "#000000" }, - { "LINK", "#0000EE" }, - { "VLINK", "#551A8B" }, - { "ALINK", "#FF0000" }, - { "TITLE1", "#000000" }, - { "TITLE2", "#000000" }, - { "BGTABLE", "#EEEEEE" }, - { "BGTITLE", "#FFEEEE" } }, - { /* Dark theme */ - { "Black background", "dark" }, - { "BGCOLOR", "#000000" }, - { "TEXT", "#FFFFFF" }, - { "LINK", "#AAAAFF" }, - { "VLINK", "#CCCCDD" }, - { "ALINK", "#FFAAAA" }, - { "TITLE1", "#AAAAFF" }, - { "TITLE2", "#FFAAAA" }, - { "BGTABLE", "#225522" }, - { "BGTITLE", "#552222" } + { /* German language */ + /* contributed by Valentin Gelhorn */ + { "German", "de" }, + { "HEADER", "Statistiken für %s von %s" }, + { "LEGEND", "Legende" }, + { "LASTDAYS", "Statistik der letzten Tage" }, + { "TOPHOURS", "Stündliche Statistik" }, + { "TOPUSERS", "Die aktivsten Personen" }, + { "OTHERS", "Es bleiben noch %d uneingetragene" }, + { "NBLINES", "Zeilen" }, + { "NICK", "Nick" }, + { "AVGLETTERS", "Buchstaben/Zeile" }, + { "HOURS", "Stunden" }, + { "QUOTE", "Zufällig ausgewaehlte Zitate" }, + { "TOPUSERSTIME", "Die aktivsten Personen zur bestimmten Tageszeit" }, + { "RANDTOPICS", "Ein paar Topics" }, + { "CHANGEDBY", "Gesetzt von" }, + { "NEWTOPIC", "Neues topic" }, + { "RANDURLS", "Ein paar URLs" }, + { "POSTEDBY", "Geschrieben von" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "Am häufigsten benutze Wörter" }, + { "WORD", "Wort" }, + { "OCCURRENCES", "Vorkommen" }, + { "BIGNUMBERS", "Ein paar grosse Zahlen" }, + { "NUMBERS", "Zahlen" }, + { "TIME", "%d Zeilen (%d Tage) analysiert in %d Sekunden" }, + { "FOOTER", "Statistiken wurden erstellt von" }, + { "C_SMILE", "ist oft glüklich :)" }, + { "C_FROWN", "ist oft traurig :(" }, + { "C_EXCLAM", "schreit oft !" }, + { "C_QUESTION", "stellt viele Fragen ?" }, + { "C_ME", "mag /me'en" }, + { "C_TOPIC", "aendert oft das Topico" }, + { "C_MODE", "aendert oft die Modes" }, + { "C_KICK", "mag /kick'en" }, + { "C_KICKED", "wird oft gekickt"}, + { "C_URL", "schreibt viele URLs"}, + { "C_JOIN", "kann sich nicht entscheiden ob er bleiben oder gehen soll" }, + { "C_NICK", "ändert oft seinen Nick" }, + { "C_MONOLOGUE", "spricht oft Monologe" } }, - { /* zeRezo theme */ - { "Green theme...", "zerezo" }, - { "BGCOLOR", "#000000" }, - { "TEXT", "#FFFFFF" }, - { "LINK", "#14F024" }, - { "VLINK", "#0CBA18" }, - { "ALINK", "#FFFFFF" }, - { "TITLE1", "#0CBA18" }, - { "TITLE2", "#84DB8C" }, - { "BGTABLE", "#085D10" }, - { "BGTITLE", "#0B810B" } + { /* Spanish language */ + /* contributed by Alex */ + { "Spanish", "es" }, + { "HEADER", "Estadísticas de %s por %s" }, + { "LEGEND", "Leyenda" }, + { "LASTDAYS", "Estadísticas de los últimos días" }, + { "TOPHOURS", "Estadísticas por horas" }, + { "TOPUSERS", "Los que más escriben" }, + { "OTHERS", "Hay %d más que no llegaron..." }, + { "NBLINES", "líneas" }, + { "NICK", "nick" }, + { "AVGLETTERS", "letras por línea" }, + { "HOURS", "horas" }, + { "QUOTE", "Frase aleatoria" }, + { "TOPUSERSTIME", "Los que más escriben según la hora" }, + { "RANDTOPICS", "Algunos topics" }, + { "CHANGEDBY", "Puestos por" }, + { "NEWTOPIC", "topic" }, + { "RANDURLS", "Algunas URLs" }, + { "POSTEDBY", "puestas por" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "Palabras más usadas" }, + { "WORD", "Palabra" }, + { "OCCURRENCES", "Frecuencia" }, + { "BIGNUMBERS", "Algunos datos..." }, + { "NUMBERS", "Número de veces" }, + { "TIME", "%d lineas (%d días) procesadas en %d segundos" }, + { "FOOTER", "Estadísticas generadas por" }, + { "C_SMILE", "Suele estar felíz :)" }, + { "C_FROWN", "Suele estar triste :(" }, + { "C_EXCLAM", "Grita mucho !" }, + { "C_QUESTION", "Hace muchas preguntas ?" }, + { "C_ME", "Abusa del comando /me" }, + { "C_TOPIC", "Suele cambiar el topic" }, + { "C_MODE", "Cambia a veces los modos del canal" }, + { "C_KICK", "Le gusta patear" }, + { "C_KICKED", "Es pateado con frecuencia" }, + { "C_URL", "Pone muchas URLs" }, + { "C_JOIN", "No sabe si irse o quedarse" }, + { "C_NICK", "Cambia mucho de nick" }, + { "C_MONOLOGUE", "Habla solo" } }, - { /* tit-namour theme */ - { "Purple and Pink", "namour" }, - { "BGCOLOR", "#9933CC" }, - { "TEXT", "#DDAAFF" }, - { "LINK", "#CC99FF" }, - { "VLINK", "#999999" }, - { "ALINK", "#FFC8C8" }, - { "TITLE1", "#FFC8C8" }, - { "TITLE2", "#FFC8C8" }, - { "BGTABLE", "#7711AA" }, - { "BGTITLE", "#550088" } + { /* Polish language */ + /* contributed by Piotr Jarmuz */ + { "Polish", "pl" }, + { "HEADER", "Statystyki dla %s przez %s" }, + { "LEGEND", "Legenda" }, + { "LASTDAYS", "Statystyki z ostatnich dni" }, + { "TOPHOURS", "Statystyki godzinne" }, + { "TOPUSERS", "Najaktywniejsi ludzie" }, + { "OTHERS", "Zostalo jeszcze %d nie sklasyfikowanych..." }, + { "NBLINES", "linie" }, + { "NICK", "nick" }, + { "AVGLETTERS", "litery/linie" }, + { "HOURS", "godziny" }, + { "QUOTE", "przypadkowa wiadomosc" }, + { "TOPUSERSTIME", "Najaktywniejsi ludzie wedlug czasu dnia" }, + { "RANDTOPICS", "Pare tematow" }, + { "CHANGEDBY", "zmienione przez" }, + { "NEWTOPIC", "nowy temat" }, + { "RANDURLS", "Pare URL-i" }, + { "POSTEDBY", "wyslane przez" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "Najczestsze slowa" }, + { "WORD", "slowo" }, + { "OCCURRENCES", "wystapienia" }, + { "BIGNUMBERS", "Pare wielkich liczb..." }, + { "NUMBERS", "liczby" }, + { "TIME", "%d linii (%d dni) sparsowanych w %d sekund" }, + { "FOOTER", "Statystyki wygenerowane przez" }, + { "C_SMILE", "jest czesto szczesliwy :)" }, + { "C_FROWN", "jest czesto smutny :(" }, + { "C_EXCLAM", "duzo krzyczy !" }, + { "C_QUESTION", "zadaje duzo pytan ?" }, + { "C_ME", "lubi /mnie polecenie" }, + { "C_TOPIC", "czesto zmienia temat" }, + { "C_MODE", "czesto zmienia tryb" }, + { "C_KICK", "lubi /kopac" }, + { "C_KICKED", "czesto go wykopuja" }, + { "C_URL", "wysyla duzo URL-i" }, + { "C_JOIN", "nie wie czy zostac czy wyjsc" }, + { "C_NICK", "czesto zmienia swojego nicka" }, + { "C_MONOLOGUE", "czesto mowi monologiem" } }, - { /* zeDuel theme */ - { "Orange theme...", "zeduel" }, - { "BGCOLOR", "#FFFFFF" }, - { "TEXT", "#000000" }, - { "LINK", "#FF7700" }, - { "VLINK", "#C05A00" }, - { "ALINK", "#FF9A41" }, - { "TITLE1", "#C05A00" }, - { "TITLE2", "#FF7700" }, - { "BGTABLE", "#FFEEEE" }, - { "BGTITLE", "#FF7700" } - } + { /* Finnish language */ + /* contributed by Antti Huopana */ + { "Finnish", "fi" }, + { "HEADER", "Kanavan %s tilastot - %s" }, + { "LEGEND", "Merkkien selitykset" }, + { "LASTDAYS", "Viime päivien tilastot" }, + { "TOPHOURS", "Tilastot tunneittain" }, + { "TOPUSERS", "Aktiivisimmat ihmiset" }, + { "OTHERS", "Jäljelle jäi %d joita ei listattu..." }, + { "NBLINES", "rivit" }, + { "NICK", "nikki" }, + { "AVGLETTERS", "kirjainta/rivi" }, + { "HOURS", "tunnit" }, + { "QUOTE", "satunnainen viesti" }, + { "TOPUSERSTIME", "Vuorokauden ajan mukaan aktiivisimmat" }, + { "RANDTOPICS", "Joitakin aiheita" }, + { "CHANGEDBY", "vaihtaja" }, + { "NEWTOPIC", "aihe" }, + { "RANDURLS", "Joitakin URLeja" }, + { "POSTEDBY", "lähettäjä" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "Eniten käytettyjä sanoja" }, + { "WORD", "sana" }, + { "OCCURRENCES", "käytetty" }, + { "BIGNUMBERS", "Joitakin isoja lukuja..." }, + { "NUMBERS", "luvut" }, + { "TIME", "%d riviä (%d päivää) parsittu %d sekunnissa" }, + { "FOOTER", "Tilastot on generoinut" }, + { "C_SMILE", "on usein iloinen :)" }, + { "C_FROWN", "on usein surullinen :(" }, + { "C_EXCLAM", "möykkää paljon !" }, + { "C_QUESTION", "kyselee liikaa ?" }, + { "C_ME", "pitää itsestään" }, + { "C_TOPIC", "vaihtaa usein aihetta" }, + { "C_MODE", "haluaa elää muuttuvassa maailmassa" }, + { "C_KICK", "pitää potkimisesta" }, + { "C_KICKED", "tykkää tulla potkituksi" }, + { "C_URL", "surffailee liikaa" }, + { "C_JOIN", "ei tiedä ollakko vai eikö olla" }, + { "C_NICK", "kärsii identiteettiongelmista" }, + { "C_MONOLOGUE", "höpöttää paljon itsekseen" } + }, + { /* Italian language */ + /* contributed by Coviello Giuseppe */ + { "Italian", "it" }, + { "HEADER", "Statistiche per il canale %s di %s" }, + { "LEGEND", "Legenda" }, + { "LASTDAYS", "Statistiche degli ultimi giorni" }, + { "TOPHOURS", "Statistiche in ore" }, + { "TOPUSERS", "Utenti più attivi" }, + { "OTHERS", "Ci sono %d utenti non classificati..." }, + { "NBLINES", "righe" }, + { "NICK", "nick" }, + { "AVGLETTERS", "lettere/righe" }, + { "HOURS", "ore" }, + { "QUOTE", "messaggio casuale" }, + { "TOPUSERSTIME", "Utenti più attivi del giorno (divisi per fasce orarie)" }, + { "RANDTOPICS", "Alcuni topic" }, + { "CHANGEDBY", "cambiato da" }, + { "NEWTOPIC", "nuovo topic" }, + { "RANDURLS", "ALcuni URL" }, + { "POSTEDBY", "postato da" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "Le parole più usate" }, + { "WORD", "parola" }, + { "OCCURRENCES", "usata" }, + { "BIGNUMBERS", "Alcuni numeri ..." }, + { "NUMBERS", "numeri" }, + { "TIME", "%d righe (%d giorni) esaminate in %d secondi" }, + { "FOOTER", "Statistiche generate da" }, + { "C_SMILE", "è spesso felice :)" }, + { "C_FROWN", "è spesso triste :(" }, + { "C_EXCLAM", "esclama molto !" }, + { "C_QUESTION", "fa molte domande ?" }, + { "C_ME", "ama il comando /me" }, + { "C_TOPIC", "cambia spesso il topic" }, + { "C_MODE", "cambia spesso i mode" }, + { "C_KICK", "ama /kick(are)" }, + { "C_KICKED", "è kickato spesso" }, + { "C_URL", "posta molti URL" }, + { "C_JOIN", "non sa se è ora di andare o restare" }, + { "C_NICK", "cambia spesso il nick" }, + { "C_MONOLOGUE", "fa molti monologhi" } + }, + { /* Dutch language */ + /* contributed by Jeroen Ubbink */ + { "Dutch", "nl" }, + { "HEADER", "Statistieken voor %s door %s" }, + { "LEGEND", "Legenda" }, + { "LASTDAYS", "Statistieken van de laatste dagen" }, + { "TOPHOURS", "Statistieken per uur" }, + { "TOPUSERS", "Meest actieve mensen" }, + { "OTHERS", "Er zijn nog %d niet in de top..." }, + { "NBLINES", "regels" }, + { "NICK", "nick" }, + { "AVGLETTERS", "letters/lijn" }, + { "HOURS", "uren" }, + { "QUOTE", "Willekeurige regel" }, + { "TOPUSERSTIME", "Meest actieve mensen per tijdstip per dag" }, + { "RANDTOPICS", "Enkele topics" }, + { "CHANGEDBY", "gewijzigd door" }, + { "NEWTOPIC", "nieuwe topic" }, + { "RANDURLS", "Enkele URLs" }, + { "POSTEDBY", "Geplaatst door" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "Meest gebruikte woorden" }, + { "WORD", "woord" }, + { "OCCURRENCES", "aantal" }, + { "BIGNUMBERS", "Enkele grote aantallen..." }, + { "NUMBERS", "numbers" }, + { "TIME", "%d regels (%d dagen) verwerkt in %d seconden" }, + { "FOOTER", "Statistieken gegenereert door" }, + { "C_SMILE", "is vaak vrolijk :)" }, + { "C_FROWN", "is vaak droevig :(" }, + { "C_EXCLAM", "schreeuwt veel !" }, + { "C_QUESTION", "stelt veel vragen ?" }, + { "C_ME", "vindt /me een leuk commando" }, + { "C_TOPIC", "verandert vaak de topic" }, + { "C_MODE", "verandert vaak de modes" }, + { "C_KICK", "vindt /kick erg leuk" }, + { "C_KICKED", "wordt vaak gekickt" }, + { "C_URL", "plaatst veel URLs" }, + { "C_JOIN", "twijfelt tussen blijven of gaan" }, + { "C_NICK", "verandert vaak van nick" }, + { "C_MONOLOGUE", "spreekt veel monologen" } + } }; -int theme; +int language=0; /* default to english */ -char *T(char *color) +char *L(char *key) { int i; - for (i=1;i<=NBCOLORS;i++) if (strcmp(color,colors[theme][i][0])==0) return(colors[theme][i][1]); - fprintf(stderr,"unknown theme color: %s\n",color); + for (i=1;i<=NBKEYS;i++) if (strcmp(key,keys[language][i][0])==0) return(keys[language][i][1]); + fprintf(stderr,"unknown language key: %s\n",key); return(""); } /* Variables */ -char *channel; -char *maintainer; +int debug=1; /* 0 = none ; 1 = normal ; 2 = verbose */ +char channel[MAXLINELENGTH]="set_channel_in_config_file"; +char maintainer[MAXLINELENGTH]="set_maintainer_in_config_file"; +char theme[MAXLINELENGTH]="default"; +int refresh_time=0; /* 0 = disabled */ +int w3c_link=1; /* 0 = disabled */ +char header[MAXLINELENGTH]="none"; +char footer[MAXLINELENGTH]="none"; +int totallines=0; +time_t debut; -struct +struct { char nick[MAXNICKLENGTH]; int lines; @@ -227,6 +412,7 @@ struct int hours[4]; char quote[MAXQUOTELENGTH+1]; int counters[NBCOUNTERS]; + int temp; } users[MAXUSERS]; int nbusers=0; @@ -280,17 +466,17 @@ void findwords(char *message) while (isletter(*message)) { c=lowercase(*message)-'a'; - if ((*pos).next[(int)c]==NULL) + if (pos->next[(int)c]==NULL) { tmp=malloc(sizeof(struct letter)); - (*tmp).nb=0; - for (i=0;i<26;i++) (*tmp).next[i]=NULL; - (*pos).next[(int)c]=tmp; + tmp->nb=0; + for (i=0;i<26;i++) tmp->next[i]=NULL; + pos->next[(int)c]=tmp; } - pos=(*pos).next[(int)c]; + pos=pos->next[(int)c]; message++; } - (*pos).nb++; + pos->nb++; } return; } @@ -318,16 +504,27 @@ void bestwords(struct letter pos,int cur) tempword[cur]='\0'; } -void printhtml(char *string) /* replace < and > by < and > */ +void freewords(struct letter *pos) +{ + int i; + for (i=0;i<26;i++) if (pos->next[i]!=NULL) + { + freewords(pos->next[i]); + free(pos->next[i]); + (*pos).next[i]=NULL; + } +} + +void printhtml(FILE *fic,char *string) /* replace < and > by < and > */ { while (*string!='\0') { switch (*string) { - case '<':printf("<"); break; - case '>':printf(">"); break; - case '&':printf("&"); break; - default:printf("%c",*string); break; + case '<':fprintf(fic,"<"); break; + case '>':fprintf(fic,">"); break; + case '&':fprintf(fic,"&"); break; + default:fprintf(fic,"%c",*string); break; } string++; } @@ -354,6 +551,7 @@ int dichotomic(char *nick) for (j=0;j<4;j++) users[i].hours[j]=users[i-1].hours[j]; strcpy(users[i].quote,users[i-1].quote); for (j=0;j /path/to/file.html\n\n"); - fprintf(stderr,"Version :\nirssistats %s\n\n",VERSION); - fprintf(stderr,"Supported languages :\n"); - for (i=0;i=MAXLINELENGTH) { fprintf(stderr,"line too long\n"); exit(1); } - if (c=='\n') + /* remove \n */ + for (i=0;line[i]!=0;i++); + if (i>=MAXLINELENGTH-1) { fprintf(stderr,"line %d is too long\n",totallines); exit(1); } + line[i-1]='\0'; + pos=0; + totallines++; + if (totallines%10000==0 && debug) { printf("."); fflush(stdout); } + if (strncmp("--- Day changed",line,15)==0) /* --- Day changed Wed May 01 2002 */ + { + for (i=30;i>0;i--) + { + lastdays[i].lines=lastdays[i-1].lines; + for (j=0;j<4;j++) lastdays[i].hours[j]=lastdays[i-1].hours[j]; + } + lastdays[0].lines=0; + for (j=0;j<4;j++) lastdays[0].hours[j]=0; + days++; + } + else if (strncmp("-!- mode/",&line[6],9)==0) /* 00:00 -!- mode/#channel [...] by (Nick, Nick2, )Nick3 */ + { + for (i=strlen(line);line[i]!=' ';i--); + nick=&line[i+1]; + users[dichotomic(nick)].counters[D_MODE]++; + } + else if (strncmp("-!-",&line[6],3)==0) /* 00:00 -!- Nick something... */ { - line[pos-1]='\0'; - totallines++; - if (totallines%10000==0) { fprintf(stderr,"."); fflush(stdout); } - if (strncmp("--- Day changed",line,15)==0) /* --- Day changed Wed May 01 2002 */ + for (i=10;line[i]!=' ';i++); + line[i]='\0'; + nick=&line[10]; + message=&line[i+1]; + if (strncmp("changed the topic of",message,20)==0) /* 00:00 -!- Nick changed the topic of #channel to: new topic */ { - for (i=30;i>0;i--) + users[dichotomic(nick)].counters[D_TOPIC]++; + for (i=21;message[i]!=':';i++); + message=&message[i+2]; + nbtopics++; + if ((nbtopics<=NBTOPICS) || (rand()%(nbtopics/NBTOPICS)==0)) { - lastdays[i].lines=lastdays[i-1].lines; - for (j=0;j<4;j++) lastdays[i].hours[j]=lastdays[i-1].hours[j]; + temp=nbtopics<=NBTOPICS?nbtopics-1:rand()%NBTOPICS; + strcpy(topics[temp].nick,nick); + strncpy(topics[temp].topic,message,MAXQUOTELENGTH); } - lastdays[0].lines=0; - for (j=0;j<4;j++) lastdays[0].hours[j]=0; - days++; } - else if (strncmp("-!- mode/",&line[6],9)==0) /* 00:00 -!- mode/#channel [...] by Nick(, Nick2, Nick3...) */ + else if (strncmp("was kicked from",message,15)==0) /* 00:00 -!- Nick was kicked from #channel by Nick [Reason] */ { - for (i=15;(line[i]!=']')||(line[i+1]!=' ');i++); - nick=&line[i+5]; - for (i=0;(nick[i]!='\0')&&(nick[i]!=',');i++); - nick[i]='\0'; - users[dichotomic(nick)].counters[D_MODE]++; + users[dichotomic(nick)].counters[D_KICKED]++; + for (i=16;message[i]!=' ';i++); + message=&message[i+4]; + for (i=0;message[i]!=' ';i++); + message[i]='\0'; + users[dichotomic(message)].counters[D_KICK]++; } - else if (strncmp("-!-",&line[6],3)==0) /* 00:00 -!- Nick something... */ + else if (strncmp("is now known as",message,15)==0) /* 00:00 -!- Nick is now known as Nick */ + users[dichotomic(nick)].counters[D_NICK]++; + else if (message[0]=='[') /* 00:00 -!- Nick [user@host] something... */ { - for (i=10;line[i]!=' ';i++); - line[i]='\0'; - nick=&line[10]; + for (i=0;message[i]!=']';i++); + message=&message[i+2]; + if (strncmp("has joined",message,10)==0) /* 00:00 -!- Nick [user@host] has joined #channel */ + users[dichotomic(nick)].counters[D_JOIN]++; + else if (strncmp("has quit",message,8)==0); /* 00:00 -!- Nick [user@host] has quit [Reason] */ + else if (strncmp("has left",message,8)==0); /* 00:00 -!- Nick [user@host] has left #channel [Reason] */ + else; + } + } + else if ((line[6]=='<') || (line[7]=='*')) + { + line[2]='\0'; + hour=atoi(line); + if (line[7]=='*') /* 00:00 * Nick the message */ + { + for (i=9;line[i]!=' ';i++); + nick=&line[9]; message=&line[i+1]; - if (strncmp("changed the topic of",message,20)==0) /* 00:00 -!- Nick changed the topic of #channel to: new topic */ - { - users[dichotomic(nick)].counters[D_TOPIC]++; - for (i=21;message[i]!=':';i++); - message=&message[i+2]; - nbtopics++; - if ((nbtopics<=5) || (rand()%nbtopics==0)) - { - for (i=4;i>0;i--) - { - strcpy(topics[i].nick,topics[i-1].nick); - strcpy(topics[i].topic,topics[i-1].topic); - } - strcpy(topics[0].nick,nick); - strncpy(topics[0].topic,message,MAXQUOTELENGTH); - } - } - else if (strncmp("was kicked from",message,15)==0) /* 00:00 -!- Nick was kicked from #channel by Nick [Reason] */ - { - users[dichotomic(nick)].counters[D_KICKED]++; - for (i=16;message[i]!=' ';i++); - message=&message[i+4]; - for (i=0;message[i]!=' ';i++); - message[i]='\0'; - users[dichotomic(message)].counters[D_KICK]++; - } - else if (strncmp("is now known as",message,15)==0) /* 00:00 -!- Nick is now known as Nick */ - users[dichotomic(nick)].counters[D_NICK]++; - else if (message[0]=='[') /* 00:00 -!- Nick [user@host] something... */ - { - for (i=0;message[i]!=']';i++); - message=&message[i+2]; - if (strncmp("has joined",message,10)==0) /* 00:00 -!- Nick [user@host] has joined #channel */ - users[dichotomic(nick)].counters[D_JOIN]++; - else if (strncmp("has quit",message,8)==0); /* 00:00 -!- Nick [user@host] has quit [Reason] */ - else if (strncmp("has left",message,8)==0); /* 00:00 -!- Nick [user@host] has left #channel [Reason] */ - else; - } } - else if ((line[6]=='<') || (line[7]=='*')) + else if (line[7]=='>') /* 00:00 <>>>?Nick<<<> the personal message */ + /* 00:00 <>>?Nick<<> the personal message */ { - line[2]='\0'; - hour=atoi(line); - if (line[7]=='*') /* 00:00 * Nick the message */ - { - for (i=9;line[i]!=' ';i++); - nick=&line[9]; - message=&line[i+1]; - } - else if (line[7]=='>') /* 00:00 <>>>?Nick<<<> the personal message */ - { - for (i=11;line[i]!='<';i++); - nick=&line[11]; - message=&line[i+5]; - } - else /* 00:00 the message */ - { - for (i=8;line[i]!='>';i++); - nick=&line[8]; - message=&line[i+2]; - } - line[i]='\0'; - i=dichotomic(nick); - if (line[7]=='*') users[i].counters[D_ME]++; - if (i==mononick) - { - monolines++; - if (monolines==5) users[i].counters[D_MONOLOGUE]++; - } - else - { - mononick=i; - monolines=1; - } - j=strlen(message); - users[i].lines++; - users[i].letters+=j; - users[i].hours[hour/6]++; - lastdays[0].lines++; - lastdays[0].hours[hour/6]++; - lines++; - hours[hour]++; - if (message[j-1]=='?') users[i].counters[D_QUESTION]++; - else if (message[j-1]=='!') users[i].counters[D_EXCLAM]++; - else if ((message[j-3]==' ')&&(message[j-2]==':')) - { - if (message[j-1]==')') users[i].counters[D_SMILE]++; - else if (message[j-1]=='(') users[i].counters[D_FROWN]++; + for (i=10;line[i]!='<';i++); + nick=&line[10]; + if (line[9]=='>') nick++; + message=&line[i+5]; + } + else /* 00:00 the message */ + { + + /* + * Irssi doesn't log channel mode with show_nickmode = OFF + * the following covers op, half-op, voice and show_nickmode_empty + */ + if (line[7]=='@' || line[7]=='%' || line[7]=='+' || line[7]==' ') { + nickstart = 8; + } else { + nickstart = 7; } - if (rand()%users[i].lines==0) strncpy(users[i].quote,message,MAXQUOTELENGTH); - if (strncmp("http://",message,7)==0) + + for (i=nickstart;line[i]!='>';i++); + nick=&line[nickstart]; + message=&line[i+2]; + } + line[i]='\0'; + i=dichotomic(nick); + if (line[7]=='*') users[i].counters[D_ME]++; + if (i==mononick) + { + monolines++; + if (monolines==5) users[i].counters[D_MONOLOGUE]++; + } + else + { + mononick=i; + monolines=1; + } + j=strlen(message); + users[i].lines++; + users[i].letters+=j; + users[i].hours[hour/6]++; + lastdays[0].lines++; + lastdays[0].hours[hour/6]++; + lines++; + hours[hour]++; + if (message[j-1]=='?') users[i].counters[D_QUESTION]++; + else if (message[j-1]=='!') users[i].counters[D_EXCLAM]++; + else if ((message[j-3]==' ')&&(message[j-2]==':')) + { + if (message[j-1]==')') users[i].counters[D_SMILE]++; + else if (message[j-1]=='(') users[i].counters[D_FROWN]++; + } + if (rand()%users[i].lines==0) strncpy(users[i].quote,message,MAXQUOTELENGTH); + if (strncmp("http://",message,7)==0) + { + users[i].counters[D_URL]++; + for (i=0;(message[i]!=' ') && (i0;i--) - { - strcpy(urls[i].nick,urls[i-1].nick); - strcpy(urls[i].url,urls[i-1].url); - strcpy(urls[i].shorturl,urls[i-1].shorturl); - } - strcpy(urls[0].nick,nick); - strcpy(urls[0].url,message); - strncpy(urls[0].shorturl,message,MAXQUOTELENGTH); - } + temp=nburls<=NBURLS?nburls-1:rand()%NBURLS; + strcpy(urls[temp].nick,nick); + strcpy(urls[temp].url,message); + strncpy(urls[temp].shorturl,message,MAXQUOTELENGTH); } - findwords(message); } - pos=0; + findwords(message); } + pos=0; } - fprintf(stderr,"done\n"); - - bestwords(words,0); + fclose(fic); + if (debug) printf(" done\n"); +} - /*** HTML ***/ +void parse_nick(char *nickfile) +{ + FILE *fic; + int i,j; + regex_t preg; + char line[MAXLINELENGTH]; + int user; + + for (i=0;i=0)) + { + if (users[i].temp>users[user].temp) /* for nick alias, keep the random quote of the most used nick */ + { + strcpy(users[user].quote,users[i].quote); + users[user].temp=users[i].temp; + } + users[user].lines+=users[i].lines; + users[user].letters+=users[i].letters; + for (j=0;j<4;j++) users[user].hours[j]+=users[i].hours[j]; + for (j=0;j"); + users[i].lines=-1; + users[i].letters=-1; + for (j=0;j<4;j++) users[i].hours[j]=-1; + for (j=0;j\n\n",VERSION,URL); - printf("\n\n\n\n"); - printf(L("HEADER"),channel,maintainer); - printf("\n\n\n"); - printf("\n\n
\n\n

",T("BGCOLOR"),T("TEXT"),T("LINK"),T("VLINK"),T("ALINK"),T("TITLE1")); - printf(L("HEADER"),channel,maintainer); - printf("

\n%s
\n

\n\n",ctime(&debut)); + if (strcmp("none",header)==0) + { + fprintf(fic,"\n\n"); + fprintf(fic,"\n\n",VERSION,URL); + fprintf(fic,"\n\n\n"); + fprintf(fic,L("HEADER"),channel,maintainer); + fprintf(fic,"\n\n"); + if (refresh_time) + fprintf(fic,"\n",refresh_time); + fprintf(fic,"\n",theme); + fprintf(fic,"\n\n"); + fprintf(fic,"\n\n"); + } + else + { + if ((sfic=fopen(header,"rt"))==NULL) { fprintf(stderr,"can't open header file \"%s\"\n",header); exit(1); } + while ((temp=fread(line,1,MAXLINELENGTH,sfic))) fwrite(line,temp,1,fic); + fclose(sfic); + } + fprintf(fic,"
\n\n
\n

"); + fprintf(fic,L("HEADER"),channel,maintainer); + fprintf(fic,"

\n

\n%s

\n
\n\n",ctime(&debut)); /* legend */ - printf("

%s

\n\n\n",T("TITLE2"),L("LEGEND"),T("BGTABLE")); - for (i=0;i<4;i++) printf("\n",i+1,L("HOURS"),i*6,i*6+5); - printf("\n
: %s %d-%d
\n

\n\n"); + fprintf(fic,"
\n

%s

\n\n\n",L("LEGEND")); + for (i=0;i<4;i++) fprintf(fic,"\n",i+1,L("HOURS"),i*6,i*6+5); + fprintf(fic,"\n
%s %d-%d
\n
\n\n"); /* last days */ - printf("

%s

\n\n\n",T("TITLE2"),L("LASTDAYS")); + fprintf(fic,"
\n

%s

\n
\n\n",L("LASTDAYS")); max=-1; for (i=30;i>=0;i--) if (lastdays[i].lines>max) max=lastdays[i].lines; for (i=30;i>=0;i--) { - printf("\n"); + fprintf(fic,"\n"); } - printf("\n\n"); + fprintf(fic,"\n\n"); for (i=30;i>=0;i--) - printf("\n",T("BGTABLE"),i); - printf("\n
%d
",lastdays[i].lines); - for (j=0;j<4;j++) if (lastdays[i].hours[j]!=0) printf("
",j+1,150*lastdays[i].hours[j]/max); - printf("
%d",lastdays[i].lines); /* width=\"15\" */ + for (j=0;j<4;j++) if (lastdays[i].hours[j]!=0) fprintf(fic,"
",j+1,150*lastdays[i].hours[j]/max); + fprintf(fic,"
%d
\n

\n\n"); + fprintf(fic,"%d\n",i); + fprintf(fic,"\n\n
\n\n"); /* top hours */ - printf("

%s

\n\n\n",T("TITLE2"),L("TOPHOURS")); + fprintf(fic,"
\n

%s

\n
\n\n",L("TOPHOURS")); max=-1; for (i=0;i<24;i++) if (hours[i]>max) max=hours[i]; for (i=0;i<24;i++) { - printf("\n"); + fprintf(fic,"\n"); } - printf("\n\n"); + fprintf(fic,"\n\n"); for (i=0;i<24;i++) - printf("\n",T("BGTABLE"),i); - printf("\n
%.1f%%
",lines!=0?(float)100*hours[i]/lines:0); - if (hours[i]!=0) printf("
",i/6+1,150*hours[i]/max); - printf("
%.1f%%",lines!=0?(float)100*hours[i]/lines:0); /* width=\"15\" */ + if (hours[i]!=0) fprintf(fic,"
",i/6+1,150*hours[i]/max); + fprintf(fic,"
%d
\n

\n\n"); + fprintf(fic,"%d\n",i); + fprintf(fic,"\n\n\n\n"); /* top users */ - printf("

%s

\n",T("TITLE2"),L("TOPUSERS")); - printf("\n\n",T("BGTITLE"),L("NICK"),T("BGTITLE"),L("NBLINES"),T("BGTITLE"),L("HOURS"),T("BGTITLE"),L("AVGLETTERS"),T("BGTITLE"),L("QUOTE")); + fprintf(fic,"
\n

%s

\n",L("TOPUSERS")); + fprintf(fic,"
%s%s%s%s%s
\n\n",L("NICK"),L("NBLINES"),L("HOURS"),L("AVGLETTERS"),L("QUOTE")); for (i=1;i<=NBUSERS;i++) { user=-1; - max=-1; + max=0; for (j=0;jmax) max=users[user=j].lines; if (user!=-1) { - printf("\n"); + fprintf(fic,"\n"); users[user].lines=-1; } } - printf("
%s%s%s%s%s
%d%s%d",T("BGTABLE"),i,T("BGTABLE"),users[user].nick,T("BGTABLE"),users[user].lines,T("BGTABLE")); - for (j=0;j<4;j++) if (users[user].hours[j]!=0) printf("",j+1,100*users[user].hours[j]/users[user].lines); - printf("%d\"",T("BGTABLE"),users[user].letters/users[user].lines,T("BGTABLE"),users[user].letters/users[user].lines,T("BGTABLE")); - printhtml(users[user].quote); - printf("\"
%d%s%d",i,users[user].nick,users[user].lines); + for (j=0;j<4;j++) if (users[user].hours[j]!=0) fprintf(fic,"
",j+1,100*users[user].hours[j]/users[user].lines); + fprintf(fic,"
%d
\"",users[user].lines!=0?users[user].letters/users[user].lines:0,users[user].lines!=0?users[user].letters/users[user].lines:0); + printhtml(fic,users[user].quote); + fprintf(fic,"\"
\n"); - if (nbusers>NBUSERS) + fprintf(fic,"\n"); + temp=0; + for (i=0;i<=nbusers;i++) if (users[i].lines>=0) temp++; + if (temp>0) { - printf("
"); - printf(L("OTHERS"),nbusers-50); - printf("
\n"); + fprintf(fic,"

"); + fprintf(fic,L("OTHERS"),temp); + fprintf(fic,"

\n"); } - printf("

\n\n"); + fprintf(fic,"\n\n"); /* top users by time */ - printf("

%s

\n",T("TITLE2"),L("TOPUSERSTIME")); - printf("\n"); - for (i=0;i<4;i++) printf("",T("BGTITLE"),L("HOURS"),i*6,i*6+5); - printf("\n"); + fprintf(fic,"
\n

%s

\n",L("TOPUSERSTIME")); + fprintf(fic,"
%s %d-%d
\n"); + for (i=0;i<4;i++) fprintf(fic,"",L("HOURS"),i*6,i*6+5); + fprintf(fic,"\n"); for (i=1;i<=NBUSERSTIME;i++) { - printf("",T("BGTABLE"),i); + fprintf(fic,"",i); for (j=0;j<4;j++) { user=-1; - max=-1; + max=0; for (k=0;kmax) max=users[user=k].hours[j]; if (user!=-1) { - printf("",T("BGTABLE"),users[user].nick,T("BGTABLE"),users[user].hours[j]); + fprintf(fic,"",users[user].nick,users[user].hours[j]); users[user].hours[j]=-1; } - else printf(""); + else fprintf(fic,""); } - printf("\n"); + fprintf(fic,"\n"); } - printf("
%s %d-%d
%d
%d%s%d%s%d
\n

\n\n"); + fprintf(fic,"\n\n\n"); /* random topics */ - printf("

%s

\n",T("TITLE2"),L("RANDTOPICS")); - printf("\n\n",T("BGTITLE"),L("CHANGEDBY"),T("BGTITLE"),L("NEWTOPIC")); + fprintf(fic,"
\n

%s

\n",L("RANDTOPICS")); + fprintf(fic,"
%s%s
\n\n",L("CHANGEDBY"),L("NEWTOPIC")); for (i=nbtopics=0;i--) { - printf("\n"); + fprintf(fic,"\n"); } - printf("
%s%s
%s\"",T("BGTABLE"),topics[i].nick,T("BGTABLE")); - printhtml(topics[i].topic); - printf("\"
%s\"",topics[i].nick); + printhtml(fic,topics[i].topic); + fprintf(fic,"\"
\n

\n\n"); + fprintf(fic,"\n\n\n"); /* random urls */ - printf("

%s

\n",T("TITLE2"),L("RANDURLS")); - printf("\n\n",T("BGTITLE"),L("POSTEDBY"),T("BGTITLE"),L("POSTEDURL")); + fprintf(fic,"
\n

%s

\n",L("RANDURLS")); + fprintf(fic,"
%s%s
\n\n",L("POSTEDBY"),L("POSTEDURL")); for (i=nburls=0;i--) { - printf("\n"); + fprintf(fic,"\n"); } - printf("
%s%s
%s\"",T("BGTABLE"),urls[i].nick,T("BGTABLE"),urls[i].url); - printhtml(urls[i].shorturl); - printf("\"
%s\""); + printhtml(fic,urls[i].shorturl); + fprintf(fic,"\"
\n

\n\n"); + fprintf(fic,"\n\n\n"); /* top words */ - printf("

%s

\n",T("TITLE2"),L("TOPWORDS")); - printf("\n\n",T("BGTITLE"),L("WORD"),T("BGTITLE"),L("OCCURRENCES")); + fprintf(fic,"
\n

%s

\n",L("TOPWORDS")); + fprintf(fic,"
%s%s
\n\n",L("WORD"),L("OCCURRENCES")); for (i=0;i\n",T("BGTABLE"),i+1,T("BGTABLE"),topwords[i].word,T("BGTABLE"),topwords[i].nb); - printf("
%s%s
%d\"%s\"%d
\n

\n\n"); + if (topwords[i].nb!=0) fprintf(fic,"%d\"%s\"%d\n",i+1,topwords[i].word,topwords[i].nb); + fprintf(fic,"\n\n\n"); /* big numbers */ - printf("

%s

\n",T("TITLE2"),L("BIGNUMBERS")); - printf("\n\n",T("BGTITLE"),L("NICK"),T("BGTITLE"),L("NUMBERS"),T("BGTITLE"),L("NBLINES")); + fprintf(fic,"
\n

%s

\n",L("BIGNUMBERS")); + fprintf(fic,"
%s%s%s
\n\n",L("NICK"),L("NUMBERS"),L("NBLINES")); for (i=0;imax) max=users[user=j].counters[i]; - if (user!=-1) printf("",T("BGTABLE"),users[user].nick,T("BGTABLE"),L(counters[i]),T("BGTABLE"),users[user].counters[i]); + if (user!=-1) fprintf(fic,"",users[user].nick,L(counters[i]),users[user].counters[i]); } - printf("
%s%s%s
%s%s%d
%s%s%d
\n

\n\n"); + fprintf(fic,"\n\n\n"); /* footer */ - printf(L("TIME"),totallines,(int)(time(NULL)-debut)); - printf("
\n%s irssistats %s",L("FOOTER"),URL,VERSION); - printf("\n\n
\n\n\n\n\n"); + fprintf(fic,"
\n

"); + fprintf(fic,L("TIME"),totallines,days,(int)(time(NULL)-debut)); + fprintf(fic,"

\n

%s irssistats %s

\n",L("FOOTER"),URL,VERSION); + if (w3c_link) + { + fprintf(fic,"

\n\"Valid\n"); + fprintf(fic,"\"Valid\n

\n"); + } + fprintf(fic,"
\n\n"); + if (strcmp("none",header)==0) + { + fprintf(fic,"\n\n\n\n\n"); + } + else + { + if ((sfic=fopen(footer,"rt"))==NULL) { fprintf(stderr,"can't open footer file \"%s\"\n",footer); exit(1); } + while ((temp=fread(line,1,MAXLINELENGTH,sfic))) fwrite(line,temp,1,fic); + fclose(sfic); + } + fclose(fic); +} + +void parse_config(char *configfile) +{ + FILE *fic; + char line[MAXLINELENGTH]; + char keyword[MAXLINELENGTH]; + char value[MAXLINELENGTH]; + int configlines=0; + int i; + + if (configfile!=NULL) + { + if ((fic=fopen(configfile,"rt"))==NULL) + { + fprintf(stderr,"can't open config file : \"%s\"\n",configfile); + exit(1); + } + } + else + { + sprintf(line,"%s/.irssistats",getenv("HOME")); + if ((fic=fopen(line,"rt"))==NULL) + if ((fic=fopen("/etc/irssistats.conf","rt"))==NULL) + { + fprintf(stderr,"can't find config file : \"%s\" nor \"/etc/irssistats.conf\"\n",line); + fprintf(stderr,"please give the path to the config file in argument\n"); + exit(1); + } + } + + while (fgets(line,MAXLINELENGTH,fic)) + { + configlines++; + if (*line!=';' && *line!='#' && *line!='/' && *line!='-' && *line!='\n') + { + if ((sscanf(line,"%s : %s\n",(char *)&keyword,(char *)&value))!=2) { fprintf(stderr,"error in config file : each line must have the format \"keyword : value\" (line %d)\n",configlines); exit(1); } + + if (strcmp("debug",keyword)==0) + { + if (strcmp("none",value)==0) debug=0; + else + if (strcmp("normal",value)==0) debug=1; + else + if (strcmp("verbose",value)==0) { debug=2; fprintf(stderr,"switching to verbose output\n"); } + else { fprintf(stderr,"unknown value for \"debug\" option, must be \"normal\", \"verbose\" or \"none\"\n"); exit(1); } + } else + + if (strcmp("channel",keyword)==0) + { + if (debug==2) fprintf(stderr,"setting channel name to \"%s\"\n",value); + strcpy(channel,value); + } + else + + if (strcmp("maintainer",keyword)==0) + { + if (debug==2) fprintf(stderr,"setting maintainer to \"%s\"\n",value); + strcpy(maintainer,value); + } + else + + if (strcmp("language",keyword)==0) + { + if (debug==2) fprintf(stderr,"setting language to \"%s\"\n",value); + for (i=0;i