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.

flood protection and channel switch

Help for those learning Tcl or writing their own scripts.
Post Reply
User avatar
spithash
Master
Posts: 249
Joined: Thu Jul 12, 2007 9:21 am
Location: Libera
Contact:

flood protection and channel switch

Post by spithash »

Hi there, can anyone help me around to add a flood protection and a channel on and off switch (.chanset #channel +lovequotes) on this script?

Code: Select all

bind pub - "!lovequotes" lovequotes::quotes::movie
 
namespace eval lovequotes {
 
variable version "0.4"
 
# file with the quotes, must be in the same directory as the script
variable quotefile "lovequotes.txt"
 
proc randline {file} {
  if {[catch {open scripts/$file r} fs]} {
    putlog "Failed to open scripts/$file"
    return ""
  } else {
    variable data [read -nonewline $fs]
    close $fs
    variable data [split $data \n]
    return [lindex $data [rand [llength $data]]]
  }
}
 
namespace eval quotes {
  proc movie {nick uhost hand chan text} {
    variable aquote [lovequotes::randline $lovequotes::quotefile]
    putserv "privmsg $chan :$lovequotes::quotes::aquote"
    return 0
    }
  }
}
 
putlog "Loaded: LoveQuotes v$lovequotes::version"
Thanks :)
Libera ##rtlsdr & ##re - Nick: spithash
Click here for troll.tcl
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

If you read a file the way you did it, basically the bot will load all that file content in the RAM memory of the PC it's running on and that's a bad idea if the file is big.

I've taken a different approach and used 'wc -l file' to count the number of lines that particular file has, create a random number and use the fetchQuote proc, that while reads the file one line at a time it doesn't store anything until it finds the exact line number we are looking for and stores only that line in RAM memory. Each time the bot is rehashed, the line count is also refreshed so this takes care of keeping the file up-to-date.

Code: Select all

namespace eval lovequotes {
	variable version "0.5"
	variable quote(count) [exec wc -l $quote(file)]
	
	bind pub - "!lovequotes" [namespace current]::randomQuote
	
	proc randomQuote {nick uhost hand chan text} {
		variable quote
		set quote [fetchQuote [rand $quote(count) +1]]
		puthep "PRIVMSG $chan :$quote"
    }

	proc fetchQuote {no} {
		variable quote
		if {[catch {open $quote(file) r} fp]} {
			putlog "Failed to open $quotefile, got error: $fp"
			close $fp
			return
		}
		set i 0
		while {[gets $fp line] != -1} {
			if {$i == $no} { break } else { incr i }
		}
		close $fp
		return $line
	}

	putlog "Loaded: LoveQuotes v$version"
}
There may be other methods to read a specific line of that file, so I'm open for suggestions.

PS: I did only a few tests in tclsh, so don't test this on a dummy bot.

Edit: Another approach is by using bash commands exclusively by replacing fetchQuote with this:

Code: Select all

	proc fetchQuote {no} {
		variable quote
		if {[file exists $quote(file)]} {
			return [exec sed -n "$no p" $quote(file)]
		}
	}
Later edit: Corrected a typo.
Last edited by caesar on Wed Jan 08, 2014 1:28 am, edited 1 time in total.
Once the game is over, the king and the pawn go back in the same box.
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

bind pub - "!moviequotes" moviequotes::movie

setudef flag moviequotes

namespace eval moviequotes {

   variable timelimit "30"
   variable repeat 3
   variable kick 5
   variable ban 7
   variable version "0.4"

   proc create {file} {
      if {[catch {open $file r} fs]} {
         putlog ">> $file cannot be read."
         return ""
      } else {
         variable quote
         variable max 0
         foreach line [split [read -nonewline $fs] \n] {
		if {[string length $line]} { set quote($max) $line ; incr max }
	   }
         close $fs
         putlog ">> $file sourced, [array size quote] quotes loaded..."
         unset max
      }
   }


   proc movie {nick uhost hand chan text} {
      if {![channel get $chan moviequotes]} { return }
      variable timelimit
      if {[lindex [set wait [throttle_ $uhost,$chan,moviequotes $timelimit]] 0]} {
         switch -- [lindex $wait 1] {
            "BAN" {
 		       putserv "MODE $chan +b [maskhost $nick!$uhost]"
 		       if {[botisop $chan]} {
 		          putserv "KICK $chan $nick :*KICKS YOUR BALLS IN (then banned you because you can't wait [lindex $wait 0] more seconds)*"
 		       } else {
 		          putserv "privmsg $chan :Somebody op me so I can kickban $nick and their balls out of the channel then!"
 		       }
 		       return
            }
            "KICK" {
 		        if {[botisop $chan]} {
 		           putserv "KICK $chan $nick :*KICKS YOUR BALLS IN (because you can't wait [lindex $wait 0] more seconds)*"
 		        } else {
 		           putserv "privmsg $chan :You are lucky im not opped. Somebody needs to kick $nick and their balls out of the channel!"
 		        }
 		        return
            }
            default { }
         }
         putserv "privmsg $chan :$nick, you have been Throttled! You're going too fast and making my head spin! Wait $wait more seconds or I will kick your balls in."
         return
      }
      variable quote
      if {[array size quote] > 0 } { putserv "privmsg $chan :$quote([rand [array size quote]])" }
      return 0
   }

