# autoReinvite by Artix <loyauflorian@gmail.com> # Version: 1.1 - 30/10/2010 # # Compatibility: Requires eggdrop 1.6 (1.8 should work too), Tcl8.5/8.6 # and the channels, server and irc modules. # # Since the script uses the watch list, you'll need to be on an unrealIRCd server # that supports it. I haven't heard of other server type that support it so far. # # Note that using other scripts that count on the watchlist at same time is a bad idea. # # Contact me by mail at loyauflorian@gmail.com # or on IRC, irc.epiknet.org, channel #eggdrop #  # # # Script description: # # Auto-reinvites (yeah, seriously!) people on a chan under # specific events.  # # Features:  #	- Auto-reinvite on part or kick #	- Add to watch list when quitting (or netsplit loss) #	- Auto-invite when reconnecting while in watch list # 	- The watch list is saved in a database file # 	- Automatic trimming of the database #	- Hourly saving of the database #	- Invites done only if the guy is not banned on channel #	- Fully (but lightly) commented code # # Version 1.1: #	- Bindings uninstalling now properly working, thanks to MenzAgitat #	- Same for bindings that would trigger on EVERY channel. Thanks once more. # 	- When the watchlist is full, oldest entries are now removed - instead of #	 	removing a random entry from the list. # # # Note that the database isn't supposed to be modified or # read. Let the script do the stuff, and delete the file # if you want to erase the database. # # The database is saved at hourly-updates time set in # the config file, once every hour. # You can change this at the end of the file if needed. # # YOU HAVE TO set the chan below in the configuration # for the script to work. # # Thanks to thommey of eggheads for fixing # my poor database writing code ._.'    # If the file was sourced already, better get rid of everything # before reloading it. if {[info procs ::autoReinvite::uninstall] ne ""} { ::autoReinvite::uninstall }  namespace eval ::autoReinvite {  	#=================== 	## CONFIG START ## 	#=================== 	 	# UNIQUE chan the script will work on 	variable bindedchan "#insert-your-chan-here" 	 	# Toggles invites 	variable enabled 1 	 	# Path to the watch nick database 	variable watchdb "autoReinvite.db" 	 	# Maximum entries in the database 	# Technical notes: previous entries will be replaced,  	# the script won't delete any entry while running. 	# The watch list is only trimmmed when saving. 	variable maxwatch 50 		 	##  CONFIG END  ## 	 	 	 	# Watch List initialisation 	variable watchlist {}  	# Either add or remove the whole watchlist at once  	# + to add, - to remove all 	proc modwatch {symbol} { 		variable watchlist 		 		# Add every nick to watch one by one 		foreach entry $watchlist { 			lappend output "$symbol[lindex $entry 0]" 		} 		 		# Send 'em to the server. 		if {![info exists output]} return 		putquick "WATCH [join $output]" 	} 	 	# Loads the watch DB. Done automatically on startup. 	proc loadWatchDB {} { 		variable watchdb 		variable watchlist 		 		# Get rid of ALL previous watches! 		modwatch - 		set watchlist {} 		 		# Open the new file and load it 		if {![file exists $watchdb]} return 		set channelID [open $watchdb r] 		set watchlist [gets $channelID] 		close $channelID 		 		# Add the new watches 		modwatch + 	} 	# Since we're loading the script, better load the DB too. 	loadWatchDB 	 	# Save the watch db 	proc saveWatchDB {args} { 		variable watchdb 		variable watchlist 		variable maxwatch 		 		# Eventually trim the database if it's too big 		if {[llength $watchlist] > $maxwatch} { 			set watchlist [lrange $watchlist 0 $maxwatch-1] 		} 		 		# Open the file and write the watchlist into it 		set channelID [open $watchdb w+] 		puts -nonewline $channelID $watchlist 		close $channelID 	}  	# Clear watches and bindings, save DB, delete the namespace 	proc uninstall {args} { 		saveWatchDB 		modwatch - 		foreach bind [binds ::autoReinvite::*] { 			catch { unbind [lindex $bind 0] [lindex $bind 1] [lindex $bind 2] [lindex $bind 4] } 		} 		namespace delete ::autoReinvite 	return } 	 	# If a watch get detected, invite the guy. 	proc watchDetection {from keyword data} {  		set data [split $data] 		::autoReinvite::invite [lindex $data 1] [lindex $data 2]@[lindex $data 3] } 		 	# In case of a part, we reinvite the guy! 	proc partDetection {nick uhost hand chan reason} { ::autoReinvite::invite $nick $uhost 1 } 	 	# In case of a kick, we reinvite the guy! 	proc kickDetection {nick uhost hand chan victim reason} { ::autoReinvite::invite $victim [getchanhost $victim $chan] 1 } 	 	# Invite someone.. if he's not banned! 	proc invite {nick uhost {override_onchan_check 0}} { 	# NOTE: We need an argument to override the onchan check 	# because the bot will say someone that triggered a part 	# or kick bind is still on channel. 	 		variable enabled 		variable bindedchan 		 		# If the guy's already here, or the script disabled, don't bother 		if {([onchan $nick $bindedchan] && !$override_onchan_check) || !$enabled} return 		 		# Check every chan ban for a match 		foreach line [chanbans $bindedchan] { 			if {[string match -nocase [string map "\[ \\\[ \] \\\]" [lindex $line 0]] $nick!$uhost]} return 		}  		# In case everything's ok, we just invite him. 		putquick "INVITE $nick $bindedchan" 	} 		 	# Add someone to the watchlist and start 	# watching him. 	proc addWatch {nick uhost hand chan reason} { 		variable bindedchan 		variable watchlist 		variable maxwatch 		 		# Cancel if it's the wrong chan 		if {$chan ne $bindedchan} return 		 		# Clear previous matching watches 		if {[clearWatch $nick $uhost $hand 1]} { 			# Start watching the guy on IRC 			putquick "WATCH +$nick" 		} 		# Add a fresh watch in the list 		lappend watchlist [list $nick $uhost $hand] 		# If the watchlist grows too big, we delete the first entry in the list 		if {([llength $watchlist] - 1) < $maxwatch} { 			clearWatch {*}[lindex $watchlist 0] 		} 	} 	 	# Deletes a current watch (on channel join) 	proc delWatch {nick uhost hand chan args} { 		variable bindedchan 		# Just laugh loud if it's the bot joining or wrong chan 		if {$nick eq $::nick || $chan ne $bindedchan} return 		# Else remove the watch 		clearWatch $nick $uhost $hand 		# Pretty simple eh? 		return 	} 	 	# Clears a watch from the watchlist 	# Based on nick/uhost/handle 	# Stuff matching either one will get removed 	# Corresponding IRC watchs get removed as well 	proc clearWatch {nick uhost hand {nowatch 0}} { 		variable watchlist 		 		# If the list is empty, just gtfo! Might cause errors otherwise. 		if {![llength $watchlist]} { return 0 } 		 		# If the nick matchs an existing watch, remove it 		if {[set nickIndex [lsearch -exact -index 0 $watchlist $nick]] != -1} { removeEntry $nickIndex  		# Same for userhost... 		} elseif {[set uhostIndex [lsearch -exact -index 1 $watchlist $uhost]] != -1} { removeEntry $uhostIndex  		# ...and handle. 		} elseif {$hand ne "*" && [set handIndex [lsearch -exact -index 2 $watchlist $hand]] != -1} { removeEntry $handIndex 		 		# If a match was found, we remove the watch on IRC too 		} else { return 0 } 		 		if {!$nowatch} { putquick "WATCH -$nick" } 		return 1 	} 	 	# Deletes an entry from the watchlist in a conveninent way 	proc removeEntry {index} { 		variable watchlist 		set watchlist [lreplace $watchlist $index $index] 	} 		 	# Bind on 'logged in' watch message 	bind raw - 600 ::autoReinvite::watchDetection 	# Bind on someone parting to reinvite him asap 	bind part - "$::autoReinvite::bindedchan *" ::autoReinvite::partDetection 	bind kick - "$::autoReinvite::bindedchan *" ::autoReinvite::kickDetection 	# Bind on someone quitting to add the watch 	bind sign - "$::autoReinvite::bindedchan *" ::autoReinvite::addWatch 	# Bind on someone rejoining to remove the watch 	bind join - "$::autoReinvite::bindedchan *" ::autoReinvite::delWatch 	# rehash script uninstall binding 	bind evnt - prerehash ::autoReinvite::uninstall 	 	putlog "autoReinvite by Artix <loyauflorian@gmail.com> loaded succesfully." }