############################
#### 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.