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.

Queuetypes / new typ

Discussion of Eggdrop's code and module programming in C.
Post Reply
User avatar
sKy
Op
Posts: 194
Joined: Thu Apr 14, 2005 5:58 pm
Location: Germany

Queuetypes / new typ

Post by sKy »

There are 4 queue types.
- putquick (the fastest)
- putserv
- puthelp
- pushmode

I don`t know were i can get good infos about that... But i think most irc servers won`t send infos to the bot every second.

There are 2 important things. How often the server sends infos to the bot and how often the bot can send something to the server without getting disconnected (ExcessFlood).

For example: 5-10 floodbots join "at the same time". Which means the server sends all this infos "at the same time" to the bot. If you have a script which will use putquick to ban them, then the bot will ban every flooder in 1 line and will not collect the bans. If you use pushmode, then this will take much longer.

I have written a little code in tcl which will solve this in my opinion much better then putquick or pushmode. It collect all modes "like pushmode" and is fast as putquick.

Code: Select all

# usage:
# put:quick channel what ?target?
#
#
#
# returns - nothing
#
# supports only mode. use this command instand of: putquick "MODE $channel $what" or putquick "MODE $channel $what $target"
# does not support +k $key / -k $key
# or +l $limit
#
# - will not set modes which are allready set / will not unset modes which are set (for op, voice, channelmodes and bans)

set put_quick_refresh 201
set put_quick_againinput 5

proc putquick:op { channel target } {
	global put_quick_againinput
	if {! [info exists ::aoped($channel,$target) ] } {
		set ::aoped($channel,$target) 1
		utimer $put_quick_againinput [list unset ::aoped($channel,$target)]
		if { [onchan $target $channel] } {
			if { ! [isop $target $channel] } {
				put:quick:input $channel +o $target
			}
		}	
	}
}

proc putquick:deop { channel target } {
	global put_quick_againinput
	if {! [info exists ::adeoped($channel,$target) ] } {
		set ::adeoped($channel,$target) 1
		utimer $put_quick_againinput [list unset ::adeoped($channel,$target)]
		if { [onchan $target $channel] } {
			if { [isop $target $channel] } {
				put:quick:input $channel -o $target
			}
		}
	}
}

proc putquick:ban { channel hostname } {
	global put_quick_againinput
	if {! [info exists ::allready_banned($channel,$hostname) ] } {
		set ::allready_banned($channel,$hostname) 1
		utimer $put_quick_againinput [list unset ::allready_banned($channel,$hostname)]
		set resultISBAN [isban:test $hostname $channel]
		if { $resultISBAN == "ISNOTBAN" } {
			put:quick:input $channel +b $hostname
		}
	}
}
# yeah, there is a function ischanban, but i don`t want to use it because the bot sends to often mode $chan +b

proc putquick:unban { channel hostname } {
	global put_quick_againinput
	if {! [info exists ::allready_unbanned($channel,$hostname) ] } {
		set ::allready_unbanned($channel,$hostname) 1
		utimer $put_quick_againinput [list unset ::allready_unbanned($channel,$hostname)]
		set resultISBAN [isban:test $hostname $channel]
		if { $resultISBAN == "ISBAN" } {
			put:quick:input $channel -b $hostname
		}
	}
}

proc putquick:mode { channel what } {
	global put_quick_againinput
	if {! [info exists ::amode($channel,$what) ] } {
		set ::amode($channel,$what) 1
		utimer $put_quick_againinput [list unset ::amode($channel,$what)]
		set plus_or_minus [string index $what 0]
		set modechange [string index $what 1]
		set modes [getchanmode $channel]
		if { $plus_or_minus == "+" } {
#			if {! [string match "*$modechange*" $modes] } {
				put:quick:input $channel $what
#			}
		}
		if { $plus_or_minus == "-" } {
#			if { [string match "*$modechange*" $modes] } {
				put:quick:input $channel $what
#			}
		}
	}
}

proc putquick:voice { channel target } {
	global put_quick_againinput
	if {! [info exists ::avoice($channel,$target) ] } {
		set ::avoice($channel,$target) 1
		utimer $put_quick_againinput [list unset ::avoice($channel,$target)]
		if { [onchan $target $channel] } {
			if { ! [isvoice $target $channel] } {
				put:quick:input $channel +v $target
			}
		}
	}
}

