1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
Writing an Eggdrop Tcl Script
So you want to write an Eggdrop Tcl script, but you don't really know
where to begin. This file will give you a very basic idea about what
Eggdrop scripting is like, using a very simple script that may help you
get started with your own scripts.
This guide assumes you know a bit about Eggdrops and IRC. You should
have already installed Eggdrop. The bot should not be on any important
or busy channels (development bots can be annoying if your script has
bugs). If you plan on doing a lot of development, enable the .tcl and
.set commands, and make sure nobody else has access to your bot. The
.tcl and .set commands are helpful in debugging and testing your code.
First, read through the script. Very few commands are listed here
intentionally, but as you want to develop more advanced scripts, you
will definitely want to get familiar with the core Tcl language
commands, especially the string- and list-related commands, as well as
Eggdrop's own library of custom Tcl commands, located in
tcl-commands.doc
If you have the .tcl command enabled, you can load a script by typing
'.tcl source script/file.tcl' to load it. Otherwise, add it to your
config file like normal (examples to do so are at the bottom of the
config file) and '.rehash' or '.restart' your bot.
Let's look at a very basic example script that greets users as they join
a channel:
# GreetScript.tcl
# Version: 1.0
# Author: Geo <geo@eggheads.org>
#
# Description:
# A simple script that greets users as they join a channel
#
### Config Section ###
# How would you like the bot to gree users?
# 0 - via public message to channel
# 1 - via private message
set pmsg 0
# What message would you like to send to users when they join?
set greetmsg "Hi! Welcome to the channel!"
### DO NOT EDIT BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING! ###
bind join - * greet
proc greet {nick uhost hand chan} {
global pmsg
global greetmsg
if {$pmsg} {
putserv "PRIVMSG $nick :$greetmsg"
} else {
putserv "PRIVMSG $chan :$greetmsg"
}
}
putlog "greetscript.tcl v1.0 by Geo"
Whew! There's a lot going on here. You'll generally see scripts broken
into a few key parts- the header, the config section, and the code
section. Ok, let's go over this piece by piece. First, the header of the
script:
# GreetScript.tcl
# Version: 1.0
# Author: Geo <geo@eggheads.org> or #eggdrop on Libera
#
# Description:
# A simple script that greets users as they join a channel
Any line prefixed by a # means it is comment, and thus ignored. You can
type whatever you want, and it won't matter. When writing scripts
(especially if you want to give them to other people, it is good to use
comments in the code to show what you're doing. Here though, we use it
to describe what the script is and, most importantly, who wrote it!
Let's give credit where credit is due, right? You may want to give users
a way to contact you as well.
Next, let's look at the configuration section:
### Config Section ###
# How would you like the bot to gree users?
# 0 - via public message to channel
# 1 - via private message
set pmsg 0
# What message would you like to send to users when they join?
set greetmsg "Hi! Welcome to the channel!"
### DO NOT EDIT BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING! ###
To make scripts easy to use, you'll want to have a section that allows
users to easily change the way the script operates, without having to
edit the script itself. Here, we have two settings: one that controls
which method the Eggdrop uses to greet a user, and a second with the
message to greet the user with. Sure, we could hard-code that into the
code section below, but in larger scripts that makes things harder to
find, and also forces you to potentially have to make the same change
multiple times in code. Why not make it simple and do it once, up top?
Notice the settings do not have #s in front of them- they are variables
that will be used by the script later on. And of course, the standard
ominous warning not to change anything below!
Now, let's look start to dissect the actual code!:
bind join - * greet
This is a bind. This sets up an action that Eggdrop will react to. You
can read all the binds that Eggdrop uses here. Generally, we like to
place all binds towards the top of the script so that they are together
and easy to find. Now, let's look at documentation of the bind join
together.
---------------------------------------------------------------------------
bind JOIN
----------------- ---------------------------------------------------------
bind join <flags>
<mask> <proc>
procname <nick>
<user@host>
<handle>
<channel>
Description:
triggered by
someone joining
the channel. The
mask in the bind
is matched
against "#channel
nick!user@host"
and can contain
wildcards.
---------------------------------------------------------------------------
So here, we can start to match the bind listed in the code to how it is
described in the documentation. The first term after the bind command is
'join', showing that it is a join bind, which means the action we define
here will take place each time a user joins a channel. The next term is
'mask', and it says it is in the form "#channel nick!user@host". This is
where we can start to refine exactly when this bind is triggered. If we
want it to work for every person joining every channel Eggdrop is on,
then a simple '' will suffice here- that will match everything. If we
wanted this bind to only work in #foo, then the mask would be "#foo *".
If we wanted to greet users on every channel, but only those who are on
AOL, the mask would be " *!*@*.aol.com". Finally the 'proc' argument is
the name of the Tcl proc we want to call, where the code that actually
does stuff is located.
So to sum up this line from the example script: When a user joins on any
channel and with any hostmask, run the code located in proc 'greet'.
Now that we told the Eggdrop what action to look for, we need to tell it
what to do when that action occurs!:
proc greet {nick uhost hand chan} {
This is how we declare a Tcl proc. As we said above, this is where the
magic happens. To set up the proc (this will look differently for
different binds), lets refer back to the bind JOIN documentation. The
second line shows procname <nick> <user@host> <handle> <channel>.
Eggdrop does a lot of stuff in the background when a bind is triggered,
and this is telling you how Eggdrop will present that information to
you. Here, Eggdrop is telling you it is going to pass the proc you
created four variables: One that contains the nickname of the person who
triggered the bind (in this case, the user who joined), the user@host of
that user, the handle of that user (if the user has one on the bot), and
the channel that the bind was triggered on.
So let's say someone with the nickname Geo with a hostmask of
awesome@aol.com joined #sexystuff and that person is not added to the
bot as a user. Eggdrop will pass 4 values to the variables you set up in
that proc: The first variable will get the value "Geo", the second
"awesome@aol.com", the third "", and the fourth "#sexystuff". (That
third value was a trick, we didn't talk about that- if the user is not
added to the bot, handle will get a "" as a value). Now, let's use those
variables!:
global pmsg
global greetmsg
This is a simple one- because we're using variables declared in the main
body of the script (remember way up top?), we have to tell this proc to
use that variable, not not create a new local variable for this proc.
And finally, let's actually send a message to the user:
if {pmsg}
putserv "PRIVMSG $nick :$greetmsg"
} else {
putserv "PRIVMSG $chan :$greetmsg"
}
Here, we're going to check if pmsg is true (any value that is not 0)
and, if yes, send a private message to the user. If pmsg is not true (it
is 0), then we will send the message to the channel. You can see that
the first putserv message sends a PRIVMSG message to $nick - this is the
nickname of the user that joined, and that Eggdrop stored for us in the
first variable of the proc, which we called 'nick'. The second putserv
message will send a PRIVMSG message to the $chan - this is the channel
the user joined, and that Eggdrop stored for us in the fourth variable
of the proc, which we called 'chan'.
And finally: get the credit you deserve when the script loads!:
putlog "greetscript.tcl v1.0 by Geo"
Like your variables at the top of the script, this line is not inside a
Tcl proc and will execute when the script is loaded. You can put this or
any other initialization code you want to run.
And there you have it- your first script! Take this, modify it and
experiment. A few challenges for you:
- How can you configure which channel it should run on, without
hard-coding it into the bind? (Maybe with a variable...)
- How can you configure it to only message a user with the nickname
"FancyPants"? (Sounds like something a bind could handle)
- How can you delay the message from sending by 5 seconds? (Hint:
utimer)
- How can you send different messages to different channels? (A new
setting may be in order...)
- How can you get the bot to not greet itself when it joins the
channel? (Eggdrop stores its own nickname in a variable called
$botnick)
- How can you add the person joining the channel's nickname to the
greet message? (You can put variables inside variables...)
If you want to try these out, join #eggdrop on Libera and check your
answers (and remember, there are dozens of ways to do this, so a) don't
be defensive of your choices, and b) take others' answers with a grain
of salt!)
<br>
Copyright (C) 2003 - 2025 Eggheads Development Team
|