All pastes #769729 Raw Edit

Stuff

public text v1 · immutable
·published 2007-11-11 17:21 UTC
rendered paste body
What if you wanted to add a definable kick msg?  Make the program a little more fancy.  The command is lrange, it takes the parameters from N'th index to N'th index.  Here it is from the TCL help file:

NAME
lrange - Return one or more adjacent elements from a list

SYNOPSIS
lrange list first last

DESCRIPTION
List must be a valid Tcl list.  This command will return a new list consisting of elements first through last, inclusive.  First or last may be end (or any abbreviation of it) to refer to the last element of the list.  If first is less than zero, it is treated as if it were zero.  If last is greater than or equal to the number of elements in the list, then it is treated as if it were end.  If first is greater than last then an empty string is returned.  Note: "lrangelist first first" does not always produce the same result as "lindexlist first" (although it often does for simple fields that aren't enclosed in braces); it does, however, produce exactly the same results as "list [lindexlist first]"

So you would need to take parameter 1 for text, and to the end...

This is how you would do it:
	bind pub O !kick pub:kick
proc pub:kick {nick host hand chan text} {
  set whom [lindex $text 0]
  set reason [lrange $text 1 end]
  putserv "KICK $chan $whom :$reason"
}


Lets make it even more spoofy, what about if $nick isn't on the channel?  Well we need an if statement don't we?  Look in tcl-commands.doc for the command.

Here is the program:
	bind pub O !kick pub:kick
proc pub:kick {nick host hand chan text} {
  set whom [lindex $text 0]
  set reason [lrange $text 1 end]
  if {[onchan $whom $chan]} {
    putserv "KICK $chan $whom :$reason"
  } else {
    puthelp $chan "$nick: $whom is not on $chan"
  }
}


This is from the TCL help file, I'll give examples for a few, but I'm sure you can figure it out

NAME
string - Manipulate strings

SYNOPSIS
string option arg ?arg ...? 

DESCRIPTION
Performs one of several string operations, depending on option.  The legal options (which may be abbreviated) are:

string compare string1 string2
    Perform a character-by-character comparison of strings string1 and string2
    in the same way as the C strcmp procedure.  Return -1, 0, or 1, depending
    on whether string1 is lexicographically less than, equal to, or greater
    than string2.

string first string1 string2
    Search string2 for a sequence of characters that exactly match the
    characters in string1.  If found, return the index of the first character
    in the first such match within string2.  If not found, return -1.

string index string charIndex
    Returns the charIndex'th character of the string argument.  A charIndex of
    0 corresponds to the first character of the string.  If charIndex is less
    than 0 or greater than or equal to the length of the string then an empty
    string is returned.

string last string1 string2
    Search string2 for a sequence of characters that exactly match the
    characters in string1.  If found, return the index of the first character
    in the last such match within string2.  If there is no match, then return
    -1.

string length string
    Returns a decimal string giving the number of characters in string.

string match pattern string
    See if pattern matches string; return 1 if it does, 0 if it doesn't.
    Matching is done in a fashion similar to that used by the C-shell.  For
    the two strings to match, their contents must be identical except that the
    following special sequences may appear in pattern:

    *     Matches any sequence of characters in string, including a null
            string.
   
    ?       Matches any single character in string.
   
    [chars] Matches any character in the set given by chars.  If a sequence of
            the form x-y appears in chars, then any character between x and y,
            inclusive, will match.
   
    \x     Matches the single character x. This provides a way of avoiding the
            special interpretation of the characters *?[]\ in pattern.

string range string first last
    Returns a range of consecutive characters from string, starting with the
    character whose index is first and ending with the character whose index
    is last.  An index of 0 refers to the first character of the string.  An
    index of end (or any abbreviation of it) refers to the last character of
    the string.  If first is less than zero then it is treated as if it were
    zero, and if last is greater than or equal to the length of the string
    then it is treated as if it were end.  If first is greater than last then
    an empty string is returned.

string tolower string
    Returns a value equal to string except that all upper case letters have
    been converted to lower case.

string toupper string
    Returns a value equal to string except that all lower case letters have
    been converted to upper case.

string trim string ?chars?
    Returns a value equal to string except that any leading or trailing
    characters from the set given by chars are removed.  If chars is not
    specified then white space is removed (spaces, tabs, newlines, and
    carriage returns).

string trimleft string ?chars?
    Returns a value equal to string except that any leading characters from
    the set given by chars are removed.  If chars is not specified then white
    space is removed (spaces, tabs, newlines, and carriage returns).

    This is usefull for creating bans!!!
    Here is a sample kick ban script I wrote...
	proc pubm:kickban {nick host hand chan text} {
  set whom [lindex $text 0]
  set mask [trimleft [maskhost [getchanhost $whom $chan]] *!]
  set mask *!*$mask
  putmsg $chan "* Kick and Ban $nick ($mask) because [lrange $text 1 end]"
  putserv "MODE -o+b $whom $mask"
  putserv "KICK $whom :[lrange $text 1 end]
}

    Notice I had to extract the person who is getting KB'd from text.  I then
    had to get his host from the command getchanhost (tcl-commands.doc), and
    then make it a usable mask host for bans.  However maskhost returns it's
    value in *!user@*.machine.end I need a *!*, so I used 'trimleft' and it
    did my job.

string trimright string ?chars?
    Returns a value equal to string except that any trailing characters from
    the set given by chars are removed.  If chars is not specified then white
    space is removed (spaces, tabs, newlines, and carriage returns).

string wordend string index
    Returns the index of the character just after the last one in the word
    containing character index of string.  A word is considered to be any
    contiguous range of alphanumeric or underscore characters, or any single
    character other than these.

string wordstart string index
    Returns the index of the first character in the word containing character
    index of string.  A word is considered to be any contiguous range of
    alphanumeric or underscore characters, or any single character other than
    these.

  (back to top)

## V - Loops ##

This section follows the following loops: foreach, for, and while (thanxs for the help from the people on the Doc Project List).

Foreach a list of items, and goes through each setting it as a var then executing commands, and goes to the next.

This proc will deop any one on the chan who doesn't have +o.

syntax for foreach:
	foreach nick [chanlist $chan] {
  if {([isop $nick $chan]) && (![matchattr $nick o]) && \
      (![matchchanattr $nick o $chan])} {
    pushmode $chan -o $nick
  }
}

chanlist gives a list of people on the chan.

# The Procedure #
    It first checks to make sure he's an op
    Then checks to see if he's a global op
    Then checks to see if he's a chan op
    If all work out, he is deoped, if not nothing happens

syntax for while:
	while {![botisop $chan]} {
  puthelp "PRIVMSG $chan :Opme!!!"
}

That will flood the bot off but you get the idea?

It will execute body until the operator changes value

syntax for for:
	for {set x 0} {$x > 5} {incr x} {
  puthelp "PRIVMSG $chan $x"
}

First of all this script will count from 1 to 6

The first set of {}'s happens only when U execute the for statement the second {}'s is the stopper.  When that is true it will stop the body the third {} is every time you complete body, do it, then do body again


## VI - User-get/User-set ##

Each user on eggdrop has a special field called "xtra" which lets you store whatever you like about users.  The field size is limited so don't get too excited.  :)

It is a line where you (and your scripts) can store things the way you want to, just like the "comment" line each user has.  But to improve it's functionality, there are two procedures which come with the "toolkit.tcl" (comes in eggdrops scripts dir) to access this field in a more organized way.

The best thing is to *only* access the xtra field using these two procedures. Make sure no other script is accessing it another way (simple way to check this is to 'grep setxtra *' and 'grep getxtra *' in your scripts directory).

The procs to use:
	user-set handle fieldname 'value...'
user-get handle fieldname

You can have any fieldname you like, like 'url' to store the users homepage, 'birthday', etc (check out 'set whois-fields' in eggdrops config file, which makes use of exactly these fields!).

You name the field, set the value with user-set and don't have to worry anymore.  And retore the value with user-get afterwards, as in:
	if {[user-get Ernst url] == ""} {putlog "Ernst has no url set"}


  (back to top)

## VII - Return command ##

The return command has two uses.  The first is to stop the current proc.  The second, and most usefull is the the abiity to return a number, or text.

Heres an example:
	if {[chkaccess $nick]} {
  pushmode $nick +o $chan
}

chkaccess would return a 0, or 1 and then it would op them based on the return.

This is from tcl-commands.doc:

    Several bindings pay attention to the value you return from the proc
    (using "return $value").  Usually they expect a 0 or 1, and failing
    to return any value is interpreted as a 0.

    Here's a list of the bindings that use the return value from procs
    they trigger:

    MSG   Return 1 to make the command get logged like so:
          (nick!user@host) !handle! command

    DCC   Return 1 to make the command get logged like so:
          #handle# command

    FIL   Return 1 to make the command get logged like so:
          #handle# files: command

    PUB   Return 1 to make the command get logged like so:
          <<nick>> !handle! command

    CTCP  Return 1 to ask the bot not to process the CTCP command on its
          own.  Otherwise it would send its own response to the CTCP
          (possibly an error message if it doesn't know how to deal with
          it).

    FILT  Return 1 to indicate the text has been processed, and the bot
          should just ignore it.  Otherwise it will treat the text like
          any other.

    FLUD  Return 1 to ask the bot not to take action on the flood.
          Otherwise it will do its normal punishment.

    RAW   Return 1 to ask the bot not to process the server text.  This
          can affect the bot's performance (by causing it to miss things
          that it would normally act on) -- you have been warned.

    WALL  Return 1 to make the command get logged liked so:
          !nick! msg