proc putquick:devoice { channel target } {
	global put_quick_againinput
	if {! [info exists ::adevoice($channel,$target) ] } {
		set ::adevoice($channel,$target) 1
		utimer $put_quick_againinput [list unset ::adevoice($channel,$target)]
		if { [onchan $target $channel] } {
			if { [isvoice $target $channel] } {
				put:quick:input $channel -v $target
			}
		}
	}
}

proc put:quick { channel what {target ""} } {
	set plus_or_minus [string index $what 0]
	set modechange [string index $what 1]
	if { $plus_or_minus == "+" } {
		if { $modechange == "o" } {
			putquick:op $channel $target
			return
		}
		if { $modechange == "b" } {
			putquick:ban $channel $target
			return
		}
		if { $modechange == "v" } {
			putquick:voice $channel $target
			return
		}
		putquick:mode $channel $what
		return
	}
	if { $plus_or_minus == "-" } {
		if { $modechange == "o" } {
			putquick:deop $channel $target
			return
		}
		if { $modechange == "b" } {
			putquick:unban $channel $target
			return
		}
		if { $modechange == "v" } {
			putquick:devoice $channel $target
			return
		}
		putquick:mode $channel $what
	}
}

proc put:quick:clearqueue { channel } {
	if { [info exists ::put_quick_list($channel) ] } {
		unset ::put_quick_list($channel)
	}
	if { [info exists ::put_quick_list_mode_plus($channel) ] } {
		unset ::put_quick_list_mode_plus($channel) 
	}
	if { [info exists ::put_quick_list_mode_minus($channel) ] } {
		unset ::put_quick_list_mode_minus($channel)
	}
	if { [info exists ::put_quick_list_bans_plus($channel) ] } {
		unset ::put_quick_list_bans_plus($channel)
	}
	if { [info exists ::put_quick_list_bans_minus($channel) ] } {
		unset ::put_quick_list_bans_minus($channel)
	}
	if { [info exists ::put_quick_list_op_plus($channel) ] } {
		set ::put_quick_list_op_plus($channel) ""
	}
	if { [info exists ::put_quick_list_op_minus($channel) ] } {
		set ::put_quick_list_op_minus($channel) ""
	}
	if { [info exists ::put_quick_list_voice_plus($channel) ] } {
		set ::put_quick_list_voice_plus($channel) ""
	}
	if { [info exists ::put_quick_list_voice_minus($channel) ] } {
		set ::put_quick_list_voice_minus($channel) ""
	}
}

proc put:quick:input { channel what {target ""} } {
	if { ! [info exists ::allreadystarted($channel)] } {
		set ::allreadystarted($channel) 1
		after 201 [list put:quick:pushnow $channel]
	}

	if { ! [info exists ::put_quick_list($channel) ] } {
		set ::put_quick_list($channel) ""
	}
	if { ! [info exists ::put_quick_list_mode_plus($channel) ] } {
		set ::put_quick_list_mode_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_mode_minus($channel) ] } {
		set ::put_quick_list_mode_minus($channel) ""
	}
	if { ! [info exists ::put_quick_list_bans_plus($channel) ] } {
		set ::put_quick_list_bans_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_bans_minus($channel) ] } {
		set ::put_quick_list_bans_minus($channel) ""
	}
	if { ! [info exists ::put_quick_list_op_plus($channel) ] } {
		set ::put_quick_list_op_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_op_minus($channel) ] } {
		set ::put_quick_list_op_minus($channel) ""
	}
	if { ! [info exists ::put_quick_list_voice_plus($channel) ] } {
		set ::put_quick_list_voice_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_voice_minus($channel) ] } {
		set ::put_quick_list_voice_minus($channel) ""
	}

	set plus_or_minus [string index $what 0]
	set modechange [string index $what 1]
	if { $plus_or_minus == "+" || $plus_or_minus == "-" } { 
		if { $plus_or_minus == "+" } {
			if { $modechange == "t" || $modechange == "n" ||
			$modechange == "i" || $modechange == "m" ||
			$modechange == "k" || $modechange == "l" ||
			$modechange == "p" || $modechange == "s" ||
			$modechange == "c" || $modechange == "C" ||
			$modechange == "N" || $modechange == "r" ||
			$modechange == "D" || $modechange == "u" } {
				append ::put_quick_list_mode_plus($channel) $modechange
				return
			}
			if { $modechange == "o" } {
				append ::put_quick_list_op_plus($channel) "$target "
			}
			if { $modechange == "v" } {
				append ::put_quick_list_voice_plus($channel) "$target "
			}
			if { $modechange == "b" } {
				append ::put_quick_list_bans_plus($channel) "$target "
			}
		}
		if { $plus_or_minus == "-" } {
			if { $modechange == "t" || $modechange == "n" ||
			$modechange == "i" || $modechange == "m" ||
			$modechange == "k" || $modechange == "l" ||
			$modechange == "p" || $modechange == "s" ||
			$modechange == "c" || $modechange == "C" ||
			$modechange == "N" || $modechange == "r" ||
			$modechange == "D" || $modechange == "u" } {
				append ::put_quick_list_mode_minus($channel) $modechange
				return
			}
			if { $modechange == "o" } {
				append ::put_quick_list_op_minus($channel) "$target "
			}
			if { $modechange == "v" } {
				append ::put_quick_list_voice_minus($channel) "$target "
			}
			if { $modechange == "b" } {
				append ::put_quick_list_bans_minus($channel) "$target "
			}
		}
		set oplist_lenght_plus [llength $::put_quick_list_op_plus($channel)]
		set oplist_lenght_minus [llength $::put_quick_list_op_minus($channel)]
		set voicelist_lenght_plus [llength $::put_quick_list_voice_plus($channel)]
		set voicelist_lenght_minus [llength $::put_quick_list_voice_minus($channel)]
		set banlist_lenght_plus [llength $::put_quick_list_bans_plus($channel)]
		set banlist_lenght_minus [llength $::put_quick_list_bans_minus($channel)]
		set lenght [expr $banlist_lenght_plus + $banlist_lenght_minus + $oplist_lenght_plus + $oplist_lenght_minus + $voicelist_lenght_plus + $voicelist_lenght_minus]
		if { $lenght == 6 } {
			put:quick:pushnow $channel
		}
	} else {
		return 
	}
}

