## # On Idle v3.0.2 # by MC_8 - Carl M. Gregory # This script will only run on eggdrop 1.6.13 or greater. # # R.I.P. Mom, To always be remembered; Nancy Marie Gregory. # # My Website - http://mc.purehype.net/ # Have a bug? http://mc.purehype.net/bugzilla/ ## ## # Information ## # If a user is caught idle'n too long, you can do any number of things settable # by this script. For instance: # - If an op is idle too long, you can deop him/ her. No reason to have an # AFK op opped -- seems like a secure idea, gotta be pretty paranoid though. # - Or maybe your running a warez channel and all your servers are specified # by +v, if idle (no FTP post) within x min's then -v that user. # - And yea, of course the traditional kick and/ or ban if someone is idle. # - Etc, etc ... configure to how you want your channel ran. # # Why not just use 'kick-idle' that's part of core eggdrop, you may ask. Well # in addition to the many settable options as explained above, you can also set # what will reset the idle timer. Such as 'don't reset there idle if they # change the topic', or 'don't reset a user's idle timer if he/ she says "bla" # in his/ her action". There are more than just topic and wild card public # criteria's, see settings below. # # Be carefull whom you give access to. You can specify /tcl as a valid command. # To those whom known how to code in TCL, much damage can be done should they # want to. # # For a list of commands and help on certin commands; after you load the script, # simply do '.help mc.on_idle' at your dcc console. # # If your loading this script for the first time, please do a restart and not a # rehash. ## ## # Configuration ## # # What user restriction should be set on the DCC console commands. Access is # restricted on a flag basis, syntax is GLOBAL|CHANNEL. Set this to "-|-" to # give access to anyone (assuming they can DCC chat to the bot). set mc_aa(:config:access) "m|m" ## SVS Client (Script Version Service) v4.0.1 ## # Once a day, the SVS Client will connect to MC_8's SVS Server to determine if # there is a newer version of this script available. If a newer version is # found, the script will be auto updated. # [0=no/1=yes] Do you want to enable auto updating? set mc_aa(:config:svs:enable) 1 # ## ## # Done with configurations, do not edit past here unless you know TCL. ## # #Script:mc_aa catch {unset temp} set mc_aa(info:vars) "" foreach {temp(name) temp(value)} [array get mc_aa :config:*] { lappend mc_aa(info:vars) [list $temp(name) $temp(value)] } set mc_aa(info:loc) [info script] array set mc_aa [list \ script "On Idle" \ version "v3.0.2" \ svs:script "antiidle" \ svs:version "003000002000" \ svs:client_version "v4.0.1" \ svs:client_svs_version "004000001000" \ svs:server "mc.svs.purehype.net" \ svs:port "81" \ svs:get "/index.tcl"] set mc_aa(svs:query) "svs=$mc_aa(svs:script)&" append mc_aa(svs:query) "version=$mc_aa(svs:version)&" append mc_aa(svs:query) "svs_version=$mc_aa(svs:client_svs_version)" if {![info exists numversion] || ($numversion < "1061300")} { set temp(tag) "$mc_aa(script) $mc_aa(version)" putloglev o * "$temp(tag) by MC_8 will only work on eggdrop 1.6.13 or greater." putloglev o * "$temp(tag) will not work with eggdrop $version." putloglev o * "$temp(tag) not loaded." return 1 } # Error system, v3.0 proc mc:aa:error {command error arg} { global mc_aa version lastbind errorInfo putlog "Error in script $mc_aa(script) $mc_aa(version)." putlog " Error System: v3.0" putlog " Last Bind: [expr {[info exists lastbind]?$lastbind:"-NULL-"}]" putlog " Command: $command" putlog " Arguments: $arg" putlog " Error Msg: $error" putlog " Egg. Version: [expr {[info exists version]?$version:"-NULL-"}]" putlog " TCL Version: [info tclversion]" putlog " TCL Patchlevel: [info patchlevel]" putlog "*** Please submit this bug so MC_8 can fix it. Visit" putlog "*** http://mc.purehype.net/bugzilla/ to properly report the bug." putlog \ "*** Please include ALL info. in the bug report, including the next(s)." error $errorInfo } proc mc:aa:errchk {command arg} { if {![catch {eval $command $arg} return]} {return $return} mc:aa:error $command $return $arg return 0 } # ^ bind dcc -|- *idle_timer mc:aa:dcc:*idle_timer proc mc:aa:dcc:*idle_timer {handle index arg} { return [mc:aa:errchk mc:aa:dcc:*idle_timer_ [list $handle $index $arg]] } proc mc:aa:dcc:*idle_timer_ {handle index arg} { global mc_aa set args [split $arg] if {[llength $args] < 2} { putdcc $index \ "$mc_aa(script): Invalid command usage, see '.help *idle_timer'." return 0 } mc:aa:unlist $args id args if {![mc:aa:list valid_id $id]} { putdcc $index "$mc_aa(script): Invalid id; $id" return 0 } set sa [split $mc_aa(:config:access) |] set ga [lindex $sa 0] set ca [lindex $sa 1] foreach entry [mc:aa:list list] { foreach channel [mc:aa:list get_value channels $entry] { if {(($channel == "global") && ![matchattr $handle $ga]) || (($channel != "global") && ![matchattr $handle $ga|$ca $channel])} { putdcc $index "$mc_aa(script): Access denied." putdcc $index \ " You must have either '$ga' globally or '$ca' on $channel." putloglev c * "#$handle# (Access denied) *idle_timer $id [join $args]" return 0 } } } set command [string tolower [lindex $args 0]] set args [join [lrange $args 1 end]] switch -- $command { "idle_time" { # 0 is valid, will disable. set args [lindex [split $args] 0] if {![regexp -- {^[0-9]*$} $args]} { putdcc $index "$mc_aa(script): Invalid number; $args" return 0 } mc:aa:list set_value $id idle_time $args putdcc $index "$mc_aa(script): Secussfully set $id's $command to $args." } "+exempt_ops" { mc:aa:list set_value $id exempt_ops 1 putdcc $index "$mc_aa(script): Secussfully set $id to $command." } "-exempt_ops" { mc:aa:list set_value $id exempt_ops 0 putdcc $index "$mc_aa(script): Secussfully set $id to $command." } "+exempt_halfops" { mc:aa:list set_value $id exempt_halfops 1 putdcc $index "$mc_aa(script): Secussfully set $id to $command." } "-exempt_halfops" { mc:aa:list set_value $id exempt_halfops 0 putdcc $index "$mc_aa(script): Secussfully set $id to $command." } "+exempt_voices" { mc:aa:list set_value $id exempt_voices 1 putdcc $index "$mc_aa(script): Secussfully set $id to $command." } "-exempt_voices" { mc:aa:list set_value $id exempt_voices 0 putdcc $index "$mc_aa(script): Secussfully set $id to $command." } "exempt_flags" { set args [split [lindex [split $args] 0] |] set args [lindex $args 0]|[lindex $args 1] mc:aa:list set_value $id exempt_flags $args putdcc $index "$mc_aa(script): Secussfully set $id's $command to $args." } "banmask" { set args [lindex [split $args] 0] if {![regexp -- {^[0-9]$} $args] && ![regexp -- {^1[0-9]$} $args]} { putdcc $index "$mc_aa(script): Invalid banmask number; $args" return 0 } mc:aa:list set_value $id banmask $args putdcc $index "$mc_aa(script): Secussfully set $id's $command to $args." } "channels" { set channels [split $args] set new_channels [list] foreach channel $channels { if {![validchan $channel] && ($channel != "global")} { putdcc $index "$mc_aa(script): Invalid channel; $channel" continue } lappend new_channels $channel } set channels $new_channels if {![llength $channels]} { putdcc $index "$mc_aa(script): No valid channels specified." return 0 } set access [split $mc_aa(:config:access) |] set g_a [lindex $access 0] set c_a [lindex $access 1] set new_channels [list] foreach channel $channels { if {(($channel != "global") && ![matchattr $handle $g_a|$c_a $channel]) || (($channel == "global") && ![matchattr $handle $g_a|])} { putdcc $index "$mc_aa(script): Insufficent access for channel; $channel" if {$channel == "global"} { putdcc $index " Global '$g_a' flag required." } else { putdcc $index " Global '$g_a' or channel '$c_a' flag required." } continue } lappend new_channels $channel } set channels $new_channels if {![llength $channels]} { putdcc $index "$mc_aa(script): No access to any channels specified." putloglev c * "#$handle# (No access) *idle_timer $id channels $args" return 0 } for {set i 0} {$i < [llength $channels]} {incr i} { set channel [lindex $channels $i] if {!$i} {mc:aa:list set_value $id channels $channel list} \ else {mc:aa:list lappend_value $id channels $channel} } set channels [join $channels ", "] putdcc $index \ "$mc_aa(script): Secussfully set $id's $command to $channels." } "commands" { regsub -all -- {\\n} $args \n value set new_value "" foreach item [split $value \n] { set item [string trim $item "\t "] if {$item == ""} {continue} lappend new_value $item }; set commands $new_value for {set i 0} {$i < [llength $commands]} {incr i} { set command_ [lindex $commands $i] if {!$i} {mc:aa:list set_value $id commands $command_ list} \ else {mc:aa:list lappend_value $id commands $command_} } putdcc $index "$mc_aa(script): Secussfully set $id's $command to;" foreach command_ $commands { putdcc $index " $command_" } } "default" { putdcc $index \ "$mc_aa(script): Invalid command, $command, see '.help *idle_timer'." return 0 } } mc:aa:list save -quiet return 1 } bind dcc -|- +idle_timer.no_reset mc:aa:dcc:+idle_timer.no_reset proc mc:aa:dcc:+idle_timer.no_reset {handle index arg} { return [mc:aa:errchk mc:aa:dcc:+idle_timer.no_reset_ \ [list $handle $index $arg]] } proc mc:aa:dcc:+idle_timer.no_reset_ {handle index arg} { global mc_aa if {$arg == ""} { putdcc $index \ "$mc_aa(script): Invalid command usage, see '.help +idle_timer.no_reset'." return 0 } set orig_arg $arg mc:aa:unlist [split $arg] channels {args ""} set args [join $args] if {$args == ""} { putdcc $index \ "$mc_aa(script): Invalid command usage, see '.help +idle_timer.no_reset'." return 0 } set strip [lindex $args [expr [llength $args]-1]] if {$strip == "-strip"} {set strip 1; set end 2} \ elseif {$strip == "-no_strip"} {set strip 0; set end 2} \ else {set strip 1; set end 1} set args [join [lrange $args 0 [expr [llength $args]-$end]]] unset end set args [split $args] set type [string tolower [lindex [split $args] 0]] set args [join [lrange $args 1 end]] if {$args != ""} {set args "$type $args"} \ else {set args $type} if {![regexp -- {^(nick|kick|mode|topic|text)$} $type]} { putdcc $index "$mc_aa(script): Invalid type, $type." putdcc $index " Must be one of nick, kick, mode, topic or text." return 0 } unset type set new_channels [list] foreach channel $channels { if {![validchan $channel] && ($channel != "global")} { putdcc $index "$mc_aa(script): Invalid channel; $channel" continue } lappend new_channels $channel } set channels $new_channels unset new_channels if {![llength $channels]} { putdcc $index "$mc_aa(script): No valid channels specified." return 0 } set access [split $mc_aa(:config:access) |] set g_a [lindex $access 0] set c_a [lindex $access 1] set new_channels [list] foreach channel $channels { if {(($channel != "global") && ![matchattr $handle $g_a|$c_a $channel]) || (($channel == "global") && ![matchattr $handle $g_a|])} { putdcc $index "$mc_aa(script): Insufficent access for channel; $channel" if {$channel == "global"} { putdcc $index " Global '$g_a' flag required." } else { putdcc $index " Global '$g_a' or channel '$c_a' flag required." } continue } lappend new_channels $channel } set channels $new_channels unset new_channels if {![llength $channels]} { putdcc $index "$mc_aa(script): No access to any channels specified." putloglev c * "#$handle# (No access) +idle_timer.no_reset $orig_arg" return 0 } set id [mc:aa:list new_entry] mc:aa:list set_value $id type no_reset for {set i 0} {$i < [llength $channels]} {incr i} { set channel [lindex $channels $i] if {!$i} {mc:aa:list set_value $id channels $channel list} \ else {mc:aa:list lappend_value $id channels $channel} } mc:aa:list set_value $id strip $strip mc:aa:list save -quiet putdcc $index "$mc_aa(script): Added idle no reset as ID $id." return 1 } bind dcc -|- +idle_timer mc:aa:dcc:+idle_timer proc mc:aa:dcc:+idle_timer {handle index arg} { return [mc:aa:errchk mc:aa:dcc:+idle_timer_ [list $handle $index $arg]] } proc mc:aa:dcc:+idle_timer_ {handle index arg} { global mc_aa if {$arg == ""} { putdcc $index \ "$mc_aa(script): Invalid command usage, see '.help +idle_timer'." return 0 } set orig_arg $arg mc:aa:unlist [split $arg] channels {idle_time ""} if {$idle_time == ""} {set idle_time $channels; set channels "global"} set channels [split $channels ,] if {![regexp -- {^[0-9]*$} $idle_time]} { putdcc $index "$mc_aa(script): Invalid idle time number: $idle_time" return 0 } set new_channels [list] foreach channel $channels { if {![validchan $channel] && ($channel != "global")} { putdcc $index "$mc_aa(script): Invalid channel; $channel" continue } lappend new_channels $channel } set channels $new_channels if {![llength $channels]} { putdcc $index "$mc_aa(script): No valid channels specified." return 0 } set access [split $mc_aa(:config:access) |] set g_a [lindex $access 0] set c_a [lindex $access 1] set new_channels [list] foreach channel $channels { if {(($channel != "global") && ![matchattr $handle $g_a|$c_a $channel]) || (($channel == "global") && ![matchattr $handle $g_a|])} { putdcc $index "$mc_aa(script): Insufficent access for channel; $channel" if {$channel == "global"} { putdcc $index " Global '$g_a' flag required." } else { putdcc $index " Global '$g_a' or channel '$c_a' flag required." } continue } lappend new_channels $channel } set channels $new_channels if {![llength $channels]} { putdcc $index "$mc_aa(script): No access to any channels specified." putloglev c * "#$handle# (No access) +idle_timer $orig_arg" return 0 } set id [mc:aa:list new_entry] mc:aa:list set_value $id type idle_timer for {set i 0} {$i < [llength $channels]} {incr i} { set channel [lindex $channels $i] if {!$i} {mc:aa:list set_value $id channels $channel list} \ else {mc:aa:list lappend_value $id channels $channel} } mc:aa:list set_value $id idle_time $idle_time mc:aa:list save -quiet putdcc $index "$mc_aa(script): Added idle timer as ID $id." return 1 } bind dcc -|- -idle_timer.no_reset mc:aa:dcc:-idle_timer.no_reset proc mc:aa:dcc:-idle_timer.no_reset {handle index arg} { return [mc:aa:errchk mc:aa:dcc:-idle_timer.no_reset_ \ [list $handle $index $arg]] } proc mc:aa:dcc:-idle_timer.no_reset_ {handle index arg} { global mc_aa mc:aa:unlist [split $arg] {id ""} if {$id == ""} { putdcc $index \ "$mc_aa(script): Invalid command usage, see '.help -idle_timer.no_reset'." return 0 } if {![mc:aa:list valid_id $id]} { putdcc $index "$mc_aa(script): Invalid id; $id" return 0 } set entry "" foreach item [mc:aa:list list] { if {[mc:aa:list get_value id $item] == $id} { set entry $item unset item break } } if {$entry == ""} { putdcc $index "$mc_aa(script): Entry not found!?" return 0 } if {[mc:aa:list get_value type $entry] == "idle_timer"} { putdcc $index "$mc_aa(script): Entry not an idle timer no reset." putdcc $index " Use '.-idle_timer' instead." return 0 } elseif {[mc:aa:list get_value type $entry] != "no_reset"} { putdcc $index "$mc_aa(script): Unknown entry type!?" return 0 } foreach channel [mc:aa:list get_value channels $entry] { set sa [split $mc_aa(:config:access) |] set ga [lindex $sa 0] set ca [lindex $sa 1] if {(($channel == "global") && ![matchattr $handle $ga]) || (($channel != "global") && ![matchattr $handle $ga|$ca $channel])} { putdcc $index "$mc_aa(script): Access denied." putdcc $index " You must have '$ga' globally or '$ca' for $channel." putloglev c * "#$handle# (Access denied) -idle_timer $id" return 0 } } mc:aa:list remove $id putdcc $index "$mc_aa(script): Removed idle timer no reset ID $id." return 1 } bind dcc -|- idle_timer.no_resets mc:aa:dcc:idle_timer.no_resets proc mc:aa:dcc:idle_timer.no_resets {handle index arg} { return [mc:aa:errchk mc:aa:dcc:idle_timer.no_resets_ \ [list $handle $index $arg]] } proc mc:aa:dcc:idle_timer.no_resets_ {handle index arg} { global mc_aa # Items in the database, excluding id and type. set db_items [list channels no_reset strip] mc:aa:unlist [split $arg] {channel "all"} set channel [string tolower $channel] set access [split $mc_aa(:config:access) |] set ga [lindex $access 0] set ca [lindex $access 1] if {![regexp -- {^(global|all)$} $channel]} { if {![validchan $channel]} { putdcc $index "$mc_aa(script): Invalid channel; $channel" return 0 } if {![matchattr $handle $ga|$ca $channel]} { putdcc $index "$mc_aa(script): Access denied." putdcc $index " You must have '$ga' globally or '$ca' for $channel." putloglev c * "#$handle# (Access denied) idle_timer.no_resets $arg" return 0 } } elseif {![matchattr $handle $ga]} { putdcc $index "$mc_aa(script): Access denied." putdcc $index " You must have '$ga' globally." putloglev c * "#$handle# (Access denied) idle_timer.no_resets $arg" return 0 } putdcc $index "$mc_aa(script): Idle timer no reset list: $channel" set list [list] foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "no_reset"} {continue} set channels [string tolower [mc:aa:list get_value channels $entry]] if {($channel == "all") || ([lsearch -exact $channels [string tolower $channel]] > -1)} { set id [mc:aa:list get_value id $entry] set rest [list] foreach item $db_items { lappend rest [list $item [mc:aa:list get_value $item $entry]] } lappend list "[list id $id] $rest" } } set list [lsort -index 0 -dictionary $list] foreach entry $list { set id [mc:aa:list get_value id $entry] foreach db_item $db_items { set value [mc:aa:list get_value $db_item $entry] if {$db_item == "strip"} { set value [expr {(!$value)?"no":"yes"}] }; set $db_item $value } set channels [join [lsort -dictionary $channels] ", "] set no_reset_0 [lindex [split $no_reset] 0] set no_reset_1 [join [lrange [split $no_reset] 1 end]] putdcc $index [format { [%3s] No reset upon: %s} $id $no_reset_0] if {$no_reset_1 != ""} { putdcc $index [format {%7s Argument: %s} "" $no_reset_1] } putdcc $index [format {%7s Channels: %s} "" $channels] putdcc $index [format {%7s Strip: %s} "" $strip] } return 1 } bind dcc -|- -idle_timer mc:aa:dcc:-idle_timer proc mc:aa:dcc:-idle_timer {handle index arg} { return [mc:aa:errchk mc:aa:dcc:-idle_timer_ [list $handle $index $arg]] } proc mc:aa:dcc:-idle_timer_ {handle index arg} { global mc_aa mc:aa:unlist [split $arg] {id ""} if {$id == ""} { putdcc $index \ "$mc_aa(script): Invalid command usage, see '.help -idle_timer'." return 0 } if {![mc:aa:list valid_id $id]} { putdcc $index "$mc_aa(script): Invalid id; $id" return 0 } set entry "" foreach item [mc:aa:list list] { if {[mc:aa:list get_value id $item] == $id} { set entry $item unset item break } } if {$entry == ""} { putdcc $index "$mc_aa(script): Entry not found!?" return 0 } if {[mc:aa:list get_value type $entry] == "no_reset"} { putdcc $index "$mc_aa(script): Entry not an idle timer." putdcc $index " Use '.-idle_timer.no_reset' instead." return 0 } elseif {[mc:aa:list get_value type $entry] != "idle_timer"} { putdcc $index "$mc_aa(script): Unknown entry type!?" return 0 } foreach channel [mc:aa:list get_value channels $entry] { set sa [split $mc_aa(:config:access) |] set ga [lindex $sa 0] set ca [lindex $sa 1] if {(($channel == "global") && ![matchattr $handle $ga]) || (($channel != "global") && ![matchattr $handle $ga|$ca $channel])} { putdcc $index "$mc_aa(script): Access denied." putdcc $index " You must have '$ga' globally or '$ca' for $channel." putloglev c * "#$handle# (Access denied) -idle_timer $id" return 0 } } mc:aa:list remove $id putdcc $index "$mc_aa(script): Removed idle timer ID $id." return 1 } bind dcc -|- idle_timers mc:aa:dcc:idle_timers proc mc:aa:dcc:idle_timers {handle index arg} { return [mc:aa:errchk mc:aa:dcc:idle_timers_ [list $handle $index $arg]] } proc mc:aa:dcc:idle_timers_ {handle index arg} { global mc_aa # Items in the database, excluding id and type. set db_items [list exempt_ops exempt_halfops exempt_voices exempt_flags \ banmask channels commands idle_time] mc:aa:unlist [split $arg] {channel "all"} set channel [string tolower $channel] set access [split $mc_aa(:config:access) |] set ga [lindex $access 0] set ca [lindex $access 1] if {![regexp -- {^(global|all)$} $channel]} { if {![validchan $channel]} { putdcc $index "$mc_aa(script): Invalid channel; $channel" return 0 } if {![matchattr $handle $ga|$ca $channel]} { putdcc $index "$mc_aa(script): Access denied." putdcc $index " You must have '$ga' globally or '$ca' for $channel." putloglev c * "#$handle# (Access denied) idle_timers $arg" return 0 } } elseif {![matchattr $handle $ga]} { putdcc $index "$mc_aa(script): Access denied." putdcc $index " You must have '$ga' globally." putloglev c * "#$handle# (Access denied) idle_timers $arg" return 0 } putdcc $index "$mc_aa(script): Idle timers list: $channel" set list [list] foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "idle_timer"} {continue} set channels [string tolower [mc:aa:list get_value channels $entry]] if {($channel == "all") || ([lsearch -exact $channels [string tolower $channel]] > -1)} { set id [mc:aa:list get_value id $entry] set rest [list] foreach item $db_items { lappend rest [list $item [mc:aa:list get_value $item $entry]] } lappend list "[list [list id $id]] $rest" } } set list [lsort -index 0 -dictionary $list] foreach entry $list { set id [mc:aa:list get_value id $entry] foreach db_item $db_items { set value [mc:aa:list get_value $db_item $entry] if {[regexp -- {^exempt_(op|halfop|voice)s$} $db_item]} { set value [expr {(!$value)?"no":"yes"}] }; set $db_item $value } set channels [join [lsort -dictionary $channels] ", "] switch -glob -- $banmask { "*0" {set banmask "$banmask - *!user@host.domain"} "*1" {set banmask "$banmask - *!*user@host.domain"} "*2" {set banmask "$banmask - *!*@host.domain"} "*3" {set banmask "$banmask - *!*user@*.domain"} "*4" {set banmask "$banmask - *!*@*.domain"} "*5" {set banmask "$banmask - nick!user@host.domain"} "*6" {set banmask "$banmask - nick!*user@host.domain"} "*7" {set banmask "$banmask - nick!*@host.domain"} "*8" {set banmask "$banmask - nick!*user@*.domain"} "*9" {set banmask "$banmask - nick!*@*.domain"} } if {[regexp -- {^1[0-9] - .*$} $banmask]} { append banmask " (if host, replace numbers with ?s)" } putdcc $index [format { [%3s] Timer: %s minutes} $id $idle_time] putdcc $index [format {%7s Channels: %s} "" $channels] putdcc $index [format {%7s Exempt Ops: %s} "" $exempt_ops] putdcc $index [format {%7s Exempt Halfops: %s} "" $exempt_halfops] putdcc $index [format {%7s Exempt Voices: %s} "" $exempt_voices] putdcc $index [format {%7s Exempt Flags: %s} "" $exempt_flags] putdcc $index [format {%7s Banmask: %s} "" $banmask] putdcc $index [format {%7s Commands:} ""] foreach command $commands { putdcc $index [format {%9s %s} "" $command] } } return 1 } ## Set's, Re-set's, Unset's. bind join - * mc:aa:join proc mc:aa:join {nick uhost handle channel} { mc:aa:list action join $nick $uhost $handle $channel } bind part - * mc:aa:leave bind sign - * mc:aa:leave proc mc:aa:leave {nick uhost handle channel {message ""}} { mc:aa:list action leave $nick $uhost $handle $channel } bind kick - * mc:aa:kick proc mc:aa:kick {nick uhost handle channel target reason} { if {$target != $nick} { mc:aa:list action kick $nick $uhost $handle $channel } mc:aa:list action leave $target [getchanhost $target $channel] \ [nick2hand $target $channel] $channel } bind nick - * mc:aa:nick proc mc:aa:nick {nick uhost handle channel new_nick} { mc:aa:list action nick $nick $uhost $new_nick $channel } bind mode - * mc:aa:mode proc mc:aa:mode {nick uhost handle channel mode_change victim} { mc:aa:list action mode $nick $uhost $handle $channel } bind topc - * mc:aa:topc proc mc:aa:topc {nick uhost handle channel topic} { mc:aa:list action topic $nick $uhost $handle $channel } bind pubm - * mc:aa:pubm proc mc:aa:pubm {nick uhost handle channel text} { set ::text_said $text mc:aa:list action text $nick $uhost $handle $channel } bind notc - * mc:aa:notc proc mc:aa:notc {nick uhost handle text {dest ""}} { if {![validchan $dest]} {return} set ::text_said $text mc:aa:list action text $nick $uhost $handle $dest } bind raw - PRIVMSG mc:aa:raw:privmsg proc mc:aa:raw:privmsg {from key arg} { return [mc:aa:errchk mc:aa:raw:privmsg_ [list $from $key $arg]] } proc mc:aa:raw:privmsg_ {from key arg} { set dest [lindex [split $arg] 0] set arg [string range [lindex [split $arg] 1] 1 end] if {(![validchan $dest]) || (![regexp -- "^\001(.*)\001\$" $arg dummy arg])} {return 0} set keyword [lindex [split $arg] 0] set arg [join [lrange [split $arg] 1 end]] set nick [lindex [split $from !] 0] set uhost [join [lrange [split $from !] 1 end] !] if {[string tolower $keyword] == "action"} {set ::text_said $arg} \ else {set ::text_said "$keyword $arg"} mc:aa:list action text $nick $uhost $handle $channel return 0 } ## ^ bind raw - 315 mc:aa:raw:315 proc mc:aa:raw:315 {from key arg} { return [mc:aa:errchk mc:aa:raw:315_ [list $from $key $arg]] } proc mc:aa:raw:315_ {from key arg} { global mc_aa set channel [lindex [split $arg] 1] if {![info exists mc_aa(waitfor315)]} {set mc_aa(waitfor315) [list]} set index [lsearch -exact $mc_aa(waitfor315) [string tolower $channel]] if {$index == "-1"} { return 0 } set mc_aa(waitfor315) [lreplace $mc_aa(waitfor315) $index $index] # Add everyone to memory as per when the bot join'd. foreach user [chanlist $channel] { if {[isbotnick $user]} {continue} set array [list idle [string tolower $user] \ [string tolower [getchanhost $user $channel]] \ $channel] set mc_aa($array) [clock seconds] } return 0 } bind time - * mc:aa:time proc mc:aa:time {args} { return [mc:aa:errchk mc:aa:time_ [list $args]] } proc mc:aa:time_ {args} { global mc_aa foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "idle_timer"} {continue} set id [mc:aa:list get_value id $entry] set idle_time [mc:aa:list get_value idle_time $entry] set channels [mc:aa:list get_value channels $entry] set exempt_ops [mc:aa:list get_value exempt_ops $entry] set exempt_halfops [mc:aa:list get_value exempt_halfops $entry] set exempt_voices [mc:aa:list get_value exempt_voices $entry] set exempt_flags [mc:aa:list get_value exempt_flags $entry] set banmask [mc:aa:list get_value banmask $entry] set commands [mc:aa:list get_value commands $entry] foreach channel $channels { if {![validchan $channel]} {continue} set channel [string tolower $channel] foreach array [array names mc_aa] { if {[lindex $array 0] != "idle"} {continue} mc:aa:unlist $array a_id a_nick a_uhost a_channel if {![onchan $a_nick $channel]} { unset mc_aa($array) continue } set a_hand [nick2hand $a_nick] if {($a_channel != $channel) || ($exempt_ops && ([isop $a_nick $channel])) || ($exempt_halfops && ([ishalfop $a_nick $channel])) || ($exempt_voices && ([isvoice $a_nick $channel])) || ([matchattr $a_hand exempt_flags $channel])} {continue} set user_idle [expr ([clock seconds]-$mc_aa($array))/60] if {$user_idle >= $idle_time} { putloglev o * \ "$mc_aa(script): $a_nick found idle'n in $channel, processing." mc:aa:process_commands $commands $id $a_nick \ [getchanhost $a_nick $channel] $channel $idle_time $user_idle \ $banmask } } } } } proc mc:aa:process_commands \ {commands id nick uhost channel idle_time user_idle banmask} { global mc_aa if {[string match {*\\n*} $commands]} { set temp(1) "Error processing commands for ID $id" set temp(2) "did you manually edit the datafile" putloglev d * "$mc_aa(script): $temp(1), $temp(2)? Auto converting..." regsub -all -- {\\n} $commands \n commands set new_value "" foreach item [split $commands \n] { set item [string trim $item "\t "] if {$item == ""} {continue} lappend new_value $item }; set commands $new_value for {set i 0} {$i < [llength $commands]} {incr i} { set command_ [lindex $commands $i] if {!$i} {mc:aa:list set_value $id commands $command_ list} \ else {mc:aa:list lappend_value $id commands $command_} } } set pending [list] set kick_message "$mc_aa(script) $mc_aa(version)" foreach line $commands { set line [string trim $line "\t "] set line [split $line] set action [string tolower [lindex $line 0]] set line [join [lrange $line 1 end]] set line [mc:aa:replace -- $line [list %nick $nick \ %channel $channel \ %max_idle $idle_time \ %user_idle $user_idle \ %botnick $::botnick]] set line [split $line] switch -- $action { "/msg" { mc:aa:unlist $line channel_ args putserv "PRIVMSG $channel_ :[join $args]" putloglev d * \ "$mc_aa(script): \[Sent\] Message $channel_: [join $args]" } "/notice" { mc:aa:unlist $line channel_ args putserv "NOTICE $channel_ :[join $args]" putloglev d * \ "$mc_aa(script): \[Sent\] Notice $channel_: [join $args]" } "/ban" { mc:aa:unlist $line channel_ nick_ {expire ""} {option "none"} if {($expire == "sticky") || ($expire == "none")} { set option $expire set expire "" } if {![validchan $channel_]} { mc:aa:process_commands \ [list "/globalban %nick $expire $option"] $id $nick $uhost \ $channel $idle_time $user_idle $banmask continue } if {$nick != $nick_} { if {[set uhost_ [getchanhost $nick_]] == ""} { putloglev d * "$mc_aa(script): Cannot find uhost for $nick_." continue } } else {set uhost_ $uhost} set banmask [mc:aa:maskhostbytype $nick_!$uhost_ $banmask] if {[onchan $nick_ $channel_]} { putserv "MODE $channel_ +b $banmask" putloglev d * \ "$mc_aa(script): \[Sent\] Ban $banmask in $channel_." } if {$expire != ""} { if {[regexp -- {^[0-9]*$} $expire]} { set expire "0d0h${expire}m" } set expire [expr \ ([mc:aa:list time_string_to_unixtime $expire]-[clock seconds])/60] } if {$expire == "0"} {continue} \ elseif {$expire == ""} {set expire 0} lappend pending "newchanban [list $channel_] [list $banmask] \ [list $mc_aa(script)] \$kick_message [list $expire] [list $option]" set temp(msg) "\\\[Sent\\\] Added $banmask to $channel_'s internal" append temp(msg) " banlist." lappend pending "putloglev d * \"$mc_aa(script): $temp(msg)\"" lappend pending \ "putloglev d * \" Duration: [duration [expr $expire*60]]\"" lappend pending \ "putloglev d * \" Reason: \$kick_message\"" } "/globalban" { mc:aa:unlist $line nick_ {expire ""} {option "none"} if {$expire == "sticky"} { set option sticky set expire "" } if {$nick != $nick_} { if {[set uhost_ [getchanhost $nick_]] == ""} { putloglev d * "$mc_aa(script): Cannot find uhost for $nick_." continue } } else {set uhost_ $uhost} set banmask [mc:aa:maskhostbytype $nick_!$uhost_ $banmask] foreach channel_ [channels] { if {[onchan $nick_ $channel_]} { putserv "MODE $channel_ +b $banmask" putloglev d * \ "$mc_aa(script): \[Sent\] Ban $banmask in $channel_." } } if {$expire != ""} { if {[regexp -- {^[0-9]*$} $expire]} { set expire "0d0h${expire}m" } set expire [expr \ ([mc:aa:list time_string_to_unixtime $expire]-[clock seconds])/60] } if {$expire == "0"} {continue} \ elseif {$expire == ""} {set expire 0} lappend pending "newban [list $banmask] [list $mc_aa(script)] \ \$kick_message [list $expire] [list $option]" set temp(msg) "\\\[Sent\\\] Added $banmask to the global ban" append temp(msg) " list." lappend pending "putloglev d * \"$mc_aa(script): $temp(msg)\"" lappend pending \ "putloglev d * \" Duration: [duration [expr $expire*60]]\"" lappend pending \ "putloglev d * \" Reason: \$kick_message\"" } "/kick" { mc:aa:unlist $line channel_ nick_ \ [list args [list $mc_aa(script) $mc_aa(version)]] set kick_message [join $args] # We have the kick_message, now lets do the pending bans. foreach pend $pending {eval $pend} set pending "" if {![onchan $nick_]} { set temp(msg) "Cannot kick $nick_ from $channel_ (nick not on " append temp(msg) "channel_)." putloglev d * "$mc_aa(script): $temp(msg)" continue } putserv "KICK $channel_ $nick_ :$kick_message" set temp(msg) "\[Sent\] Kicking $nick from $channel_: $kick_message" putloglev d * "$mc_aa(script): $temp(msg)" } "/raw" { putserv [join $line] putloglev d * "$mc_aa(script): \[Sent\] RAW: [join $line]" } "/tcl" { uplevel #0 "eval {[join $line]}" putloglev d * "$mc_aa(script): \[Sent\] TCL: [join $line]" } "/reset" { set uhost [getchanhost $nick $channel] set handle [nick2hand $nick $channel] mc:aa:list action leave $nick $uhost $handle $channel mc:aa:list action join $nick $uhost $handle $channel } default { set temp() "\[Invalid Command ($action)\]" putloglev d * \ "$mc_aa(script): $temp() $action [join $line]" } } } # Incase there was no /kick, let's clear out the ban queue. foreach pend $pending {eval $pend} } proc mc:aa:list {command {args ""}} { return [mc:aa:errchk mc:aa:list_ [list $command $args]] } proc mc:aa:list_ {command arg} { global mc_aa # Note: When giving arguments to the list command, ensure each item does not # contain a list it's self # ie mc:aa:list command [list a b c] [list a b c] # The list characters will get converted to the encoding system, should # the system be in a strange language, it will NOT be able to see the # list correctly. # # (bin) 15 % lindex [encoding convertto jis0212 [list "a b" "a b"]] 0 # list element in quotes followed by "D"D"D"D"D"D"D"D"D"D"" instead of space if {![info exists mc_aa(list)]} {set mc_aa(list) ""} if {[info tclversion] > 8.0} { set new_arg [list] foreach item $arg { lappend new_arg [encoding convertto [encoding system] $item] }; set args $new_arg } else {set args $arg} switch -- $command { "action" { # When something is preformed, goes here to possibly reset users idle # time. mc:aa:unlist $args action nick uhost handle channel set nick [string tolower $nick] set uhost [string tolower $uhost] set handle [string tolower $handle] set channel [string tolower $channel] set array [list idle $nick $uhost $channel] switch -- $action { "join" { if {[isbotnick $nick]} { if {[info exists mc_aa(waitfor315)]} { lappend mc_aa(waitfor315) $channel } else { set mc_aa(waitfor315) $channel } # Clear memory for that channel, but just join'd. foreach item [array names mc_aa] { if {([lindex $item 0] == "idle") && ([lindex $item 3] == $channel)} { unset mc_aa($item) } } return } else { set mc_aa($array) [clock seconds] } } "leave" { if {[isbotnick $nick]} { # Clear memory for that channel, but just join'd. foreach item [array names mc_aa] { if {([lindex $item 0] == "idle") && ([lindex $item 3] == $channel)} { unset mc_aa($item) } } } else { catch {unset mc_aa($array)} } } "kick" { if {[isbotnick $nick]} {return 0} set reset 1 foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "no_reset"} {continue} set channels [mc:aa:list get_value channels $entry] set new_channels [list] foreach chan $channels {lappend new_channels [string tolower $chan]} set channels $new_channels unset chan; unset new_channels if {([lsearch -exact $channels $channel] == "-1") && ([lsearch -exact $channels global] == "-1")} {continue} if {[mc:aa:list get_value no_reset $entry] != "kick"} {continue} set reset 0 break } if {$reset} {set mc_aa($array) [clock seconds]} } "nick" { set new_nick $handle if {[isbotnick $nick]} {return 0} set reset 1 foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "no_reset"} {continue} set channels [mc:aa:list get_value channels $entry] set new_channels [list] foreach chan $channels {lappend new_channels [string tolower $chan]} set channels $new_channels unset chan; unset new_channels if {([lsearch -exact $channels $channel] == "-1") && ([lsearch -exact $channels global] == "-1")} {continue} if {[mc:aa:list get_value no_reset $entry] != "nick"} {continue} set reset 0 break } if {$reset} {set mc_aa($array) [clock seconds]} if {![info exists mc_aa($array)]} {set mc_aa($array) [clock seconds]} set mc_aa([list idle $new_nick $uhost $channel]) $mc_aa($array) unset mc_aa($array) } "mode" { if {[isbotnick $nick]} {return 0} set reset 1 foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "no_reset"} {continue} set channels [mc:aa:list get_value channels $entry] set new_channels [list] foreach chan $channels {lappend new_channels [string tolower $chan]} set channels $new_channels unset chan; unset new_channels if {([lsearch -exact $channels $channel] == "-1") && ([lsearch -exact $channels global] == "-1")} {continue} if {[mc:aa:list get_value no_reset $entry] != "mode"} {continue} set reset 0 break } if {$reset} {set mc_aa($array) [clock seconds]} } "topic" { if {[isbotnick $nick]} {return 0} set reset 1 foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "no_reset"} {continue} set channels [mc:aa:list get_value channels $entry] set new_channels [list] foreach chan $channels {lappend new_channels [string tolower $chan]} set channels $new_channels unset chan; unset new_channels if {([lsearch -exact $channels $channel] == "-1") && ([lsearch -exact $channels global] == "-1")} {continue} if {[mc:aa:list get_value no_reset $entry] != "topic"} {continue} set reset 0 break } if {$reset} {set mc_aa($array) [clock seconds]} } "text" { if {[isbotnick $nick]} {return 0} set reset 1 foreach entry [mc:aa:list list] { if {[mc:aa:list get_value type $entry] != "no_reset"} {continue} set channels [mc:aa:list get_value channels $entry] set new_channels [list] foreach chan $channels {lappend new_channels [string tolower $chan]} set channels $new_channels unset chan; unset new_channels if {([lsearch -exact $channels $channel] == "-1") && ([lsearch -exact $channels global] == "-1")} {continue} set no_reset [mc:aa:list get_value no_reset $entry] if {![string match $no_reset "text $::text_said"]} {continue} set reset 0 break } if {$reset} {set mc_aa($array) [clock seconds]} } } } "remove" { # Remove an entry by it's ID. mc:aa:unlist $args id set new_list [list] foreach entry [mc:aa:list list] { if {[mc:aa:list get_value id $entry] == $id} {continue} lappend new_list $entry } set mc_aa(list) $new_list } "valid_id" { # Returns 1 or 0, to determin if given id is a valid one in the database. mc:aa:unlist $args id foreach entry [mc:aa:list list] { if {[mc:aa:list get_value id $entry] == $id} {return 1} }; return 0 } "new_entry" { # Creates a new empty ID entry in the data file list. # Returns the id created. set id [mc:aa:list get_next_id] set entry [list [list id $id]] foreach {item value} [list type "" exempt_ops 0 exempt_halfops 0 \ exempt_voices 0 exempt_flags -|- banmask 2 channels "" commands "" \ idle_time 0] { lappend entry [list $item $value] } lappend mc_aa(list) $entry return $id } "set_value" { # Set's name's value for given ID. Specify 'list' as the option should # you want the value in a list rather than a string (good if you expect to # do an 'lappend_value' to this id's name later on). mc:aa:unlist $args id name value {option ""} if {$name == "id"} {error "Cannot set_value for id."} set new_list [list] foreach entry [mc:aa:list list] { if {[mc:aa:list get_value id $entry] != $id} { lappend new_list $entry } else { set new_item [list] foreach item $entry { if {[lindex $item 0] != $name} {lappend new_item $item} \ else { if {$option == "list"} { lappend new_item [list $name [list $value]] } else {lappend new_item [list $name $value]} } } lappend new_list $new_item } } set mc_aa(list) $new_list } "lappend_value" { # Set's name's value for given ID. mc:aa:unlist $args id name value if {$name == "id"} {error "Cannot lappend_value for id."} set new_list [list] foreach entry [mc:aa:list list] { if {[mc:aa:list get_value id $entry] != $id} { lappend new_list $entry } else { set new_item [list] foreach item $entry { if {[lindex $item 0] != $name} {lappend new_item $item} \ else { set new_value [lindex $item 1] lappend new_value $value lappend new_item [list $name $new_value] } } lappend new_list $new_item } } set mc_aa(list) $new_list } "get_next_id" { # Returns the next free id. # Starts counting at 1. set id_list 0 foreach entry [mc:aa:list list] { set id [mc:aa:list get_value id $entry] if {$id == ""} {continue} lappend id_list $id } set id_list [lsort -dictionary $id_list] for {set i 0} {$i < [llength $id_list]} {incr i} { set id [lindex $id_list $i] set next_id [lindex $id_list [expr $i+1]] if {[expr $id+1] != $next_id} { set usable_id [expr $id+1] break } }; return $usable_id } "get_value" { # Get name's value from line. # Line must be valid datafile list format of; # {{name1} {value1}} {{name2} {value2}} {{nameN} {valueN}} # Returns name's value from line, else return "". mc:aa:unlist $args name line foreach item $line { if {[lindex $item 0] == $name} {return [lindex $item 1]} }; return "" } "list" {return $mc_aa(list)} "save" { if {[lsearch -exact $args -quiet] == -1} { putloglev o * "Writing $mc_aa(script) file..." } set io [open ./.mc_aa.data w] puts $io "#v1:$mc_aa(script):$mc_aa(version):[clock seconds]" foreach line [mc:aa:list list] {puts $io " $line"} close $io } "load" { if {[lsearch -exact $args -quiet] == -1} { putloglev o * "Loading $mc_aa(script) file..." } set mc_aa(list) [list] set io [open ./.mc_aa.data r] while {![eof $io]} { gets $io line if {([string index $line 0] != " ") || ([string trim $line] == "")} {continue} lappend mc_aa(list) $line } close $io } "time_string_to_unixtime" { # No need to clean_time_string, this does it also. # Returns unixtime of the time_string, relative to now. # time_string is XdXhXm mc:aa:unlist $args str if {![regexp -- {([0-9]*)m} $str -> min] || ($min == "")} {set min 0} if {![regexp -- {([0-9]*)h} $str -> hour] || ($hour == "")} {set hour 0} if {![regexp -- {([0-9]*)d} $str -> day] || ($day == "")} {set day 0} return [expr [clock seconds]+($min*60)+($hour*3600)+($day*86400)] } "unbind" { mc:aa:unlist $args proc foreach temp(bind) [binds $proc] { mc:aa:unlist $temp(bind) \ temp(type) temp(access) temp(key) - temp(proc) unbind $temp(type) $temp(access) $temp(key) $temp(proc) } } } } utimer 1 [list mc:aa:list load] bind evnt - save mc:aa:save proc mc:aa:save {type} {mc:aa:list save} proc mc:aa:help {index name} { global mc_aa switch -- $name { "mc.on_idle" { /* set temp(help) \ "$mc_aa(script) $mc_aa(version) by MC_8 - Carl M. Gregory This script will only run on eggdrop 1.6.13 or greater. R.I.P. Mom, To always be remembered; Nancy Marie Gregory. My Website - http://mc.purehype.net/ Have a bug? http://mc.purehype.net/bugzilla/ ------------------------------------------------------------------------------ If a user is caught idle'n too long, you can do any number of things settable by this script. For instance: - If an op is idle too long, you can deop him/ her. No reason to have an AFK op opped -- seems like a secure idea, gotta be pretty paranoid though. - Or maybe your running a warez channel and all your servers are specified by +v, if idle (no FTP post) within x min's then -v that user. - And yea, of course the traditional kick and/ or ban if someone is idle. - Etc, etc ... configure to how you want your channel ran. Why not just use 'kick-idle' that's part of core eggdrop, you may ask. Well in addition to the many settable options as explained above, you can also set what will reset the idle timer. Such as 'don't reset there idle if they change the topic', or 'don't reset a user's idle timer if he/ she says \"bla\" in his/ her action\". There are more than just topic and wild card public criteria's, see settings below. Be carefull whom you give access to. You can specify /tcl as a valid command. To those whom known how to code in TCL, much damage can be done should they want to. ------------------------------------------------------------------------------ Available commands are: idle_timers idle_timer.no_resets +idle_timer +idle_timer.no_reset -idle_timer -idle_timer.no_reset *idle_timer For help on a particular command, do: help " */ } "idle_timers" { /* set temp(help) \ {Usage: idle_timers [channel||'global'|'all'] Displays on idle timers for specified channel, global timers, or all. Default is all. Examples: .idle_timers Displays on idle timers for all channels. .idle_timers #eggdrop Displays on idle timers for #eggdrop only.} */ } "+idle_timer" { /* set temp(help) \ {Usage: +idle_timer [channel1[','channel2[','channelN]]|'global'] Adds an idle timer for specified channel. Time is in minutes. Default for [channel1[','channel2[','channelN]]|'global'] is global. Examples: .+idle_timer 300 Adds an idle timer of 300 minutes. .+idle_timer #eggdrop 5 Adds an idle timer of 5 minutes for #eggdrop.} */ } "-idle_timer" { /* set temp(help) \ {Usage: -idle_timer Removed an idle timer specified by it's ID. Examples: .-idle_timer 1 Removes idle timer ID 1. .-idle_timer 5 Removes idle timer ID 5.} */ } "*idle_timer" { /* set temp(help) \ {Usage: *idle_timer This will set paramaters of the idle timer ID. Valid arguments: idle_time This will re-set the idle timer's max idle time, in minutes. <+/->exempt_ops Exempt (+) physical ops from being triggered by this idle timer. <+/->exempt_halfops Exempt (+) physical half ops from being triggered by this idle timer. <+/->exempt_voices Exempt (+) physical voices from being triggered by this idle timer. exempt_flags Exempt flagged users from being triggered by this idle timer. Flag structure goes as GLOBAL|CHANNEL. Set to -|- to exempt no one. banmask This will set how you want to mask the ban, should one be setup to be preformed upon triggering this idle timer. Valid numbers: 0 - *!user@host.domain 1 - *!*user@host.domain 2 - *!*@host.domain 3 - *!*user@*.domain 4 - *!*@*.domain 5 - nick!user@host.domain 6 - nick!*user@host.domain 7 - nick!*@host.domain 8 - nick!*user@*.domain 9 - nick!*@*.domain You can also specify a type of 10 to 19 which correspond to masks 0 to 9. But if the host.domain is a; hostname = Instead of using a * wildcard to replace portions of the host.domain, it replaces the numbers in the host.domain with a '?' (question mark) wildcard. ip = It will mask as normal, with no '?' (question mark) replacements as does hostname. Default number is 2. channels [channel1[ channel2[ channelN]]|'global'] Will set the active channels the idle timer should be active for. Seperate each channel with a space. commands When an idle timer is triggered, the commands set here are what is preformed. Seperate each command by 2 characters, \n. Valid commands: /msg Sends a message. /notice Sends a notice. /ban [expire] [option] Will ban in . Expire time is in minutes. If no expire, is perm. If 0, is server ban (not in bot's internal banlist). If you specify 'sticky' at the end, it will make the ban sticky, read '.help stick' in the DCC console. /globalban [expire] [option] Will ban in all channels. Expire time is in minutes. If no expire, is perm. If 0, is server ban (not in bot's internal banlist). If you specify 'sticky' at the end, it will make the ban sticky, read '.help stick' in the DCC console. /kick [reason] Will kick from . If reason not specified, will be 'Anti Idle v'. /raw Sends RAW irc information to the irc server. If you want to learn about IRC raw's, visit this site: http://www.user-com.undernet.org/documents/rfc1459.txt /tcl Does tcl (for experts). /reset This will reset the users idle timer. Replacement variables: %nick - The nick of the person that said the bad word. %channel - The channel it was said in. %max_idle - Idle time user caught by. %user_idle - Users current idle time. %botnick - The bots current IRC nickname. Examples: .*idle_timer 1 banmask 2 Sets idle timer 1 to start using ban masking number 2 for it's ban's. .*idle_timer 5 channels #eggdrop #tcl Set's idle timer 5 to only be valid on #eggdrop and #tcl. .*idle_timer 3 commands /ban %channel %nick\n/kick %channel %nick No idle'n Set's idle timer 3 to ban then kick as it's reaction commands.} */ } "idle_timer.no_resets" { /* set temp(help) \ {Usage: idle_timer.no_resets [channel|'global'|'all'] Displays the current anti idle no reset's for the specified channel, global or all. Default for [channel|'global'|'all'] is all. Examples: .idle_timer.no_resets Views all idle timer no reset's. .idle_timer.no_resets #eggdrop Views idle timer no reset's for #eggdrop only.} */ } "+idle_timer.no_reset" { /* set temp(help) \ {Usage: +idle_timer.no_reset [channel1[','channel2[','channelN]]|'global'] <'nick'|'kick'|'mode'|'topic'|'text' ['-strip'|'-no_strip']> Somtimes you do not want a users' idle time to be reset. This is usefull for things like blocking anti idle script which is really just a timer on the users client to say something every so often. As you see, there are many arguments you could use; Arguments: nick -- Specify this to ensure anti idle timers are not reset upon changing his/her nickname. kick -- Specify this to ensure anti idle timers are not reset upon kicking a user. mode -- Specify this to ensure anti idle timers are not reset upon performing a mode change, either on the channel or any user. topic -- Specify this to ensure anti idle timers are not reset upon changing the channel topic. text ['-strip'|'-no_strip'] -- Specify text followed by a glob style string of text said that you don't want to reset the timers. You can specify if you want the text strip'd of mIRC control codes, such as color, before evaluating it. Default for ['-strip'|'-no_strip'] is -strip. Default for [channel1[','channel2[','channelN]]|'global'] is global. Examples: +anti_idle.no_reset #eggdrop nick This ensures idle timers for #eggdrop are not reset upon nick changes. +anti_idle.no_reset text *no idle* This ensures idle timers for all channels, global, are not reset upon text said, either privmsg/ notice/ action, matches *no idle*.} */ } "-idle_timer.no_reset" { /* set temp(help) \ {Usage: -idle_timer.no_reset Removes an on idle no reset specified by it's ID. Examples: -idle_timer.no_reset 1 Removes idle timer no reset number 1. -idle_timer.no_reset 5 Removes idle timer no reset number 5.} */ } default {set temp(help) "No help available."} } foreach line [split $temp(help) \n] {putdcc $index $line} return 0 } catch {unset name} utimer 1 [list mc:aa:list unbind mc:aa:filt:help] foreach name [set mc_aa(:help:list) [list \ "mc.on_idle" \ "idle_timers" "idle_timer.no_resets" \ "+idle_timer" "+idle_timer.no_reset" \ "-idle_timer" "-idle_timer.no_reset" \ "*idle_timer"]] { utimer 2 [list bind filt -|- ".help $name" mc:aa:filt:help] } proc mc:aa:filt:help {index text} { global mc_aa set name [string tolower [join [lrange [split $text] 1 end]]] if {[lsearch -exact $mc_aa(:help:list) $name] > -1} { mc:aa:help $index $name putloglev c * "#[idx2hand $index]# help $name" return "" } return $text } proc /* {{args ""}} {;# I use this for my syntax hi lighting.} proc */ {{args ""}} {;# I use this for my syntax hi lighting.} ## More Tools quick procs. ## -- http://mc.purehype.net:81/script_info.tcl?script=moretools # badargs # version: # v1.0 proc mc:aa:badargs {{args ""}} { if {[llength $args] < 4} { error { wrong # args: should be "mc:aa:badargs args min_llength max_llength argNames" } } set index 0 foreach varName [list args min max names] { set check_$varName [lindex $args $index] incr index } if {[regexp -- {([^0-9])} $check_min -> bad]} { error "bad number \"$bad\" in: $check_min" } if {[regexp -- {([^0-9])} $check_max -> bad] && ($check_max != "end")} { error "bad number \"$bad\" in: $check_max" } # Make sure $check_args is in list format, if not then make it so. # Were not going to use 2list here, don't want to evoke a 'too many nested # calls to Tcl_EvalObj' error since '2list' uses on this proc. if {[catch {llength $check_args} llength]} { set check_args [split $check_args] set llength $check_args } if {($llength < $check_min) || (($llength != "end") && ($llength > $check_max))} { if {[info level] == "1"} {return 1} error "wrong # args: should be \"[lindex [info level -1] 0] $check_names\"" }; return 0 } # unlist [varName1] [varName2] ... [varNameN] # version: # v1.0 proc mc:aa:unlist {{args ""}} { mc:aa:badargs $args 1 end "argsList ?varName varName ...?" set argList [lindex $args 0] set argList [expr {([catch {llength $argList}])?[split $argList]:$argList}] set argNames [lrange $args 1 end] if {![llength $argNames]} { return [expr {(![catch {llength $argList}])?[join $argList]:$argList}] } for {set index 0} {$index < [llength $argNames]} {incr index 1} { set argName [lindex $argNames $index] set argListItem [lindex $argList $index] set argName_ [expr {([catch {llength $argName}])?[split $argName]:$argName}] set setTo [lindex $argName_ 1] set argName [lindex $argName_ 0] if {$argName == ""} {continue} upvar 1 $argName var if {[expr $index+1] > [llength $argList]} { if {[llength $argName_] == "2"} {set var $setTo} } else { if {$argName == "args"} { set var [lrange $argList $index end] incr index [expr [llength $var]-1] } else {set var $argListItem} } }; return $index } # maskhostbytype [type] # version: # v2.1 proc mc:aa:maskhostbytype {{args ""}} { mc:aa:badargs $args 1 2 "nick!ident@host.domain ?type?" mc:aa:unlist $args nuhost type set type [expr {($type == "")?5:$type}] if {![regexp -- {^1?[0-9]$} $type]} { set valid "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 {or 19}" error "bad type \"$type\": must be [join $valid ", "]" } # Define the maximum length the ircd allows for an ident. Standard is 9, # however I made it to a variable incase someone wants to change it up. set ident_max-length 9 # Define the maximum length the ircd allows for a hostname/ ip. Standard is # 63, however I made it to a variable incase someone wants to change it up. set host_max-length 63 if {![regexp -- {^(.*[^!])!((.*)@(.*))$} $nuhost -> nick uhost ident host]} { error "invalid nick!ident@host.domain: $nuhost" } set maskhost 1 if {[string length $type] == "2"} { # Type must be 10-19. if {[info tclversion] < "8.1"} { set re_syntax_1 {([12][0-9][0-9]|[1-9][0-9]|[1-9])} set re_syntax_2 {([12][0-9][0-9]|[1-9][0-9]|[0-9])} } else { set re_syntax_1 {([12]\d{2}|[1-9][0-9]|[1-9])} set re_syntax_2 {([12]\d{2}|[1-9][0-9]|[0-9])} } set re_syntax ^$re_syntax_1\\.$re_syntax_2\\.$re_syntax_2\\.$re_syntax_2\$ if {![regexp -- $re_syntax $host]} { regsub -all -- {[0-9]} $host ? host set maskhost 0 }; set type [string index $type 1] } # Previous version used regexp instead of these string matches. String match # in this case is ~3 microseconds faster. if {[string match {[0-4]} $type]} {set nick *} if {[string match {[2479]} $type]} {set ident *} if {[string match {[1368]} $type]} {regsub -- {^~?(.*)$} $ident *\\1 ident} if {[string match {[3489]} $type] && $maskhost} { set host [lindex [split [maskhost $host] @] end] } if {[set length [string length $ident]] > ${ident_max-length}} { set ident *[string range $ident [expr $length-${ident_max-length}] end] } if {[set length [string length $host]] > ${host_max-length}} { set host *[string range $host [expr $length-${host_max-length}] end] } return $nick!$ident@$host } # replace [switches] # version: # v1.3 proc mc:aa:replace {{args ""}} { mc:aa:badargs $args 2 4 "?switches? text substitutions" set switches "" for {set i 0} {[string match -* [set arg [lindex $args $i]]]} {incr i} { if {![regexp -- {^-(nocase|-)$} $arg -> switch]} { error "bad switch \"$arg\": must be -nocase, or --" } if {$switch == "-"} { incr i break }; lappend switches $switch } set nocase [expr {([lsearch -exact $switches "nocase"] >= "0") ? 1 : 0}] set text [lindex $args $i] set substitutions [lindex $args [expr $i+1]] mc:aa:badargs [lrange $args $i end] 2 2 "?switches? text substitutions" # Check to see if $substitutions is in list format, if not make it so. set substitutions [mc:aa:2list $substitutions] if {[info tclversion] >= "8.1"} { return [expr {($nocase)? [string map -nocase $substitutions $text]: [string map $substitutions $text]}] } set re_syntax {([][\\\*\+\?\{\}\,\(\)\:\.\^\$\=\!\|])} foreach {a b} $substitutions { regsub -all -- $re_syntax $a {\\\1} a if {$nocase} {regsub -all -nocase -- $a $text $b text} \ else {regsub -all -- $a $text $b text} }; return $text } # 2list # version: # v1.0 proc mc:aa:2list {{args ""}} { mc:aa:badargs $args 1 1 "text" mc:aa:unlist $args text return [expr {([catch {llength $text}])?[split $text]:$text}] } ## End of More Tools quick procs. ## SVS if {![info exists mc_aa(:config:svs:enable)] || ![string match {[01]} $mc_aa(:config:svs:enable)]} { set mc_aa(:config:svs:enable) 0 } bind time - "00 00 *" mc:aa:do_svs proc mc:aa:do_svs {{args ""}} { global mc_aa set query $mc_aa(svs:query) if {$args == ""} {append query "&log=0"} set index [connect $mc_aa(svs:server) $mc_aa(svs:port)] putdcc $index "GET $mc_aa(svs:get)?$query HTTP/1.0\n" putdcc $index "Host: $mc_aa(svs:server):$mc_aa(svs:port)\n\n" control $index mc:aa:svs_talk } proc mc:aa:svs_talk {index text} { global mc_aa set header [list svs header $index] set memory [list svs memory $index] if {$text == ""} { catch {unset mc_aa($header)} catch {unset mc_aa($memory)} return 1 } set text [split $text] set rfc [lindex $text 0] set text [join [lrange $text 1 end]] if {![info exist mc_aa($header)]} { if {$rfc == "002"} { # Done with http header and useless information. if {!$mc_aa(:config:svs:enable)} { catch {unset mc_aa($header)} catch {unset mc_aa($memory)} return 1 } set mc_aa($header) 1 } return 0 } switch -- $rfc { 001 {return 0} 002 {return 0} 003 {return 0} 010 { if {$text != $mc_aa(svs:script)} { set temp(1) "wanted $mc_aa(svs:script), got $temp(text:0)" putloglev d * "$mc_aa(script): SVS Error: $temp(1)" catch {unset mc_aa($header)} catch {unset mc_aa($memory)} return 1 } return 0 } 011 {return 0} 012 {return 0} 013 {return 0} 014 {return 0} 017 {return 0} 004 { if {[info exists mc_aa($memory)]} { set file $mc_aa(info:loc)~new set temp(vars) $mc_aa(info:vars) set io [open $file w] for {set i 0} {$i <= [llength $mc_aa($memory)]} {incr i} { set line [lindex $mc_aa($memory) $i] set regexp {^[; ]*set mc_aa\((:config:[^)]*)\) *(.?)} if {[regexp -- $regexp $line -> name type]} { set continue 0 foreach item $temp(vars) { set item_name [lindex $item 0] set item_value [lindex $item 1] if {$name != $item_name} {continue} set index [lsearch -exact $temp(vars) $item] set temp(vars) [lreplace $temp(vars) $index $index] puts $io [list set mc_aa($name) $item_value] if {$type == "\{"} { while {1} { if {[regexp -- {\}(?:;* *(.*))?} $line -> extra]} { if {$extra != ""} { puts $io $extra } break } incr i set line [lindex $mc_aa($memory) $i] } puts $io "" } elseif {$type == "\""} { regsub -- {"} $line "" line while {1} { if {[regexp -- {[^\\]"(?:;* *(.*))?} $line -> extra] || [regexp -- {^"(?:;* *(.*))?} $line -> extra]} { if {$extra != ""} { puts $io $extra } break } incr i set line [lindex $mc_aa($memory) $i] } puts $io "" } set continue 1 break } if {$continue} {continue} } puts $io $line } close $io set file $mc_aa(info:loc) putloglev o * "$mc_aa(script): Auto update testing new script..." if {[catch {uplevel "source $file~new"} error]} { file delete -force -- $file~new putloglev o * "$mc_aa(script): Auto update failed: $error" putloglev o * "$mc_aa(script): Auto update loading previous script." uplevel "source $file" } else { file rename -force -- $file~new $file putloglev o * "$mc_aa(script): Auto update test good, reloading." uplevel "source $file" } } catch {unset mc_aa($header)} catch {unset mc_aa($memory)} return 1 } 200 { set temp(host) [lindex $text 1] set temp(port) [lindex $text 2] set temp(get) [lindex $text 3] set temp(cache) "$temp(host) at $temp(port)" putloglev d * \ "$mc_aa(script): SVS is being redirected to $temp(cache)." utimer 5 [list mc:aa:do_svs_ $temp(host) $temp(port) $temp(get)] catch {unset mc_aa($header)} catch {unset mc_aa($memory)} return 1 } 300 { lappend mc_aa($memory) $text return 0 } } } catch {unset index} if {![info exists mc_loaded]} {set mc_loaded(scripts) ""} set index [lsearch -exact $mc_loaded(scripts) mc_aa] lreplace mc_loaded(scripts) $index $index mc_aa ## ^ putloglev o * "$mc_aa(script) $mc_aa(version) by MC_8 loaded." # ## ## # History ( - [Found by] - ) ## # v3.0.2 (07.11.03) # MC_8 - Normand - Fixed 'invalid command name "mc:bw:errchk"'. # Bugzilla Bug 300 # # v3.0.1 (07.10.03) # MC_8 - Normand - Fixed 'can't read "mc_ss(script)": no such variable'. # Bugzilla Bug 297 # # v3.0 (07.07.03) # MC_8 - - Added .help system. # MC_8 - - Upgraded SVS. v3.0.1 -> v4.0.1 # MC_8 - - Changed script's name from Anti Idle to On Idle. #! MC_8 - - Rewrote entire script. # MC_8 - - Fixed 'invalid command name "mc:aa:mirc_script"'. # (bugzilla # 168) # MC_8 - - Added `unlist` tcl command. none -> v1.0 # MC_8 - - Added `2list` tcl command. none -> v1.0 # MC_8 - - Added `badargs` tcl command. none -> v1.0 # MC_8 - - Upgraded `masktype` tcl command, renamed to `maskhostbytype`. # v1.2 -> v2.0 # MC_8 - - Upgraded `chanint` tcl command. v2.0 -> v3.2 # MC_8 - - Upgraded the `replace` tcl command. v1.1 -> v1.3 # MC_8 - - Replace the `strip:all` tcl command with `mirc_strip`. # v1.1 -> v1.0 # MC_8 - - Upgraded Error Catching System. old -> v3.0 # MC_8 - - Upgraded SVS Client. v2.1 -> v3.0.1 # MC_8 - Don - Fixed 'couldn't set variable "temp"'. (bugzilla # 165) # # v2.0 (06.17.02) # MC_8 - Nhubbard1 - Wasn't resetting idle time on public text/ actions. # MC_8 - - Upgraded masktype proc. v1.0 -> v1.2 # MC_8 - - Upgraded chanint proc. v1.0 -> v2.0 # MC_8 - - Upgraded replace proc. v1.0 -> v1.1 # MC_8 - - Upgraded strip:all proc. v1.0 -> v1.1 # MC_8 - - Upgraded SVS. v2.0 -> v2.1 # MC_8 - Nhubbard1 - Fixed 'Tcl error [mc:aa:time]: missing # close-bracket'. # << Hrm, it was published as v1.1.1 at this point -- however it was still a # beta, to be version 2.0 (major version change). >> # MC_8 - - Removed 'scan''s for finding ident and host from # uhost. Using split to find proper values -- more # accurate. # MC_8 - - Removed an 'array unset' and replaced it with catch # {unset ...}, this would cause problems with pre TCL # 8.3. # MC_8 - - Wasn't activating an idle time stamp if one not # already found. # MC_8 - - Fixed 'TCL error [mc:aa:leave]: can't read "chan": no # such variable'. # Bugzilla bug #41. # MC_8 - - Added error catching system, gives a good debug for # bug reports. # MC_8 - - I evidently had an anti idle script out there, both # equally functional. But after looking everything # over, I decided I like this format better. Closing # my old mc.antiidle.tcl for good, using this version # instead. # MC_8 - - Changed the scripts name from 'Idle DeMode' to 'Anti # Idle', carrying the version over. # MC_8 - - Added SVS v2.0. # MC_8 - - Veriables added: active, exempt:flag, exempt:voice, # message, exempt:op, mode, reset:mode, # reset:topic, reset:nick, # reset:kick, reset:pub, strip, kick, ban, # banmask. # MC_8 - - Veriables removed: exempt, devoice, deop_msg, # devoice_msg, deop, chan, idle, freq. # MC_8 - - Updated the replace procedure. # MC_8 - - Added chanset channel int 'mc.antiidle'. # MaSsKilla - - Fixed issue with exempt. # # v1.1 (08.14.00) # MC_8 - Buffers - Added devoice and deop message. # MC_8 - - Added ability to have all channels by setting 'chan' to "". # MC_8 - Buffers - The bot was deop'n it's self, fixed. # # v1.0 (01-28-00) # MC_8 - Matt - Inital release. ##