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.

Banning a user second time he breaks the rule

Help for those learning Tcl or writing their own scripts.
Post Reply
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Banning a user second time he breaks the rule

Post by Fill »

Hi mates, I am learning TCL and this is my first script:

Code: Select all

bind join - "#cyber-world *" nick:join

proc nick:join {nick host handle chan} {
 set nletters [string length $nick]
 if { $nletters > 15 } {
   putserv "KICK $chan $nick :Please choose a nick with less than 15 characters. To do so, please type /nick NewNickHere. Thanks."
 }
}
As you can see, it's quite simple, and all it does is banning someone who has more than 15 characteres in the nick length. Now, I wanted to improve this and make the bot ban the user for 3 hours if he returns after the kick. How could I do this?

Thanks in advance for the help,
Fill
User avatar
tomekk
Master
Posts: 255
Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:

Post by tomekk »

In my point of view, this should be something like this:

1st file with hosts of kicked ppl
2nd file with hosts of banned ppl

If someone joins the channel bot checking it host and compare it with hosts from file (file with kicked ppl hosts), if match (and time is less than 3 hours) bot making +b for this person.

After ban, bot moving this host entry from "kicked file" to "banned file".

Next, some timer in script is checking ie. for every 1 minute banned hosts file.
If some host has more than XX minutes ban bot making -b on this host.
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

You're certainly right, but I don't know how to do that, is it very difficult? Thanks for the help, I'll try to read some tutorials, but if you posted the code it would be nice.

Thanks
Fill
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Personally, I'd say using external files would be overkill for a first attempt.

First off, you'll need some kind of "id" to keep track of a single offender. This will very much affect the behaviour of your bot, as it will determine how easy it will be to "avoid" the second kick. A few ideas for id would be nickname, user@host, host, user@host#channel, etc.
I would also recommend converting the id to lowercase (string tolower is your friend here).

Secondly, you'll like to store some kind of time-dependant data along with this id, so you'll be able to determine whether sufficient has passed since the last offence or not. My recommendation would be to use timestamps (clock seconds is your friend here).

Finally, you'll need some kind of storage facility that allows you to "attach" this timestamp to the id. My suggestion here is arrays (indexed variables).

When this has been accomplished, what is left to do is a test whether this indeed is a repeated offence, and in such cases, add a temporary ban to your eggdrops internal banlist (newban / newchanban).

If you need a good example on this kind of approach, search the forum for "throttled", as you'll find several hits illustrating a generic way of doing this.
NML_375
User avatar
tomekk
Master
Posts: 255
Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:

Post by tomekk »

try:

Code: Select all

# Author: tomekk 
# e-mail:  tomekk/@/oswiecim/./eu/./org 
# home page: http://tomekk.oswiecim.eu.org/ 
# 
# Version 0.1 
# 
# This file is Copyrighted under the GNU Public License. 
# http://www.gnu.org/copyleft/gpl.html

# channel name
set nick_channel "#channel"

# max nick length
set nick_max_len 15

# time between joins (minutes)
set time_between_joins 180

# kick message
set kick_msg "your nick is to long ;p"

# ban kick message
set kick_ban_msg "now u got! ban! ;p"

# 1 = *!*ident@somehost.com, 2 = *!*@somehost.com
set ident_type 2

# ban duration (minutes)
set ban_time 120

# check bans every X minutes
set ban_check_int 2

# db file with kicked hosts
set kicks_db "kicks.txt"

# db file with banned hosts
set bans_db "bans.txt"

########################################################################
bind join - "*" job_onjoin

if {![file exist $kicks_db]} {
	set k_h [open $kicks_db w]
	close $k_h
}

if {![file exist $bans_db]} {
        set b_h [open $bans_db w]
	close $b_h
}

proc add_db_host { db input_data } {
	set add_h [open $db a]
	puts $add_h $input_data
	close $add_h
}