proc put:quick:pushnow { channel } {
	if { ! [info exists ::put_quick_list($channel) ] } {
		set ::put_quick_list($channel) ""
	}
	if { ! [info exists ::put_quick_list_mode_plus($channel) ] } {
		set ::put_quick_list_mode_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_mode_minus($channel) ] } {
		set ::put_quick_list_mode_minus($channel) ""
	}
	if { ! [info exists ::put_quick_list_bans_plus($channel) ] } {
		set ::put_quick_list_bans_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_bans_minus($channel) ] } {
		set ::put_quick_list_bans_minus($channel) ""
	}
	if { ! [info exists ::put_quick_list_op_plus($channel) ] } {
		set ::put_quick_list_op_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_op_minus($channel) ] } {
		set ::put_quick_list_op_minus($channel) ""
	}
	if { ! [info exists ::put_quick_list_voice_plus($channel) ] } {
		set ::put_quick_list_voice_plus($channel) ""
	}
	if { ! [info exists ::put_quick_list_voice_minus($channel) ] } {
		set ::put_quick_list_voice_minus($channel) ""
	}
	global put_quick_refresh botnick
	set change_plus "+$::put_quick_list_mode_plus($channel)[string repeat "b" [llength $::put_quick_list_bans_plus($channel)]][string repeat "o" [llength $::put_quick_list_op_plus($channel)]][string repeat "v" [llength $::put_quick_list_voice_plus($channel)]]"
	if { $change_plus == "+" } { set change_plus "" }
	set change_minus "-$::put_quick_list_mode_minus($channel)[string repeat "b" [llength $::put_quick_list_bans_minus($channel)]][string repeat "o" [llength $::put_quick_list_op_minus($channel)]][string repeat "v" [llength $::put_quick_list_voice_minus($channel)]]"
	if { $change_minus == "-" } { set change_minus "" }
	set change "$change_minus$change_plus $::put_quick_list_bans_minus($channel)$::put_quick_list_op_minus($channel)$::put_quick_list_voice_minus($channel)$::put_quick_list_bans_plus($channel)$::put_quick_list_op_plus($channel)$::put_quick_list_voice_plus($channel)"
	set x [string map {" " ""} $change]
	if { $x != "" } {
		if { [isop $botnick $channel] } {
			putquick "MODE $channel $change" -next
		}
		put:quick:clearqueue $channel
	}
	after $put_quick_refresh [list put:quick:pushnow $channel]
}
Here a good example how useful this queue type can be:

Code: Select all

bind join - * banned:user:join
bind nick - * banned:user:nickchange

