# ---------- # Channel Management # # Detailed explanations: https://git.0bin.xyz/pegasus/tclscripts/src/branch/main/Chanban#readme # ---------- namespace eval cmgmt { # ---------- # Configuration # ---------- # Language to be use on this script # Available languages: en (English), it (Italian), pt (Portuguese European) variable locale "en" # Directory where the language files are located variable lang_dir "scripts/cmgmt_langs" # Trigger to be used variable trigger "@" # Temporary ban duration, in minutes variable tBanDuration "30" # Command to upload the file # The ban list file is piped into the command via stdin (with `cat $filename |`) # so your command must read from stdin variable upCommand "curl -s -F file=@- https://x0.at/" # Set the banmask type to use in banning the user # Recommended type: 2 # Available types are: # 0 *!user@host # 1 *!*user@host # 2 *!*@host # 3 *!*user@*.host # 4 *!*@*.host # 5 nick!user@host # 6 nick!*user@host # 7 nick!*@host # 8 nick!*user@*.host # 9 nick!*@*.host variable banMask "2" # Mask type to be used when adding an op. Same types as above # We advise to use 1, as it's more secure variable addOpMask "1" # Masks to protect from bans, always on the format *!ident@hostname variable protectMasks { *!*@services.libera.chat } # Nicks to ignore for auto adding bans variable noAddNicks { ChanServ NickServ ChanBot } # Masks to ignore for auto adding bans variable noAddMasks { *!*@services.libera.chat } # ---------- # Binds # ---------- ### Public bind pub * ${::cmgmt::trigger}addban ::cmgmt::addban_pub bind pub * ${::cmgmt::trigger}ban ::cmgmt::ban_pub bind pub * ${::cmgmt::trigger}tban ::cmgmt::tban_pub bind pub * ${::cmgmt::trigger}kick ::cmgmt::kick_pub bind pub * ${::cmgmt::trigger}voice ::cmgmt::voice_pub bind pub * ${::cmgmt::trigger}devoice ::cmgmt::devoice_pub bind pub * ${::cmgmt::trigger}unban ::cmgmt::unban_pub bind pub * ${::cmgmt::trigger}banlist ::cmgmt::banlist_pub bind pub * ${::cmgmt::trigger}autoadd ::cmgmt::autoban_pub bind pub * ${::cmgmt::trigger}opcmds ::cmgmt::opcmds_pub bind pub * ${::cmgmt::trigger}addop ::cmgmt::addop_pub bind pub * ${::cmgmt::trigger}delop ::cmgmt::delop_pub bind pub * ${::cmgmt::trigger}addvoice ::cmgmt::addvoice_pub bind pub * ${::cmgmt::trigger}delvoice ::cmgmt::delvoice_pub bind pub * ${::cmgmt::trigger}ops ::cmgmt::chanops_pub bind pub * ${::cmgmt::trigger}voices ::cmgmt::chanvoices_pub ### Private bind msg * addban ::cmgmt::addban_msg bind msg * ban ::cmgmt::ban_msg bind msg * tban ::cmgmt::tban_msg bind msg * kick ::cmgmt::kick_msg bind msg * unban ::cmgmt::unban_msg bind msg * voice ::cmgmt::voice_msg bind msg * devoice ::cmgmt::devoice_msg bind msg * banlist ::cmgmt::banlist_msg bind msg * autoadd ::cmgmt::autoban_msg bind msg * opcmds ::cmgmt::opcmds_msg bind msg * addop ::cmgmt::addop_msg bind msg * delop ::cmgmt::delop_msg bind msg * addvoice ::cmgmt::addvoice_msg bind msg * delvoice ::cmgmt::delvoice_msg bind msg * ops ::cmgmt::chanops_msg bind msg * voices ::cmgmt::chanvoices_msg # Channel flag to auto add bans to the bot ban list setudef flag addBans # ---------- # End of configuration # ---------- # ---------- # DON'T TOUCH ANYTHING BELOW UNLESS YOU KNOW WHAT YOU ARE DOING # # If you touch the code below and then complain the script "suddenly stopped working" I'll touch you at night. # ---------- if { [catch { package require msgcat }] } { if {$cmgmt::locale eq "en"} { putloglev o * "\[Channel Management\] This script needs msgcat package to work. The script cannot be loaded." return } if {$::cmgmt::locale eq "it"} { putloglev o * "\[Channel Management\] Questo script richiede il pacchetto msgcat per funzionare. Lo script non può essere caricato." return } if {$::cmgmt::locale eq "pt"} { putloglev o * "\[Channel Management\] Este script necessita do pacote msgcat para funcionar. O script não pode ser carregado." return } } ::msgcat::mclocale $::cmgmt::locale ::msgcat::mcload [file join $cmgmt::lang_dir] # ---------- # Script name and author variable scriptName "Channel Management v1.1 \(06/03/2026-09:30\)" variable scriptAuthor "PeGaSuS" # ---------- # Public procs # ---------- ### Pub Addban - Be aware that this commands expects the mask to properly formatted proc addban_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set banmask [lindex [split $text] 0] set reason [join [lrange [split $text] 1 end] " "] if {$reason eq ""} { set reason [::msgcat::mc ban.reason] } if {$banmask eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]addban \[reason\]" return 0 } if {[matchstr $::botname $banmask] || [matchstr $banmask $::botname]} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } foreach pmask $::cmgmt::protectMasks { if {[matchstr $pmask $banmask] || [matchstr $banmask $pmask]} { putserv "PRIVMSG $chan :[::msgcat::mc prot.user.addban]" return 0 } } foreach nmask $::cmgmt::noAddMasks { if {[matchstr $nmask $banmask] || [matchstr $banmask $nmask]} { putserv "PRIVMSG $chan :[::msgcat::mc prot.user.addban]" return 0 } } foreach user [userlist] { if {[matchattr $user mno|mno $chan]} { foreach host [getuser $user HOSTS] { if {[matchstr $banmask $host] || [matchstr $host $banmask]} { putserv "PRIVMSG $chan :[::msgcat::mc prot.user.addban]" return 0 } } } } newchanban $chan $banmask $nick $reason 0 pushmode $chan +b $banmask putserv "PRIVMSG $chan :[::msgcat::mc ban.added $banmask $chan]" return 0 } ### Pub Ban proc ban_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 0] set reason [join [lrange [split $text] 1 end] " "] if {$reason eq ""} { set reason [::msgcat::mc ban.reason] } if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]ban \[reason\]" return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq $::botnick} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc protected.user $target]" return 0 } set bhost [string trim [getchanhost $target $chan] ~] foreach pmask $::cmgmt::protectMasks { if {[matchstr $pmask "${target}!$bhost"] || [matchstr "${target}!$bhost" $pmask]} { putserv "NOTICE $nick :[::msgcat::mc protected.user $target]" return 0 } } if {[matchstr "uid*" $bhost] || [matchstr "sid*" $bhost]} { set banmask *!*$bhost } else { set banmask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::banMask] } newchanban $chan $banmask $nick $reason 0 pushmode $chan +b $banmask putkick $chan $target $reason putserv "PRIVMSG $chan :[::msgcat::mc ban.added $banmask $chan]" return 0 } ### Pub Tban proc tban_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 0] set reason [join [lrange [split $text] 1 end] " "] if {$reason eq ""} { set reason [::msgcat::mc temp.ban.reason] } if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]tban \[reason\]" return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq $::botnick} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc protected.user $target]" return 0 } set bhost [string trim [getchanhost $target $chan] ~] foreach pmask $::cmgmt::protectMasks { if {[matchstr $pmask "${target}!$bhost"] || [matchstr "${target}!$bhost" $pmask]} { putserv "NOTICE $nick :[::msgcat::mc protected.user $target]" return 0 } } if {[matchstr "uid*" $bhost] || [matchstr "sid*" $bhost]} { set banmask *!*$bhost } else { set banmask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::banMask] } newchanban $chan $banmask $nick $reason $::cmgmt::tBanDuration pushmode $chan +b $banmask putkick $chan $target $reason putserv "PRIVMSG $chan :[::msgcat::mc tmp.ban.added $banmask $chan]" return 0 } ### Pub Kick proc kick_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 0] set reason [join [lrange [split $text] 1 end] " "] if {$reason eq ""} { set reason [::msgcat::mc kick.reason] } if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]kick \[reason\]" return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq $::botnick} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc protected.user $target]" return 0 } putkick $chan $target $reason return 0 } ### Pub Voice proc voice_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 0] if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]voice " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc protected.user $target]" return 0 } pushmode $chan +v $target return 0 } ### Pub Devoice proc devoice_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 0] if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]devoice " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc protected.user $target]" return 0 } pushmode $chan -v $target return 0 } ### Pub Unban proc unban_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set banmask [lindex [split $text] 0] if {$banmask eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]unban " return 0 } if {![isban $banmask $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.ban.mask $banmask $chan]" return 0 } killchanban $chan $banmask pushmode $chan -b $banmask putserv "PRIVMSG $chan :[::msgcat::mc ban.removed $banmask $chan]" return 0 } ### Pub Banlist proc banlist_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set cbans [banlist $chan] set cbans [lsearch -all -inline -not -index 1 $cbans "EXTBAN"] if {[llength $cbans] == 0} { putserv "PRIVMSG $chan :[::msgcat::mc banlist.empty $chan]" return 0 } set filename [string trim "$chan" #]_banlist.txt set bancount [llength $cbans] set blist [open $filename "w"] set i 1 puts $blist "[::msgcat::mc banlist.open $chan $bancount]" puts $blist "" foreach botban $cbans { set banmask [lindex $botban 0] set reason [lindex $botban 1] if {[isbansticky $banmask $chan]} { set freason "$reason \(sticky\)" } else { set freason "$reason" } set tstamp [lindex $botban 3] set date [clock format $tstamp -format "%d/%m/%Y - %H:%M:%S"] set creator [lindex $botban end] puts $blist "\[${i}\] [::msgcat::mc banlist.format $banmask $freason $creator $date]" puts $blist "" incr i } puts $blist "[::msgcat::mc banlist.end $chan]" puts $blist "" puts $blist "[::msgcat::mc banlist.explain $::cmgmt::trigger]unban " close $blist if {[catch { set result [exec cat $filename | {*}$::cmgmt::upCommand] } err]} { putserv "PRIVMSG $chan :[::msgcat::mc banlist.upload.fail $err]" file delete $filename return 0 } putserv "PRIVMSG $chan :[::msgcat::mc banlist.url $chan $result]" file delete $filename return 0 } ### Pub Autoadd proc autoban_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set option [lindex [split $text] 0] switch $option { on { if {[channel get $chan addBans]} { putserv "PRIVMSG $chan :[::msgcat::mc autoadd.enabled $chan]" return 0 } else { channel set $chan +addBans putserv "PRIVMSG $chan :[::msgcat::mc autoadd.enable $chan]" return 0 } } off { if {![channel get $chan addBans]} { putserv "PRIVMSG $chan :[::msgcat::mc autoadd.disabled $chan]" return 0 } else { channel set $chan -addBans putserv "PRIVMSG $chan :[::msgcat::mc autoadd.disable $chan]" return 0 } } status { if {[channel get $chan addBans]} { set turned [::msgcat::mc is.enabled] } else { set turned [::msgcat::mc is.disabled] } putserv "PRIVMSG $chan :[::msgcat::mc autoadd.status $turned $chan]" return 0 } default { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]autoadd " return 0 } } return 0 } ### Pub OPcmds proc opcmds_pub {nick uhost hand chan text} { if {![matchattr $hand o|o $chan]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } putserv "PRIVMSG $chan :[::msgcat::mc cmgmt.cmds $::cmgmt::trigger]" return 0 } ### Pub Addop proc addop_pub {nick uhost hand chan text} { set target [lindex [split $text] 0] if {![matchattr $hand n]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]addop " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq "$::botnick"} { return 0 } set opMask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::addOpMask] if {[validuser $target]} { if {[matchattr [nick2hand $target] mno|o $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc got.oflag $target $chan]" return 0 } else { chattr $target |+o $chan pushmode $chan +o $target putserv "PRIVMSG $chan :[::msgcat::mc added.chanop $target $chan]" return 0 } } adduser $target $opMask chattr $target |+o $chan pushmode $chan +o $target putserv "PRIVMSG $chan :[::msgcat::mc added.chanop $target $chan]" return 0 } ### Pub Delop proc delop_pub {nick uhost hand chan text} { set visop 0 if {![matchattr $hand n]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 0] if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]delop " return 0 } if {![validuser $target]} { putserv "PRIVMSG $chan :[::msgcat::mc inexistent.user $target]" return 0 } set user [nick2hand $target] chattr $user |-o $chan foreach tc [channels] { if {[matchattr $user |o $tc]} { incr visop } } if {$visop == 0 && ![matchattr $user mno]} { deluser $user pushmode $chan -o $target putserv "PRIVMSG $chan :[::msgcat::mc op.deleted $target $chan]" putserv "NOTICE $nick :[::msgcat::mc db.user.deleted $target]" return 0 } else { pushmode $chan -o $target putserv "PRIVMSG $chan :[::msgcat::mc op.deleted $target $chan]" return 0 } } ### Pub Addvoice proc addvoice_pub {nick uhost hand chan text} { set target [lindex [split $text] 0] if {![matchattr $hand n]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]addvoice " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq "$::botnick"} { return 0 } set voiceMask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::addOpMask] if {[validuser $target]} { if {[matchattr [nick2hand $target] mno|o $chan]} { putserv "PRIVMSG $chan :[::msgcat::mc got.oflag $target $chan]" return 0 } else { chattr $target |+v $chan pushmode $chan +v $target putserv "PRIVMSG $chan :[::msgcat::mc added.chanvoice $target $chan]" return 0 } } adduser $target $voiceMask chattr $target |+v $chan pushmode $chan +v $target putserv "PRIVMSG $chan :[::msgcat::mc added.chanvoice $target $chan]" return 0 } ### Pub Delvoice proc delvoice_pub {nick uhost hand chan text} { set visvoice 0 if {![matchattr $hand n]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 0] if {$target eq ""} { putserv "PRIVMSG $chan :[::msgcat::mc error.syntax $::cmgmt::trigger]delvoice " return 0 } if {![validuser $target]} { putserv "PRIVMSG $chan :[::msgcat::mc inexistent.user $target]" return 0 } set user [nick2hand $target] chattr $user |-v $chan foreach tc [channels] { if {[matchattr $user |vo $tc]} { incr visvoice } } if {$visvoice == 0 && ![matchattr $user mno]} { deluser $user pushmode $chan -v $target putserv "PRIVMSG $chan :[::msgcat::mc voice.deleted $target $chan]" putserv "NOTICE $nick :[::msgcat::mc db.user.deleted $target]" return 0 } else { pushmode $chan -v $target putserv "PRIVMSG $chan :[::msgcat::mc voice.deleted $target $chan]" return 0 } } # Pub Ops proc chanops_pub {nick uhost hand chan text} { if {![matchattr $hand n]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } putserv "PRIVMSG $chan :[::msgcat::mc chanop.list $chan] [join [userlist |o $chan] {, }]" return 0 } # Pub Voices proc chanvoices_pub {nick uhost hand chan text} { if {![matchattr $hand n]} { putserv "NOTICE $nick :[::msgcat::mc error.no.access $nick]" return 0 } putserv "PRIVMSG $chan :[::msgcat::mc chanvoice.list $chan] [join [userlist |v $chan] {, }]" return 0 } # ---------- # Private procs # ---------- ### PM Addban - Be aware that this commands expects the mask to properly formatted proc addban_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] addban <#chan> \[reason\]" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set banmask [lindex [split $text] 1] set reason [join [lrange [split $text] 2 end] " "] if {$reason eq ""} { set reason [::msgcat::mc ban.reason] } if {$banmask eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] addban <#chan> \[reason\]" return 0 } if {[matchstr $::botname $banmask] || [matchstr $banmask $::botname]} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } foreach pmask $::cmgmt::protectMasks { if {[matchstr $pmask $banmask] || [matchstr $banmask $pmask]} { putserv "PRIVMSG $chan :[::msgcat::mc prot.user.addban]" return 0 } } foreach nmask $::cmgmt::noAddMasks { if {[matchstr $nmask $banmask] || [matchstr $banmask $nmask]} { putserv "PRIVMSG $chan :[::msgcat::mc prot.user.addban]" return 0 } } foreach user [userlist] { if {[matchattr $user mno|mno $chan]} { foreach host [getuser $user HOSTS] { if {[matchstr $banmask $host] || [matchstr $host $banmask]} { putserv "PRIVMSG $chan :[::msgcat::mc prot.user.addban]" return 0 } } } } newchanban $chan $banmask $nick $reason 0 pushmode $chan +b $banmask putserv "PRIVMSG $nick :[::msgcat::mc ban.added $banmask $chan]" return 0 } ### PM Ban proc ban_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] ban <#chan> \[reason\]" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] set reason [join [lrange [split $text] 2 end] " "] if {$reason eq ""} { set reason [::msgcat::mc ban.reason] } if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] ban <#chan> \[reason\]" return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq $::botnick} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc protected.user $target]" return 0 } set bhost [string trim [getchanhost $target $chan] ~] foreach pmask $::cmgmt::protectMasks { if {[matchstr $pmask "${target}!$bhost"] || [matchstr "${target}!$bhost" $pmask]} { putserv "PRIVMSG $nick :[::msgcat::mc protected.user $target]" return 0 } } if {[matchstr "uid*" $bhost] || [matchstr "sid*" $bhost]} { set banmask *!*$bhost } else { set banmask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::banMask] } newchanban $chan $banmask $nick $reason 0 pushmode $chan +b $banmask putkick $chan $target $reason putserv "PRIVMSG $nick :[::msgcat::mc ban.added $banmask $chan]" return 0 } ### PM Tban proc tban_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] tban <#chan> \[reason\]" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] set reason [join [lrange [split $text] 2 end] " "] if {$reason eq ""} { set reason [::msgcat::mc temp.ban.reason] } if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] tban <#chan> \[reason\]" return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq $::botnick} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc protected.user $target]" return 0 } set bhost [string trim [getchanhost $target $chan] ~] foreach pmask $::cmgmt::protectMasks { if {[matchstr $pmask "${target}!$bhost"] || [matchstr "${target}!$bhost" $pmask]} { putserv "PRIVMSG $nick :[::msgcat::mc protected.user $target]" return 0 } } if {[matchstr "uid*" $bhost] || [matchstr "sid*" $bhost]} { set banmask *!*$bhost } else { set banmask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::banMask] } newchanban $chan $banmask $nick $reason $::cmgmt::tBanDuration pushmode $chan +b $banmask putkick $chan $target $reason putserv "PRIVMSG $nick :[::msgcat::mc tmp.ban.added $banmask $chan]" return 0 } ### PM Kick proc kick_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] kick <#chan> \[reason\]" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] set reason [join [lrange [split $text] 2 end] " "] if {$reason eq ""} { set reason [::msgcat::mc kick.reason] } if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] kick <#chan> \[reason\]" return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq $::botnick} { putkick $chan $nick [::msgcat::mc revenge.kick] return 0 } if {[isop $target $chan] || [matchattr [nick2hand $target] o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc protected.user $target]" return 0 } putkick $chan $target $reason return 0 } ### PM Voice proc voice_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] voice <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] voice <#chan> " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.on.chan $target $chan]" return 0 } pushmode $chan +v $target return 0 } ### PM Devoice proc devoice_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] devoice <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] devoice <#chan> " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.on.chan $target $chan]" return 0 } pushmode $chan -v $target return 0 } ### PM Unban proc unban_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] unban <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set banmask [lindex [split $text] 1] if {$banmask eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] unban <#chan> " return 0 } if {![isban $banmask $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.ban.mask $banmask $chan]" return 0 } killchanban $chan $banmask pushmode $chan -b $banmask putserv "PRIVMSG $nick :[::msgcat::mc ban.removed $banmask $chan]" return 0 } ### PM Banlist proc banlist_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] banlist <#chan>" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set cbans [banlist $chan] set cbans [lsearch -all -inline -not -index 1 $cbans "EXTBAN"] if {[llength $cbans] == 0} { putserv "PRIVMSG $nick :[::msgcat::mc banlist.empty $chan]" return 0 } set filename [string trim "$chan" #]_banlist.txt set bancount [llength $cbans] set blist [open $filename "w"] set i 1 puts $blist "[::msgcat::mc banlist.open $chan $bancount]" puts $blist "" foreach botban $cbans { set banmask [lindex $botban 0] set reason [lindex $botban 1] if {[isbansticky $banmask $chan]} { set freason "$reason \(sticky\)" } else { set freason "$reason" } set tstamp [lindex $botban 3] set date [clock format $tstamp -format "%d/%m/%Y - %H:%M:%S"] set creator [lindex $botban end] puts $blist "\[${i}\] [::msgcat::mc banlist.format $banmask $freason $creator $date]" puts $blist "" incr i } puts $blist "[::msgcat::mc banlist.end $chan]" puts $blist "" puts $blist "[::msgcat::mc pm.banlist.explain $::botnick] unban " close $blist if {[catch { set result [exec cat $filename | {*}$::cmgmt::upCommand] } err]} { putserv "PRIVMSG $nick :[::msgcat::mc banlist.upload.fail $err]" file delete $filename return 0 } putserv "PRIVMSG $nick :[::msgcat::mc banlist.url $chan $result]" file delete $filename return 0 } ### PM Auto add proc autoban_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] autoadd <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set option [lindex [split $text] 1] switch $option { on { if {[channel get $chan addBans]} { putserv "PRIVMSG $nick :[::msgcat::mc autoadd.enabled $chan]" return 0 } else { channel set $chan +addBans putserv "PRIVMSG $nick :[::msgcat::mc autoadd.enable $chan]" return 0 } } off { if {![channel get $chan addBans]} { putserv "PRIVMSG $nick :[::msgcat::mc autoadd.disabled $chan]" return 0 } else { channel set $chan -addBans putserv "PRIVMSG $nick :[::msgcat::mc autoadd.disable $chan]" return 0 } } status { if {[channel get $chan addBans]} { set turned [::msgcat::mc is.enabled] } else { set turned [::msgcat::mc is.disabled] } putserv "PRIVMSG $nick :[::msgcat::mc autoadd.status $turned $chan]" return 0 } default { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] autoadd <#chan> " return 0 } } return 0 } ### PM Opcmds proc opcmds_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] opcmds <#chan>" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand o|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } putserv "PRIVMSG $nick :[::msgcat::mc msg.cmgmt.cmds]" return 0 } ### PM Addop proc addop_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] addop <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand n]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] addop <#chan> " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq "$::botnick"} { return 0 } set opMask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::addOpMask] if {[validuser $target]} { if {[matchattr [nick2hand $target] mno|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc got.oflag $target $chan]" return 0 } else { chattr $target |+o $chan pushmode $chan +o $target putserv "PRIVMSG $nick :[::msgcat::mc added.chanop $target $chan]" return 0 } } adduser $target $opMask chattr $target |+o $chan pushmode $chan +o $target putserv "PRIVMSG $nick :[::msgcat::mc added.chanop $target $chan]" return 0 } ### PM Delop proc delop_msg {nick uhost hand text} { set chan [lindex [split $text] 0] set visop 0 if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] delop <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand n]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] delop <#chan> " return 0 } if {![validuser $target]} { putserv "PRIVMSG $nick :[::msgcat::mc inexistent.user $target]" return 0 } set user [nick2hand $target] chattr $user |-o $chan foreach tc [channels] { if {[matchattr $user |o $tc]} { incr visop } } if {$visop == 0 && ![matchattr $user mno]} { deluser $user pushmode $chan -o $target putserv "PRIVMSG $nick :[::msgcat::mc op.deleted $target $chan]" putserv "PRIVMSG $nick :[::msgcat::mc db.user.deleted $target]" return 0 } else { pushmode $chan -o $target putserv "PRIVMSG $nick :[::msgcat::mc op.deleted $target $chan]" return 0 } } ### PM Addvoice proc addvoice_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] addvoice <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand n]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] addvoice <#chan> " return 0 } if {![onchan $target $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc not.on.chan $target $chan]" return 0 } if {$target eq "$::botnick"} { return 0 } set voiceMask [maskhost ${target}![getchanhost $target $chan] $::cmgmt::addOpMask] if {[validuser $target]} { if {[matchattr [nick2hand $target] mno|o $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc got.oflag $target $chan]" return 0 } else { chattr $target |+v $chan pushmode $chan +v $target putserv "PRIVMSG $nick :[::msgcat::mc added.chanvoice $target $chan]" return 0 } } adduser $target $voiceMask chattr $target |+v $chan pushmode $chan +v $target putserv "PRIVMSG $nick :[::msgcat::mc added.chanvoice $target $chan]" return 0 } ### PM Delvoice proc delvoice_msg {nick uhost hand text} { set chan [lindex [split $text] 0] set visvoice 0 if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] delvoice <#chan> " return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand n]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } set target [lindex [split $text] 1] if {$target eq ""} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] delvoice <#chan> " return 0 } if {![validuser $target]} { putserv "PRIVMSG $nick :[::msgcat::mc inexistent.user $target]" return 0 } set user [nick2hand $target] chattr $user |-v $chan foreach tc [channels] { if {[matchattr $user |vo $tc]} { incr visvoice } } if {$visvoice == 0 && ![matchattr $user mno]} { deluser $user pushmode $chan -v $target putserv "PRIVMSG $nick :[::msgcat::mc voice.deleted $target $chan]" putserv "PRIVMSG $nick :[::msgcat::mc db.user.deleted $target]" return 0 } else { pushmode $chan -v $target putserv "PRIVMSG $nick :[::msgcat::mc voice.deleted $target $chan]" return 0 } } # PM Ops proc chanops_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] ops <#chan>" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand n]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } putserv "PRIVMSG $nick :[::msgcat::mc chanop.list $chan] [join [userlist |o $chan] {, }]" return 0 } # PM Voices proc chanvoices_msg {nick uhost hand text} { set chan [lindex [split $text] 0] if {![matchstr "#*" $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc pm.error.syntax] voices <#chan>" return 0 } if {![validchan $chan]} { putserv "PRIVMSG $nick :[::msgcat::mc bot.not.onchan $chan]" return 0 } if {![matchattr $hand n]} { putserv "PRIVMSG $nick :[::msgcat::mc error.no.access $nick]" return 0 } putserv "PRIVMSG $nick :[::msgcat::mc chanvoice.list $chan] [join [userlist |v $chan] {, }]" return 0 } # ---------- DON'T TOUCH UNLESS YOU KNOW WHAT YOU'RE DOING ---------- # # ---------- # Auto add bans binds # ---------- # Add bans bind mode * "*+b*" ::cmgmt::abans bind mode * "*-b*" ::cmgmt::rbans # ---------- # Auto add bans # ---------- proc abans {nick uhost hand chan mode target} { # putlog "DEBUG autobans: nick=$nick chan=$chan mode=$mode target=$target" set banReason "[::msgcat::mc ban.reason] \(auto-added\)" if {$nick ne "$::botnick" && $nick ni $::cmgmt::noAddNicks} { foreach pmask $::cmgmt::protectMasks { if {[matchstr $pmask $target] || [matchstr $target $pmask]} { pushmode $chan -b $target flushmode $chan return 0 } } foreach nmask $::cmgmt::noAddMasks { if {[matchstr $nmask $target] || [matchstr $target $nmask]} { pushmode $chan -b $target flushmode $chan return 0 } } foreach user [userlist] { if {[matchattr $user mno|mno $chan]} { foreach host [getuser $user HOSTS] { if {[matchstr $target $host] || [matchstr $host $target]} { pushmode $chan -b $target flushmode $chan return 0 } } } } if {![channel get $chan addBans]} { return 0 } # We also need to deal with the addition of extbans, since we don't deal with them internally # but we need to add them as sticky to our database to prevent the bot from removing them if {[matchstr "~*" $target] && ![isban $target $chan]} { newchanban $chan $target $nick EXTBAN 0 sticky return 0 } else { newchanban $chan $target $nick $banReason 0 putserv "NOTICE @$chan :[::msgcat::mc auto.added $target $chan]" return 0 } } return 0 } proc rbans {nick uhost hand chan mode target} { # putlog "DEBUG autobans: nick=$nick chan=$chan mode=$mode target=$target" if {![channel get $chan addBans]} { return 0 } if {$nick ne "$::botnick"} { if {[matchstr "~*" $target] && [isban $target $chan]} { killchanban $chan $target return 0 } } } # Lets check for existing extbans and add them to our ban list # and make them sticky so the bot doesn't remove them # The removal will be mirrored (if the bot is online) as soon as # a chanop removes the extban in the channel bind cron * "*/5 * * * *" ::cmgmt::addextbans proc addextbans {minute hour day month weekday} { # putlog "Adding existing extbans to banlist" foreach chan [channels] { foreach cban [chanbans $chan] { set mask [lindex [split $cban] 0] if {[matchstr "~*" $mask] && ![isban $mask $chan]} { newchanban $chan $mask $::botnick EXTBAN 0 sticky } } } return 0 } putlog "-= $::cmgmt::scriptName by $::cmgmt::scriptAuthor loaded =-" }