proc del_db_host { db input_host } {
	set all_h [open $db r]
	set all_data [read $all_h]
	close $all_h

	set new_data [open $db w]

	foreach db_host [split $all_data "\n"] {
		if {$db_host != ""} {
			set just_host [lindex [split $db_host ";"] 0]

			if {$just_host != $input_host} {
				puts $new_data $db_host
			}
		}
	}

	close $new_data
}

proc check_host { db input_host } {
	set host_exists 0
	set host_time 0

	set check_h [open $db r]
	set check_data [read $check_h]
	close $check_h

	foreach db_line [split $check_data "\n"] {
		if {$db_line != ""} {
			set data_split [split $db_line ";"]
			set db_host [lindex $data_split 0]
			set db_time [lindex $data_split 1]

			if {$input_host == $db_host} {
				set host_exists 1
				set host_time $db_time
				break
			}
		}
	}

	return [list $host_exists $host_time]
}

proc ban_clean { } {
	global ban_check_int

	refresh_bans

	if {[string match *ban_clean* [timers]] != 1} {
		timer $ban_check_int ban_clean
	}
}

proc job_onjoin {nick uhost hand chan} {
	global nick_channel nick_max_len kicks_db bans_db ident_type time_between_joins kick_msg kick_ban_msg botnick

	if {$chan == $nick_channel} {
		if {$nick != $botnick} {
			set nick_l [string length $nick]
			if {$nick_l > $nick_max_len} {
				if {$ident_type == 1} {
					set prepared_host "*!*$uhost"
				} {
					set prepared_host "*!*@[lindex [split $uhost "@"] 1]"
				}

				set proc_out [split [check_host $kicks_db $prepared_host]]
				set host_in_db [lindex $proc_out 0]
				set host_add_time [lindex $proc_out 1]

				set clock_seconds [clock seconds]

				if {$host_in_db == 0} {
					add_db_host $kicks_db "$prepared_host;$clock_seconds"
					putkick $nick_channel $nick $kick_msg
				} {
					if {[expr $clock_seconds - $host_add_time] > [expr $time_between_joins * 60]} {
						del_db_host $kicks_db $prepared_host
						add_db_host $kicks_db "$prepared_host;$clock_seconds"
						putkick $nick_channel $nick $kick_msg
					} {
						del_db_host $kicks_db $prepared_host
						add_db_host $bans_db "$prepared_host;$clock_seconds"
						putserv "MODE $nick_channel +b $prepared_host"
						putkick $nick_channel $nick $kick_ban_msg
					}
				}
			}
		}
	}
}

proc refresh_bans { } {
	global ban_time bans_db nick_channel

	set bans_h [open $bans_db r]
	set get_all_bans [read $bans_h]
	close $bans_h

	set curr_time [clock seconds]

	set new_bans_db [open $bans_db w]
	foreach simple_ban [split $get_all_bans "\n"] {
		if {$simple_ban != ""} {
			set data_rows [split $simple_ban ";"]
			set ban_add_host [lindex $data_rows 0]
			set ban_add_time [lindex $data_rows 1]
			if {[expr $curr_time - $ban_add_time] > [expr $ban_time * 60]} {
				putserv "MODE $nick_channel -b $ban_add_host"
			} {
				puts $new_bans_db $simple_ban
			}
		}
	}
	close $new_bans_db
}

if {[string match *ban_clean* [timers]] != 1} {
        timer $ban_check_int ban_clean
}

putlog "check-nick.tcl ver 0.1 by tomekk loaded"
I tested it with 10k hosts, its working well.
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

wow, thanks a lot, it worked and helped me, because I got what I wanted and I learnt some new stuff with your script. Thanks ! :)
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

Hey there again.

I've added a new setting to this script (this does the same thing that happens on join, but instead of monitoring the joins it keeps track of nickchanges, so a user is kicked even if he changes from a small nick to a big nick):

Code: Select all

bind nick - "*" job_nickchange

