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.
Help for those learning Tcl or writing their own scripts.
Fill
Halfop
Posts: 80 Joined: Sun Jan 18, 2009 6:08 pm
Post
by Fill » Mon Feb 09, 2009 1:31 pm
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
tomekk
Master
Posts: 255 Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:
Post
by tomekk » Tue Feb 10, 2009 6:55 am
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.
Fill
Halfop
Posts: 80 Joined: Sun Jan 18, 2009 6:08 pm
Post
by Fill » Tue Feb 10, 2009 10:08 am
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
nml375
Revered One
Posts: 2860 Joined: Fri Aug 04, 2006 2:09 pm
Post
by nml375 » Tue Feb 10, 2009 2:18 pm
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
tomekk
Master
Posts: 255 Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:
Post
by tomekk » Wed Feb 11, 2009 6:31 am
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.
Fill
Halfop
Posts: 80 Joined: Sun Jan 18, 2009 6:08 pm
Post
by Fill » Wed Feb 11, 2009 10:11 am
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 !
Fill
Halfop
Posts: 80 Joined: Sun Jan 18, 2009 6:08 pm
Post
by Fill » Wed Feb 11, 2009 12:18 pm
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
speechles
Revered One
Posts: 1398 Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)
Post
by speechles » Wed Feb 11, 2009 4:59 pm
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...
tomekk
Master
Posts: 255 Joined: Fri Nov 28, 2008 11:35 am
Location: Oswiecim / Poland
Contact:
Post
by tomekk » Wed Feb 11, 2009 8:06 pm
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.