This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

TCL Error in clone detect

Old posts that have not been replied to for several years.
Locked
Y
Yoda
Halfop
Posts: 78
Joined: Thu Oct 24, 2002 2:57 am
Location: Milano, Italy
Contact:

TCL Error in clone detect

Post by Yoda »

Hi,
eggdrop has this error:

Tcl error [clone_detect]: can't read "hand": no such variable

this is the script:

Code: Select all

# -- Configuration ------------------------------------------------------------

# "Fast-kick" - If your IRC server allows it, you can kick many people at once
# in just one command (I have tried it with 20 kicks on IRCnet). If you think
# this works on your irc network, set to "1", if not, set to "0".
# Here is what I got by testing on some networks:
#   Dalnet   - 0
#   Efnet    - 1
#   IRCnet   - 1
#   Undernet - 0
set fastkick 0

# Is the whole clone-checking on or off by default?
# (use .clonecheck on/off to change while bot is running)
set clonecheck 1

# Hosts to except from clone-checking, wildcards (?*) allowed:
# - hosts which more than one users can use at the same time
# - hosts of your "friends" which are neither masters nor bots
# - hosts of bots on the channel which have no +b flag
# - etc etc
# Note: Use HOST, the thing after the users "@"
#       e.g.  "yo!yaba@yeba.edu" has host "yeba.edu"
set noclonehost {
}

# People with those flags are never clones: (Separate the list with spaces)
# Channel and Global flags are matched
set nocloneflag "b c m"

# How many minutes will a clone-host banning last
set clonebantime 2

# If this number of clones is reached, bot kicks and bans
set maxclone 1

# NOTICE other ops (if opped) when ANY clone joins/parts the channel? (0 = no)
# (for paranoid people only!)
set cloneopnotice 0

# -- Script -------------------------------------------------------------------

# A little proc to turn console +1 when a +m or +o joins:
bind chon - * dcc_on
proc dcc_on { hand idx } {
  set cons1on 0
  foreach chan [channels] {
    if {[matchattr $hand m|m $chan] || [matchattr $hand o|o $chan]} {
      set cons1on 1
    }
  }
  if {$cons1on} { utimer 1 "console $idx -+1" }
  return 0
}

# Opnotice proc, sends a notice to every op on a channel (if opped)
proc opnotice { chan text } {
	global botnick
	if {![botisop $chan]} { return 0 }
	if {$text == ""} { return 0 }
	# I set maxnicks to send the same NOTICE to maximal 10 nicks at the same
	# time. Rise it if you want. (I don't know what the maximum IRC-allowed is)
	set maxnicks 10
	set oplist ""
	set curnicks 0
	foreach thisnick [chanlist $chan] {
		# don't notice who's not op, the bot itself and other bots
		if {([isop $thisnick $chan]) && ($thisnick != $botnick) && (![matchattr [nick2hand $thisnick $chan] b])} {
			incr curnicks
			# Add next op
			lappend oplist $thisnick
			# Reached maxnicks?
			if {$curnicks == $maxnicks} {
				# Send the text to the current list
				regsub -all " " $oplist "," oplist
				puthelp "NOTICE $oplist :$text"
				# Clean up to begin next block
				set curnicks 0
				set oplist ""
			}
		}
	}
	if {$oplist != ""} {
		# still some left to process
		regsub -all " " $oplist "," oplist
		puthelp "NOTICE $oplist :$text"
	}
	return 1
}

bind dcc m|m clones dcc_clone_stats
bind dcc m|m clonescheck dcc_clonecheck
bind dcc m|m clonecheck dcc_clonecheck

# Kicks users matching $mask from $chan. Uses "fastkick", if enabled.
# Returns a list of kicked users (may not have been executed, because of lag)
proc kickall { mask chan reason } {
	global fastkick	botnick nocloneflag
	if {![validchan $chan]} { return "" }
	set kicked ""
	foreach thisnick [chanlist $chan] {
		if {$thisnick == $botnick} { continue }
		if {[string match "$mask" "$thisnick![getchanhost $thisnick $chan]"]} {
			set dontkick 0
			foreach exceptionflag $nocloneflag {
				if {[matchattr $hand $exceptionflag|$exceptionflag $chan]} {
					set dontkick 1
					break
				}
			}
			if {$dontkick} { continue }
			if {[botisop $chan]} {
			# We only can kick if we are op. But we want to return the list
			# of "kicked" even if we aren't
				if {$fastkick} {
					lappend knick $thisnick
					lappend kchan $chan
				} {
					putserv "KICK $chan $thisnick :$reason"
				}
			}
			lappend kicked $thisnick
		}
		if {$fastkick && [info exist knick]} {
			# Dump a KICK-line if it reaches 480 bytes
			if {[string length "KICK $knick $kchan :$reason"] > 480} {
				regsub -all " " $knick "," knick
				regsub -all " " $kchan "," kchan
				putserv "KICK $kchan $knick :$reason"
				unset knick
				unset kchan
			}
		}
	}
	if {$fastkick && [info exist knick]} {
		regsub -all " " $knick "," knick
		regsub -all " " $kchan "," kchan
		putserv "KICK $kchan $knick :$reason"
	}
	return "$kicked"
}