proc job_nickchange {nick host hand chan newnick} {
   global nick_channel nick_max_len kicks_db bans_db ident_type time_between_joins kick_msg kick_ban_msg botnick

   if {$chan == $nick_channel} {
      if {$nick != $botnick} {
         set nick_l [string length $newnick]
         if {$nick_l > $nick_max_len} {
            if {$ident_type == 1} {
               set prepared_host "*!*$host"
            } {
               set prepared_host "*!*@[lindex [split $host "@"] 1]"
            }

            set proc_out [split [check_host $kicks_db $prepared_host]]
            set host_in_db [lindex $proc_out 0]
            set host_add_time [lindex $proc_out 1]

            set clock_seconds [clock seconds]

            if {$host_in_db == 0} {
               add_db_host $kicks_db "$prepared_host;$clock_seconds"
               putkick $nick_channel $newnick $kick_msg
            } {
               if {[expr $clock_seconds - $host_add_time] > [expr $time_between_joins * 60]} {
                  del_db_host $kicks_db $prepared_host
                  add_db_host $kicks_db "$prepared_host;$clock_seconds"
                  putkick $nick_channel $newnick $kick_msg
               } {
                  del_db_host $kicks_db $prepared_host
                  add_db_host $bans_db "$prepared_host;$clock_seconds"
                  putserv "MODE $nick_channel +b $prepared_host"
                  putkick $nick_channel $newnick $kick_ban_msg
               }
            }
         }
      }
   }
}
Tested and everything is working. Once again, thanks for the help.
See ya
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Post by speechles »

Code: Select all

proc check_host { db input_host } {
   ...snipped irrelevant sections...
   return [list $host_exists $host_time]
}

