From cfcf15a6f6799d424044c81c81bf92a907cae095 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Sun, 21 Mar 2004 00:00:00 +0100 Subject: [PATCH 1/1] version 0.6 * no hard user limit anymore (dynamic table size) * alternate CSS themes * quarters support in top hours statistics * words/letters ranking * top words can be disabled to use less memory * old polish translation was restored --- CHANGELOG | 80 ++++++++++++++++ README | 2 +- data/pisg.css | 1 + irssistats.c | 226 +++++++++++++++++++++++++++++++++++++++------- sample.configfile | 18 +++- 5 files changed, 293 insertions(+), 34 deletions(-) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..ecb08b7 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,80 @@ +Change log file for irssistats + +version 0.6 (2004-03-21) + * no hard user limit anymore (dynamic table size) + * alternate CSS themes + * quarters support in top hours statistics + * words/letters ranking + * top words can be disabled to use less memory + * old polish translation was restored + +version 0.51 (2003-12-14) + * bugfixes and polish language updated (thank you Jakub Jankowski) + * "CHARSET" is now a language parameter + * Internet Explorer specific bugfix in themes + +version 0.5 (2003-12-07) + * configuration file + * it is now possible to build multiple stats in one run + * customizable header and footer + * now produces XHTML with CSS templates as suggested by some users + * "grayscale" and "pisg" theme were added + * italian support (thank you Coviello Giuseppe) + * dutch support and BSD include patch (thank you Jeroen Ubbink) + * patch nickmode (thank you Philipp Haegi) + +version 0.44 (2003-05-25) + * finnish support (thank you Antti Huopana) + * minor updates + +version 0.43 (2002-11-24) + * manpage was added + * increased number of users + * "blue" theme was added + * improved Makefile + +version 0.42 (2002-11-16) + * W3C validated HTML + * better quote selection during nick alias + * auto refresh (suggested by Charles Blackburn) + +version 0.41 (2002-10-19) + * polish support (thank you Piotr Jarmuz) + * you can now ignore some users + * improved Makefile + * the # in channel name is not imposed anymore (to support "&channels") + * number of total days are now displayed + +version 0.4 (2002-10-14) + * nick alias support using regular expression + * some code fix + +version 0.32 (2002-09-30) + * german support (thank you Valentin Gelhorn) + +version 0.31 (2002-09-01) + * spanish support (thank you Alex) + * minor code changes + * bugfix : division by 0 (thank you Qball) + * better random topics / urls algorithm + +version 0.3 (2002-05-29) + * top users by time of day + * some big numbers + * some new themes + * increased number of users + * better HTML output + +version 0.2 (2002-05-16) + * languages support (currently english and french) + * themes support + * most used words + * now handles personal messages and "/me" + * parameters on command line + * some code change + * faster + * no more image when 0 lines + * maximum height for graph is now calculated + +version 0.1 (2002-05-01) + * initial release \ No newline at end of file diff --git a/README b/README index 3e1adf0..53a1565 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -irssistats 0.51 +irssistats 0.6 site: http://royale.zerezo.com/irssistats/ mail: royale@zerezo.com diff --git a/data/pisg.css b/data/pisg.css index c306040..e4fb009 100644 --- a/data/pisg.css +++ b/data/pisg.css @@ -125,6 +125,7 @@ body { padding: 0; border: 0; font-size: 0; + margin: auto; } #irssistats div.h1 { diff --git a/irssistats.c b/irssistats.c index 7b5d209..7bb52cf 100644 --- a/irssistats.c +++ b/irssistats.c @@ -1,4 +1,27 @@ -/* Usage: irssistats [/path/to/file.conf] */ +/* + * irssistats version 0.6 + * + * This tool generates IRC stats based on irssi logs. + * Usage: irssistats [/path/to/file.conf] + * + * Copyright (C) 2002-2004 Antoine Jacquet + * http://royale.zerezo.com/irssistats/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include #include @@ -8,7 +31,7 @@ #include /* Config */ -#define MAXUSERS 10000 +#define BASEUSERS 1000 #define MAXNICKLENGTH 50 #define MAXLINELENGTH 2000 #define MAXQUOTELENGTH 100 @@ -20,7 +43,7 @@ #define MINWORDLENGTH 5 /* irssistats */ -#define VERSION "0.51" +#define VERSION "0.6" #define URL "http://royale.zerezo.com/irssistats/" /* Counters */ @@ -41,7 +64,7 @@ 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 8 +#define NBLANGUAGES 9 #define NBKEYS 39 char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and abbreviation */ { @@ -216,8 +239,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "C_MONOLOGUE", "Habla solo" } }, { /* Polish language */ - /* contributed by Piotr Jarmuz */ - /* updated by Jakub Jankowski */ + /* contributed by Jakub Jankowski */ { "Polish", "pl" }, { "CHARSET", "ISO-8859-2" }, { "HEADER", "Statystyki dla %s zebrane przez %s" }, @@ -259,6 +281,49 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "C_NICK", "czêsto zmienia nick" }, { "C_MONOLOGUE", "uwielbia monologi" } }, + { /* Polish language */ + /* contributed by Piotr Jarmuz */ + { "Polish", "pl-old" }, + { "CHARSET", "ISO-8859-1" }, + { "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" } + }, { /* Finnish language */ /* contributed by Antti Huopana */ { "Finnish", "fi" }, @@ -405,25 +470,30 @@ char *L(char *key) 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"; +char theme[MAXLINELENGTH]="default,blue,dark,grayscale,namour,pisg,zeduel,zerezo"; 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; +int top_words=1; /* 0 = disabled */ +int ranking=0; /* 0 = lines ; 1 = words ; 2 = letters */ +int quarter=0; /* 1 = enabled */ -struct +struct user { char nick[MAXNICKLENGTH]; int lines; + int words; int letters; int hours[4]; char quote[MAXQUOTELENGTH+1]; int counters[NBCOUNTERS]; int temp; -} users[MAXUSERS]; +} *users; int nbusers=0; +int maxusers=BASEUSERS; struct { @@ -447,7 +517,7 @@ struct } lastdays[31]; int days=0; -int hours[24]; +int hours[24*4]; int lines=0; struct letter @@ -464,13 +534,13 @@ struct #define isletter(c) (((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z'))) #define lowercase(c) (((c>='A')&&(c<='Z'))?c-'A'+'a':c) -void findwords(char *message) +int findwords(char *message) { - int i,c; + int i,c,n=0; struct letter *pos,*tmp; for (;;) { - while (!isletter(*message)) if (*message=='\0') return; else message++; + while (!isletter(*message)) if (*message=='\0') return n; else message++; pos=&words; while (isletter(*message)) { @@ -491,8 +561,9 @@ void findwords(char *message) message++; } pos->nb++; + n++; } - return; + return n; } char tempword[MAXLINELENGTH]; @@ -556,11 +627,17 @@ int dichotomic(char *nick) if (strcmp(nick,users[start].nick)!=0) { nbusers++; - if (nbusers>=MAXUSERS) { fprintf(stderr,"too many users\n"); exit(1); } + if (nbusers>=maxusers) + { + maxusers+=BASEUSERS; + if (debug==2) fprintf(stderr,"allocating more users : %d\n",maxusers); + if ((users=realloc(users,maxusers*sizeof(struct user)))==NULL) { fprintf(stderr,"too many users : unable to realloc memory\n"); exit(1); } + } for (i=nbusers-1;i>start;i--) { strcpy(users[i].nick,users[i-1].nick); users[i].lines=users[i-1].lines; + users[i].words=users[i-1].words; users[i].letters=users[i-1].letters; for (j=0;j<4;j++) users[i].hours[j]=users[i-1].hours[j]; strcpy(users[i].quote,users[i-1].quote); @@ -569,6 +646,7 @@ int dichotomic(char *nick) } strcpy(users[start].nick,nick); users[start].lines=0; + users[start].words=0; users[start].letters=0; for (j=0;j<4;j++) users[start].hours[j]=0; users[start].quote[0]='\0'; @@ -708,11 +786,17 @@ void parse_log(char *logfile) } j=strlen(message); users[i].lines++; + if (top_words || ranking==1) users[i].words+=findwords(message); users[i].letters+=j; users[i].hours[hour/6]++; lastdays[0].lines++; lastdays[0].hours[hour/6]++; lines++; + if (quarter) + { + line[5]='\0'; + hour=hour*4+atoi(&line[3])/15; + } hours[hour]++; if (message[j-1]=='?') users[i].counters[D_QUESTION]++; else if (message[j-1]=='!') users[i].counters[D_EXCLAM]++; @@ -736,7 +820,6 @@ void parse_log(char *logfile) strncpy(urls[temp].shorturl,message,MAXQUOTELENGTH); } } - findwords(message); } pos=0; } @@ -767,11 +850,13 @@ void parse_nick(char *nickfile) users[user].temp=users[i].temp; } users[user].lines+=users[i].lines; + users[user].words+=users[i].words; 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].words=-1; users[i].letters=-1; for (j=0;j<4;j++) users[i].hours[j]=-1; for (j=0;j\n\n",L("CHARSET")); if (refresh_time) fprintf(fic,"\n",refresh_time); - fprintf(fic,"\n",theme); + subtheme=strtok(theme,","); + fprintf(fic,"\n",subtheme,subtheme); + while ((subtheme=strtok(NULL,","))!=NULL) + fprintf(fic,"\n",subtheme,subtheme); fprintf(fic,"\n\n"); fprintf(fic,"\n\n"); } @@ -844,8 +934,14 @@ void gen_xhtml(char *xhtmlfile) /* top hours */ 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++) + for (i=0;i<24*4;i++) if (hours[i]>max) max=hours[i]; + if (quarter) for (i=0;i<24*4;i++) + { + fprintf(fic,"\n"); + } + else for (i=0;i<24;i++) { fprintf(fic,"\n\n"); for (i=0;i<24;i++) - fprintf(fic,"\n",i); + if (quarter) fprintf(fic,"\n",i); + else fprintf(fic,"\n",i); fprintf(fic,"\n
"); + if (hours[i]!=0) fprintf(fic,"
",i/4/6+1,150*hours[i]/max); + fprintf(fic,"
%.1f%%",lines!=0?(float)100*hours[i]/lines:0); if (hours[i]!=0) fprintf(fic,"
",i/6+1,150*hours[i]/max); @@ -853,25 +949,59 @@ void gen_xhtml(char *xhtmlfile) } fprintf(fic,"
%d%d%d
\n
\n\n"); /* top users */ fprintf(fic,"
\n

