Universal channel script

Support & discussion of released scripts, and announcements of new releases.
Post Reply
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

because I would have wasted more time searching for scripts that feature what I need (specific commands) than I actually wasted writing that 20-line Tcl cloner
m
mm
Halfop
Posts: 78
Joined: Thu Jul 01, 2004 10:24 pm

Post by mm »

demond, awesome work. I've a question to change the bantype, or change "reason" via partyline? or repeating rate etc.. or we have to change in the script?

thanks
MM
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

no, the whole idea is that you don't edit the script at all, any configuration change is done via .chanset:

Code: Select all

.chanset #chan x:flood:bantype 2
.chanset #chan x:repeat:rate 2:8
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

and another important thing:

you probably have already noticed that, but all protections are off by default; you need to explicitly .chanset #chan +x:repeat (or x:spam, or x:lame, or whatever; note however that default -x:flood doesn't mean the bot won't punish flood, it means it will punish flood using its built-in protection, not script's protection)

also, "kick" and "deop" floods (bind FLUD) are not handled by the script, they're simply passed to eggdrop to handle further with its default built-in protection (you can't have effective deop/kick protection by a script anyway); basically, the script ignores any offense done by chanops or +o/+f bot user (global or for that channel)
m
mm
Halfop
Posts: 78
Joined: Thu Jul 01, 2004 10:24 pm

Post by mm »

Thank you demond, it works great.
I was testing/playing around with repeat, flood thing, it works like a champ. except i've noticed one thing

if you set -> .chanset #name x:flood:punish w it works fine, it sends pvt warning msg.

but when you change -> .chanset #name x:flood:punish w:k then it kicks fine but doesn't give warning in pvt.

and when you change -> .chanset #name x:flood:punish w:k:b then it kicks, bans fine but no pvt warning msg

and same is true in repeat process.

Thanks
MM
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

hmm I have tested extensively but haven't noticed such erratic behaviour

you have probably changed punish set in-between offenses (offense records expire by default after 12 hours)

you can play with offense records directly via .tcl, e.g. to clear offenses array you do:

Code: Select all

.tcl unset ::xchannel::offenses
Last edited by demond on Fri Sep 09, 2005 12:04 am, edited 1 time in total.
m
mm
Halfop
Posts: 78
Joined: Thu Jul 01, 2004 10:24 pm

Post by mm »

well i've used 3,4 different clones to play around..

Could you pls show me some example so i know how to use .tcl to play with offense records.? i mean i know .tcl stuff but how do i use with offense record?

Thanks
MM
m
mm
Halfop
Posts: 78
Joined: Thu Jul 01, 2004 10:24 pm

Post by mm »

OK, Thank you.

I've cleared the offense record using .tcl unset ::xchannel::offenses so everything is fresh and i've added another channel for testing

and here is the settings:

Code: Select all

