Disregarding the current $time, here we go again (replace the lengthy recent code with this one)

; text event: add IPs announced in channel #admin to an ini-file
on $*:text:/^(\S+) \(ID\W\d+\)'s Ip is ((\d{1,3}\.){3}\d{1,3})\.$/:#admin: {
var %ini = $qt($shortfn($mircdirini\ips.ini)), %name = $replace($regml(1),[,$chr(40),],$chr(41))
; remove existing entry of that user and that ip
if ($ini(%ini,%name)) {
var %n = 1
while ($ini(%ini,%name,%n)) {
if ($readini(%ini,%name,$v1) == $regml(2)) {
remini -n %ini %name $ini(%ini,%name,%n)
break
}
inc %n
}
}
; and readd (updating the "timestamp") or simply add the data to to the ini
writeini -n %ini %name $ctime $regml(2)
}
; trigger in chan #CnR|LV to scan the database for ips (!ip <Name> [full]) or names (!ip <IP> [full])
on *:text:!ip*:#CnR|LV: {
var %ini = $qt($shortfn($mircdirini\ips.ini)), %name = $replace($2,[,$chr(40),],$chr(41))
var %reg = /^(?:\d{1,3}\.){3}\d{1,3}$/, %isIP = $iif($regex(%name,%reg),$true,$false)
; no match / error outputs
if (!$2) {
msg $chan No nickname/IP given. Use !ip <name> to get matching IPs, $&
or !ip <IP> to get matching names. You can use "full" as second parameter.
}
elseif (!$ini(%ini,0)) { msg $chan IP-database is empty. }
; scan for name matches
elseif (!%isIP) {
if (!$ini(%ini,%name,0)) { msg $chan No entry for Name $qt($2) found. }
; loop matches for player name
else {
var %t = $ini(%ini,%name,0), %ips = $+($chr(31),IPs used by $2,$chr(15),:)
while ((%t > 0) && ($ini(%ini,%name,%t))) {
var %stamp = $v1, %ip = $readini(%ini,%name,%stamp)
var %ips = %ips $iif(($3 == full),$+($chr(2),%ip,$chr(2)) $asctime(%stamp,(dd.mm.yy, HH:nn)),%ip)
; output of matches
if ($len(%ips) > 300) {
msg $chan $makestringIP(%ips)
var %ips
}
dec %t
}
if (%ips) { msg $chan $makestringIP($v1) }
}
}
; scan for IP matches
else {
var %reg = $+(/^\[|,$replace(%name,.,\.),$/), %tempini = $qt($shortfn($mircdirini\ipsTEMP.ini))
; filter the ini to a temporary ini, removing everything that's no ini topic or IP match
filter -ffcg %ini %tempini %reg
; replace the matched IP in the data part of ini items with the player name (ini topic)
var %n = 1
while ($ini(%tempini,%n)) {
var %topic = $v1
if ($ini(%tempini,%topic,1)) { writeini -n %tempini %topic $v1 %topic }
inc %n
}
; filter tempini to remove ini topics (no longer needed), sort it (get timestamps in order)
filter -ffcgxteu 1 61 %tempini %tempini ^\[
; no matches (no lines left)
if (!$read(%tempini,1)) { msg $chan No entry for IP %name found. }
; loop and output the filtered matches
else {
var %n = 1, %names = $+($chr(31),Names used on IP %name,$chr(15),:)
while ($read(%tempini,%n)) {
var %stamp = $gettok($v1,1,61), %player = $replace($gettok($v1,2,61),$chr(40),[,$chr(41),])
var %names = %names $iif(($3 == full),$+($chr(2),%player,$chr(2)) $asctime(%stamp,(dd.mm.yy, HH:nn)),%player)
if ($len(%names) > 300) {
msg $chan $makestringN(%names)
var %names
}
inc %n
}
if (%names) { msg $chan $makestringN(%names) }
.remove %tempini
}
}
}
; text formatting routines (output of !ip)
alias -l makestringIP { return $regsubex($1-,/(?<=\d\51|\d)\s/g,$+($chr(32),-,$chr(32))) }
alias -l makestringN { return $regsubex($1-,/(?<=\d\51)\s/g,$+($chr(32),-,$chr(32))) }
; text trigger for database cleanup: !cleanips <deadline>.
; (restricted to opped users at #CnR|LV)
on @*:text:!cleanips*:#CnR|LV: {
if (($2 !isnum) && ($duration($2-) > 0)) {
var %ini = $qt($shortfn($mircdirini\ips.ini))
msg $chan There are currently $ini(%ini,0) players in the database. $&
Start removing all IPs older than $duration($v1) ...
set -e %ips.c.duration $v1
set -e %ips.c.kept 0
set -e %ips.c.removed 0
; init the cleaning (filter through an alias)
if ($window(@ips.c)) { window -c @ips.c }
window -h @ips.c
filter -fk %ini clean.ips
filter -wfc @ips.c %ini
window -c @ips.c
; remove "dead" nick topics in the ini as well
var %n = 1
while ($ini(%ini,%n)) {
var %name = $v1
if (!$ini(%ini,%name,1)) { writeini -n %ini %name x y | remini -n %ini %name }
inc %n
}
msg $chan ... Done. IPs kept: %ips.c.kept • IPs removed: %ips.c.removed • $&
Players remaining in database: $ini(%ini,0) $+ .
unset %ips.c.*
}
else {
msg $chan Syntax is: !cleanips <deadline>
msg $chan e.g. "!cleanips 3d" will remove all entries older than 3 days; $&
"!cleanips 2 weeks 3 hrs"
}
}
; ip cleaning routine (filter-alias for !cleanips)
alias -l clean.ips {
if ($gettok($1,1,61) isnum) {
if ($v1 >= $calc($ctime - %ips.c.duration)) { aline @ips.c $1- | inc %ips.c.kept }
else { inc %ips.c.removed }
}
elseif ($1) { aline @ips.c $1- }
}
According to my tests it's working now as expected. Note that I was testing in a single channel (changing the #channels in the on text definition), but this shouldn't be an issue. And note that I act like the "bot" (the one with the script), while I use [Bot] to trigger the inputs :-)
[&Bot] •• !ip test
<~Horstl> IP-database is empty.
now I was first adding some IPs (10) and nicks (6)
[&Bot] •• Testnick (ID:123)'s Ip is 123.123.123.1.
[&Bot] •• Testnick (ID:123)'s Ip is 123.123.123.2.
[&Bot] •• {weird}|nick[x] (ID:77)'s Ip is 77.77.77.7.
[&Bot] •• Testnick (ID:123)'s Ip is 321.321.321.3.
[&Bot] •• {weird}|nick[x] (ID:77)'s Ip is 88.88.88.8.
[&Bot] •• XYZ (ID:5)'s Ip is 2.2.2.2.
[&Bot] •• {weird}|nick[x] (ID:77)'s Ip is 99.99.99.9.
[&Bot] •• Faker (ID:10)'s Ip is 321.321.321.3.
[&Bot] •• Faker2 (ID:11)'s Ip is 88.88.88.8.
[&Bot] •• Faker3 (ID:99)'s Ip is 321.321.321.3.
And started the testing...
<~Horstl> !ip testnick
[&Bot] •• !ip testnick
<~Horstl> IPs used by testnick: 321.321.321.3 - 123.123.123.2 - 123.123.123.1
[&Bot] •• !ip {weird}|nick[x]
<~Horstl> IPs used by {weird}|nick[x]: 99.99.99.9 - 88.88.88.8 - 77.77.77.7
[&Bot] •• !ip {weird}|nick[x] full
<~Horstl> IPs used by {weird}|nick[x]: 99.99.99.9 (02.11.08, 02:58) - 88.88.88.8 (02.11.08, 02:57) - 77.77.77.7 (02.11.08, 02:57)
[&Bot] •• !ip 88.88.88.8
<~Horstl> Names used on IP 88.88.88.8: Faker2 {weird}|nick[x]
[&Bot] •• !ip 88.88.88.8 full
<~Horstl> Names used on IP 88.88.88.8: Faker2 (02.11.08, 02:59) - {weird}|nick[x] (02.11.08, 02:57)
[&Bot] •• !ip 5.5.5.5
<~Horstl> No entry for IP 5.5.5.5 found.
[&Bot] •• !ip
<~Horstl> No nickname/IP given. Use !ip <name> to get matching IPs, or !ip <IP> to get matching names. You can use "full" as second parameter.
[&Bot] •• !ip Abc
<~Horstl> No entry for Name "Abc" found.
[&Bot] •• !ip Faker
<~Horstl> IPs used by Faker: 321.321.321.3
[&Bot] •• !ip Faker2
<~Horstl> IPs used by Faker2: 88.88.88.8
[&Bot] •• !cleanips 3hrs
<~Horstl> There are currently 6 players in the database. Start removing all IPs older than 3hrs ...
<~Horstl> ... Done. IPs kept: 10 • IPs removed: 0 • Players remaining in database: 6.
[&Bot] •• !cleanips 5mins
<~Horstl> There are currently 6 players in the database. Start removing all IPs older than 5mins ...
<~Horstl> ... Done. IPs kept: 5 • IPs removed: 5 • Players remaining in database: 5.
The only -minor- issue I found is the "players removed in database" info showing a "wrong" value due to strange /remini behaviour (It the ini topic holds no items, /remini refuses to remove the topic - I'm thus adding a dummy value in the cleaning procedure and /remove the topic right after, but sometimes this is failing, too). Repetitive cleaning will show the right count.