;; ============================================================================ ;; RegFix - regular-voicer for AdiIRC / mIRC ;; Auto +v's channel regulars on join, scored by DISTINCT DAYS SEEN. ;; Multi-channel. Per-channel right-click enable/disable. Per-channel logging. ;; Disabled = keeps scoring + logging, just stops auto-voicing. ;; Data: \RegFix\ (one .hsh file per channel + regfix.ini config) ;; ;; Quick start: ;; 1) Load this script. ;; 2) Right-click in a channel -> RegFix -> "Start tracking here". ;; 3) Right-click -> RegFix -> "Set log channel..." ;; 4) (optional) set the voice threshold; default is 7 distinct days. ;; ============================================================================ ;; ----- storage / config helpers -------------------------------------------- alias -l rf.dir { var %d = $+($mircdir,RegFix\) if (!$isdir(%d)) mkdir %d return %d } alias -l rf.cfg return $+($rf.dir,regfix.ini) alias -l rf.safe return $regsubex($1,/[^a-z0-9]/gi,$null) alias -l rf.datafile return $+($rf.dir,data-,$rf.safe($1),.hsh) alias -l rf.table return $+(rf.tbl.,$rf.safe($1)) alias -l rf.open { var %t = $rf.table($1) if (!$hget(%t)) { hmake %t 100 if ($isfile($rf.datafile($1))) hload %t $rf.datafile($1) } return %t } alias -l rf.saveone { if ($hget($rf.table($1))) hsave $rf.table($1) $rf.datafile($1) } alias -l rf.saveall { var %i = 1 while (%i <= $ini($rf.cfg,0)) { rf.saveone $ini($rf.cfg,%i) inc %i } } ;; ----- per-channel config getters ------------------------------------------ alias -l rf.tracked return $iif($readini($rf.cfg,n,$1,tracked) == 1,1,0) alias -l rf.enabled return $iif($readini($rf.cfg,n,$1,enabled) == 1,1,0) alias -l rf.logchan return $readini($rf.cfg,n,$1,logchan) alias -l rf.threshold { var %v = $readini($rf.cfg,n,$1,threshold) return $iif(%v isnum,%v,7) } ;; ----- record field helpers (tab-delimited) -------------------------------- ;; 1 nick | 2 ident@host | 3 ip(or -) | 4 days | 5 firstday | 6 lastday ;; 7 lastseen(ctime) | 8 flag(normal/force/never) alias -l rf.fld return $gettok($1,$2,9) alias -l rf.setfld return $puttok($1,$3,$2,9) alias -l rf.mkrec return $+($1,$chr(9),$2,$chr(9),$3,$chr(9),$4,$chr(9),$5,$chr(9),$6,$chr(9),$7,$chr(9),$8) alias -l rf.today return $int($calc($ctime / 86400)) alias -l rf.idh { var %u = $ial($1).user, %h = $ial($1).host if (%h != $null) return $+(%u,@,%h) var %a = $address($1,6) if (%a) return $gettok(%a,2,33) return $null } alias -l rf.isip { if ($regex($1,/^(\d{1,3}\.){3}\d{1,3}$/)) return $true if ($regex($1,/^[0-9a-f:]+:[0-9a-f:]+$/i)) return $true return $false } alias -l rf.nextid { var %t = $rf.open($1), %id = $hget(%t,nextid) if (%id == $null) %id = 1 hadd %t nextid $calc(%id + 1) return %id } ;; ----- find an existing record by nick OR host OR ip (exact) ---------------- alias -l rf.find { ; $1 chan $2 nick $3 ident@host $4 ip(optional) var %t = $rf.open($1), %i = 1, %tot = $hget(%t,0).item while (%i <= %tot) { var %k = $hget(%t,%i).item if (%k != nextid) { var %rec = $hget(%t,%k) if (($2 != $null) && ($rf.fld(%rec,1) == $2)) return %k if (($3 != $null) && ($rf.fld(%rec,2) == $3)) return %k if (($4 != $null) && ($rf.fld(%rec,3) != -) && ($rf.fld(%rec,3) == $4)) return %k } inc %i } return $null } ;; ----- credit a day (create or update). Returns record id ------------------ alias -l rf.credit { ; $1 chan $2 nick $3 ident@host $4 ip(optional) if (!$rf.tracked($1)) return var %t = $rf.open($1), %ip = $iif($4 != $null,$4,-) var %id = $rf.find($1,$2,$3,$iif(%ip != -,%ip,$null)), %today = $rf.today if (%id == $null) { %id = $rf.nextid($1) hadd %t %id $rf.mkrec($2,$3,%ip,1,%today,%today,$ctime,normal) rf.saveone $1 rf.log $1 New entry: $2 ( $+ $3 $+ ) - day 1 return %id } var %rec = $hget(%t,%id) %rec = $rf.setfld(%rec,1,$2) %rec = $rf.setfld(%rec,2,$3) if (%ip != -) %rec = $rf.setfld(%rec,3,%ip) %rec = $rf.setfld(%rec,7,$ctime) if (%today > $rf.fld(%rec,6)) { var %days = $calc($rf.fld(%rec,4) + 1) %rec = $rf.setfld(%rec,4,%days) %rec = $rf.setfld(%rec,6,%today) hadd %t %id %rec rf.saveone $1 if (%days == $rf.threshold($1)) rf.log $1 $2 reached %days days - now a regular (threshold $rf.threshold($1)) } else hadd %t %id %rec return %id } ;; ----- logging to the per-channel back-channel ------------------------------ alias -l rf.log { var %lc = $rf.logchan($1) if (%lc == $null) return if ($me ison %lc) msg %lc [RegFix $1] $2- else echo -a [RegFix $1] (log %lc offline) $2- } ;; ----- events --------------------------------------------------------------- on *:JOIN:#: { if ($nick == $me) return if (!$rf.tracked($chan)) return var %idh = $rf.idh($nick) if (%idh == $null) return var %host = $gettok(%idh,2,64) var %ip = $iif($rf.isip(%host),%host,$null) var %id = $rf.credit($chan,$nick,%idh,%ip) var %rec = $hget($rf.table($chan),%id), %flag = $rf.fld(%rec,8) if (%flag == never) return if (!$rf.enabled($chan)) return if (!$me isop $chan) return if (%flag == force) || ($rf.fld(%rec,4) >= $rf.threshold($chan)) { if ($left($nick($chan,$nick).pnick,1) !isin $+(~,&,@,%,+)) { .timer 1 1 mode $chan +v $nick rf.log $chan Voiced $nick ( $+ $rf.fld(%rec,4) days, flag %flag $+ ) } } } ;; periodic sweep: credits everyone currently present (catches users who were ;; here before the script loaded, and midnight roll-overs). Scoring only. alias -l rf.scan { var %ci = 1 while (%ci <= $chan(0)) { var %c = $chan(%ci) if ($rf.tracked(%c)) { var %ni = 1 while (%ni <= $nick(%c,0)) { var %n = $nick(%c,%ni), %idh = $rf.idh(%n) if (%idh != $null) { var %host = $gettok(%idh,2,64) rf.credit %c %n %idh $iif($rf.isip(%host),%host,$null) } inc %ni } } inc %ci } } alias -l rf.starttimer { .timerRegFix off .timerRegFix 0 1800 rf.scan } on *:START:rf.starttimer on *:LOAD:{ rf.starttimer | echo -a [RegFix] Loaded. Right-click a channel -> RegFix -> Start tracking here. } on *:UNLOAD:rf.saveall on *:EXIT:rf.saveall ;; ----- actions used by the menus ------------------------------------------- alias -l rf.track { if ($2 == 1) { writeini $rf.cfg $1 tracked 1 if ($readini($rf.cfg,n,$1,enabled) == $null) writeini $rf.cfg $1 enabled 1 if ($readini($rf.cfg,n,$1,threshold) == $null) writeini $rf.cfg $1 threshold 7 rf.open $1 echo -a [RegFix] Now tracking $1 $+ . Set a log channel via the menu. rf.log $1 Tracking started by $me } else { writeini $rf.cfg $1 tracked 0 echo -a [RegFix] Stopped tracking $1 (data kept). rf.log $1 Tracking stopped by $me } } alias -l rf.toggleenable { if ($rf.enabled($1)) { writeini $rf.cfg $1 enabled 0 echo -a [RegFix] Auto-voice DISABLED for $1 (still scoring). rf.log $1 Auto-voice disabled by $me } else { writeini $rf.cfg $1 enabled 1 echo -a [RegFix] Auto-voice ENABLED for $1 $+ . rf.log $1 Auto-voice enabled by $me } } alias -l rf.setlog { var %c = $input(Log / back-channel for $1 (include the #):,e,RegFix Setup) if (%c != $null) { writeini $rf.cfg $1 logchan %c echo -a [RegFix] Log channel for $1 set to %c rf.log $1 Log channel set to %c by $me } } alias -l rf.setthreshold { var %v = $input(Distinct days seen before auto-voicing in $1 :,e,RegFix Setup,$rf.threshold($1)) if (%v isnum) { writeini $rf.cfg $1 threshold $int(%v) echo -a [RegFix] Voice threshold for $1 set to $int(%v) days. rf.log $1 Voice threshold set to $int(%v) by $me } } alias -l rf.showscore { var %idh = $rf.idh($2), %host = $gettok(%idh,2,64) var %id = $rf.find($1,$2,%idh,$iif($rf.isip(%host),%host,$null)) if (%id == $null) { echo -a [RegFix] No record for $2 in $1 $+ . | return } var %rec = $hget($rf.table($1),%id) echo -a [RegFix] $2 in $1 : $rf.fld(%rec,4) days | flag: $rf.fld(%rec,8) | last seen: $asctime($rf.fld(%rec,7),mmm d HH:nn) | host: $rf.fld(%rec,2) } alias -l rf.remove { var %idh = $rf.idh($2), %host = $gettok(%idh,2,64) var %id = $rf.find($1,$2,%idh,$iif($rf.isip(%host),%host,$null)) if (%id == $null) { echo -a [RegFix] No record for $2 in $1 $+ . | return } hdel $rf.table($1) %id rf.saveone $1 echo -a [RegFix] Removed $2 from $1 scores. rf.log $1 Removed $2 from scores by $me } alias -l rf.setflag { ; $1 chan $2 nick $3 flag(normal/force/never) var %t = $rf.open($1), %idh = $rf.idh($2), %host = $gettok(%idh,2,64) var %id = $rf.find($1,$2,%idh,$iif($rf.isip(%host),%host,$null)) if (%id == $null) { %id = $rf.nextid($1) var %today = $rf.today hadd %t %id $rf.mkrec($2,%idh,$iif($rf.isip(%host),%host,-),0,%today,0,$ctime,$3) } else hadd %t %id $rf.setfld($hget(%t,%id),8,$3) rf.saveone $1 echo -a [RegFix] $2 flag set to $3 in $1 $+ . rf.log $1 $2 flag set to $3 by $me } alias -l rf.top { var %t = $rf.open($1), %i = 1, %tot = $hget(%t,0).item, %list while (%i <= %tot) { var %k = $hget(%t,%i).item if (%k != nextid) { var %rec = $hget(%t,%k) if (%list != $null) %list = %list $+ $chr(59) %list = %list $+ $rf.fld(%rec,4) $rf.fld(%rec,1) [ $+ $rf.fld(%rec,8) $+ ] } inc %i } %list = $sorttok(%list,59,nr) echo -a [RegFix] Top regulars in $1 (threshold $rf.threshold($1) days): var %j = 1 while (%j <= 20) && (%j <= $numtok(%list,59)) { echo -a [RegFix] $+ $chr(32) $gettok(%list,%j,59) days inc %j } } alias -l rf.purge { ; remove records whose lastseen is older than $2 days (force-flagged kept) var %t = $rf.open($1), %cut = $calc($ctime - ($2 * 86400)), %i = 1, %tot = $hget(%t,0).item, %kill while (%i <= %tot) { var %k = $hget(%t,%i).item if (%k != nextid) { var %rec = $hget(%t,%k) if (($rf.fld(%rec,7) < %cut) && ($rf.fld(%rec,8) != force)) %kill = $addtok(%kill,%k,59) } inc %i } var %j = 1 while (%j <= $numtok(%kill,59)) { hdel %t $gettok(%kill,%j,59) | inc %j } rf.saveone $1 echo -a [RegFix] Purged $numtok(%kill,59) entries (inactive > $2 d) in $1 $+ . if ($numtok(%kill,59) > 0) rf.log $1 Purged $numtok(%kill,59) inactive entries (> $2 d) by $me } ;; ----- menus ---------------------------------------------------------------- menu channel { - RegFix .$iif(!$rf.tracked($chan),Start tracking here):rf.track $chan 1 .$iif($rf.tracked($chan),$iif($rf.enabled($chan),$style(1)) Auto-voice regulars):rf.toggleenable $chan .$iif($rf.tracked($chan),Set log channel...):rf.setlog $chan .$iif($rf.tracked($chan),Set voice threshold...):rf.setthreshold $chan .$iif($rf.tracked($chan),Show top regulars):rf.top $chan .$iif($rf.tracked($chan),-) .$iif($rf.tracked($chan),Save scores now):rf.saveall .$iif($rf.tracked($chan),Purge inactive (90d+)):rf.purge $chan 90 .$iif($rf.tracked($chan),Stop tracking (keep data)):rf.track $chan 0 } menu nicklist { - RegFix .$iif($rf.tracked($chan),Score for $1):rf.showscore $chan $1 .$iif($rf.tracked($chan),Voice now):mode $chan +v $1 .$iif($rf.tracked($chan),Remove from scores):rf.remove $chan $1 .$iif($rf.tracked($chan),-) .$iif($rf.tracked($chan),Force voice (always)):rf.setflag $chan $1 force .$iif($rf.tracked($chan),Never voice):rf.setflag $chan $1 never .$iif($rf.tracked($chan),Clear flag (normal)):rf.setflag $chan $1 normal }