<(TBOT> User defined channel flags:
<(TBOT>      +x:flood +x:repeat
<(TBOT> User defined channel settings:
<(TBOT> x:flood:bantype: 2   x:flood:bantime: 0   x:repeat:bantype: 2   x:repeat:bantime: 10   
<(TBOT> User defined channel strings:
<(TBOT> x:flood:punish: w:k
<(TBOT> x:flood:reason: {don't flood}
<(TBOT> x:repeat:punish: w:k
<(TBOT> x:repeat:reason: {repeating is lame}
<(TBOT> x:repeat:rate: 3:8
<(TBOT> flood settings: chan ctcp join kick deop nick
<(TBOT> number:           10    3    5    3    3    5
<(TBOT> time  :           60   60   60   10   10   60
for repeat/flood punish is w:k but on first offense it just sends pvt warnings, no KICK but on 2nd offense it doesn't send pvt warning but it does kick fine. same is true for flood as well.

Thanks
MM
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

but it is supposed to do exactly that ;)

w:k:b means:
  • on 1st offense of the some type, warn only
  • on 2nd offense of the same type, kick only
  • on 3rd and more offenses of the same type, ban+kick (no warning)
logical, isn't it?

w:w:k:k:b would mean: 1st warn, 2nd warn again, 3rd kick, 4th kick again, 5th and more - ban(+kick)
m
mm
Halfop
Posts: 78
Joined: Thu Jul 01, 2004 10:24 pm

Post by mm »

oh ic, you are right, that makes sense, sorry i thought with this setting w:k it will always warn/kick both...next time i'll keep your document/explanation next to me heh..

So far everything works nicely.


thnaks again, i'll keep checking your site for the latest upgrades and will continue testing the script to give you feedback.
MM
m
mm
Halfop
Posts: 78
Joined: Thu Jul 01, 2004 10:24 pm

Post by mm »

Hi demond:

*FYI*
Tcl error [::xchannel::mass]: can't read "maxr": no such variable


Thanks
MM
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Let's roll

Post by demond »

Okay let's roll out this thing, here's 1.0 (surprisingly, it turns out to be quite compact for the features supported):

Code: Select all

###########################################################################################
#                                                                                         #
# xchannel.tcl -- universal channel protection script for eggdrop by demond@demond.net    #
#                                                                                         #
#                 a higly-optimized, versatile and modular script for all of your channel #
#                 protection needs; using an uniform routine for counting and punishing   #
#                 offenses, it's been designed for easier further enhancement and adding  #
#                 new offense type handlers; all configuration is done via .chanset       #
#                                                                                         #
#                 as of the current version, supported offense types are:                 #
#                                                                                         #
#                   % plain public flood (via chan message, notice, ctcp action)          #
#                   % mass flood (by a botnet via mass join, part, nick, public flood)    #
#                   % repeating                                                           #
#                   % using CAPS                                                          #
#                   % using colors                                                        #
#                   % spamming with URLs                                                  #
#                   % profanity (using bad words)                                         #
#                   % in addition, the script features automatic +l limiter               #
#                                                                                         #
#                 DO NOT EDIT this script (even if you know what you are doing ;)         #
#                 instead, configure it to suit you from bot's party-line by using        #
#                 .chanset command and the following settings (you have to specify any    #
#                 of these only if you need default value changed; to see defaults, use   #
#                 .chaninfo #chan):                                                       #
#                                                                                         #
#       common -- (these are mandatory for each offense type handler)                     #
#                                                                                         #
#                 below, 'type' is one of: repeat, flood, color, spam, caps, bad          #
#                                                                                         #
#                 x:type         - the on/off switch                                      #
#                 x:type:punish  - sequence of letters w, k, or b, separated by a colon   #
#                                  for example, w:k:b means: on 1st offense, warn only;   #
#                                  on 2nd offense, kick; on 3rd and more offenses, ban    #
#                 x:type:bantype - ban type number (see [maskhost] proc below for types)  #
#                 x:type:bantime - ban time in minutes                                    #
#                 x:type:reason  - the kick/ban reason                                    #
#                                                                                         #
#       custom -- (these are specific for a particular offense type)                      #
#                                                                                         #
#                 repeat handler     - x:repeat:rate   (n:m) n repeats in m seconds       #
#                 mass flood handler - x:mass:rate     (n:m) n events in m seconds        #
#                                      x:mass:duration (n)   +mi locking duration, in min #
#                 caps handler       - x:caps:percent  (n)   percentage of cap letters    #
#                 bad words handler  - x:bad:file   (name)   file name of bad words file  # 
#                 +l limiter         - x:limit:slack   (n)   minimal difference between   #
#                                                            current user count and +l    #
#                                                                                         #
#                 IMPORTANT: all offense handlers (except mass) are disabled by default   #
#                            to enable particular protection, use .chanset #chan +x:type  #
#                                                                                         #
#                      NOTE: defined bad words are treated as regular expressions (RE)    #
#                                                                                         #
#  ver.history -- 1.0 - initial version                                                   #
#                                                                                         #
###########################################################################################

package require Tcl 8.3
package require eggdrop 1.6

namespace eval xchannel {

variable version "xchannel-1.0"

variable names {punish bantype bantime reason}
variable udefs {str    int     int     str}

set conf1g(repeat) {pubm w:k:b 1 10 "repeating is lame"}
set conf1g(flood)  {flud w:k:b 1 10 "stop flooding"}
set conf1g(color)  {pubm w:k:b 1 10 "no colors"}
set conf1g(spam)   {pubm w:k:b 1 10 "spam"}
set conf1g(caps)   {pubm w:k:b 1 10 "caps off"}
set conf1g(bad)    {pubm w:k:b 1 10 "do not curse"}

set custom(repeat) {rate:str:3:10}
set custom(mass)   {rate:str:20:3 duration:int:5}
set custom(limit)  {slack:int:5}
set custom(caps)   {percent:int:70}
set custom(bad)    {file:str:badwords.txt}

variable mbinds {join part nick pubm}
variable lbinds {join part kick sign}
variable arrays {offenses:10:720 repeats:2:5}

variable handlers {repeat color spam caps bad}

variable colore {([\002\017\026\037]|[\003]{1}[0-9]{0,2}[\,]{0,1}[0-9]{0,2})}

bind time - * [namespace current]::timer

proc maskhost {nuhost {type 0}} {
	scan $nuhost {%[^!]!%[^@]@%s} nick user host
	scan [set mask [::maskhost $nuhost]] {%*[^@]@%s} mhost
	switch $type {
	0 - 1 {return $mask}       ;# *!*foo@*.bar.com
	2 {return *!*@$host}       ;# *!*@moo.bar.com
	3 {return *!*@$mhost}      ;# *!*@*.bar.com
	4 {return *!*$user@$host}  ;# *!*foo@moo.bar.com
	5 {return *!*$user@*}      ;# *!*foo@*
	6 {return $nuhost}
	}
}

proc fixargs {chan text args} {
	upvar $chan xchan; upvar $text xtext
	if {$::lastbind == "**"} {
		set xtext $xchan
		set xchan [lindex $args 0]
	} {
		set n [llength $args]
		set xtext [lindex $args [incr n -1]]
	}
}

proc init {chan} {
	variable handlers
	variable names; variable udefs
	variable mbinds; variable lbinds
	variable conf1g; variable custom
	setudef flag x:limit
	foreach elem $lbinds {
		bind $elem - * [namespace current]::limit
	}
	foreach elem $mbinds {
		bind $elem - * [namespace current]::mass
	}
	foreach {type data} [array get conf1g] {
		setudef flag x:$type
		bind [lindex $data 0] - * [namespace current]::$type
		if {[lsearch $handlers $type] != -1} {
			bind notc - ** [namespace current]::$type
			bind ctcp - * [namespace current]::$type
		}
		foreach val [lrange $data 1 e] name $names udef $udefs {
			setudef $udef x:$type:$name
			if {$udef == "int"} {set void 0} {set void ""}
			if {[channel get $chan x:$type:$name] == $void} {
				channel set $chan x:$type:$name $val
			}
		}
	}
	foreach {type data} [array get custom] {
		foreach elem $data {
			scan $elem {%[^:]:%[^:]:%s} name udef val
			setudef $udef x:$type:$name
			if {$udef == "int"} {set void 0} {set void ""}
			if {[channel get $chan x:$type:$name] == $void} {
				channel set $chan x:$type:$name $val
			}
		}		
	}
}

proc timer {min hour day month year} {
	variable arrays
	foreach elem $arrays {
		scan $elem {%[^:]:%[^:]:%s} name freq val
		upvar #1 [namespace current]::$name arr
		if {([unixtime]/60) % $freq == 0} {
			if {[info exists arr]} {
			foreach {hash data} [array get arr] {
				set ts [lindex $data 0]
				if {[unixtime] - $ts >= $val*60} {
					unset arr($hash)
				}
			}}
		} 
	}
}

proc punish {nick uhost hand chan type {subtype ""}} {
	variable offenses
	if {[isop $nick $chan] || 
	    [matchattr $hand of|of $chan]} {return}
	if {$subtype == ""} {set what $type} {set what $subtype}
	set chan [string tolower $chan]
	set hash [md5 $chan:$what:[maskhost $nick!$uhost]]
	if {![info exists offenses($hash)]} {set n 1} {
		set n [lindex $offenses($hash) 1]; incr n
	}
	set offenses($hash) [list [unixtime] $n]
	set reason "[channel get $chan x:$type:reason] ($n)"
	set punish [split [channel get $chan x:$type:punish] :]
	set len [llength $punish]; if {$n > $len} {set n $len}
	switch [lindex $punish [incr n -1]] {
	"w" {putserv "privmsg $nick :$reason"}
	"k" {if {[botisop $chan]} {putkick $chan $nick $reason}}
	"b" {
		set time [channel get $chan x:$type:bantime]
		set type [channel get $chan x:$type:bantype]
		newchanban $chan [maskhost $nick!$uhost $type] $::nick $reason $time
		if {[botisop $chan]} {putkick $chan $nick $reason}
	}}
}

proc repeat {nick uhost hand chan args} {
	variable repeats
	fixargs chan text $args
	if {[isbotnick $chan]} {return}
	set chan [string tolower $chan]
	if {![channel get $chan x:repeat]} {return}
	scan [channel get $chan x:repeat:rate] {%[^:]:%s} maxr maxt
	set hash [md5 $chan:$text:[maskhost $nick!$uhost]]
	if {![info exists repeats($hash)]} {
		set n 1; set ts [unixtime]
	} {
		set n [lindex $repeats($hash) 1]; incr n
		set ts [lindex $repeats($hash) 0]
		if {[unixtime] - $ts >= $maxt} {
			set n 1; set ts [unixtime]
		} {
			if {$n >= $maxr} {
				punish $nick $uhost $hand $chan repeat
				unset repeats($hash); return
			}
		} 
	}
	set repeats($hash) [list $ts $n]
}

proc mass {nick uhost hand chan args} {
	variable mcount; variable version
	set chan [string tolower $chan]
	if {![info exists mcount($chan)]} {
		set n 1; set ts [unixtime]
	} {
		set n [lindex $mcount($chan) 1]; incr n
		set ts [lindex $mcount($chan) 0]
		scan [channel get $chan x:mass:rate] {%[^:]:%s} maxr maxt
		if {$n >= $maxr} {
			if {[unixtime] - $ts <= $maxt} {
				#set buf "mode $chan +mi\n"
				#putdccraw 0 [llength $buf] $buf
				putquick "mode $chan +im" -next
				putlog "$version: Mass Flood on $chan!!! Locking..."
		utimer	5 [list	putserv "notice $chan :Mass Flood!!! We'll re-open shortly..."]
				set dur [channel get $chan x:mass:duration]
				::timer $dur [list putserv "mode $chan -mi"]
				unset mcount($chan); return
			} {
				set n 1; set ts [unixtime]
			}
		}
	}
	set mcount($chan) [list $ts $n]
}

proc limit {nick uhost hand chan args} {
	if {![channel get $chan x:limit]} {return}
	set slack [channel get $chan x:limit:slack]
	set len [llength [chanlist $chan]]
	set lim [split [getchanmode $chan]]
	if {[string first l [lindex $lim 0]] == -1} {
		set limit $len
	} elseif {[string first k [lindex $lim 0]] == -1} {
		set limit [lindex $lim 1]
	} {
		set limit [lindex $lim 2]
	}
	if {$limit - $len < $slack} {
		incr limit $slack
	} elseif {$limit - $len > [expr 2*$slack]} {
		incr limit -$slack
	} {return}
	putserv "mode $chan +l $limit" 
}

proc bad {nick uhost hand chan args} {
	variable words; variable colore
	fixargs chan text $args
	if {[isbotnick $chan]} {return}
	set chan [string tolower $chan]
	if {![channel get $chan x:bad]} {return}
	if {[info exists words($chan)]} {
	regsub -all $colore $text {} text
	foreach elem $words($chan) {
		if {[regexp -nocase -- $elem $text]} {
			punish $nick $uhost $hand $chan bad
		}
	}} 
}

proc caps {nick uhost hand chan args} {
	fixargs chan text $args
	if {[isbotnick $chan]} {return}
	if {![channel get $chan x:caps]} {return}
	set n 0; foreach c [split $text {}] {
		if {[string is upper $c]} {incr n}
	}
	set pct [channel get $chan x:caps:percent]
	if {100*$n/[string length $text] >= $pct} {
		punish $nick $uhost $hand $chan caps
	}
}

proc color {nick uhost hand chan args} {
	variable colore
	fixargs chan text $args
	if {[isbotnick $chan]} {return}
	if {![channel get $chan x:color]} {return}
	if {[regexp $colore $text]} {
		punish $nick $uhost $hand $chan color
	}
}

proc spam {nick uhost hand chan args} {
	variable colore
	fixargs chan text $args
	if {[isbotnick $chan]} {return}
	if {![channel get $chan x:spam]} {return}
	regsub -all $colore $text {} text
	if {[regexp {(?i)(http://|www\.|irc\.|\s#)} $text]} {
		punish $nick $uhost $hand $chan spam
	}
}

proc flood {nick uhost hand type chan} {
	if {$chan == "*"} {return}
	if {![channel get $chan x:flood]} {return}
	if {$type == "kick" || $type == "deop"} {return}
	punish $nick $uhost $hand $chan flood $type
	return 1
}

foreach chan [channels] {
	init $chan
	set fn [channel get $chan x:bad:file] 
	set chan [string tolower $chan]
	if {![catch {set f [open $fn]} err]} {
		set words($chan) {}
		foreach elem [split [read $f] " \t\r\n\f"] {
			if {$elem != ""} {lappend words($chan) $elem} 
		}
		close $f
	} {
		putlog "$version: $err"
	}
}

putlog "$version by demond loaded"

}
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

as always, feedback is much appreciated; I did my best to test this thing, including mass flood by vhost drones but, without a doubt, there's much left to be done

you can also download current version of this script from the usual source, click *HERE*
m
mm
Halfop
Posts: 78
Joined: Thu Jul 01, 2004 10:24 pm

Post by mm »

Hi demond, Thank you for an excellant modular script, great great work.

i was playing with the scripts so i can give you some feedback so we can improve this wonderfull script.

1: i still see this error -> Tcl error [::xchannel::mass]: can't read "maxr": no such variable
2: color routine: it triggered even we use just one color character.. i think we should count the lines?
2: spam routine: if i am on #A, and if i type xyz is join #A, it triggers, may be it should ignore if we type the channel we are on. and may be we can have some exception list , like sometime ppl say ok join #nohack to remove the virus etc. or ppl say visit www.cservice.orf or www.egghelp.org..

3: bad word : we can define the file name via .chanset but we cann't add/delete the bad words using partryline? i've define the badwords file using .chanset but i don't see in the bot's dir, so i can add the words..

4:caps:
i've changed percent to 90, 50..different numbers, but it seems it triggers even you type one cap character.


thanks again
MM
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

@mm:

1) post backtrace of the error using .set errorInfo, but most likely you have played with x:mass:rate and set it incorrectly
2) I don't intend to add percentage analysys of used colors, it seems like overkill to me; what I will probably do is add setting to differentiate between using colors and using other control chars (bold, underline, reverse)
3) I will add configure setting for spam URLs and, on the other hand, for spamming with alien irc servers and channel invitations
4) I didn't experience this, we'll have to wait for someone else to confirm that behaviour
Post Reply