syntax for return:
    return <numeric>

Example:
    return 0

  (back to top)

## VIII - Good Programming habits ##

Many people load tons of scripts at once, and they don't want conflicts! There are a few ways to help avoid conflicts.  USE RETURN 0 AS LITTLE AS POSSIBLE or else it will stop all bind searching after your proc..  Here are some other ideas

(1) Label your procs sensable.  Such as in my scripts I some times use
        proc mbti:antiidle {} {}
    Not some thing like
        proc script {} {}

(2) Same with your variables.  If you use '-'s in your variables when calling
    them you must ${mbti-antiidle} some thing like that

(3) If your script uses timers make it compatable so you don't don't have too
    many of them (see examples in IX)

If you've noticed in all my procecdures I've used an indentation system, I suggest you also use one. Most common methods consist of either a TAB or Double Spacing.

<N> where N is the number of spaces

Example

    proc bla {} {
    <1> globlal testchan
    <1> if {[botisop $testchan]} {
    <1> <2> puthelp "PRIVMSG $testchan :I'm oped!
    <1> }
    }

  (back to top)

## IX - Program Examples, then explained. ##

I've taken some of these from programs I've written, or I just made them up =) (Many thanxs to the people on the Doc Project Listserv for suggestions!)

###
	bind pubm O !rules pubm:ab_rules