proc banned:user:nickchange { nickname hostname handle channel newnick } {
	global botnick
	if { ! [validchan $channel] } { return }
	if { $nickname == $botnick } { return }
	if { $newnick == $botnick } { return }
	if { $channel == "*" } { return }
	set nickname $newnick
	banned:user:join $nickname $hostname $handle $channel
}

proc banned:user:join { nickname hostname handle channel } {
	set hostname "$nickname!$hostname"
	set banmask ""
	foreach ban [banlist $channel] {
		set host [lindex [split $ban] 0]
		if { [string match -nocase $host $hostname] } {
			set banmask $host
		}
		if { $banmask != "" } {
			banned:user:getout $nickname $hostname $handle $channel $banmask
			return
		}
	}
	foreach ban [banlist] {
		set host [lindex [split $ban] 0]
		if { [string match -nocase $host $hostname] } {
			set banmask $host
		}
		if { $banmask != "" } {
			banned:user:getout $nickname $hostname $handle $channel $banmask
			return
		}
	}
}

proc banned:user:getout { nickname hostname handle channel banmask } {
	flood:detect $channel
	kc $channel
	put:quick $channel +b $banmask
}
The standard function off the eggdrop will ban and kick every user in single lines. If anyone got 5-10 eggdrops and use them for flood (flood join and then spamming the channel) it will taken a long time until the bot banned and kicked all. This script in combination with my new queue type will make the bot much faster. It will ban 4-6 flooders in 1 line and after that kick all. (if them are banned them can`t spam)

The problem is, all this is a little bit cpu intensiv. If the bot runs 4-7 days without restart you will have a cpu uasage of 10% (of a 2 GHZ machine).

Maybe, written in C (or a recode of the putquick command) this will be much better and less cpu intensiv.
User avatar
Sir_Fz
Revered One
Posts: 3793
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

This code is too long and can be reduced to 1 proc, I remember user once wrote a proc that will gather mode changes in 1 line (depends on modes-per-line setting) and uses putdccraw to send them to the server. All you would need is the 'after' or 'utimer' to append the modes.

Remember, the shorter the code the better it is.
User avatar
sKy
Op
Posts: 194
Joined: Thu Apr 14, 2005 5:58 pm
Location: Germany

Post by sKy »

Yes, a shorte code will be better. But it will be still a endless loop.

If someone allready have done a better version will be nice. I am not good at such complicated things.
User avatar
Sir_Fz
Revered One
Posts: 3793
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

user's code:

Code: Select all

proc massmode {chan mode arg} { 
   scan $mode {%[-+]%[bov]} p m 
   set j [llength $arg] 
   set k [expr {${::modes-per-line}-1}] 
   set out ""; 
   for {set i 0} {$i<$j} {incr i} { 
      set args [lrange $arg $i [incr i $k]] 
      append out "MODE $chan $p[string repeat $m [llength $args]] [join $args]\n" 
   } 
   putdccraw 0 [string len $out] $out 
} 
# then 
massmode #yourchan -o [chanlist #yourchan];#;)
got it from this thread.
User avatar
sKy
Op
Posts: 194
Joined: Thu Apr 14, 2005 5:58 pm
Location: Germany

Post by sKy »

I know my english isn`t really good :/ (if you read the code i hope you know what i tryed)

(i don`t want be rude)
But my original post hast nothing to do with massmode or foreach. I tryed to make my own queue, mode collection like pushmode and speed like putquick.

To say better what i mean:

Code: Select all

bind pub - * very:well:badword:example:script
proc very:well:badword:example:script { nickname hostname handle channel text } {
 if { [string match -nocase "*\[censored\]*"] } {
  set host "*!$hostname"
  putquick +b "mode $channel +b $host"
  putkick $channel $nickname "very stupid and simple badword example script ;)"
 }
}
If some floodbots (with differnt hosts) will join fast and then trigger this script, the bot will ban every one in a new line.

So i change putquick +b "mode $channel +b $host" to put:quick $channel +b $host to make this more effectively (because the put:quick proc will gather all modechanges before, but is much faster then pushmode).
User avatar
Sir_Fz
Revered One
Posts: 3793
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

If you understood user's code, you'd know that if you lappend the bans to a list and then use massmode to ban them, the bot will arrange the bans to be sent in as least lines as possible. So my idea is to make a proc which will lappend the bans and use 'after' to trigger massmode on this list, ofcourse you might want to do some modifications to the code as it suites your needs.
Post Reply