#version 0.2 /* * nickserv.dsm - Module to automatically keep track of NickServ nicks and * passwords on different networks (server groups). For * DarkStar/EPIC 1.1.7+. * * The format of the data file is: server_group:nick:password * * The server_group field is matched against whatever the fifth field of * /server info is, which is always at least '', and can be a pattern * which is used in $match(). Therefore, if you use multiple servers with the * same nick, you'll need to specify a server group for each server which are * on different networks to avoid overwriting '' when updating the * data file. Multiple nicks in the same server group are supported. * * Note that this has only been tested on FreeNode/OpenProjects so far. Also, * if you have a defualt server specified (IRCSERVER environment variable), * then setting it to a full server spec with a server group might help if you * use multiple servers with the same nick. For example: * * % export IRCSERVER=irc.us.freenode.net:6667:::freenode:IRC * * Here, 'freenode' is the server group. * * This script uses serial number 499 for all /on hooks. * * Changes 0.2 * - use $delarray() to delete arrays, not delitem in a loop (thanks fudd) * - change internal alias names _nickserv. to nickserv. to take advantage * of auto cleanup (thanks fudd again) * - use //msg when communicating with NickServ, not //quote * - pause half a second before IDENTIFY * Changes 0.1 * - initial release * * Written by Ben Kibbey . Use at your own risk. */ /****** CLEANUP QUEUE ******/ QUEUE cleanup.nickserv { for _a in (ns) { ^alias -$_a } ^on #^notice 499 -"NickServ *" } /****** CONFIG/FORMAT VARIABLES ******/ eval config.add NICKSERV_DATAFILE $twiddle($DS.SAVE_DIR)/nickserv.data config.add -b NICKSERV_AUTO_IDENTIFY 1 config.add -b NICKSERV_AUTO_UPDATE 1 config.add -b NICKSERV_QUIET 0 config.add -b NICKSERV_SAVE_PASSWORD 1 config.add -b NICKSERV_PROMPT_PASSWORD 1 # These PATTERN's are patterns used in a switch{} statement. This should # hopefully make it easier to adapt to other NickServ NOTICE's. The defaults # below work on the FreeNode/OpenProjects network (9/21/2002). config.add NICKSERV_AUTH_PATTERN This nickname is owned by someone else* config.add NICKSERV_AUTH_SUCCESS_PATTERN Password accepted* config.add NICKSERV_AUTH_FAILURE_PATTERN Password Incorrect* config.add NICKSERV_PASSWORD_PATTERN Your password \[is has\]* config.add NICKSERV_DROPNICK_PATTERN The nickname [*] has been dropped* format.add NICKSERV_AUTH $G Authenticating $2 on $1 to NickServ ... format.add NICKSERV_AUTH_PROMPT NickServ password for $2 on $1: format.add NICKSERV_AUTH_SUCCESS $G NickServ successfully authenticated. format.add NICKSERV_AUTH_FAILURE $G NickServ authentication failed. format.add NICKSERV_NO_GROUP $G No known NickServ information for $2 on $1. format.add NICKSERV_UPDATE_SUCCESS $G Successfully updated $1 format.add NICKSERV_UPDATE_FAILURE $G Error updating $1 module.load_saved_settings ^assign NICKSERV.DATA_GROUP 0 ^assign NICKSERV.DATA_NICK 1 ^assign NICKSERV.DATA_PASS 2 /****** USER ALIASES ******/ ALIAS ns { unless (@) { //^msg NickServ help return } //^msg NickServ $* } # Update information for a nick or remove a nick from the data file. ALIAS nickserv.update_datafile (data,update) { if (fexist($CONFIG.NICKSERV_DATAFILE) == 1) { @:index = 0 @:fd = open($CONFIG.NICKSERV_DATAFILE R) # Read datafile lines into an array. for (@:s = read($fd), s, @:s = read($fd)) { @setitem(lines $index $s) @:index++ } @close($fd) if (rename($CONFIG.NICKSERV_DATAFILE ${CONFIG.NICKSERV_DATAFILE}.old) == -1) { @delarray(lines) return 0 } } @:fd = open($CONFIG.NICKSERV_DATAFILE W) unless (fd) { return 0 } # Dump array to datafile skipping lines matching existing 'data', sorted. for (@:n = 0, n < numitems(lines), @:n++) { @:line = split(: $igetitem(lines $n)) if (match($word(0 $line) $getitem(data $NICKSERV.DATA_GROUP)) > 0) { if (match($word(1 $line) $getitem(data $NICKSERV.DATA_NICK)) > 0) { continue } } @write($fd $igetitem(lines $n)) } @delarray(lines) if (update) { @write($fd $getitem(data $NICKSERV.DATA_GROUP):$getitem(data $NICKSERV.DATA_NICK):${(CONFIG.NICKSERV_SAVE_PASSWORD) ? getitem(data $NICKSERV.DATA_PASS) : []}) } @close($fd) return 1 } # Check to see if the current nick is in the data file and store values in an # array. ALIAS nickserv.get_group_data { unless (fexist($CONFIG.NICKSERV_DATAFILE) == 1) { return } @:fd = open($CONFIG.NICKSERV_DATAFILE R) # The server group will always be at least ''. @:group = servergroup() @:snick = servernick() @setitem(data $NICKSERV.DATA_GROUP $group) for (@:line = read($fd), line, @:line = read($fd)) { @:line = split(: $line) if (match($getitem(data $NICKSERV.DATA_GROUP) $word(0 $line)) > 0) { @:nick = word(1 $line) # Check for multiple nicks in the same server group. unless ([$nick] == [$snick]) { continue } @setitem(data $NICKSERV.DATA_NICK $nick) @setitem(data $NICKSERV.DATA_PASS $word(2 $line)) break } } @close($fd) # Make sure there was a match in the data file (nick). unless (getitem(data $NICKSERV.DATA_NICK)) { return } return data } ALIAS nickserv.identify (data) { unless (CONFIG.NICKSERV_QUIET) { echo $fparse(NICKSERV_AUTH $getitem(data $NICKSERV.DATA_GROUP) $getitem(data $NICKSERV.DATA_NICK)) } # A pause is nessesary on startup for some servers. pause 0.5 ns IDENTIFY $getitem(data $NICKSERV.DATA_PASS) } # Prompt user for password. ALIAS nickserv.get_password (data) { input -noecho "$fparse(NICKSERV_AUTH_PROMPT $getitem(data $NICKSERV.DATA_GROUP) $getitem(data $NICKSERV.DATA_NICK))" { if ([$0]) { @setitem(data $NICKSERV.DATA_PASS $0) @nickserv.identify(data) } } return } /****** ON HOOKS ******/ ^on #^notice 499 "NickServ *" { switch ($1-) { ($CONFIG.NICKSERV_AUTH_PATTERN) { if (CONFIG.NICKSERV_AUTO_IDENTIFY == 1) { @:data = nickserv.get_group_data() unless (data) { unless (CONFIG.NICKSERV_QUIET) { echo $fparse(NICKSERV_NO_GROUP $servergroup() $servernick()) } return } unless (getitem(data $NICKSERV.DATA_PASS)) { if (CONFIG.NICKSERV_PROMPT_PASSWORD == 1) { @nickserv.get_password(data) return } } @nickserv.identify(data) } else { return } } ($CONFIG.NICKSERV_AUTH_SUCCESS_PATTERN) { unless (CONFIG.NICKSERV_QUIET) { echo $fparse(NICKSERV_AUTH_SUCCESS) } return } ($CONFIG.NICKSERV_AUTH_FAILURE_PATTERN) { unless (CONFIG.NICKSERV_QUIET) { echo $fparse(NICKSERV_AUTH_FAILURE) } return } ($CONFIG.NICKSERV_PASSWORD_PATTERN) { unless (CONFIG.NICKSERV_AUTO_UPDATE) { return } @:password = stripcrap("ALL" $1-) # Need to fix this for other networks. @:password = strip([] $pattern([*] $password)) @:data = nickserv.get_group_data() unless (data) { @setitem(data $NICKSERV.DATA_GROUP $servergroup()) @setitem(data $NICKSERV.DATA_NICK $servernick()) } @setitem(data $NICKSERV.DATA_PASS $password) unless (nickserv.update_datafile(data 1)) { echo $fparse(NICKSERV_UPDATE_FAILURE $CONFIG.NICKSERV_DATAFILE) } else { unless (CONFIG.NICKSERV_QUIET) { echo $fparse(NICKSERV_UPDATE_SUCCESS $CONFIG.NICKSERV_DATAFILE) } } } ($CONFIG.NICKSERV_DROPNICK_PATTERN) { unless (CONFIG.NICKSERV_AUTO_UPDATE) { return } @:data = nickserv.get_group_data() if (data) { unless (nickserv.update_datafile(data 0)) { echo $fparse(NICKSERV_UPDATE_FAILURE $CONFIG.NICKSERV_DATAFILE) } else { unless (CONFIG.NICKSERV_QUIET) { echo $fparse(NICKSERV_UPDATE_SUCCESS $CONFIG.NICKSERV_DATAFILE) } } } } (*) { return } } @delarray(data) return }