   # Throttle Proc (slightly altered, super action missles) - Thanks to user
   # see this post: http://forum.egghelp.org/viewtopic.php?t=9009&start=3
   proc throttle_ {id seconds} {
      variable throttle
      variable repeat
      variable kick
      variable ban
      if {[info exists throttle($id)]&&[lindex $throttle($id) 0]>[clock seconds]} {
         set throttle($id) [list [lindex $throttle($id) 0] [set value [expr {[lindex $throttle($id) 1] +1}]]]
         if {$value > $ban} { return [list [expr {[lindex $throttle($id) 0] - [clock seconds]}] "BAN"] }
         if {$value > $kick} { return [list [expr {[lindex $throttle($id) 0] - [clock seconds]}] "KICK"] }
         if {$value > $repeat} { return [expr {[lindex $throttle($id) 0] - [clock seconds]}] } { set id 0 }
      } {
         set throttle($id) [list [expr {[clock seconds]+$seconds}] 1]
         set id 0
      }
   }

   # sub - clean throttled users
   proc throttleclean_ {args} {
      variable throttle
      set now [clock seconds]
      foreach {id time} [array get throttle] {
         if {[lindex $time 0]<=$now} {unset throttle($id)}
      }
   }
}

catch {array unset moviequotes::quote}
# file with the quotes
moviequotes::create "scripts/moviequotes.txt"

putlog "Loaded: MovieQuotes v$moviequotes::version"
.chanset #chan +moviequotes to enable. Also added throttle, change timelimit to tell size of time window. Change repeat for how many queries are allowed in that window. Not sure if this was a love quote or movie quote, so cleaned it all up to resemble movie quotes. ;)
Last edited by speechles on Tue Nov 05, 2013 6:29 am, edited 6 times in total.
User avatar
spithash
Master
Posts: 249
Joined: Thu Jul 12, 2007 9:21 am
Location: Libera
Contact:

Post by spithash »

Thank you guys for all the help!

I used speechless' script, here's the update:

Code: Select all

bind pub - "!moviequotes" moviequotes::movie

setudef flag moviequotes

namespace eval moviequotes {

   variable timelimit "30"
   variable repeat 3
   variable kick 5
   variable ban 7
   variable version "0.4"

   proc create {file} {
      if {[catch {open $file r} fs]} {
         putlog ">> $file cannot be read."
         return ""
      } else {
         variable quote
         variable max 0
         foreach line [split [read -nonewline $fs] \n] {
		if {[string length $line]} { set quote($max) $line ; incr max }
	   }
         close $fs
         putlog ">> $file sourced, [array size quote] quotes loaded..."
         unset max
      }
   }


   proc movie {nick uhost hand chan text} {
      if {![channel get $chan moviequotes]} { return }
      variable timelimit
      if {[lindex [set wait [throttle_ $uhost,$chan,moviequotes $timelimit]] 0]} {
         putlog "--> $uhost,$chan,moviequotes :: $wait"
         switch -- [lindex $wait 1] {
            "BAN" {
                    putserv "MODE $chan +b [maskhost $nick!$uhost]"
 		        if {[botisop $chan]} {
				putserv "KICK $chan $nick :*KICKS YOUR BALLS IN (then banned you because you can't wait [lindex $wait 0] more seconds)*"
			  } else {
				putserv "privmsg $chan :Somebody op me so I can kickban $nick and their balls out of the channel then!"
			  }
 	              return
            }
            "KICK" {
 		        if {[botisop $chan]} {
 		            putserv "KICK $chan $nick :*KICKS YOUR BALLS IN (because you can't wait [lindex $wait 0] more seconds)*"
			  } else {
				putserv "privmsg $chan :You are lucky im not opped. Somebody needs to kick $nick and their balls out of the channel!"
			  }
 	              return
            }
            default { }
         }
         putserv "privmsg $chan :$nick, you have been Throttled! You're going too fast and making my head spin! Wait $wait more seconds or I will kick your balls in."
         return
      }
      variable quote
      if {[array size quote] > 0 } { putserv "privmsg $chan :$quote([rand [array size quote]])" }
      return 0
   }

   # Throttle Proc (slightly altered, super action missles) - Thanks to user
   # see this post: http://forum.egghelp.org/viewtopic.php?t=9009&start=3
   proc throttle_ {id seconds} {
      variable throttle
      variable repeat
      variable kick
      variable ban
      if {[info exists throttle($id)]&&[lindex $throttle($id) 0]>[clock seconds]} {
         set throttle($id) [list [lindex $throttle($id) 0] [set value [expr {[lindex $throttle($id) 1] +1}]]]
         if {$value > $ban} { return [list [expr {[lindex $throttle($id) 0] - [clock seconds]}] "BAN"] }
         if {$value > $kick} { return [list [expr {[lindex $throttle($id) 0] - [clock seconds]}] "KICK"] }
         if {$value > $repeat} { return [expr {[lindex $throttle($id) 0] - [clock seconds]}] } { set id 0 }
      } {
         set throttle($id) [list [expr {[clock seconds]+$seconds}] 1]
         set id 0
      }
   }

   # sub - clean throttled users
   proc throttleclean_ {args} {
      variable throttle
      set now [clock seconds]
      foreach {id time} [array get throttle] {
         if {[lindex $time 0]<=$now} {unset throttle($id)}
      }
   }
}

catch {array unset moviequotes::quote}
# file with the quotes
moviequotes::create "scripts/moviequotes.txt"

putlog "Loaded: MovieQuotes v$moviequotes::version"

This one works around with utf8 .txt files :)
Libera ##rtlsdr & ##re - Nick: spithash
Click here for troll.tcl
Post Reply