# version:0.2.3 loader:pf # $Id: nickmgr.dsm,v 1.21 2007/03/24 07:09:08 brian Exp $ # # nickmgr.dsm - Nick management module for DarkStar/EPIC5 # Copyright (c) 2003, 2004 Brian Weiss # See the 'COPYRIGHT' file for more information. # # This script uses serial number 422 for all /ON hooks. # queue cleanup.nickmgr { ^alias -nick; ^alias -nickscan; ^on #hook 422 -"CONFIG NICKMGR_SCAN_INTERVAL *"; ^on #join 422 -"*"; ^on #raw_irc 422 -"% NICK *"; ^on #raw_irc 422 -"% QUIT *"; ^on #timer 422 -"*"; @ timerctl(DELETE nickmgr); foreach NICKMGR.NICKCHANGE_PENDING xx { ^on #-raw_irc 422 -"$servernick($decode($xx))!% NICK *"; }; }; addconfig -b NICKMGR 0; addconfig -b NICKMGR_AUTO_ADD_NICKS 1; addconfig -b NICKMGR_IGNORE_NETSPLITS 0; addconfig NICKMGR_IGNORE_TIMEOUT 900; addconfig NICKMGR_NICKLIST; addconfig NICKMGR_SCAN_INTERVAL 60; addconfig NICKMGR_SCAN_TIMEOUT 900; assign NICKMGR.NICKCHANGE_TIMEOUT 60; alias nick (...) { if (CONFIG.NICKMGR && CONFIG.NICKMGR_AUTO_ADD_NICKS && findw($0 $CONFIG.NICKMGR_NICKLIST) == -1) { push CONFIG.NICKMGR_NICKLIST $0; }; //nick $*; }; # # nickmgr [[-a|-d] ...] ... # # Adds or removes nicks from NICKMGR_NICKLIST. The -a and -d options specify # which action to perform (add/delete). If neither option is provided then # -a will be assumed. # alias nickmgr (args) { ^local action add; ^local nicklist $CONFIG.NICKMGR_NICKLIST; if (!args) { dset NICKMGR_NICKLIST; return; }; while (:arg = shift(args)) { switch ($arg) { (-a) {@ action = [add]} (-d) {@ action = [delete]} (*) { if (action == [add]) { @ push(nicklist $arg); } else if (action == [delete]) { @ nicklist = remw($arg $nicklist); }; } }; }; if (nicklist != CONFIG.NICKMGR_NICKLIST) { dset NICKMGR_NICKLIST $nicklist; } else { dset NICKMGR_NICKLIST; }; }; alias nickscan (...) { nickmgr.scan $*; }; alias nickmgr.add_timer (void) { @ timerctl(DELETE nickmgr); timer -ref nickmgr -rep -1 -win -1 $CONFIG.NICKMGR_SCAN_INTERVAL nickmgr.scan; }; alias nickmgr.clean_ignore_list (void) { for array in ($getarrays(nickmgr.ignore.*)) { for ii from $numitems($array) to 1 { @ :ts = word(1 $getitem($array ${ii-1})); @ :diff = time() - ts; if (diff > CONFIG.NICKMGR_IGNORE_TIMEOUT) { @ delitem($array ${ii-1}); }; }; }; }; alias nickmgr.hook (nick, serv default "$servernum()", void) { if (!nick) return; if (CONFIG.NICKMGR && nickmgr.wantnick($nick)) { nickmgr.nickchange $nick; }; }; # # Adds a nick to the nick manager's ignore list. This allows # signoffs that appear to be netsplits to be ignored, even by # the nickmgr.scan alias. # alias nickmgr.ignore (nick, serv default "$servernum()", void) { if (!nick) return; nickmgr.clean_ignore_list; if ((:item = matchitem(nickmgr.ignore.$serv $nick *)) > -1) { @ setitem(nickmgr.ignore.$serv $item $nick $time()); } else { @ setitem(nickmgr.ignore.$serv $numitems(nickmgr.ignore.$serv) $nick $time()); }; }; # # This is a wrapper to DarkStar's $is_on() function that makes # it server specific. # alias nickmgr.is_on (nick, serv default "$servernum()", void) { xeval -s $serv { @ function_return = is_on($nick); }; }; alias nickmgr.nickchange (nick, serv default "$servernum()", void) { if (!nick || serv < 0 || !isconnected($serv) || nick == servernick($serv)) return; # Make sure we don't send more than one request at a time to a server. if (NICKMGR.NICKCHANGE_PENDING[$encode($serv)]) return; xecho -b NICKMGR: Changing nick on $servername($serv) to $nick; @ NICKMGR.NICKCHANGE_PENDING.$encode($serv) = [$nick $time()]; ^on #-raw_irc 422 "$servernick($serv)!% NICK *" { @ NICKMGR.NICKCHANGE_PENDING.$encode($servernum()) = []; ^on #-raw_irc 422 -"$servernick()!% NICK *"; }; xeval -s $serv { nick $nick; }; }; # # This will check each nick in $CONFIG.NICKMGR_NICKLIST, for each server # connection, until it either 1) finds one available, 2) reaches the end # of the list, or 3) reaches a nick less desirable than our current nick. # # In an attempt to ensure that servers don't get flooded with ISON requests # due to lag, a global variable in the NICKMGR.SCAN_PENDING structure will be # created containing a timestamp of when the scan began. While this variable # exists no scans will be allowed to take place for that server. # alias nickmgr.scan (void) { @ :nlist = CONFIG.NICKMGR_NICKLIST; if (!CONFIG.NICKMGR || !nlist) return; nickmgr.clean_ignore_list; for serv in ($myservers(0)) { if (serv > -1 && isconnected($serv)) { if (!NICKMGR.SCAN_PENDING[$encode(serv)]) { @ NICKMGR.SCAN_PENDING.$encode($serv) = time(); for ii from 1 to $numwords($nlist) { @ :nick = word(${ii-1} $nlist); if (!nickmgr.wantnick($nick $serv)) { break; } else if (matchitem(nickmgr.ignore.$serv $nick *) < 0) { if (!nickmgr.is_on($nick $serv)) { nickmgr.nickchange $nick $serv; break; }; }; }; ^assign -NICKMGR.SCAN_PENDING.$encode($serv); }; }; }; }; # # Returns the specified nick if it is more desirable than our current # nick according to the value of $CONFIG.NICKMGR_NICKLIST. # alias nickmgr.wantnick (nick, serv default "$servernum()", void) { if (!nick || nick == servernick($serv)) return; @ :list = CONFIG.NICKMGR_NICKLIST; @ :index = findw($nick $list); @ :c_index = findw($servernick($serv) $list); if (index > -1) { if (c_index == -1) { @ function_return = nick; } else if (index < c_index) { @ function_return = nick; }; }; }; on #-hook 422 "CONFIG NICKMGR_IGNORE_TIMEOUT *" { @ :newval = CONFIG.NICKMGR_IGNORE_TIMEOUT; @ :oldval = [$2-]; if (newval != [] && (!isnumber(b10 $newval) || newval < 0)) { xecho -b Value must be an integer greater than or equal to 0; if (oldval == []) { defer dset -NICKMGR_IGNORE_TIMEOUT; } else { defer dset NICKMGR_IGNORE_TIMEOUT $oldval; }; }; }; on #-hook 422 "CONFIG NICKMGR_SCAN_INTERVAL *" { @ :newval = CONFIG.NICKMGR_SCAN_INTERVAL; @ :oldval = [$2-]; if (!isnumber(b10 $newval) || newval < 5) { xecho -b Value must be an integer greater than or equal to 5; defer dset NICKMGR_SCAN_INTERVAL ${[$2] ? [$2] : 60}; }; # Restart the scan timer. defer { @ timerctl(DELETE nickmgr); nickmgr.add_timer; }; }; on #-hook 422 "CONFIG NICKMGR_SCAN_TIMEOUT *" { @ :newval = CONFIG.NICKMGR_SCAN_TIMEOUT; @ :oldval = [$2-]; if (!newval || !isnumber(b10 $newval)) { xecho -b Value must be a positive integer; defer dset NICKMGR_SCAN_TIMEOUT $oldval; }; }; # # Remove ignored nicks when they rejoin. # on #-join 422 "*" { @ :serv = servernum(); @ :item = matchitem(nickmgr.ignore.$serv $0); if (item > -1) { @ delitem(nickmgr.ignore.$serv $item); }; }; on #-raw_irc 422 "% NICK *" { @ :nick = before(1 ! $0); nickmgr.hook $nick; }; on #-raw_irc 422 "% QUIT *" { @ :nick = before(1 ! $0); @ :reason = after(1 : $2-); if (CONFIG.NICKMGR_IGNORE_NETSPLITS && match("%.%.% %.%.%" "$reason")) { nickmgr.clean_ignore_list; nickmgr.ignore $nick; }{ nickmgr.hook $nick; }; }; on #-timer 422 "*" { if (!timerctl(REFNUM nickmgr)) nickmgr.add_timer; foreach NICKMGR.SCAN_PENDING xx { @ :diff = time() - NICKMGR.SCAN_PENDING[$xx]; if (diff > CONFIG.NICKMGR_SCAN_TIMEOUT) { ^assign -NICKMGR.SCAN_PENDING.$xx; }; }; foreach NICKMGR.NICKCHANGE_PENDING xx { @ :diff = time() - NICKMGR.NICKCHANGE_PENDING[$xx]; @ :serv = decode($xx); if (diff > NICKMGR.NICKCHANGE_TIMEOUT) { ^on #-raw_irc 422 -"$servernick($serv)!% NICK *"; ^assign -NICKMGR.NICKCHANGE_PENDING.$xx; }; }; }; defer nickmgr.scan; defer nickmgr.add_timer;