# Goes through the channel user list, marking clones. Called 10 secs after a
# rehash/restart and 1 min after the bot joins the chan	and after the bot is
# opped (to kick eventual unkicked clones)
proc set_clones { } {
	global clonelist botnick maxclone fastkick
	global noclonehost nocloneflag clonebantime
	if [array exists clonelist] { unset clonelist }
	foreach chan [channels] {
		set chan [string tolower $chan]
		set kicked ""
		foreach nick [chanlist $chan] {
			set hand [nick2hand $nick $chan]
			if {[lsearch -exact $kicked $nick] >= 0} {
				# This nick was already kicked
				continue
			}
      set host [string tolower [lindex [split [getchanhost $nick $chan] @] 1]]
			if [info exists clonelist($chan!$host)] {
				incr clonelist($chan!$host) 1
				if {$clonelist($chan!$host) >= $maxclone} {
					newchanban $chan "*!*@$host" $botnick "Clones \($clonelist($chan!$host)\)" $clonebantime
					set thiskicked [kickall "*!*@$host" $chan "Too many clones from $host"]
					set kicked [concat $kicked $thiskicked]
					putloglev 1 $chan "Max clones reached from $host in $chan: $thiskicked"
				}
				continue
			}
			set clonelist($chan!$host) 0
			if {$nick == $botnick} {unset clonelist($chan!$host)}
			foreach exceptionflag $nocloneflag {
				if {[matchattr $hand $exceptionflag|$exceptionflag $chan]} {
					if {[info exists clonelist($chan!$host)]} { unset clonelist($chan!$host) }
					break
				}
			}
			if {[info exists clonelist($chan!$host)]} {
				foreach exceptionhost $noclonehost {
					# remove it, if it is an exception
					if {[string match [string tolower $exceptionhost] [string tolower $host]]} {
						unset clonelist($chan!$host)
						break
					}
				}
			}
		}
	}
}
# (i love those 6-level identations...)

# Someone joining, check if this host already has someone here
proc clone_detect { nick uhost hand chan } {
	global clonelist maxclone botnick
	global nocloneflag noclonehost clonebantime cloneopnotice
	set chan [string tolower $chan]
	# It is me joining! Let's rescan the channels list for clones in 1 min!
	if {$nick == $botnick} {
		# previous timer exists, kill it, start a new one
		foreach this [timers] {
			if {[string compare [lindex $this 1] "set_clones"] == 0} {
				killtimer [lindex $this 2]
			}
		}
		timer 1 set_clones
		return 0
	}
	# Someone joining. Check if bot needs to update cloneslist first
	foreach this [timers] {
		if {[string compare [lindex $this 1] "set_clones"] == 0} {
			# Just relax, I need to refresh the clones-list first...
			return 0
		}
	}
	foreach exceptionflag $nocloneflag {
		if {[matchattr $hand $exceptionflag|$exceptionflag $chan]} {
			return 0
		}
	}
  set host [string tolower [lindex [split $uhost @] 1]]
	foreach exceptionhost $noclonehost {
		# if it is an exception do nothing
		if {[string match [string tolower $exceptionhost] $host]} {return 0}
	}
	if [info exists clonelist($chan!$host)] {
		incr clonelist($chan!$host) 1
		if {$clonelist($chan!$host) >= $maxclone} {
			newchanban $chan "*!*@$host" $botnick "Cloni, espulsi per 5 minuti \($clonelist($chan!$host)\)" $clonebantime
			set thiskicked [kickall "*!*@$host" $chan "Too many clones from $host"]
			putloglev 1 $chan "Max clones reached from $host in $chan: $thiskicked"
			return 1
		}
		foreach nick2 [chanlist $chan] {
      set host2 [string tolower [lindex [split [getchanhost $nick2 $chan] @] 1]]
			if {$host == $host2 && $nick != $nick2} { lappend clonenicks $nick2 }
		}
		regsub -all " " $clonenicks ", " clonenicks
		if {$cloneopnotice} {
			opnotice $chan "Clone IN: $nick \($uhost\) is a clone to $clonenicks in $chan"
		}
		putloglev 1 $chan "Clone IN $chan: $nick \($uhost\) is clone \#$clonelist($chan!$host) \($clonenicks\)"
		return 1
	}
	set clonelist($chan!$host) 0
	return 0
}

