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.
Unfortunately channel banlists get often rather populated. Because all the servers in the network need to be aware of all the bans, the banlist usually has a limit somewhere between 20 and 100 items. Since the channel bans last forever if they aren't removed by the operators, there is often need to clear the banlist. Scripting an alias that does that is not rocket science. The common problem is not making an algorithm but the knowledge about IRC protocol and the way mIRC provides access to channel banlists.
The IRC client is not aware of the bans unless it sees the mode change on the channel. To be aware of all the bans or lack of bans, you need to request the banlist. This can be done by using /mode command for the channel with +b as the only argument. It doesn't require operator privileges so it's possible to request the banlist every time you join a channel. Each channel ban will come in numeric 367. After all the bans, you will receive the numeric 368 which means the end of banlist.
After you have requested the channel banlist, you can use the $ibl(<channel>,<number>) identifier. When the number is 0, you will get the total number of bans. When the number is 1, you will get the first ban, when the number is 2, you will get the second ban etc. It's also necessary to check the value of $chan(<channel>).ibl. It's $true when the list is updated, $inmode if the listing is in progress, and $false if the list is not updated.
It's always a good idea to optimize the mode changes. If the server allows six targets for one /mode command, you can remove 30 bans with five commands instead of doing a massive mode flood. You can get the number of allowed mode changes from $modespl identifier. It varies from server to server. If the banmasks are really long and the server allows a lot targets for /mode, it's a good idea to check that the message fits to 512 bytes. Some servers might accept longer messages but it's not a big issue to add a small check for that.
The example script is a bit unusual for this site. It actually checks for user errors. :-) Checking for user errors is rarely needed when writing remote events because the communication happens between the script and the server. However as soon as the human factor comes into play, the number of possible errors raises a lot. Although this example alias includes some error checking, there are still lots of possible problems. The alias also tries to be powerful and userfriendly. It includes the option to remove only the bans that match certain mask. If you have 30 bans on your channel of which 7 are for aol.com users, /clearbans #channel *!*@*.aol.com would remove the seven bans for aol.com and leave the rest untouched. If the internal ban list hasn't been filled, the script requests it, and clears the bans when it has received the list.
; Clean the variables on start if they haven't been unset properly
on *:START: unset %clearbans*
; Syntax: /clearbans <channel> <mask>
alias clearbans {
; %channel is set to the first argument or the active channel window
if ( $1 ischan ) var %channel = $1
elseif ( $active ischan ) var %channel = $active
else {
echo -se * No channel for /clearbans
return
}
; %mask is set to the second given argument or *!*@* if it's not specified
if ( $2 ) var %mask = $2
else var %mask = *!*@*
; If you aren't operator or half-operator, print error message
; You can add checks for more rare modes or remove this check completely
if ( ($me !isop %channel) && ($me !ishop %channel) ) {
echo %channel * You don't have privileges to clear the banlist
return
}
; If the internal ban list isn't filled, request it from the server
; The script will continue when the list is updated
if ( $chan(%channel).ibl == $false ) {
set $+(%,clearbans,$cid,%channel) %mask
mode %channel +b
return
}
elseif ( $chan(%channel).ibl == $inmode ) {
; Confusing situation!
; Is the user trying to clear banlist twice? Is some other script requesting the list?
; Do a safe solution and don't do anything. Feel free to come up with more advanced one.
return
}
; Make a hash table called clearbans<cid><channel>
; The table will include all the bans that are to be removed
var %bantable = $+(clearbans,$cid,%channel)
hmake %bantable $ibl(%channel,0)
; Fill the table with all the bans that fit to the mask
var %x = 1
while ( $ibl($1,%x) ) {
if ( %mask iswm $ibl($1,%x) ) hadd %bantable $ibl($1,%x)
inc %x
}
; The final loop that actually removes the bans
var %x = 1, %bans
while ( $hget(%bantable,0).item > 0 ) {
; Get item from the hash table, add it %bans, and remove the item from the table
var %item = $hget(%bantable,1).item
%bans = %bans %item
hdel %bantable %item
; If we can add more items to the mode message, jump to the beginning of the loop
; The $len(%bans) < 400 is elemental check to prevent going over 512 bytes
if ( (%x < $modespl) && ($len(%bans) < 400) && ($hget(%bantable,0).item > 0) ) {
inc %x
continue
}
; Remove the bans
mode %channel - $+ $str(b,%x) %bans
var %x = 1, %bans
}
hfree %bantable
}
; If the banlist was requested by /clearbans, don't show the ban items
; This is just a visual issue so you can freely remove this
raw 367:*: if ( $eval($+(%,clearbans,$cid,$2),2) ) halt
; 368 is the end of banlist. If it was called by /clearbans, call /clearbans again.
raw 368:*: {
if ( $eval($+(%,clearbans,$cid,$2),2) ) {
clearbans $2 $ifmatch
unset $+(%,clearbans,$cid,$2)
halt
}
}