proc job_onjoin {nick uhost hand chan} {
   global nick_channel nick_max_len kicks_db bans_db ident_type time_between_joins kick_msg kick_ban_msg botnick

   if {$chan == $nick_channel} {
     ...snipped irrelevant sections...
            set proc_out [split [check_host $kicks_db $prepared_host]] 
@ tomekk, you see your flaw above? Why do you return a list from your check_host proc and then split it? You can get rid of that split as it will introduce braces {} into the output...
User avatar
tomekk
Master
Posts: 255
Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:

Post by tomekk »

ohh crap, thanks speechles

Its my fault,I just forget to remove it before paste. In first version there was smth like return "aaa bbb".

Its nonsens to make list from another list, he he :)

here is version without this split:

Code: Select all

# Author: tomekk 
# e-mail:  tomekk/@/oswiecim/./eu/./org 
# home page: http://tomekk.oswiecim.eu.org/ 
# 
# Version 0.1 
# 
# This file is Copyrighted under the GNU Public License. 
# http://www.gnu.org/copyleft/gpl.html

# channel name
set nick_channel "#channel"

# max nick length
set nick_max_len 15

# time between joins (minutes)
set time_between_joins 180

# kick message
set kick_msg "your nick is to long ;p"

# ban kick message
set kick_ban_msg "now u got! ban! ;p"

# 1 = *!*ident@somehost.com, 2 = *!*@somehost.com
set ident_type 2

# ban duration (minutes)
set ban_time 120

# check bans every X minutes
set ban_check_int 2

# db file with kicked hosts
set kicks_db "kicks.txt"

# db file with banned hosts
set bans_db "bans.txt"

########################################################################
bind join - "*" job_onjoin

if {![file exist $kicks_db]} {
	set k_h [open $kicks_db w]
	close $k_h
}

if {![file exist $bans_db]} {
        set b_h [open $bans_db w]
	close $b_h
}

proc add_db_host { db input_data } {
	set add_h [open $db a]
	puts $add_h $input_data
	close $add_h
}

proc del_db_host { db input_host } {
	set all_h [open $db r]
	set all_data [read $all_h]
	close $all_h

	set new_data [open $db w]

	foreach db_host [split $all_data "\n"] {
		if {$db_host != ""} {
			set just_host [lindex [split $db_host ";"] 0]

			if {$just_host != $input_host} {
				puts $new_data $db_host
			}
		}
	}

	close $new_data
}

proc check_host { db input_host } {
	set host_exists 0
	set host_time 0

	set check_h [open $db r]
	set check_data [read $check_h]
	close $check_h

	foreach db_line [split $check_data "\n"] {
		if {$db_line != ""} {
			set data_split [split $db_line ";"]
			set db_host [lindex $data_split 0]
			set db_time [lindex $data_split 1]

			if {$input_host == $db_host} {
				set host_exists 1
				set host_time $db_time
				break
			}
		}
	}

	return [list $host_exists $host_time]
}

proc ban_clean { } {
	global ban_check_int

	refresh_bans

	if {[string match *ban_clean* [timers]] != 1} {
		timer $ban_check_int ban_clean
	}
}

proc job_onjoin {nick uhost hand chan} {
	global nick_channel nick_max_len kicks_db bans_db ident_type time_between_joins kick_msg kick_ban_msg botnick

	if {$chan == $nick_channel} {
		if {$nick != $botnick} {
			set nick_l [string length $nick]
			if {$nick_l > $nick_max_len} {
				if {$ident_type == 1} {
					set prepared_host "*!*$uhost"
				} {
					set prepared_host "*!*@[lindex [split $uhost "@"] 1]"
				}

				set proc_out [check_host $kicks_db $prepared_host]
				set host_in_db [lindex $proc_out 0]
				set host_add_time [lindex $proc_out 1]

				set clock_seconds [clock seconds]

				if {$host_in_db == 0} {
					add_db_host $kicks_db "$prepared_host;$clock_seconds"
					putkick $nick_channel $nick $kick_msg
				} {
					if {[expr $clock_seconds - $host_add_time] > [expr $time_between_joins * 60]} {
						del_db_host $kicks_db $prepared_host
						add_db_host $kicks_db "$prepared_host;$clock_seconds"
						putkick $nick_channel $nick $kick_msg
					} {
						del_db_host $kicks_db $prepared_host
						add_db_host $bans_db "$prepared_host;$clock_seconds"
						putserv "MODE $nick_channel +b $prepared_host"
						putkick $nick_channel $nick $kick_ban_msg
					}
				}
			}
		}
	}
}

proc refresh_bans { } {
	global ban_time bans_db nick_channel

	set bans_h [open $bans_db r]
	set get_all_bans [read $bans_h]
	close $bans_h

	set curr_time [clock seconds]

	set new_bans_db [open $bans_db w]
	foreach simple_ban [split $get_all_bans "\n"] {
		if {$simple_ban != ""} {
			set data_rows [split $simple_ban ";"]
			set ban_add_host [lindex $data_rows 0]
			set ban_add_time [lindex $data_rows 1]
			if {[expr $curr_time - $ban_add_time] > [expr $ban_time * 60]} {
				putserv "MODE $nick_channel -b $ban_add_host"
			} {
				puts $new_bans_db $simple_ban
			}
		}
	}
	close $new_bans_db
}

if {[string match *ban_clean* [timers]] != 1} {
        timer $ban_check_int ban_clean
}

putlog "check-nick.tcl ver 0.1 by tomekk loaded"
@Fill that's cool. TCL is not to hard, you need just solid documentation and some examples :)

HF

P.S.
http://www.tcl.tk/man/

And look into eggdrop doc directory in source package. There is a txt file called "tcl-commands.doc", you can find there descriptions of eggdrop TCL functions.
F
Fill
Halfop
Posts: 80
Joined: Sun Jan 18, 2009 6:08 pm

Post by Fill »

Yup, I already knew that tcl-commands document, and I am following this website: http://johoho.eggheads.org/eggdrop/other/guide2tcl.html

I'll check http://www.tcl.tk/man/

Thanks for the tips :)
Post Reply