small irssistats localization patch
[irssistats] / irssistats.c
index 66522e8..9c924c9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * irssistats version 0.72
+ * irssistats version 0.75
  *
  * This tool generates IRC stats based on irssi logs.
  * Usage: irssistats [/path/to/file.conf]
@@ -49,7 +49,7 @@
 #define MINWORDLENGTH 5
 
 /* irssistats */
-#define VERSION "0.72"
+#define VERSION "0.75"
 #define URL "http://royale.zerezo.com/irssistats/"
 
 /* Counters */
@@ -71,7 +71,7 @@ char *counters[NBCOUNTERS]={"C_SMILE","C_FROWN","C_EXCLAM","C_QUESTION","C_ME","
 
 /* Languages */
 #define NBLANGUAGES 11
-#define NBKEYS 39
+#define NBKEYS 41
 char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and abbreviation */
 {
   { /* English language */
@@ -79,7 +79,9 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "CHARSET",      "ISO-8859-1" },
     { "HEADER",       "Statistics for %s by %s" },
     { "LEGEND",       "Legend" },
-    { "LASTDAYS",     "Lastdays statistics" },
+    { "LASTDAYS",     "Last days statistics" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Hourly statistics" },
     { "TOPUSERS",     "Most active people" },
     { "OTHERS",       "There are %d left not ranked..." },
@@ -122,6 +124,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Statistiques de %s par %s" },
     { "LEGEND",       "Légende" },
     { "LASTDAYS",     "Statistiques des derniers jours" },
+    { "LASTWEEKS",    "Statistiques des dernières semaines" },
+    { "LASTMONTHS",   "Statistiques des derniers mois" },
     { "TOPHOURS",     "Statistiques horaires" },
     { "TOPUSERS",     "Personnes les plus actives" },
     { "OTHERS",       "Il reste %d personnes non classées..." },
@@ -165,6 +169,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Statistiken für %s von %s" },
     { "LEGEND",       "Legende" },
     { "LASTDAYS",     "Statistik der letzten Tage" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Stündliche Statistik" },
     { "TOPUSERS",     "Die aktivsten Personen" },
     { "OTHERS",       "Es bleiben noch %d uneingetragene" },
@@ -192,7 +198,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "C_EXCLAM",     "schreit oft !" },
     { "C_QUESTION",   "stellt viele Fragen ?" },
     { "C_ME",         "mag /me'en" },
-    { "C_TOPIC",      "aendert oft das Topico" },
+    { "C_TOPIC",      "aendert oft das Topic" },
     { "C_MODE",       "aendert oft die Modes" },
     { "C_KICK",       "mag /kick'en" },
     { "C_KICKED",     "wird oft gekickt"},
@@ -208,6 +214,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Estadísticas de %s por %s" },
     { "LEGEND",       "Leyenda" },
     { "LASTDAYS",     "Estadísticas de los últimos días" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Estadísticas por horas" },
     { "TOPUSERS",     "Los que más escriben" },
     { "OTHERS",       "Hay %d más que no llegaron..." },
@@ -251,6 +259,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Statystyki dla %s zebrane przez %s" },
     { "LEGEND",       "Legenda" },
     { "LASTDAYS",     "Statystyki z ostatnich dni" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Statystyki godzinowe" },
     { "TOPUSERS",     "Najaktywniejsi" },
     { "OTHERS",       "Jest jeszcze %d nie sklasyfikowanych..." },
@@ -294,6 +304,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Statystyki dla %s przez %s" },
     { "LEGEND",       "Legenda" },
     { "LASTDAYS",     "Statystyki z ostatnich dni" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Statystyki godzinne" },
     { "TOPUSERS",     "Najaktywniejsi ludzie" },
     { "OTHERS",       "Zostalo jeszcze %d nie sklasyfikowanych..." },
@@ -337,6 +349,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Kanavan %s tilastot - %s" },
     { "LEGEND",       "Merkkien selitykset" },
     { "LASTDAYS",     "Viime päivien tilastot" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Tilastot tunneittain" },
     { "TOPUSERS",     "Aktiivisimmat ihmiset" },
     { "OTHERS",       "Jäljelle jäi %d joita ei listattu..." },
@@ -380,6 +394,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Statistiche per il canale %s di %s" },
     { "LEGEND",       "Legenda" },
     { "LASTDAYS",     "Statistiche degli ultimi giorni" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Statistiche in ore" },
     { "TOPUSERS",     "Utenti più attivi" },
     { "OTHERS",       "Ci sono %d utenti non classificati..." },
@@ -424,6 +440,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Statistieken voor %s door %s" },
     { "LEGEND",       "Legenda" },
     { "LASTDAYS",     "Statistieken van de laatste dagen" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Statistieken per uur" },
     { "TOPUSERS",     "Meest actieve mensen" },
     { "OTHERS",       "Er zijn nog %d mensen die de top niet haalden..." },
@@ -467,9 +485,11 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "óÔÁÔÉÓÔÉËÁ ÄÌÑ %s ÏÔ %s" },
     { "LEGEND",       "ïÂÏÚÎÁÞÅÎÉÑ" },
     { "LASTDAYS",     "óÔÁÔÉÓÔÉËÁ ÐÏÓÌÅÄÎÉÈ ÄÎÅÊ" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "ðÏÞÁÓÏ×ÁÑ ÓÔÁÔÉÓÔÉËÁ" },
     { "TOPUSERS",     "áËÔÉ×ÎÅÊÛÉÅ ÌÀÄÉ" },
-    { "OTHERS",       "ïÓÔÁÌÏÓØ %d ÎÅÐÏÄÓÞÉÔÁÎÙÈ..." },
+    { "OTHERS",       "ïÓÔÁÌÏÓØ %d ÎÅÐÏÄÓÞÉÔÁÎÎÙÈ..." },
     { "NBLINES",      "ÓÔÒÏËÉ" },
     { "NICK",         "ÎÉË" },
     { "AVGLETTERS",   "ÂÕË×Ù/ÓÔÒÏËÉ" },
@@ -484,12 +504,12 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "POSTEDURL",    "URL" },
     { "TOPWORDS",     "þÁÓÔÏ ÉÓÐÏÌØÚÕÅÍÙÅ ÓÌÏ×Á" },
     { "WORD",         "ÓÌÏ×Ï" },
-    { "OCCURRENCES",  "ÐÒÏÉÛÅÓÔ×ÉÑ" },
+    { "OCCURRENCES",  "ÐÒÏÉÓÛÅÓÔ×ÉÑ" },
     { "BIGNUMBERS",   "îÅÓËÏÌØËÏ ÂÏÌØÛÉÈ ÞÉÓÅÌ..." },
     { "NUMBERS",      "ÞÉÓÌÁ" },
     { "TIME",         "%d ÓÔÒÏË (%d ÄÎÅÊ) ÏÂÒÁÂÏÔÁÎÏ ÚÁ %d ÓÅËÕÎÄ" },
     { "FOOTER",       "óÔÁÔÉÓÔÉËÁ ÓÇÅÎÅÒÉÒÏ×ÁÎÁ" },
-    { "C_SMILE",      "ÞÁÓÔÏ ÓÞÁÓÌÉ× :)" },
+    { "C_SMILE",      "ÞÁÓÔÏ ÓÞÁÓÔÌÉ× :)" },
     { "C_FROWN",      "ÞÁÓÔÏ ÎÅÓÞÁÓÔÅΠ:(" },
     { "C_EXCLAM",     "ÍÎÏÇÏ ×ÏÓËÌÉÃÁÅÔ !" },
     { "C_QUESTION",   "ÚÁÄÁ£Ô ÍÎÏÇÏ ×ÏÐÒÏÓÏ× ?" },
@@ -510,6 +530,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "HEADER",       "Statistika kanalile %s on koostanud %s" },
     { "LEGEND",       "Legend" },
     { "LASTDAYS",     "Viimaste päevade statistika" },
+    { "LASTWEEKS",    "Last weeks statistics" },
+    { "LASTMONTHS",   "Last months statistics" },
     { "TOPHOURS",     "Tunni statistika" },
     { "TOPUSERS",     "Kõige aktiivsemad inimesed" },
     { "OTHERS",       "%d inimest on rääkinud" },
@@ -574,6 +596,8 @@ time_t debut;
 int top_words=1; /* 0 = disabled */
 int ranking=0; /* 0 = lines ; 1 = words ; 2 = letters */
 int quarter=0; /* 1 = enabled */
+int months=0; /* 1 = enabled */
+int weeks=0; /* 1 = enabled */
 int photo_size=60;
 
 struct user
@@ -610,9 +634,10 @@ struct
 {
   int lines;
   int hours[4];
-} lastdays[31];
+} lastdays[31], lastweeks[31], lastmonths[31];
 int days=0;
 char currday[16];
+int currwday=-1, currmon=-1;
 
 int hours[24*4];
 int lines=0;
@@ -862,6 +887,7 @@ void day_changed(char* date)
 {
   int i,j;
   char newday[16];
+  struct tm currdate;
 
   memcpy(newday, date, 11);
   if (date[13]==':')
@@ -886,6 +912,36 @@ void day_changed(char* date)
     memcpy(currday, newday, 15);
     if (debug==2)
       fprintf(stderr, "day %d changed to: %s\n", days, currday);
+    
+    /* try to parse the date for weeks/months stats */
+    if (strptime(currday, "%a %b %d %Y", &currdate))
+    {
+      /* each monday we change the week number */
+      if (currdate.tm_wday == 1)
+      {
+        for (i=30;i>0;i--)
+        {
+          lastweeks[i].lines=lastweeks[i-1].lines;
+          for (j=0;j<4;j++) lastweeks[i].hours[j]=lastweeks[i-1].hours[j];
+        }
+        lastweeks[0].lines=0;
+        for (j=0;j<4;j++) lastweeks[0].hours[j]=0;
+      }
+      /* if the month has changed */
+      if (currdate.tm_mon != currmon && currmon > 0)
+      {
+        for (i=30;i>0;i--)
+        {
+          lastmonths[i].lines=lastmonths[i-1].lines;
+          for (j=0;j<4;j++) lastmonths[i].hours[j]=lastmonths[i-1].hours[j];
+        }
+        lastmonths[0].lines=0;
+        for (j=0;j<4;j++) lastmonths[0].hours[j]=0;
+      }
+      currwday = currdate.tm_wday;
+      currmon = currdate.tm_mon;
+      
+    }
   } else {
     if (debug==2)
       fprintf(stderr, "but day did not change\n");
@@ -1041,6 +1097,8 @@ void parse_log(char *logfile)
             case '@':
             case '%':
             case '+':
+            case '&':
+            case '~':
             case ' ': 
               nickstart = timelen+2; 
               break;
@@ -1088,6 +1146,10 @@ void parse_log(char *logfile)
         users[i].hours[hour/6]++;
         lastdays[0].lines++;
         lastdays[0].hours[hour/6]++;
+        lastweeks[0].lines++;
+        lastweeks[0].hours[hour/6]++;
+        lastmonths[0].lines++;
+        lastmonths[0].hours[hour/6]++;
         lines++;
         if (quarter)
         {
@@ -1102,7 +1164,24 @@ void parse_log(char *logfile)
           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);
+        // Fetch a random message, messages between 25 and 70 chars are
+        // preferred (pisg-style, gets "better" quotes)
+        //
+        if (rand()%users[i].lines==0) {
+            
+            int len = strlen(message);
+            // if we have a "good" quote, use it
+            if ( len > 25 && len < 70 )
+            {
+                strncpy(users[i].quote,message,MAXQUOTELENGTH);
+            } else {
+                int len2 = strlen(users[i].quote);
+                if ( !(len2 > 25 && len2 < 70 )) {
+                    strncpy(users[i].quote,message,MAXQUOTELENGTH);
+                } 
+            }
+        } 
+
         if (strncmp("http://",message,7)==0)
         {
           users[i].counters[D_URL]++;
@@ -1214,7 +1293,8 @@ void gen_xhtml(char *xhtmlfile)
     fprintf(fic,"</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\" />\n",L("CHARSET"));
     if (refresh_time)
       fprintf(fic,"<meta http-equiv=\"Refresh\" content=\"%d\" />\n",refresh_time);
-    subtheme=strtok(theme,",");
+    strcpy(line, theme);
+    subtheme=strtok(line,",");
     fprintf(fic,"<link rel=\"stylesheet\" type=\"text/css\" href=\"%s.css\" title=\"%s\" />\n",subtheme,subtheme);
     while ((subtheme=strtok(NULL,","))!=NULL)
       fprintf(fic,"<link rel=\"alternate stylesheet\" type=\"text/css\" href=\"%s.css\" title=\"%s\" />\n",subtheme,subtheme);
@@ -1236,6 +1316,42 @@ void gen_xhtml(char *xhtmlfile)
   for (i=0;i<4;i++) fprintf(fic,"<td><div class=\"h%d\" style=\"width: 40px\"></div></td><td>%s %d-%d</td>\n",i+1,L("HOURS"),i*6,i*6+5);
   fprintf(fic,"</tr>\n</table>\n</div>\n\n");
   
+  if (months)
+  {
+    /* last months */
+    fprintf(fic,"<div id=\"irssistats_lastmonths\">\n<h2>%s</h2>\n<table>\n<tr>\n",L("LASTMONTHS"));
+    max=-1;
+    for (i=30;i>=0;i--) if (lastmonths[i].lines>max) max=lastmonths[i].lines;
+    for (i=30;i>=0;i--)
+    {
+      fprintf(fic,"<td align=\"center\" valign=\"bottom\"><small>%d</small>",lastmonths[i].lines);
+      for (j=0;j<4;j++) if (lastmonths[i].hours[j]!=0) fprintf(fic,"<div class=\"v%d\" style=\"height:%dpx\"></div>",j+1,150*lastmonths[i].hours[j]/max);
+      fprintf(fic,"</td>\n");
+    }
+    fprintf(fic,"</tr>\n<tr>\n");
+    for (i=30;i>=0;i--)
+      fprintf(fic,"<th>%d</th>\n",i);
+    fprintf(fic,"</tr>\n</table>\n</div>\n\n");
+  }
+  
+  if (weeks)
+  {
+    /* last weeks */
+    fprintf(fic,"<div id=\"irssistats_lastweeks\">\n<h2>%s</h2>\n<table>\n<tr>\n",L("LASTWEEKS"));
+    max=-1;
+    for (i=30;i>=0;i--) if (lastweeks[i].lines>max) max=lastweeks[i].lines;
+    for (i=30;i>=0;i--)
+    {
+      fprintf(fic,"<td align=\"center\" valign=\"bottom\"><small>%d</small>",lastweeks[i].lines);
+      for (j=0;j<4;j++) if (lastweeks[i].hours[j]!=0) fprintf(fic,"<div class=\"v%d\" style=\"height:%dpx\"></div>",j+1,150*lastweeks[i].hours[j]/max);
+      fprintf(fic,"</td>\n");
+    }
+    fprintf(fic,"</tr>\n<tr>\n");
+    for (i=30;i>=0;i--)
+      fprintf(fic,"<th>%d</th>\n",i);
+    fprintf(fic,"</tr>\n</table>\n</div>\n\n");
+  }
+  
   /* last days */
   fprintf(fic,"<div id=\"irssistats_lastdays\">\n<h2>%s</h2>\n<table>\n<tr>\n",L("LASTDAYS"));
   max=-1;
@@ -1430,9 +1546,10 @@ void gen_xhtml(char *xhtmlfile)
   if (logo) fprintf(fic,"<div class=\"logo\"></div>\n\n");
   
   /* end */
+  fprintf(fic,"</div>\n\n");
   if (strcmp("none",footer)==0)
   {
-    fprintf(fic,"</div>\n\n</body>\n\n</html>\n");
+    fprintf(fic,"</body>\n\n</html>\n");
   }
   else
   {
@@ -1444,25 +1561,25 @@ void gen_xhtml(char *xhtmlfile)
   fclose(fic);
 }
 
-void parse_config(char *configfile)
+void expand(char *path)
 {
-  void expand(char *path)
+  char temp[MAXLINELENGTH];
+  if (*path=='~')
   {
-    char temp[MAXLINELENGTH];
-    if (*path=='~')
-    {
-      snprintf(temp,MAXLINELENGTH-1,"%s%s",getenv("HOME"),path+1);
-      temp[MAXLINELENGTH-1]='\0';
-      strcpy(path,temp);
-    }
+    snprintf(temp,MAXLINELENGTH-1,"%s%s",getenv("HOME"),path+1);
+    temp[MAXLINELENGTH-1]='\0';
+    strcpy(path,temp);
   }
-  
+}
+
+void parse_config(char *configfile)
+{
   FILE *fic;
   char line[MAXLINELENGTH];
   char keyword[MAXLINELENGTH];
   char value[MAXLINELENGTH];
   int configlines=0;
-  int i;
+  int i,j;
   
   if (configfile!=NULL)
   {
@@ -1627,8 +1744,22 @@ void parse_config(char *configfile)
         nburls=0;
         nbtopics=0;
         days=0;
+        currwday=-1;
+        currmon=-1;
         for (i=0;i<24*4;i++) hours[i]=0;
         lines=0;
+        for (i=0;i<31;i++)
+        {
+          lastdays[i].lines=0;
+          lastweeks[i].lines=0;
+          lastmonths[i].lines=0;
+          for (j=0;j<4;j++)
+          {
+            lastdays[i].hours[j]=0;
+            lastweeks[i].hours[j]=0;
+            lastmonths[i].hours[j]=0;
+          }
+        }
         freewords(&words);
         freeruswords(&ruswords);
         for (i=0;i<NBWORDS;i++) topwords[i].nb=0;
@@ -1669,8 +1800,27 @@ void parse_config(char *configfile)
         else if (strcmp("yes",value)==0) quarter=1;
         else { fprintf(stderr,"unknown value for \"quarter\" option, must be \"yes\" or \"no\"\n"); exit(1); }
       }
-
-      else { fprintf(stderr,"error in config file : \"%s\" is an unknown keyword (line %d)\n",keyword,configlines); exit(1); }        
+      else
+      
+      if (strcmp("months",keyword)==0)
+      {
+        if (debug==2) fprintf(stderr,"setting months to \"%s\"\n",value);
+        if (strcmp("no",value)==0) months=0;
+        else if (strcmp("yes",value)==0) months=1;
+        else { fprintf(stderr,"unknown value for \"months\" option, must be \"yes\" or \"no\"\n"); exit(1); }
+      }
+      else
+      
+      if (strcmp("weeks",keyword)==0)
+      {
+        if (debug==2) fprintf(stderr,"setting weeks to \"%s\"\n",value);
+        if (strcmp("no",value)==0) weeks=0;
+        else if (strcmp("yes",value)==0) weeks=1;
+        else { fprintf(stderr,"unknown value for \"weeks\" option, must be \"yes\" or \"no\"\n"); exit(1); }
+      }
+      else
+      
+      { fprintf(stderr,"error in config file : \"%s\" is an unknown keyword (line %d)\n",keyword,configlines); exit(1); }        
     }
   }
   fclose(fic);
@@ -1679,7 +1829,6 @@ void parse_config(char *configfile)
 int main(int argc,char *argv[])
 {
   (void) setlocale(LC_ALL, "");
-  
   if ((users=malloc(maxusers*sizeof(struct user)))==NULL) { fprintf(stderr,"unable to malloc memory\n"); exit(1); }
   srand(debut=time(NULL));
   if (argc==1) parse_config(NULL);
@@ -1692,3 +1841,4 @@ int main(int argc,char *argv[])
   }
   return(0);
 }
+