# version:1.2.6 loader:pf # $Id: channel.dsm,v 1.90 2011/08/29 17:25:42 brian Exp $ # # channel.dsm - Channel related module for DarkStar/EPIC5 # Copyright (c) 2002-2005 Brian Weiss (except where noted) # See the 'COPYRIGHT' file for more information. # # This script uses serial number 423 for /ON hooks. # queue cleanup.channel { ^bind ^X nothing; for alias in (addtopic alldeop alldop allop ban bankick banlist bans bk c cmode cycle deop dop devoice dvoice et etopic i invite j join k kb key kick kickban l leave lk massmode mdeop mdop mdevoice mdvoice mme mop msay mvoice op part partall settopic t tban tedit tempban tempbk tempkb topics tt ttopic unban unkey untopic voice wall) { ^alias -$alias; }; ^on #332 423 -"*"; ^on #topic 423 -"*"; ^on #hook 423 -"CONFIG CHANNEL_WALL_TYPE *"; ^on #hook 423 -"CONFIG REMEMBER_TOPICS *"; }; addconfig ADDTOPIC_DELIMETER |; addconfig BANTYPE 3; addconfig CHANNEL_WALL_TYPE 1; addconfig DEFAULT_KICK_REASON No soup for you!; addconfig REMEMBER_TOPICS 5; bind ^X switch_channels; alias addtopic (newtopic) { if (!newtopic) { xecho -b Usage: /ADDTOPIC ; return; }; if (!C) { xecho -b No active channel for this window; return; }; @ :serv = winserv(); @ :array = [channel.topics.$serv\.$C]; @ :topic = getitem($array ${numitems($array) - 1}); if (topic) { //topic $C $topic $CONFIG.ADDTOPIC_DELIMETER $newtopic; }{ @ CHANNEL.ADDTOPIC = newtopic; # No topic set ^on -331 "$servername() $C *" { //topic $1 $CHANNEL.ADDTOPIC; @ CHANNEL.ADDTOPIC = []; defer ^on 331 -"$0 $1 *"; defer ^on 332 -"$0 $1 *"; defer ^on 333 -"$0 $1 *"; }; # The actual topic ^on ^332 "$servername() $C *" { //topic $1 $2- $CONFIG.ADDTOPIC_DELIMETER $CHANNEL.ADDTOPIC; @ CHANNEL.ADDTOPIC = []; defer ^on 332 -"$0 $1 *"; }; # Topic set by ^on ^333 "$servername() $C *" { defer ^on 333 -"$0 $1 *"; }; //topic; }; }; alias alldop alldeop alias alldeop (nicks) { if (!nicks) { xecho -b Usage: /ALLDEOP ...; return; }; for chan in ($mychannels()) { for nick in ($nicks) { if (ischanop($servernick() $chan) && ischanop($nick $chan)) { //mode $chan -o $nick; }; }; }; }; alias allop (nicks) { if (!nicks) { xecho -b Usage: /ALLOP ...; return; }; for chan in ($mychannels()) { for nick in ($nicks) { if (ischanop($servernick() $chan) && onchannel($nick $chan) && !ischanop($nick $chan)) { //mode $chan +o $nick; }; }; }; }; alias ban (targets) { if (!targets) { xecho -b Usage: /BAN ...; return; }; for target in ($targets) { switch ($pass(!@. $target)) { () { # # Target is a nickname. Attempt to get the user@host from # $userhost() or $uh() then pass it through $mask(). If # both functions fail to return a usable host, just pass # the target through and let the client handle it. # @ :uhost = userhost($target) == [@] ? uh($target) : userhost($target); # Check again in case $uh() failed too. if (uhost && uhost != [@]) { @ push(:bans $mask($CONFIG.BANTYPE $uhost)); } else { @ push(:bans $target); }; } (.) { # Target is a hostname or IP, pass it through $mask() only. @ push(:bans $mask($CONFIG.BANTYPE $target)); } (*) { # Target is already a hostmask, just pass it on through. @ push(:bans $target); } }; }; massmode $C + b $bans; # # Allow this alias to be called as a function so that /TEMPBAN # can use it to do the banning but still know which hostmask to # remove from the ban list later. # if (functioncall()) { @ function_return = bans; }; }; alias bk (...) { bankick $*; }; alias bankick (nick, reason default "$CONFIG.DEFAULT_KICK_REASON") { if (!nick) { xecho -b Usage: /BANKICK [reason]; return; }; ban $nick; if (onchannel($nick $C)) { //kick $C $nick $reason; }; }; alias bans (...) { banlist $*; }; alias banlist (chan default "$C", void) { //mode $chan +b; }; alias c (...) {cmode $*}; alias cmode (mode, ...) { if (!mode) { xecho -b Usage: /CMODE ; return; }; //mode $C $mode $*; }; alias cycle (chan default "$C", void) { @ :key = key($chan); //part $chan; wait; //join $chan $key; }; alias dop (...) { deop $*; }; alias deop (nicks) { if (!nicks) { xecho -b Usage: /DEOP ...; return; }; massmode $C - o $nicks; }; alias dvoice (...) { devoice $*; }; alias devoice (nicks) { if (!nicks) { xecho -b Usage: /DEVOICE ...; return; }; massmode $C - v $nicks; }; alias et (...) { etopic $*; }; # # Edit the current topic. This places "/TOPIC " on the # input line so that you can edit it and re-set it. # alias etopic (void) { if (C) { # # Attempt to get the current topic from a channel.topics array # but query the server if that fails. # @ :serv = winserv(); @ :array = [channel.topics.$serv\.$C]; @ :topic = getitem($array ${numitems($array) - 1}); if (topic) { parsekey erase_line; xtype -l $K\TOPIC $topic; }{ # No topic set. ^on -331 "$servername() $C *" { defer ^on 331 -"$0 $1 *"; defer ^on 332 -"$0 $1 *"; defer ^on 333 -"$0 $1 *"; }; # The actual topic. ^on ^332 "$servername() $C *" { parsekey erase_line; xtype -l $K\TOPIC $2-; defer ^on 332 -"$0 $1 *"; }; # Topic set by. ^on ^333 "$servername() $C *" { defer ^on 333 -"$0 $1 *"; }; //topic; }; }; }; alias i (...) { invite $*; }; alias invite (nick, channel default "$C", void) { if (!nick) { xecho -b Usage: /INVITE [channel]; return; }; //invite $nick $channel; }; alias j (...) { join $*; }; # # /JOIN taken from the 2.8script file distributed with EPIC4. # alias join { switch ($*) { (*,*) { join $before(, $0) $1-; join $after(, $0) $1-; } (#*) (&*) (0) (-*) (!*) (+*) { //join $*; } () { //join -i; } (*) { //join #$*; } }; }; alias key (key, void) { if (!key) { xecho -b Usage: /KEY ; return; }; //mode $C +k $key; }; alias k (...) { kick $*; }; alias kick (nick, reason default "$CONFIG.DEFAULT_KICK_REASON") { if (!nick) { xecho -b Usage: /KICK [reason]; return; }; //kick $C $nick $reason; }; alias kb (...) { kickban $*; }; alias kickban (nick, reason default "$CONFIG.DEFAULT_KICK_REASON") { if (!nick) { xecho -b Usage: /KICKBAN [reason]; return; }; if (onchannel($nick $C)) { //kick $C $nick $reason; }; ban $nick; }; alias part (...) { leave $*; }; alias l (...) { leave $*; }; # # /LEAVE taken from the 2.8script file distributed with EPIC4. # alias leave { switch ($0) { (*,*) { leave $before(, $0) $1-; leave $after(, $0) $1-; } (#*) (&*) (0) (-*) (!*) (+*) { //part $*; } () (\\*) { //part * $1-; } (*) { //part #$*; } }; }; # # Your standard /LK. Kicks everyone but +[o|h|v] users out of # the current channel. # alias lk (reason default "$CONFIG.DEFAULT_KICK_REASON") { if (!ischanop($N $C)) { xecho -b Sorry, you must be +o to kick people; return; }; ^local ask $"Kick all lusers from $C? "; if (left(1 $ask) == [y]) { for user in ($channel()) { @ :nick = mid(2 $strlen($user) $user); if (match(.. $left(2 $user))) { //kick $C $nick $reason; } else if (match(.? $left(2 $user))) { //kick $C $nick $reason; }; }; }; }; alias massmode (chan, action, mode, args) { if (!args) { xecho -b Usage: /MASSMODE <+|-> ; return; }; if (!ischanop($servernick() $chan)) { xecho -b Sorry, you must be +o to set channel modes; return; }; @ :maxmodes = serverctl(GET $servernum() 005 MODES); @ :maxmodes = maxmodes ? maxmodes : 4; for cnt from 1 to $maxmodes { @ push(:tmp mode.$cnt); }; fe ($args) $tmp { @ :nicks = []; for (@:cnt = 1, mode[$cnt], @:cnt++) { eval push :nicks \$mode[$cnt]; }; //mode $chan $action$repeat($#nicks $mode) $nicks; }; }; alias mdop (...) { mdeop $*; }; alias mdeop (chan default "$C", void) { if (chops($chan)) { massmode $chan - o $remw($servernick() $chops($chan)); } else { xecho -b No channel operators found on $chan; }; }; alias mdvoice (...) { mdevoice $*; }; alias mdevoice (chan default "$C", void) { massmode $chan - v $remw($servernick() $onchannel($chan)); }; alias mme { if (match($0 -a -all)) { @ :all_servers = 1; @ :text = [$1-]; }{ @ :text = [$*]; }; if (!text) { xecho -b Usage: /MME [-all] ; return; }; if (all_servers) { for sref in ($myservers(0)) { for chan in ($mychannels($sref)) { xeval -s $sref {describe $chan $text}; }; }; }{ for chan in ($mychannels()) { describe $chan $text; }; }; }; alias mop (chan default "$C", void) { if (nochops($chan)) { massmode $chan + o $remw($servernick() $nochops($chan)); } else { xecho -b No normal users found on $chan; }; }; alias msay { if (match($0 -a -all)) { @ :all_servers = 1; @ :text = [$1-]; }{ @ :text = [$*]; }; if (!text) { xecho -b Usage: /MSAY [-all] ; return; }; if (all_servers) { for sref in ($myservers(0)) { for chan in ($mychannels($sref)) { xeval -s $sref {msg $chan $text}; }; }; }{ for chan in ($mychannels()) { msg $chan $text; }; }; }; alias mvoice (chan default "$C", void) { massmode $chan + v $remw($servernick() $onchannel($chan)); }; alias op (nicks) { if (!nicks) { xecho -b Usage: /OP ...; return; }; massmode $C + o $nicks; }; alias partall (void) { input "Are you sure you want to part all your channels? " { if (left(1 $0) == [y]) { for chan in ($mychannels()) { //part $chan; }; }; }; }; alias settopic (chan default "$C", void) { @ :serv = winserv($winchan($chan)); @ :array = [channel.topics.$serv\.$chan]; if (serv < 0) { xecho -b No server for this window; return; }; topics $chan; ^local prompt $"Change topic on $chan? (Enter a # or 'n' for new): "; if (prompt == [n]) { ^local newtopic $"Enter new topic: "; //topic $chan $newtopic; } else if (!isnumber(b10 $prompt)) { xecho -b You must enter an integer or 'n' to set a new topic; } else if (prompt > 0 && prompt <= numitems($array)) { @ :item = word(${prompt-1} $jot(${numitems($array)-1} 0)); //topic $chan $getitem($array $item); } else if (!numitems($array)) { xecho -b No topics stored for $chan; } else { xecho -b Number out of range; }; }; alias t (...) { topic $*; }; # # This imitates the /TBAN command in BitchX. It provides an interactive # way to remove bans. I have no idea why this is named what it is and # perhaps it should be renamed so that it is not confused with /TEMPBAN. # alias tban (chan default "$C", void) { @ delarray(channel.tban); ^on #^367 424 "% $chan *" { @ setitem(channel.tban $numitems(channel.tban) $*); }; ^on #^368 424 "% % $chan" { ^local chan $2; ^local ask $"Which ban(s) to remove? (1, 2-5, ...) "; for bannum in ($split(, $ask)) { @ :start = before(- $bannum); @ :end = after(- $bannum); if (start < end && start < numitems(channel.tban) && end <= numitems(channel.tban)) { for cnt from $start to $end { @ push(:bans $word(2 $getitem(channel.tban ${cnt - 1}))); }; } else if (bannum <= numitems(channel.tban)) { @ push(:bans $word(2 $getitem(channel.tban ${bannum - 1}))); }; }; @ :maxmodes = serverctl(GET $servernum() 005 MODES); @ :maxmodes = maxmodes ? maxmodes : 4; for ii from 1 to $maxmodes { @ push(:tmp mode.$ii); }; fe ($bans) $tmp { @:masks = []; for (@:cnt = 1, mode[$cnt], @:cnt++) { eval push :masks \$mode[$cnt]; }; //mode $chan -$repeat($#masks b) $masks; }; ^on #^367 424 -"% $chan *"; ^on #^368 424 -"% % $chan"; }; //mode $chan +b; }; alias tedit (...) { etopic $*; }; alias tempban (time, target, void) { if (!target || !isnumber(b10 $time) || time < 1) { xecho -b Usage: /TEMPBAN ; return; }; @ :banmask = ban($target); timer $time //mode $C -b $banmask; }; alias tempbk (time, nick, reason default "$CONFIG.DEFAULT_KICK_REASON") { if (!nick) { xecho -b Usage: /TEMPBK [reason]; return; }; tempban $time $nick; if (onchannel($nick $C)) { //kick $C $nick $reason; }; }; alias tempkb (time, nick, reason default "$CONFIG.DEFAULT_KICK_REASON") { if (!nick) { xecho -b Usage: /TEMPKB [reason]; return; }; if (onchannel($nick $C)) { //kick $C $nick $reason; }; tempban $time $nick; }; alias topics (chan default "$C", void) { @ :serv = winserv($winchan($chan)); @ :array = [channel.topics.$serv\.$chan]; if (serv < 0) { xecho -b No server for this window; return; }; if (numitems($array)) { xecho -b Stored topics for $chan (most recent first):; @ :cnt = 1; for ii in ($jot($numitems($array) 1)) { @ :topic = getitem($array ${ii-1}); echo $[3]cnt $topic; @ :cnt++; }; }{ xecho -b No topics stored for $chan; }; }; alias tt (...) { etopic $*; }; alias ttopic (...) { etopic $*; }; alias unban (bans) { if (!bans) { xecho -b Usage: /UNBAN ...; return; }; massmode $C - b $bans; }; alias unkey (void) { if (match(*k* $chanmode())) { //mode $C -k; } else { xecho -b No key on channel $C; }; }; alias untopic (chan default "$C", void) { //topic -$chan; }; alias voice (nicks) { if (!nicks) { xecho -b Usage: /VOICE ...; return; }; massmode $C + v $nicks; }; # # Sends a NOTICE to all +o nicks in the current channel using one # of three methods. The method used is determined by the value of # the CHANNEL_WALL_TYPE config variable. # # The possible types are: # 1 - Send a single NOTICE to @ # 2 - Send NOTICEs to all +o users according to MAXTARGETS (005) # 3 - Send NOTICEs to all +o users one at a time # alias wall (text) { if (!text) { xecho -b Usage: /WALL ; return; }; @ :chan = winchan($winnum()); switch ($CONFIG.CHANNEL_WALL_TYPE) { (1) { ^notice @$chan [wall/$chan] $text; } (2) { @ :maxtargets = serverctl(GET $servernum() 005 MAXTARGETS); @ :maxtargets = maxtargets ? maxtargets : 4; for ii from 1 to $maxtargets { @ push(:tmp t.$ii); }; fe ($filter($servernick() $chops())) $tmp { @ :targets = []; for (@ :ii = 1, t[$ii], @ :ii++) { @ push(:targets $t[$ii]); }; ^notice $unsplit(, $targets) [wall/$chan] $text; }; } (3) { # This should never be used on large channels. for nick in ($filter($servernick() $chops())) { ^notice $nick [wall/$chan] $text; }; } (*) { xecho -b WALL: Invalid CHANNEL_WALL_TYPE; return; } }; echo $fparse(SEND_WALL $chan $text); }; # # Maintains the arrays containing channel topics. This is called by # the 332 and TOPIC hooks. # # The arrays will be named channel.topics.. and # only as many topics as the value of REMEMBER_TOPICS will be kept. # alias channel.topic (serv, chan, topic) { if (isnumber(b10 $CONFIG.REMEMBER_TOPICS) && CONFIG.REMEMBER_TOPICS > 0) { @ :array = [channel.topics.$serv\.$chan]; if ((:item = matchitem($array $topic)) > -1) { @ delitem($array $item); }; while (numitems($array) >= CONFIG.REMEMBER_TOPICS) { @ delitem($array 0); }; @ setitem($array $numitems($array) $topic); }; }; on #-332 423 "*" { channel.topic $servernum($0) $1-; }; on #-topic 423 "*" { channel.topic $servernum() $1-; }; # # Restrict the value of the CHANNEL_WALL_TYPE config variable. # Allowed values: 1, 2, 3 # on #-hook 423 "CONFIG CHANNEL_WALL_TYPE *" { if (!match($CONFIG.CHANNEL_WALL_TYPE 1 2 3)) { xecho -b Valid types are 1, 2, and 3; defer dset CHANNEL_WALL_TYPE $2; }; }; # # Restrict the value of the REMEMBER_TOPICS config variable to an integer # that is greater than or equal to zero. # on #-hook 423 "CONFIG REMEMBER_TOPICS *" { if (!isnumber(b10 $CONFIG.REMEMBER_TOPICS) || CONFIG.REMEMBER_TOPICS < 0) { xecho -b Value must be an integer greater than or equal to zero; if (CONFIG.REMEMBER_TOPICS == []) { defer dset REMEMBER_TOPICS 0; } else { defer dset REMEMBER_TOPICS $2; }; }; # # Make sure that the size of all the channel topic arrays is no # greater than the new value of REMEMBER_TOPICS. # defer { for array in ($getarrays(channel.topics.*)) { while (numitems($array) > CONFIG.REMEMBER_TOPICS) { @ delitem($array 0); }; }; }; };