proc clone_remove { nick uhost hand chan { rest "" } } {
	global clonelist botnick cloneopnotice nocloneflag noclonehost
	set chan [string tolower $chan]
	if {$nick == $botnick} {return 0}
	foreach this [timers] {
		if {[string compare [lindex $this 1] "set_clones"] == 0} {
			# Just relax, I need to refresh the clones-list first...
			return 0
		}
	}
  set host [string tolower [lindex [split $uhost @] 1]]
	foreach exceptionflag $nocloneflag {
		if {[matchattr $hand $exceptionflag|$exceptionflag $chan]} {
			return 0
		}
	}
	foreach exceptionhost $noclonehost {
		# if it is an exception do nothing
		if {[string match [string tolower $exceptionhost] [string tolower $host]]} {return 0}
	}
	if ![info exists clonelist($chan!$host)] {return 0}
	if {$clonelist($chan!$host) < 0} {
		putloglev 1 $chan "Negative number of clones listed?? Something is wrong with the script!"
		return 0
	} elseif {$clonelist($chan!$host) == 0} {
		unset clonelist($chan!$host)
		return 1
	} elseif {$clonelist($chan!$host) > 0} {
		incr clonelist($chan!$host) -1
		foreach n [chanlist $chan] {
      set host2 [string tolower [lindex [split [getchanhost $n $chan] @] 1]]
			if {($host == $host2) && ($n != $nick)} { lappend clonenicks $n }
		}
		regsub -all " " $clonenicks ", " clonenicks
		putloglev 1 $chan "Clone OUT $chan: $nick \($uhost\) left \($clonenicks remaining\)"
		if {$cloneopnotice} {
			opnotice $chan "Clone OUT: $nick \($uhost\) left $chan \($clonenicks remaining\)"
		}
		return 1
	}
}

proc clone_kick { nick host hand chan knick rest } {
	clone_remove $knick [getchanhost $knick $chan] [nick2hand $knick $chan] $chan
}

proc clone_quit { nick host hand chan rest } {
	clone_remove $nick $host $hand $chan
}

proc dcc_clonecheck { hand idx onoff } {
	global clonecheck
	set choice [string tolower $onoff]
	if {$onoff == ""} {
		if {$clonecheck} { set status "on" } { set status "off" }
		putdcc $idx "Clone-checking currently \002${status}\002."
		return 0
	}
	if {($choice != "on") && ($choice != "off")} {
		putdcc $idx "Usage: '.clonecheck \[on/off\]'"
		return 0
	}
	if {$choice == "on"} {
		if {$clonecheck == 0} {
			set clonecheck 1
			putdcc $idx "Clone-checking is now \002on\002."
			clonecheckload
			return 1
		} {
			putdcc $idx "Clone-checking was already \002on\002."
			return 0
		}
	} {
		if {$clonecheck == 1} {
			set clonecheck 0
			putdcc $idx "Clone-checking is now \002off\002."
			clonecheckload
			return 1
		} {
			putdcc $idx "Clone-checking was already \002off\002."
			return 0
		}
	}
}

proc dcc_clone_stats { hand idx chan } {
	global clonecheck
	if {$clonecheck == 0} {
		putdcc $idx "Sorry, clone-checking currently off. Use \002.clonecheck on\002 to turn it on."
		return 0
	}
	global clonelist
	if {$chan == ""} {
		set channel [lindex [console $idx] 0]
	} {
		regsub -nocase -all \[{}] $chan "" chan
		set channel [lindex $chan 0]
	}
	putdcc $idx "Clones in $channel:"
  set channel [string tolower $channel]
	foreach addy [array names clonelist] {
		if {$clonelist($addy) > 0} {
			scan $addy "%\[^!]!%s" chan host
			if {$chan != [string tolower $channel]} { continue }
			foreach nick [chanlist $chan] {
        set host2 [string tolower [lindex [split [getchanhost $nick $chan] @] 1]]
				if {$host == $host2} { lappend clonenicks $nick	}
			}
		}
		if [info exists clonenicks] {
			regsub -all " " $clonenicks ", " clonenicks
			set clones($host) $clonenicks
			unset clonenicks
		}
	}
	if [array exists clones] {
		set counter 0
		foreach addy [array names clones] {
			incr counter
			putdcc $idx " $counter. $addy \($clones($addy)): $clonelist($channel!$addy)"
		}
		unset counter
	} { putdcc $idx "No clones detected in $channel" }
	return 1
}