proc pubm:ab_rules {nick host hand chan text} {
  set who [lindex $text 0]
  if {$who == ""} {
# Because of line wraping it will not fit on one line, but you get the idea
    putmsg $chan "There is  NO  Cursing, Harrasment, Abusing the bot, Flooding, Clones, Advertising.  Violation of this policy may result in a kick, and/or ban."
    return 1
  }
  putmsg $who "There is  NO  Cursing, Harrasment, Abusing the bot, Flooding, Clones, Advertising.  Violation of this policy may result in a kick, and/or ban."
}

# The Bind #
    Public Match
    Op Access on that Channel, or Global Op Access
    Trigger: !rules
    Proc Name: pubm:ab_rules

# The Procedure #
    If the first parameter in $text is valid it will be set to who; if it doesn't exists
    whom will be "".  Now it says, if who has no value msg the channel the rules
    of the channel But if there is a a nick put a msg to $nick

####


###
	# Script name   : antiidle10-mbti.tcl
# Script Version: 1.0
# Script Author : The |mmortaL [asn@cdc.net] (PGP Public key Avaible, put
#                 "send key" in the subject.)
# Script Desc.  : An Anti Idle script for 1.1.x (Probably work with 1.0
#                 though)

# Please edit the following variables: (Channel to which a msg is to be
# sent, How often that message should be sent, and what to send; in that
# order)
set antiidlechan #lamechan
set antiidletime 5
set antiidlemsg "antiidle10-mbti.tcl - Made By The |mmortaL"

## Do not change any thing under this point! ##
## Do not change any thing under this point! ##
## Do not change any thing under this point! ##

# This makes all the data in $antiidlechan lower case
set antiidlechan [string tolower $antiidlechan]

