Note: The mainteinance of the scripting examples is discontinued since I no longer have an interest to continue doing so. The pages will remain here, for now, but that might not be the case in the future. You are free to download all the material on these pages and set a up mirror, or even continue the maintenance of the material by enhancing the examples yourself.

All the material in these examples are for the mIRC version 6.03. It is very likely that some or most of these examples won't work in future versions.

Smart requesting and filling channel lists during join

Every IRC channel contains a couple of lists. The way the lists are stored on the server varies from network to network but the way they are sent to the client is very universal.

When you join a channel, the first list you get is the list of all the nicks with their channelmodes. The list is NAMES reply sent in raw 353. If there are lots of people on the channel, there might be several 353's. Finally there is numeric 366, the end of NAMES. These replies are always sent. The default mIRC behavior is to echo the names replies into status window. However if you are on many big channels, you might want to hide the echos.

If you have already read the page about Internal Address List (IAL), you should understand that nearly all scripts that take advantage of channel operator status need the full addresses of all nicks on the channel. The NAMES reply has just the nicks, not full addresses so you must send a request to the server asking for the addresses. The most common way to do this is to send /who #channel. There are some situations when doing /userhost on multiple nicks at the same time might be a bit faster but doing /who is a lot easier and it always works. When you have sent the /who request, you will get a numeric 352 for every user and finally the 315, end of WHO.

Every channel has a list of banned addresses. It's possible for a client to request the list of bans and then maintain a list of them when client receives new bans and removal of old bans. The mIRC's ban list is called IBL. IBL stands for Internal Ban List. You can request channel's ban list with /mode #channel +b It's just like a new ban but just without a target. You will get a numeric 367 for every banned address and finally a numeric 368 for the end of channel ban list.

Requesting these lists is a very simple procedure. The list of nicks comes automatically, you can send /who #channel to get the addresses and /mode #channel +b to get the banlist. However the biggest problem is that the default behavior of mIRC is to echo all these lists. Even three channels with 50 users in each can effectively flood the status window with a couple of hunded lines you probably don't want to read. It would also be very easy to simply hide all /who and banlist numerics. The problem is that you usually want to be able to use those commands also after you have synchronized the lists.

The solution is to set some kind of a flag to indicate when the lists are sent for the first time. The solution I'm going to present is to use a hash table called 'chsynch<cid>' where <cid> is the connection id for the current connection. The table will have a key for each channel you join. When you join a channel, the data value for the respectable key will be set to 'names who bans'. As long as a token with content 'names' is there, all names replies will be hidden. When you get the end of names, the token 'names' will be removed. Same logic will be used for /who and banlist replies.

Example script

; Set up the hash table and request addresses and banlist
on *:JOIN:#: {
  if ( $nick == $me ) {
    ; Normal channels
    if ( +* !iswm $chan ) {
      ; Put $ticks to indicate the time of join for later stats
      hadd -m chsynch $+ $cid $chan $ticks names who bans
      who $chan
      mode $chan +b
    }
    else {
      ; Don't request banlist for modeless +channels
      hadd -m chsynch $+ $cid $chan $ticks names who
      who $chan
    }
  }
}

; Clear channel data when you leave the channel
on *:PART:#: if ( $nick == $me ) hdel chsynch $+ $cid $chan

; Clear the channel data when you are kicked
on *:KICK:#: if ( $knick == $me ) hdel chsynch $+ $cid $chan

; Clear all channel data when you disconnect
on *:DISCONNECT: if ( $hget(chsynch $+ $cid) != $null ) hfree chsynch $+ $cid

; Names reply
; Note that some servers have the channel on $2 and some on $3
; (I don't understand why though)
raw 353:*: {
  var %chan
  if ( $2 ischan ) %chan = $2
  else %chan = $3
  if ( $istok($hget(chsynch $+ $cid,%chan),names,32) == $true ) halt
}
; End of names
raw 366:*: {
  if ( $istok($hget(chsynch $+ $cid,$2),names,32) == $true ) {
    hadd chsynch $+ $cid $2 $remtok($hget(chsynch $+ $cid,$2),names,1,32)
    halt
  }
}

; Who reply
raw 352:*: if ( $istok($hget(chsynch $+ $cid,$2),who,32) == $true ) halt
; End of who
raw 315:*: {
  if ( $istok($hget(chsynch $+ $cid,$2),who,32) == $true ) {
    hadd chsynch $+ $cid $2 $remtok($hget(chsynch $+ $cid,$2),who,1,32)
    ; Display synch stats
    ; Note: you can't trust that who and ban replies come in certain order
    if ( $numtok($hget(chsynch $+ $cid,$2),32) == 1 ) {
      var %secs = $calc(($ticks - $gettok($hget(chsynch $+ $cid,$2),1,32)) / 1000)
      echo $color(join text) -t $2 * Synchronized in %secs seconds
    }
    halt
  }
}

; Ban item reply
raw 367:*: if ( $istok($hget(chsynch $+ $cid,$2),bans,32) == $true ) halt
; End of channel banlist
raw 368:*: {
  if ( $istok($hget(chsynch $+ $cid,$2),bans,32) == $true ) {
    hadd chsynch $+ $cid $2 $remtok($hget(chsynch $+ $cid,$2),bans,1,32)
    ; Display synch stats
    if ( $numtok($hget(chsynch $+ $cid,$2),32) == 1 ) {
      var %secs = $calc(($ticks - $gettok($hget(chsynch $+ $cid,$2),1,32)) / 1000)
      echo $color(join text) -t $2 * Synchronized in %secs seconds
    }
    halt
  }
}

Last updated 2003-04-05, Janne 'Geetee' Nikula, jn-mirc@zkelvin.net