stats (6868B)
1 #!/usr/bin/env zsh 2 # 3 # Jaro Mail, your humble and faithful electronic postman 4 # 5 # a tool to easily and privately handle your e-mail communication 6 # 7 # Copyleft (C) 2010-2014 Denis Roio <jaromil@dyne.org> 8 # 9 # This source code is free software; you can redistribute it and/or 10 # modify it under the terms of the GNU Public License as published by 11 # the Free Software Foundation; either version 3 of the License, or 12 # (at your option) any later version. 13 # 14 # This source code is distributed in the hope that it will be useful, 15 # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 # Please refer to the GNU Public License for more details. 18 # 19 # You should have received a copy of the GNU Public License along with 20 # this source code; if not, write to: 21 # Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23 24 25 stats() { 26 fn stats $* 27 28 # make index of all maildirs 29 notice "Computing statistics on stdin" 30 typeset -A count 31 num=0 32 33 case $1 in 34 35 # timecloud) timecloud ;; 36 37 # weeks) weeks ;; 38 39 domain*) 40 _domain="" 41 for i in "${(f)$(cat)}"; do 42 _domain=${i[(ws:@:)-1]/>/} 43 num=${count[$_domain]:-0} 44 count[$_domain]=$(( $num + 1 )) 45 done 46 47 ;; 48 49 email*) 50 _email="" 51 for i in "${(f)$(cat)}"; do 52 _email=${i[(ws:<:)2]/>/} 53 num=${count[$_email]:-0} 54 count[$_email]=$(( $num + 1 )) 55 done 56 ;; 57 58 name*) 59 _name="" 60 for i in "${(f)$(cat)}"; do 61 _name=${i[(ws:<:)1]//} 62 num=${count[$_name]:-0} 63 count[$_name]=$(( $num + 1 )) 64 done 65 ;; 66 67 folder*) 68 69 _folder="" 70 71 for i in `cat`; do 72 _folder=${i[(ws:/:)-3]} 73 74 # find maildir prefixes 75 # pfx="${_folder[(ws:.:)1]}" 76 # is it a new prefix? 77 num=${count[$_folder]:-0} 78 count[$_folder]=$(( $num + 1 )) 79 done 80 81 ;; 82 83 *) 84 error "Stats type not specified, available:" 85 error "domain, email, name, folder" 86 return 1 87 ;; 88 esac 89 90 # calculate screen size and bigger tot 91 maxtot=0 92 for x in ${(v)count}; do # find max 93 if [ $x -gt $maxtot ]; then 94 maxtot=$x; fi 95 done 96 97 for k in ${(k)count}; do 98 v=${count[$k]} 99 sbar="" 100 # Euclides: cols : x = maxtot : tot 101 cols=$(( $COLUMNS - 20 )) 102 bar=$(( $cols * $v )) 103 bar=$(( $bar / $maxtot )) 104 for b in {0..$bar}; do sbar="${sbar}#"; done 105 print " $v\t$sbar $k" 106 done 107 notice "Total: ${#count}" 108 109 110 return 0 111 } 112 113 weeks() { 114 id=$RANDOM 115 db=$TMPDIR/weekstats.db.$id 116 sql=$TMPDIR/weekstats.select.$id 117 list_maildirs 118 notice "Computing weekly statistics on ${#maildirs} maildirs" 119 func "Creating temporary database" 120 cat <<EOF | ${SQL} -batch $db 121 CREATE TABLE stats 122 ( 123 date text nocase, 124 ml text collate nocase, 125 hits int 126 ); 127 EOF 128 { test $? != 0 } && { 129 error "Error creating temporary week stats database." 130 return 1 } 131 132 act "gathering timestamps..." 133 for m in ${maildirs}; do 134 func " ${m}" 135 rm -rf $TMPDIR/weekstats.db.mdir 136 cp -r $MAILDIRS/${m} $TMPDIR/weekstats.db.mdir 137 for f in `${=find} $TMPDIR/weekstats.db.mdir -type f`; do 138 timestamp=`fetchdate ${f} "%Y-%U"` 139 mdir="${m[(ws:.:)1]}" 140 cat <<EOF | ${SQL} -batch $db > $sql 141 SELECT * FROM stats 142 WHERE ml IS "${mdir}" AND date IS "${timestamp}"; 143 EOF 144 res=`cat $sql` 145 if [ "$res" = "" ]; then 146 # new tag 147 cat <<EOF | ${SQL} -batch $db 148 INSERT INTO stats (date, ml, hits) 149 VALUES ("${timestamp}", "${mdir}", 1); 150 EOF 151 else 152 cat <<EOF | ${SQL} -batch $db 153 UPDATE stats SET hits = hits + 1 154 WHERE ml IS "${mdir}" AND date IS "${timestamp}"; 155 EOF 156 fi 157 done 158 done 159 # render results from the database 160 act "rendering results..." 161 162 table=$WORKDIR/.stats/jaromail.html 163 ${=mkdir} $WORKDIR/.stats 164 165 cat <<EOF > $table 166 <table > 167 <caption>Jaro Mail weekly statistics</caption> 168 <thead> 169 <tr> 170 <td></td> 171 EOF 172 typeset -al week 173 cat <<EOF | ${SQL} -batch $db > $sql 174 SELECT date FROM stats ORDER BY date; 175 EOF 176 for w in `cat $sql | uniq`; do 177 week+=($w) 178 print "<th scope=\"col\">${w}</th>" >> $table 179 done 180 cat <<EOF >> $table 181 </tr> 182 </thead> 183 <tbody> 184 185 EOF 186 prevmdir="" 187 for m in ${maildirs}; do 188 mdir="${m[(ws:.:)1]}" 189 # skip duplicates 190 if [ "$prevmdir" = "$mdir" ]; then continue 191 else prevmdir=$mdir; fi 192 193 print -n "<tr><th scopre=\"row\">$mdir</th>" >> $table 194 for w in ${week}; do 195 cat <<EOF | ${SQL} -batch $db > $sql 196 SELECT hits FROM stats 197 WHERE ml IS "${mdir}" AND date IS "${w}"; 198 EOF 199 sum=0 200 for h in `cat $sql`; do 201 sum=$(( $sum + $h )) 202 done 203 print -n "<td>$sum</td>" >> $table 204 done 205 print "</tr>" >> $table 206 done 207 208 cat <<EOF >> $table 209 </tbody> 210 </table> 211 EOF 212 cp $WORKDIR/.stats/visualize/header.html \ 213 $WORKDIR/.stats/index.html 214 cat $table >> $WORKDIR/.stats/index.html 215 print "</body>\n</html>\n" >> $WORKDIR/.stats/index.html 216 } 217 218 timecloud() { 219 id=$RANDOM 220 list_maildirs 221 notice "Computing timecloud statistics on ${#maildirs} maildirs" 222 func "Creating temporary database" 223 cat <<EOF | ${SQL} -batch $TMPDIR/timecloud.db.$id 224 CREATE TABLE stats 225 ( 226 date text collate nocase, 227 tag text collate nocase, 228 hits int 229 ); 230 EOF 231 { test $? != 0 } && { 232 error "Error creating temporary timecloud database." 233 return 1 } 234 235 for m in ${maildirs}; do 236 for f in `${=find} $MAILDIRS/${m} -type f`; do 237 timestamp=`fetchdate ${f} "%Y-%m-%d"` 238 cat <<EOF | ${SQL} -batch $TMPDIR/timecloud.db.$id > $TMPDIR/timecloud.select.$id 239 SELECT * FROM stats 240 WHERE tag IS "${m}" AND date IS "${timestamp}"; 241 EOF 242 res=`cat $TMPDIR/timecloud.select.$id` 243 if [ "$res" = "" ]; then 244 # new tag 245 cat <<EOF | ${SQL} -batch $TMPDIR/timecloud.db.$id 246 INSERT INTO stats (date, tag, hits) 247 VALUES ("${timestamp}", "${m}", 1); 248 EOF 249 else 250 cat <<EOF | ${SQL} -batch $TMPDIR/timecloud.db.$id 251 UPDATE stats SET hits = hits + 1 252 WHERE tag IS "${m}" AND date IS "${timestamp}"; 253 EOF 254 fi 255 done 256 done 257 # gather results from the database 258 cat <<EOF | ${SQL} -batch $TMPDIR/timecloud.db.$id > $TMPDIR/timecloud.results.$id 259 .separator \t 260 SELECT * FROM stats ORDER BY date; 261 EOF 262 # format the results into a JSON string 263 awk 'BEGIN { date=0; printf "[" } 264 { if(date != $1) { 265 if( date != 0 ) printf "]]," 266 date=$1 267 printf "[\"" date "\",[" 268 printf "[\"" $2 "\",\"" $3 "\"]" 269 } else { 270 printf ",[\"" $2 "\",\"" $3 "\"]" 271 } 272 } 273 END { print "]]];" } 274 ' $TMPDIR/timecloud.results.$id > $TMPDIR/timecloud.json.$id 275 ${=mkdir} $WORKDIR/timecloud 276 cat <<EOF > $WORKDIR/timecloud/jaromail.js 277 var jaromail=`cat $TMPDIR/timecloud.json.$id` 278 EOF 279 rm $TMPDIR/timecloud.*.$id 280 }