;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TOPICEXEC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;info: ; ; by wiebe @ QuakeNet ; version 1.0 (written and tested on mIRC 6.14) ; ; ; last edit: Sun Feb 29 2004 ; ; ;What does this script do? ; ; gets the topic, who set it and when it was set and returns this to an alias ; ; ;How to use this script? ; ; /topicexec [-cpuN] [params] ; to request the topic for channel and send the info to alias ; ; the -c switch will clear the queue, can be used with or without parameters ; /topicexec -c or /topicexec -c [params] ; would clear the queue first, then add the items ; ; the -p switch means passive, the script will not request the topic for the channel ; but will perform the specified alias when it gets the topic from the server ; usefull for example when joining a channel, the server sends the topic, ; you do not have to request it in that case ; ; the -uN switch can be used to place the item N seconds in the queue, ; if the topic is not requested or received before that ; the item is dropped ; ; the script sends the following things to the alias: ; ; 333 ; channel, from where the topic is ; nick, who set the topic ; ctime, when the topic was set ; topic, the topic itself ; ; 422 You're not on that channel ; this means you can not see the topic because you are not on it and chanmode s is set ; ; 331 No topic is set ; this means no topic is set on the channel ; ; 403 No such channel ; this means that channel does not exist ; ; the script uses a queue to send the request as much together as possible ; with /TOPIC chan1,chan2,chan3,chanN ; TOPIC requests are send out with a delay specified below ; ; $topicexec(channel) ; can be used for channels that you are on, returns ; you can get specific parts with the by, ctime and topic property ; $topicexec(channel).by $topicexec(channel).ctime $topicexec(channel).topic ; the last one is just the same as $chan(channel).topic ; ; ; ; WARNING: DO NOT USE HALT IN AN ALIAS, USE RETURN! ; halt also halts the calling alias/event, return only stops the current alias ; and gives control back to the calling alias/event ; using halt in alias'es that are called from this script can cause it not to work 100% ; ; example script included at end of script ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.DELAY ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; alias -l topicexec.delay { ; topicexec will start after N seconds when being used ; if you are not sure about this, leave it !return 1 } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.RESTART ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; alias -l topicexec.restart { ; topicexec will wait N seconds between TOPIC requests ; if you are not sure about this, leave it !return 5 } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.MAXLITEMS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; alias -l topicexec.maxitems { ; script does not request the topic for more then N channels at once ; /topic ; if you are not sure about this, leave it !return 50 } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.MAXLEN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; alias -l topicexec.maxlen { ; max length of the /topic request ; a too long line may cause the server to ignore the command ; 300 should be a good default number ; the script does /topic never longer then N chars ; if you are not sure about this, leave it !return 300 } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; /topicexec [-cpuN] [params..] alias topicexec { ; we are connected if ($status == connected) { ; used as identifier if ($isid) && ($me ison $1) && ($hget($+(topicexec.,$cid,.topicsave),$topicexec.lower($1))) { !var %info = $ifmatch if ($prop == by) { !return $gettok(%info,1,32) } if ($prop == ctime) { !return $gettok(%info,2,32) } if ($prop == topic) { !return $chan($1).topic } !return %info $chan($1).topic } ; not used as identifier else { ; $2 or $1 starts with a - and $3 is there if ($iif($left($1,1) == -,$3,$2)) { !var %p, %u ; 1st word starts with a - if ($left($1,1) == -) { ; p isin '$1' if (p isin $1) { !var %p = 1 } ; c isin '$1' if (c isin $1) { ; clear the queue $topicexec.queue($+(topicexec.queue.,$cid)).clear ; if item hash table exists, free the hash table if ($hget($+(topicexec.queue.,$cid,.item))) { !hfree $+(topicexec.queue.,$cid,.item) } } ; u isin $1 and $1 without -, c, u and p is greater then 0 if (u isin $1) && ($remove($1,p,u,c,-) > 0) { !var %u = $+(-u,$remove($1,p,u,c,-)) } !tokenize 32 $2- } ; we got at least 2 parameters, else return if ($0 <= 1) { !return } !var %x = $numtok($1,44) ; loop as long as '%x' is greater then 0 while (%x) { if ($left($gettok($1,%x,44),1) isin $chantypes) { ; passive switch is not used, add to queue if (!%p) { topicexec.queue $+(topicexec.queue.,$cid) $topicexec.lower($gettok($1,%x,44)) } ; passive switch is used, enable group else { .!enable #topicexec } ; check if '$topicexec.lower($gettok($1,%x,44)) $2-' is not already in the hash table, increase and add if (!$hfind($+(topicexec.queue.,$cid,.item),$topicexec.lower($gettok($1,%x,44)) $2-,0).data) { !hinc -m $+(topicexec.queue.,$cid,.item) last !hadd %u $+(topicexec.queue.,$cid,.item) $hget($+(topicexec.queue.,$cid,.item),last) $topicexec.lower($gettok($1,%x,44)) $1- } } !dec %x } ; check if the timer does not already run, start timer if (!$timer($+($cid,.topicexec))) && (!%p) { .!timer $+ $cid $+ .topicexec 1 $$topicexec.delay topicexec.dump } } } } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.DUMP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; alias -l topicexec.dump { !var %topic = $topicexec.queue($+(topicexec.queue.,$cid,.lo)).next, %l = $len(%topic) ; loop as long as there are items in the queue and length of '%topic' is smaller or equal to the value defined above, number of nicks is lower then defined above while ($topicexec.queue($+(topicexec.queue.,$cid)).size > 0) && (%l <= $$topicexec.maxlen) && ($numtok(%topic,44) < $$topicexec.maxitems) { !var %next = $topicexec.queue($+(topicexec.queue.,$cid)).next ; check if '%next' is in the hash table if ($hfind($+(topicexec.queue.,$cid,.item),%next *,0,w).data) { !inc %l $len(%next) if (%l > $$topicexec.maxlen) { topicexec.queue $+(topicexec.queue.,$cid,.lo) %next !break } !var %topic = $addtok(%topic,%next,44) } } ; '%topic' contains something, enable group, request topic if (%topic) { .!enable #topicexec .!quote TOPIC %topic } ; there are items left in the normal queue or remote queue, start timer if ($topicexec.queue($+(topicexec.queue.,$cid)).size > 0) || ($topicexec.queue($+(topicexec.queue.,$cid,.lo)).size > 0) { .!timer $+ $cid $+ .topicexec 1 $$topicexec.restart topicexec.dump } } ; start of '#topicexec' group #topicexec off ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RAW 332 TOPIC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;raw 332 me chan :topic raw 332:& & *:{ ; check hash table, add topic to hash table if ($hfind($+(topicexec.queue.,$cid,.item),$topicexec.lower($2) *,0,w).data > 0) { !hadd -m $+(topicexec.,$cid,.topic) $topicexec.lower($2) $3- !haltdef } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RAW 333 TOPIC NICK CTIME ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;raw 333 me chan nick time raw 333:& & & &:{ ; check hash table if ($hfind($+(topicexec.queue.,$cid,.item),$topicexec.lower($2) *,0,w).data) { !var %chan = $topicexec.lower($2) ; loop, send info to alias, remove from hash table while ($hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) { !var %t = $hget($+(topicexec.queue.,$cid,.item),$hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) $gettok(%t,3-,32) 333 $gettok(%t,2,32) $3-4 $hget($+(topicexec.,$cid,.topic),%chan) !hdel $+(topicexec.queue.,$cid,.item) $hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data } ; check hash table, free hash table if ($hget($+(topicexec.queue.,$cid,.item),0).item == 1) { !hfree $+(topicexec.queue.,$cid,.item) } ; remove from hash table !hdel $+(topicexec.,$cid,.topic) %chan ; check hash table, free hash table if ($hget($+(topicexec.,$cid,.topic),0).item == 0) { !hfree $+(topicexec.,$cid,.topic) } ; on channel $2, add info to hash table if ($me ison $2) { !hadd -m $+(topicexec.,$cid,.topicsave) $topicexec.lower($2) $3 $4 } !haltdef topicexec.disable } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RAW 331 NO TOPIC IS SET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;raw 331 me chan :No topic is set. raw 331:& & No topic is set*:{ ; check hash table if ($hfind($+(topicexec.queue.,$cid,.item),$topicexec.lower($2) *,0,w).data) { !var %chan = $topicexec.lower($2) ; loop, send info to alias, remove from hash table while ($hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) { !var %t = $hget($+(topicexec.queue.,$cid,.item),$hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) $gettok(%t,3-,32) 331 $gettok(%t,2,32) No topic is set !hdel $+(topicexec.queue.,$cid,.item) $hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data } ; check hash table, free hash table if ($hget($+(topicexec.queue.,$cid,.item),0).item == 1) { !hfree $+(topicexec.queue.,$cid,.item) } !haltdef topicexec.disable } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RAW 442 NOT ON CHANNEL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; raw 442 me chan :You're not on that channel raw 442:& & You're not on that channel:{ ; check hash table if ($hfind($+(topicexec.queue.,$cid,.item),$topicexec.lower($2) *,0,w).data) { !var %chan = $topicexec.lower($2) ; loop, send info to alias, remove from hash table while ($hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) { !var %t = $hget($+(topicexec.queue.,$cid,.item),$hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) $gettok(%t,3-,32) 422 $gettok(%t,2,32) You're not on that channel !hdel $+(topicexec.queue.,$cid,.item) $hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data } ; check hash table, free hash table if ($hget($+(topicexec.queue.,$cid,.item),0).item == 1) { !hfree $+(topicexec.queue.,$cid,.item) } !haltdef topicexec.disable } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RAW 403 NO SUCH CHANNEL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; raw 403 me chan :No such channel raw 403:& & No such channel:{ ; check hash table if ($hfind($+(topicexec.queue.,$cid,.item),$topicexec.lower($2) *,0,w).data) { !var %chan = $topicexec.lower($2) ; loop, send info to alias, remove from hash table while ($hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) { !var %t = $hget($+(topicexec.queue.,$cid,.item),$hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data) $gettok(%t,3-,32) 403 $gettok(%t,2,32) No such channel !hdel $+(topicexec.queue.,$cid,.item) $hfind($+(topicexec.queue.,$cid,.item),%chan *,1,w).data } ; check hash table, free hash table if ($hget($+(topicexec.queue.,$cid,.item),0).item == 1) { !hfree $+(topicexec.queue.,$cid,.item) } !haltdef topicexec.disable } } ; end of '#topicexec' group #topicexec end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.LOWER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $topicexec.lower(nick/chan) alias -l topicexec.lower { ; on IRC these chars are upper(lower) case of eachother: { = [, } = ], | = \, ~ = ^ ; so here we replace them to make sure we compare the right things right !return $replace($1,$chr(123),$chr(91),$chr(125),$chr(93),$chr(124),$chr(92),$chr(126),$chr(94)) } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.DISABLE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; this alias will only disable the group '#topicexec' if it is nolonger needed (checks all connections) alias -l topicexec.disable { !var %x = 1 ; loop through all connection id's while (%x <= $scid(0)) { ; there is 1 item in the 'item' queue, free hash table if ($hget($+(topicexec.queue.,$scid(%x),.item),0).item == 1) { !hfree $+(topicexec.queue.,$scid(%x),.item) } ; more then 1 item in the 'item' queue elseif ($hget($+(topicexec.queue.,$scid(%x),.item),0).item > 1) { !return } !inc %x } .!disable #topicexec } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ALIAS TOPICEXEC.QUEUE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $1 = table, $2- = thing alias -l topicexec.queue { ; there is a 2nd parameter and mode '$2-' is not already in the queue, increase and add if ($2 != $null) && ((!$hfind($1,$2-)) || ($hfind($1,$2-).data == 0)) { !hinc -m $1 last !hadd $1 $hget($1,last) $2- } ; called as identifier and propertie is next and hash table '$1' exists elseif ($isid) && ($prop == next) && ($hget($1)) { !hinc -m $1 first ; 'first' is smaller or equal to 'last' if ($hget($1,first) <= $hget($1,last)) { !var %next = $hget($1,$hget($1,first)) !hdel $1 $hget($1,first) ; this is the last item, free hash table if ($hget($1,first) >= $hget($1,last)) { !hfree $1 } !return %next } } ; called as identifier and propertie is size elseif ($isid) && ($prop == size) { ; decrease number of items with 1, (1 item in queue, and last is there) !return $iif($calc($hget($1,0).item -1) >= 0,$ifmatch,0) } ; called as identifier and propertie is clear, free elseif ($isid) && ($prop == clear) { !hfree -w $1 } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TOPIC EVENT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; on *:topic:#:{ ; add to the hash table ; if you are on a server where nick!user@host is saved for whom set the topic, change $nick to $fulladdress !hadd -m $+(topicexec.,$cid,.topicsave) $topicexec.lower($chan) $nick $ctime } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RAW 333 TOPIC NICK CTIME ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;raw 333 me chan nick time raw 333:& & & &:{ if ($me ison $2) { !hadd -m $+(topicexec.,$cid,.topicsave) $topicexec.lower($2) $3 $4 } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISCONNECT EVENT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; on *:disconnect: { ; check if the 'item' hash table exist, free hash table if ($hget($+(topicexec.queue.,$cid,.item))) { !hfree $+(topicexec.queue.,$cid,.item) } ; check if the 'item' hash table exist, free hash table if ($hget($+(topicexec.,$cid,.topicsave))) { !hfree $+(topicexec.,$cid,.topicsave) } $topicexec.queue($+(topicexec.queue.,$cid)).clear topicexec.disable } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EXAMPLE SCRIPT 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; public !topic command on *:text:!topic &:#channel:{ if ($left($2,1) isin $chantypes) { topicexec $2 topicpub $chan } } alias -l topicpub { if ($2 == 331) { !msg $1 $3 has no topic set } elseif ($2 == 422) { !msg $1 Can not retrieve topic from $3 (+s) } elseif ($2 == 403 ) { !msg $1 channel $3 does not exist } else { !msg $1 Topic for $3 set by $4 at $asctime($5) ( $+ $gettok($duration($calc($ctime - $5)),1,32) ago), topic: ' $iif(c isincs $gettok($chan($1).mode,1,32),$strip($6-,c),$6-) ' ( $+ $len($6-) chars) } } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EXAMPLE SCRIPT 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; changes the how the topic is shown when you join on *:join:#:{ if ($nick == $me) { topicexec -pu1 $chan topicexec.show } } ; chan nick time topic alias -l topicexec.show { if ($2 == 331) { !echo $color(topic) -ti2 $1 * No topic is set } elseif ($5 != $null) { !echo $color(topic) -ti2 $2 * Topic is ' $+ $5- $+ ' ( $+ $len($5-) chars) by $3 on $asctime($4,ddd dd mmm yyyy) ( $+ $gettok($duration($calc($ctime - $4)),1-2,32) ago) } } ; an alias to show the topic on 1 line alias ctopic { if ($chan) { if (!$1) { topicexec $chan topicexec.show } else { !topic $chan $1- } } }