From 200873633854ff35ca47b1392c73c80fcfbcda75 Mon Sep 17 00:00:00 2001 Message-Id: <200873633854ff35ca47b1392c73c80fcfbcda75.1715761441.git.mdw@distorted.org.uk> From: Mark Wooding Date: Thu, 7 Sep 2000 01:02:56 +0000 Subject: [PATCH] Bugfixes. New channel management stuff. Organization: Straylight/Edgeware From: Ian Jackson --- .cvsignore | 1 + bot.tcl | 245 ++++++++++++++++++++++++++++++++++++++++++----------- helpinfos | 51 ++++++----- 3 files changed, 227 insertions(+), 70 deletions(-) diff --git a/.cvsignore b/.cvsignore index f40c7c1..74a7527 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,2 +1,3 @@ summon users +chans diff --git a/bot.tcl b/bot.tcl index 09c4ca2..598223b 100755 --- a/bot.tcl +++ b/bot.tcl @@ -15,6 +15,13 @@ if {![info exists globalsecret]} { unset gsfile } +proc manyset {list args} { + foreach val $list var $args { + upvar 1 $var my + set my $val + } +} + proc try_except_finally {try except finally} { global errorInfo errorCode set er [catch { uplevel 1 $try } emsg] @@ -138,7 +145,9 @@ proc onread {args} { } proc sendprivmsg {dest l} { - sendout [expr {[ischan $dest] ? "PRIVMSG" : "NOTICE"}] $dest $l + foreach v [split $l "\n"] { + sendout [expr {[ischan $dest] ? "PRIVMSG" : "NOTICE"}] $dest $v + } } proc sendaction {dest what} { sendout PRIVMSG $dest "\001ACTION $what\001" } proc msendprivmsg {dest ll} { foreach l $ll { sendprivmsg $dest $l } } @@ -340,12 +349,26 @@ proc chanmode_arg {} { } proc chanmode_o1 {m g p chan} { - global nick + global nick chan_initialop prefix_nick set who [chanmode_arg] recordlastseen_n $n "being nice to $who" 1 if {"[irctolower $who]" == "[irctolower $nick]"} { - sendprivmsg $n Thanks. + set nl [irctolower $n] + upvar #0 nick_unique($n) u + if {[chandb_exists $chan]} { + sendprivmsg $n Thanks. + } elseif {![info exists u]} { + sendprivmsg $n {Op me while not on the channel, why don't you ?} + } else { + set chan_initialop([irctolower $chan]) $u + sendprivmsg $n \ + "Thanks. You can use `channel manager ...' to register this channel." + if {![nickdb_exists $n] || ![string length [nickdb_get $n username]]} { + sendprivmsg $n \ + "(But to do that you must register your nick securely first.)" + } + } } } @@ -414,7 +437,8 @@ proc msg_KILL {p c user why} { nick_forget $user } -set nick_arys {onchans username} +set nick_counter 0 +set nick_arys {onchans username unique} proc nick_forget {n} { global nick_arys @@ -444,12 +468,19 @@ proc msg_NICK {p c newnick} { nick_case $newnick } +proc nick_ishere {n} { + global nick_counter + upvar #0 nick_unique($n) u + if {![info exists u]} { set u [incr nick_counter].$n.[clock seconds] } + nick_case $n +} + proc msg_JOIN {p c chan} { prefix_nick recordlastseen_n $n "joining $chan" 1 upvar #0 nick_onchans($n) oc lappend oc [irctolower $chan] - nick_case $n + nick_ishere $n } proc msg_PART {p c chan} { prefix_nick @@ -523,7 +554,7 @@ proc msg_353 {p c dest type chan nicklist} { check_nick $n upvar #0 nick_onchans($n) oc lappend oc $chan - nick_case $n + nick_ishere $n } } @@ -618,13 +649,6 @@ def_ucmd ? { ucmdr $help_topics() {} } -proc manyset {list args} { - foreach val $list var $args { - upvar 1 $var my - set my $val - } -} - proc check_username {target} { if { [string length $target] > 8 || @@ -633,66 +657,64 @@ proc check_username {target} { } { error "invalid username" } } -proc nickdb__head {} { +proc somedb__head {} { uplevel 1 { - set nl [irctolower $n] - upvar #0 nickdb($nl) ndbe - binary scan $nl H* nh - set nfn users/n$nh - if {![info exists ndbe] && [file exists $nfn]} { - set f [open $nfn r] + set idl [irctolower $id] + upvar #0 ${nickchan}db($idl) ndbe + binary scan $idl H* idh + set idfn $fprefix$idh + if {![info exists iddbe] && [file exists $idfn]} { + set f [open $idfn r] try_except_finally { set newval [read $f] } {} { close $f } if {[llength $newval] % 2} { error "invalid length" } - set ndbe $newval + set iddbe $newval } } } -proc def_nickdb {name arglist body} { - proc nickdb_$name $arglist "nickdb__head; $body" +proc def_somedb {name arglist body} { + foreach {nickchan fprefix} {nick users/n chan chans/c} { + proc ${nickchan}db_$name $arglist \ + "set nickchan $nickchan; set fprefix $fprefix; somedb__head; $body" + } } -def_nickdb exists {n} { - return [info exists ndbe] +def_somedb exists {id} { + return [info exists iddbe] } -def_nickdb delete {n} { - catch { unset ndbe } - file delete $nfn +def_somedb delete {id} { + catch { unset iddbe } + file delete $idfn } -set default_settings {timeformat ks} +set default_settings_nick {timeformat ks} +set default_settings_chan {autojoin 1} -def_nickdb set {n args} { - global default_settings - if {![info exists ndbe]} { set ndbe $default_settings } - foreach {key value} [concat $ndbe $args] { set a($key) $value } +def_somedb set {id args} { + upvar #0 default_settings_$nickchan def + if {![info exists iddbe]} { set iddbe $def } + foreach {key value} [concat $iddbe $args] { set a($key) $value } set newval {} foreach {key value} [array get a] { lappend newval $key $value } - set f [open $nfn.new w] + set f [open $idfn.new w] try_except_finally { puts $f $newval close $f - file rename -force $nfn.new $nfn + file rename -force $idfn.new $idfn } { } { catch { close $f } } - set ndbe $newval + set iddbe $newval } -proc opt {key} { - global calling_nick - if {[info exists calling_nick]} { set n $calling_nick } { set n {} } - return [nickdb_opt $n $key] -} - -def_nickdb opt {n key} { - global default_settings - if {[info exists ndbe]} { - set l $ndbe +def_somedb get {id key} { + upvar #0 default_settings_$nickchan def + if {[info exists iddbe]} { + set l $iddbe } else { - set l $default_settings + set l $def } foreach {tkey value} $l { if {"$tkey" == "$key"} { return $value } @@ -700,6 +722,12 @@ def_nickdb opt {n key} { error "unset setting $key" } +proc opt {key} { + global calling_nick + if {[info exists calling_nick]} { set n $calling_nick } { set n {} } + return [nickdb_get $n $key] +} + proc check_notonchan {} { upvar 1 dest dest if {[ischan $dest]} { error "that command must be sent privately" } @@ -708,7 +736,7 @@ proc check_notonchan {} { proc nick_securitycheck {strict} { upvar 1 n n if {![nickdb_exists $n]} { error "you are unknown to me, use `register'." } - set wantu [nickdb_opt $n username] + set wantu [nickdb_get $n username] if {![string length $wantu]} { if {$strict} { error "that feature is only available to secure users, sorry." @@ -725,6 +753,121 @@ proc nick_securitycheck {strict} { } } +proc channel_securitycheck {channel n} { + # You must also call `nick_securitycheck 1' + if {[lsearch -exact [irctolower [chandb_get $channel managers]] $n] < 0} { + error "you are not a manager of $channel" + } +} + +proc def_chancmd {name body} { + proc channel/$name {} \ + " upvar 1 target chan; upvar 1 n n; upvar 1 text text; $body" +} + +def_chancmd manager { + set opcode [ta_word] + switch -exact _$opcode { + _= { set ml {} } + _+ - _- { + if {[chandb_exists $chan]} { + set ml [chandb_get $chan managers] + } else { + set ml [list [irctolower $n]] + } + } + default { + error "`channel manager' opcode must be one of + - =" + } + } + foreach nn [split $text " "] { + if {![string length $nn]} continue + check_nick $nn + set nn [irctolower $nn] + if {"$opcode" != "-"} { + lappend ml $nn + } else { + set ml [grep nq {"$nq" != "$nn"} $ml] + } + } + if {[llength $ml]} { + chandb_set $chan managers $ml + ucmdr "Managers of $chan: $ml" {} + } else { + chandb_delete $chan + ucmdr {} {} "forgets about managing $chan." {} + } +} + +def_chancmd autojoin { + set yesno [ta_word] + switch -exact [string tolower $yesno] { + no { set nv 0 } + yes { set nv 1 } + default { error "channel autojoin must be `yes' or `no' } + } + chandb_set $chan autojoin $nv +} + +def_chancmd show { + if {[chandb_exists $chan]} { + set l "Settings for $chan: autojoin " + append l [lindex {no yes} [chandb_get $chan autojoin]] + append l "\nManagers: " + append l [join [chandb_get $chan managers] " "] + ucmdr {} $l + } else { + ucmdr {} "The channel $chan is not managed." + } +} + +def_ucmd op { + if {[ischan $dest]} { set target $dest } + if {[ta_anymore]} { set target [ta_word] } + ta_nomore + if {![info exists target]} { error "you must specify, or !... on, the channel" } + if {![ischan $target]} { error "not a valid channel" } + if {![chandb_exists $target]} { error "$target is not a managed channel." } + prefix_nick + nick_securitycheck 1 + channel_securitycheck $target $n + sendout MODE $target +o $n +} + +def_ucmd channel { + if {[ischan $dest]} { set target $dest } + if {![ta_anymore]} { + set subcmd show + } else { + set subcmd [ta_word] + } + if {[ischan $subcmd]} { + set target $subcmd + if {![ta_anymore]} { + set subcmd show + } else { + set subcmd [ta_word] + } + } + if {![info exists target]} { error "privately, you must specify a channel" } + set procname channel/$subcmd + if {"$subcmd" != "show"} { + if {[catch { info body $procname }]} { error "unknown channel setting $subcmd" } + prefix_nick + nick_securitycheck 1 + if {[chandb_exists $target]} { + channel_securitycheck $target $n + } else { + upvar #0 chan_initialop([irctolower $target]) io + upvar #0 nick_unique($n) u + if {![info exists io]} { error "$target is not a managed channel" } + if {"$io" != "$u"} { error "you are not the interim manager of $target" } + if {"$subcmd" != "manager"} { error "use `channel manager' first" } + } + } + channel/$subcmd +} + def_ucmd who { if {[ta_anymore]} { set target [ta_word]; ta_nomore @@ -743,7 +886,7 @@ def_ucmd who { } if {![nickdb_exists $target]} { set ol "$nshow is not a registered nick." - } elseif {[string length [set username [nickdb_opt $target username]]]} { + } elseif {[string length [set username [nickdb_get $target username]]]} { set ol "The nick $nshow belongs to the user $username." } else { set ol "The nick $nshow is registered (but not to a username)." @@ -818,7 +961,7 @@ proc def_setting {opt show_body set_body} { } def_setting timeformat { - set tf [nickdb_opt $n timeformat] + set tf [nickdb_get $n timeformat] return "$tf: [timeformat_desc $tf]" } { set tf [string tolower [ta_word]] @@ -829,7 +972,7 @@ def_setting timeformat { } def_setting security { - set s [nickdb_opt $n username] + set s [nickdb_get $n username] if {[string length $s]} { return "Your nick, $n, is controlled by the user $s." } else { diff --git a/helpinfos b/helpinfos index d421bab..18b5402 100644 --- a/helpinfos +++ b/helpinfos @@ -3,8 +3,8 @@ General commands: Registration and user settings: help [||] register [insecure|delete] seen set [ []] who [] summon (See `help identify', `help blight-id') - convert Channel settings: - ops oplist [] [+|-|= [?] ...] + convert Channel settings (see `help channel'): + ops channel [] [....] Options: Additional help topics: timeformat ks|hms identify identpass invite blight-id Send commands to me by /msg, or say them in channel with ! in front. @@ -38,24 +38,34 @@ convert Converts the specified quantity into SI units. Units that are understood are any understood by units(1) and also kelvin celsius fahrenheit (convert to celsius or kelvin) +(Not yet implemented.) -!ops -ops on channel -ops (privately) - Asks me to give you channel operator privilege. You must be using - a secure nick and have identified yourself (see `help identify'). -(Not yet implemented!) - -!oplist -oplist [] show chop list -oplist [] + ... add nicks to chop list -oplist [] - ... remove nicks from chop list -oplist [] = ... set chop list - Configures the list of who may use the `ops' command. You must be - on the oplist yourself to do this. If you op me on a channel I'll - automatically add you to the oplist if you have identified yourself. - If you make the channel op list empty I'll forget about the channel. -(Not yet implemented!) +!op +op on channel +op (privately) + I'll give you channel operator privilege, if you're a manager. + +!channel +channel [] [show] show settings +channel [] manager +|-|= ... set manager list +channel [] autojoin yes|no join at bot start ? + See `help ' (eg, `help manager') for more info. + +!autojoin +channel [] autojoin yes|no (`yes' is default.) + Controls whether I'll join the channel when I'm (re)started. +(Not yet implemented.) + +!manager +channel [] manager + ... add managers +channel [] manager - ... remove managers +channel [] manager = ... set new manager list + Managers are those who can use the `channel' command to change + channel settings. Manager status is only effective for secure + nicks, after the manager has identified themselves. + If you op me on an unmanaged channel you become the only manager, + but you must use `channel' to change a channel setting to make this + permanent. To make a channel unmanaged, make it have no managers. !identify You must identify yourself to change your settings and to use channel @@ -102,3 +112,6 @@ set timeformat ks show times in seconds, kiloseconds, etc. set timeformat hms use days, hours, minutes, seconds # +# Local variables: +# fill-column: 69 +# End. -- [mdw]