+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_somedb exists {id} {
+ return [info exists iddbe]
+}
+
+def_somedb delete {id} {
+ catch { unset iddbe }
+ file delete $idfn
+}
+
+set default_settings_nick {timeformat ks}
+set default_settings_chan {autojoin 1}
+
+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 $idfn.new w]
+ try_except_finally {
+ puts $f $newval
+ close $f
+ file rename -force $idfn.new $idfn
+ } {
+ } {
+ catch { close $f }
+ }
+ set iddbe $newval
+}
+
+def_somedb get {id key} {
+ upvar #0 default_settings_$nickchan def
+ if {[info exists iddbe]} {
+ set l $iddbe
+ } else {
+ set l $def
+ }
+ foreach {tkey value} $l {
+ if {"$tkey" == "$key"} { return $value }
+ }
+ 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" }
+}
+
+proc nick_securitycheck {strict} {
+ upvar 1 n n
+ if {![nickdb_exists $n]} { error "you are unknown to me, use `register'." }
+ set wantu [nickdb_get $n username]
+ if {![string length $wantu]} {
+ if {$strict} {
+ error "that feature is only available to secure users, sorry."
+ } else {
+ return
+ }
+ }
+ upvar #0 nick_username($n) nu
+ if {![info exists nu]} {
+ error "nick $n is secure, you must identify yourself first."
+ }
+ if {"$wantu" != "$nu"} {
+ error "you are the wrong user - the nick $n belongs to $wantu, not $nu"
+ }
+}
+
+proc channel_securitycheck {channel n} {
+ # You must also call `nick_securitycheck 1'
+ set mgrs [chandb_get $channel managers]
+ if {[lsearch -exact [irctolower $mgrs] [irctolower $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] }