############################ #### Checkaccess script #### ############################ ## Info # This script is made to work with the Undernet +D channelmode. # The +D mode makes joiners to a channel invisible, untill they speak. # This protects the channel more against join/part flooders, but also allows users to stay invisible. # This Tcl detects invisible users, and makes the bot execute all bind join scripts. # The detection happens 1 minute apart. This is the lowest timespan, without using timers, and should # be enough. # # What can you use this Tcl for? # Making autovoice and greet scripts work with +D # (or any other script that does something when a user joins the channel) # # Things to watch out for when using this Tcl # All the users that are found, are added all at once to the bot's internal channel list. # This can cause some problems with anti-flood scripts. Make sure to test out different # settings before using this tcl on very busy channels. # # - Voice scripts : # It's advised to use a voice script that waits a few seconds before voicing. # This is especially important when using defensive scripts like clonecheckers # or versioncheckers (that way, the offenders are weeded out, before they get voiced) # - Protective scripts : # Load protection scripts immediatly after this script, and before general scripts # like autovoice or greet scripts. This will make sure that protection is done before serving. # # This script adds a channel setting called 'checkhidden'. This script will only work on # a channel that's +D or +d, AND has the checkhidden-setting set to '+'. # You can do this by entering '.chanset #channel +checkhidden' in the partyline. # # ## Custom Commands # - none # ## Todo # - none at the moment. # ## How to install # You can install this tcl by editing your eggdrop.conf. # First copy this tcl to your prefered directory, then add a line to your eggdrop.conf # source path/to/script.tcl # Save the config and rehash your bot. # After this, the script is installed. # ## I want to contact you! # If you want to contact me, you can find me on: # - #tcl and #eggies @Undernet (irc.undernet.org) # Call "wanderer" in one of those channels, and if I'm there I will respond. # If you can't find me on irc, you're welcome to drop me an email on wanderer@powersource.cx # # Please check http://tcl.powersource.cx if you have problems with this tcl. If you can't find an update # or your problem isn't fixed by it, contact me. # I can't promise this tcl being without bugs, I do know that I've already put a lot of effort in them # and want to make them as good as possible. So please, let me know if you find a bug, or the script # isn't working for you. # ################# ### Variables ### ################# # Should feedback be sent to a "monitoring" channel? # set di(logchan) "#channel" set di(logchan) "" # Should feedback be sent to the partyline? # set di(pl) 0 set di(pl) 1 ############# ### Binds ### ############# bind time - "* * * * *" checkinvisible:check bind raw - 354 checkinvisible:raw:354 bind raw - 315 checkinvisible:raw:315 ############# ### Procs ### ############# ### ## Proc that handles the logging to logchan & partyline # proc checkinvisible:feedback {text} { if {[string index $::di(logchan) 0]=="#"} {puthelp "privmsg $::di(logchan) :$text"} if {$::di(pl)} {putlog "$text"} } ### ## Forking proc for *raw:irc:join # proc new:irc:join {nuh cmd channel} { set nuh [split $nuh "!"] set nick [lindex $nuh 0] set uhost [lindex $nuh 1] if {[string index $channel 0]==":"} {set channel [string range $channel 1 end]} if {![info exists ::di(hiddenusers,$channel)]} { set ::di(hiddenusers,$channel) {} } if {![string match *D* [getchanmode $channel]]||([lsearch -exact $::di(hiddenusers,$channel) $nick]>"-1"&&[lsearch -exact [chanlist $channel] $nick]=="-1")} { *raw:irc:joinreal "$nick!$uhost" "JOIN" ":$channel" } } ### ## Forking proc for *raw:irc:part # proc new:irc:part {nuh cmd text} { set nuh [split $nuh "@"] set nick [lindex $nuh 0] set uhost [lindex $nuh 1] if {[string index $text 0]==":"} { set channel [string range $text 1 end] } else { set channel [lindex [split $text " "] 0] } if {![info exists ::di(hiddenusers,$channel)]} { set ::di(hiddenusers,$channel) {} } # if in di(hiddenusers,$channel) -> remove from list if {[set i [lsearch -exact $::di(hiddenusers,$channel)]]>"-1"} {set ::di(hiddenusers,$channel) [lreplace $::di(hiddenusers,$channel) $i $i]} *raw:irc:partreal "$nick!uhost" "PART" "$text" } ### ## Proc that start the checking # proc checkinvisible:check {args} { set counter 1 foreach c [channels] { if {[channel get $c checkhidden]} { if {[string match -nocase *D* [getchanmode $c]]} { # This channel wants to check for hidden users AND has the D or d flag int:unset ::di(list,$c) set ::di(list,$c) {} set ::di(counter,$counter) $c set ::di(channel,$c) $counter puthelp "WHO $c d%tnuh,$counter" #checkinvisible:feedback "\002\[CheckInvisible\]\002 Checked for users in $c (WHO)" incr counter } } } } ### ## Raw 354 = reply from the WHO-command # proc checkinvisible:raw:354 {from cmd text} { if {[llength $text]==5} { set text [split $text " "] set counter [lindex $text 1] set nick [lindex $text 4] set uname [lindex $text 2] set host [lindex $text 3] set channel $::di(counter,$counter) lappend ::di(list,$channel) $nick $uname $host } } ### ## Raw 315 = End of WHO-command # proc checkinvisible:raw:315 {from cmd text} { set channel [lindex [split $text " "] 1] if {[info exists ::di(channel,$channel)]&&[info exists ::di(list,$channel)]} { set foundusers {} set goneusers {} set counter $::di(channel,$channel) set detected [chanlist $channel] set undetected $::di(list,$channel) int:unset ::di($channel) int:unset ::di($counter) int:unset ::di(list,$channel) foreach {user uname host} $undetected { # is this user known? if {[lsearch -exact $detected $user]=="-1"} { lappend foundusers $user lappend ::di(hiddenusers,$channel) $user *raw:irc:join $user!$uname@$host JOIN $channel } } set ::di(hiddenusers,$channel) [lsort -unique $::di(hiddenusers,$channel)] # are there users in hiddenusers, that aren't found (left/quit)? foreach user $detected { if {[lsearch -exact $undetected $user]=="-1"} { lappend goneusers $user *raw:irc:part $user![getchanhost $user] PART :$channel } } if {[llength $foundusers]>0} { checkinvisible:feedback "\002\[CheckInvisible\]\002 The following new hidden user(s) were detected on $channel: [join $foundusers ", "]" } if {[llength $goneusers]>0} { checkinvisible:feedback "\002\[CheckInvisible\]\002 The following hidden user(s) left $channel: [join $goneusers ", "]" } } } ############ ### Init ### ############ # check if the *raw:irc:join proc exists # check if the *raw:irc:joinreal proc exists if {[string eq [info command "*raw:irc:join"] "*raw:irc:join"]} { if {[string eq [info command "*raw:irc:joinreal"] "*raw:irc:joinreal"]} { # the joinreal exists, clear the *raw:irc:join proc & rename new:irc:join rename *raw:irc:join "" rename new:irc:join *raw:irc:join } { # rename *raw:irc:join to *raw:irc:joinreal rename *raw:irc:join *raw:irc:joinreal rename new:irc:join *raw:irc:join } # o ooh... no *raw:irc:join proc... Something must be wrong... restarting. } {restart} # check if the *raw:irc:part proc exists # check if the *raw:irc:partreal proc exists if {[string eq [info command "*raw:irc:part"] "*raw:irc:part"]} { if {[string eq [info command "*raw:irc:partreal"] "*raw:irc:partreal"]} { # the partreal exists, clear the *raw:irc:part proc & rename new:irc:part rename *raw:irc:part "" rename new:irc:part *raw:irc:part } { # rename *raw:irc:part to *raw:irc:partreal rename *raw:irc:part *raw:irc:partreal rename new:irc:part *raw:irc:part } # o ooh... no *raw:irc:join proc... Something must be wrong... restarting. } {restart} proc int:unset {var} {if {[info exists $var]} {unset $var}} setudef flag checkhidden set psversion(checkinvisible) "1.11" putlog "\002\[CheckInvisible\]\002 $psversion(checkinvisible) -=\002LOADED\002=- (c)wanderer - http://tcl.powersource.cx" ################ ### Versions ### ################ # - 1.0 : Original version # Thanks to DammiT (#defence @ Undernet) to allow me to use his channel for testing purposes. # - 1.1 : Small bugfix concerning the parsing of RAW PART. # - 1.11 : Another bugfix in the part proc. The bug caused an error to display, when the script is newly loaded # and the first action on a channel is a part, not a join. # Thanks to n-iCe for reporting this. ################# ### Statement ### ################# # I was asked by some people from the "tcl committee" to not release this script to the public. I believe these people # to be the same ones that made the EAFS-tcl (#Ayuda @ Undernet - http://www.canal-ayuda.org/bulletin/forumdisplay.php?f=40) # The reason they asked me this, is because they firmly believe that only big channels who "deserve" it should have this tcl. # As you can see, I don't agree with that statement. Undernet doesn't place a requirement on +D mode itself either, does it? # # To all channel owners out there... If you have a good idea for a channel protection script, but can't write it... Come and find me. # # Regards, # Wanderer.