proc clonecheckload {} {
	global clonecheck clonelist clone_loaded
	
	if {$clonecheck} {
	# When activated, make all binds, and refresh clones-array
		bind join - * clone_detect
		bind part - * clone_remove
		bind sign - * clone_quit
		bind kick - * clone_kick
		bind splt - * clone_remove
		bind rejn - * clone_detect
		set clone_loaded 1
		# begins in 10 secs (not ON rehash, cause chan-userlist is not ok yet)
		# if bot was restarted, set_clones is called 1 min after bot joins chan
		# (see clone_detect)
		utimer 10 set_clones
	} {
	# When not activated, remove all bindings and clean the clonelist from mem
		if {$clone_loaded} {
			unbind join - * clone_detect
			unbind part - * clone_remove
			unbind sign - * clone_quit
			unbind kick - * clone_kick
			unbind splt - * clone_remove
			unbind rejn - * clone_detect
		}
		set clone_loaded 1
		if {[array exists clonelist]} { unset clonelist }
	}
}

global clone_loaded
set clone_loaded 0
clonecheckload

if {$clonecheck} { set clonestatus "on" } { set clonestatus "off" }

putlog "- Clone detection v3.5 \($clonestatus\) by By-Tor, Ernst & Flash."
putlog "  Max clones allowed: $maxclone. Banning for $clonebantime mins."

unset clonestatus
can someone help me to resolve it? I checked many times but I dont see where error is. the script work ok apart this error that get both nicks banned instead to ban only the clone.

thanks a lot

Yoda :roll:
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

this error occurs, because the script tries to use a variable called "hand" that is not defined. e.g.

Code: Select all

proc kickall { mask chan reason } { 
   global fastkick   botnick nocloneflag 
   if {![validchan $chan]} { return "" } 
   set kicked "" 
   foreach thisnick [chanlist $chan] { 
      if {$thisnick == $botnick} { continue } 
      if {[string match "$mask" "$thisnick![getchanhost $thisnick $chan]"]} { 
         set dontkick 0 
         foreach exceptionflag $nocloneflag { 
            if {[matchattr $hand $exceptionflag|$exceptionflag $chan]} { 
in "matchattr $hand" you try to use the variable "hand", but this variable is neither given in the arguments of the function nor is it global nor is it set in the function. on my quick look at the script i noticed one more function with this problem. all i can say so far is: add the "hand" to your function arguments and always call the function with a "hand" given.

Code: Select all

proc kickall { mask hand chan reason } { 
and e.g.

Code: Select all

set thiskicked [kickall "*!*@$host" $hand $chan "Too many clones from $host"] 
Y
Yoda
Halfop
Posts: 78
Joined: Thu Oct 24, 2002 2:57 am
Location: Milano, Italy
Contact:

Post by Yoda »

thanks for your answer.
Onestly I'm not able to correct the script, maibe I dont understand right what to do, too. You or someone else could be able to correct the script and post it here? :lol:

Yoda
(too much new) :cry:
User avatar
stdragon
Owner
Posts: 959
Joined: Sun Sep 23, 2001 8:00 pm
Contact:

Post by stdragon »

Just a note, I think that part is trying to ge the handle for each nick on the channel, not the original handle. It looks like it kicks people based on a mask, but if the person has certain flags it exempts them. So the handle needs to be looked up for each person.

Code: Select all

proc kickall { mask chan reason } {
   global fastkick   botnick nocloneflag
   if {![validchan $chan]} { return "" }
   set kicked ""
   foreach thisnick [chanlist $chan] {
      if {$thisnick == $botnick} { continue }
      if {[string match "$mask" "$thisnick![getchanhost $thisnick $chan]"]} {
         set dontkick 0
         ######## Here's the added line:
         set hand [nick2hand $thisnick $chan]
         foreach exceptionflag $nocloneflag {
            if {[matchattr $hand $exceptionflag|$exceptionflag $chan]} {
Y
Yoda
Halfop
Posts: 78
Joined: Thu Oct 24, 2002 2:57 am
Location: Milano, Italy
Contact:

Post by Yoda »

who know a REALLY good and WORKING clone detector and handler with party line config and commands that works with eggdrop .13?

I tried all the clone tcls here but noone full work, errors everytime :(
Y
Yoda
Halfop
Posts: 78
Joined: Thu Oct 24, 2002 2:57 am
Location: Milano, Italy
Contact:

Post by Yoda »

I adde the line as you said

######## Here's the added line:
set hand [nick2hand $thisnick $chan]

and now no more tlc error, thanks a lot :lol:

but still ban both, nick and clone. I dont see where I have to correct to get that only the clone will be banned but not the first user, someone can help?
Locked