# This makes sure that your on the channel which you specified. String
# match is case sensitive that is why I made everything lower case
# putlog is a command that puts some thing in the main logs of the bot,
# and when the bot rehashs, or loads up you see that message.
# return 1 stops the script from loading, in the event that it isn't on
# that channel.
if {![string match *$antiidlechan* [string tolower [channels]]]} {
  putlog "ERROR ERROR I am not on $antiidlechan!!!!"
  return 1
}

# VERY VERY VERY VERY VERY VERY VERY IMPORTANT!!
# If your script is gonna cause major problems if a person .rehashs, like
# if you set a timer use some thing to this equivelent:

# Make a variable, like antiidleloaded, by default that variable doesn't
# exist.  Put an if statement of info exists (checks to see if a variable
# is there).  And if it isn't set to 1, set it to 1, and load the timer,
# if the variable is there, and set to 1, then do nothing.
if {![info exists antiidleloaded]} {
  timer $antiidletime proc:antiidle
  set antiidleloaded 1
}

proc proc:antiidle {} {
  global antiidlechan antiidletime antiidlemsg
  puthelp "PRIVMSG $antiidlechan :$antiidlemsg"
  timer $antiidletime proc:antiidle
}


# This is fairly simple, put a global statement for each of the global variables, because
# you need to access them.  Send the msg to the channel, and then re-set the timer.

# The Bind #
    This script does not function with a bind.
    Trigger: "if {!info exists antiidleloaded}" checks to see if script is running
    Proc Name: proc:antiidle

# The Procedure #
    If info does not exist for $antiidleloaded, timer for proc:antiidle begins, if it
    does exists, proc:antiidle continues running.
    When timer fires, put $antiidlemsg to $antiidlechan and start another timer

###


###
	set flag1 i
set chanflag1 i
set flag2 v
set chanflag2 v

bind join i * join:mbti_autoop
bind join v * join:mbti_autovoice
bind join - * join:mbti_cautoop
bind join - * join:mbti_cautovoice

proc join:mbti_autoop {nick host hand chan} {
  pushmode $chan +o $nick
}

proc join:mbti_autovoice {nick host hand chan} {
  pushmode $chan +v $nick
}

proc join:mbti_cautoop {nick host hand chan} {
  if {[matchchanattr $hand i $chan]} {pushmode $nick +o $chan}
}

proc join:mbti_cautovoice {nick host hand chan} {
  if {[matchchanattr $hand v $chan]} {pushmode $nick +v $chan}
}


This is a fairly easy script, the only new thing is the newflags.  Eggdrop lets you add as many new flags as there aren't used.
Set newflag[num] z
where [num] is a number that doesn't exists...

set newchanflag[num]
Ditto :P

# The Bind #
    Join on channel
    AutoOp and AutoVoice Access on that Channel
    Trigger: users with +i or +v joining the channel
    Proc Name: join:mbti_autoop
                        join:mbti_autovoice
                        join:mbti_cautoop
                        join:mbti_cautovoice

# The Procedure #
    When join bind is triggered by specified users, pushmode $nick flag $chan
    or matchchanattr $hand flag $chan is true pushmode $nick flag $chan

###


###
	bind mode - "*+o $botnick*" mode:automode
proc mode:automode {nick host hand chan modechg} {
  foreach nick [chanlist $chan] {
    set hnick [nick2hand $nick]
    if {![isop $nick $chan]} {
      if {([matchattr $hnick o]) || ([matchchanattr $hnick o $chan])} {
        pushmode $chan +o $nick
      }
      if {([isop $nick $chan]) && ([matchchanattr $hnick d $chan])} {
        pushmode $chan -o $nick
      }
    }
  }
}


foreach nick [chanlist $chan] basicly says to do this for every one in the chan.

One check to see if he has ops, if he dosn't and he has OP access then op him!!

Then If he has ops, and he's supposed to be deoped them deop him!
###


## X - The Credits ##

Author: The |mmortaL [asn@cdc.net] - 'send key' in topic for PGP public key
People who helped (Major Thanxs):
Ec|ipse - tomas@primenet.com
janni - janni@itt.org
Cold Fusion - fusion@pbcs.com
Ernesto Baschny baschneo@trick.informatik.uni-stuttgart.de