%s

\n",L("TOPUSERS")); - fprintf(fic,"\n\n",L("NICK"),L("NBLINES"),L("HOURS"),L("AVGLETTERS"),L("QUOTE")); + switch (ranking) + { + case 0: + fprintf(fic,"
%s%s%s%s%s
\n\n",L("NICK"),L("NBLINES"),L("HOURS"),L("AVGLETTERS"),L("QUOTE")); + break; + default: + /* "letters" and "words" ranking are not yet translated so we use the generic word "rank" ... */ + fprintf(fic,"
%s%s%s%s%s
\n\n",L("NICK"),"rank",L("HOURS"),L("AVGLETTERS"),L("QUOTE")); + break; + } for (i=1;i<=NBUSERS;i++) { user=-1; max=0; - for (j=0;jmax) max=users[user=j].lines; + switch (ranking) + { + case 0: + for (j=0;jmax) max=users[user=j].lines; + break; + case 1: + for (j=0;jmax) max=users[user=j].words; + break; + case 2: + for (j=0;jmax) max=users[user=j].letters; + break; + } if (user!=-1) { - fprintf(fic,"\n"); users[user].lines=-1; + users[user].words=-1; + users[user].letters=-1; } } fprintf(fic,"
%s%s%s%s%s
%d%s%d",i,users[user].nick,users[user].lines); + switch (ranking) + { + case 0: + fprintf(fic,"
%d%s%d",i,users[user].nick,users[user].lines); + break; + case 1: + fprintf(fic,"
%d%s%d",i,users[user].nick,users[user].words); + break; + case 2: + fprintf(fic,"
%d%s%d",i,users[user].nick,users[user].letters); + break; + } 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"); @@ -934,12 +1064,15 @@ void gen_xhtml(char *xhtmlfile) fprintf(fic,"\n
\n\n"); /* top words */ - fprintf(fic,"
\n

%s

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

%s

\n",L("TOPWORDS")); + fprintf(fic,"\n\n",L("WORD"),L("OCCURRENCES")); + for (i=0;i\n",i+1,topwords[i].word,topwords[i].nb); + fprintf(fic,"
%s%s
%d\"%s\"%d
\n
\n\n"); + } + /* big numbers */ fprintf(fic,"
\n

%s

\n",L("BIGNUMBERS")); fprintf(fic,"\n\n",L("NICK"),L("NUMBERS"),L("NBLINES")); @@ -1020,7 +1153,8 @@ void parse_config(char *configfile) 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 + } + else if (strcmp("channel",keyword)==0) { @@ -1112,14 +1246,43 @@ void parse_config(char *configfile) nburls=0; nbtopics=0; days=0; - for (i=0;i<24;i++) hours[i]=0; + for (i=0;i<24*4;i++) hours[i]=0; lines=0; freewords(&words); for (i=0;i
%s%s%s