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 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
|
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Writing a Basic Eggdrop Module — Eggdrop 1.10.1rc2 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="../_static/eggdrop.css?v=ab48a1b6" />
<script src="../_static/documentation_options.js?v=290de6c6"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Eggdrop Module Information" href="../modules/index.html" />
<link rel="prev" title="Writing an Eggdrop Tcl Script" href="firstscript.html" />
</head><body>
<div class="header-wrapper" role="banner">
<div class="header">
<div class="headertitle"><a
href="../index.html">Eggdrop 1.10.1rc2 documentation</a></div>
<div class="rel" role="navigation" aria-label="related navigation">
<a href="firstscript.html" title="Writing an Eggdrop Tcl Script"
accesskey="P">previous</a> |
<a href="../modules/index.html" title="Eggdrop Module Information"
accesskey="N">next</a>
</div>
</div>
</div>
<div class="content-wrapper">
<div class="content">
<div class="sidebar">
<h3>Table of Contents</h3>
<p class="caption" role="heading"><span class="caption-text">Installing Eggdrop</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../install/readme.html">README</a></li>
<li class="toctree-l1"><a class="reference internal" href="../install/install.html">Installing Eggdrop</a></li>
<li class="toctree-l1"><a class="reference internal" href="../install/upgrading.html">Upgrading Eggdrop</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Using Eggdrop</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../using/features.html">Eggdrop Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/core.html">Eggdrop Core Settings</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/partyline.html">The Party Line</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/autoscripts.html">Eggdrop Autoscripts</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/users.html">Users and Flags</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/bans.html">Bans, Invites, and Exempts</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/botnet.html">Botnet Sharing and Linking</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/ipv6.html">IPv6 support</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/tls.html">TLS support</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/ircv3.html">IRCv3 support</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/accounts.html">Account tracking in Eggdrop</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/pbkdf2info.html">Encryption/Hashing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/python.html">Using the Python Module</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/twitchinfo.html">Twitch</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/tricks.html">Advanced Tips</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/text-sub.html">Textfile Substitutions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/tcl-commands.html">Eggdrop Tcl Commands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/twitch-tcl-commands.html">Eggdrop Twitch Tcl Commands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using/patch.html">Patching Eggdrop</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Tutorials</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="setup.html">Setting Up Eggdrop</a></li>
<li class="toctree-l1"><a class="reference internal" href="firststeps.html">Common First Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="tlssetup.html">Enabling TLS Security on Eggdrop</a></li>
<li class="toctree-l1"><a class="reference internal" href="userfilesharing.html">Sharing Userfiles</a></li>
<li class="toctree-l1"><a class="reference internal" href="firstscript.html">Writing an Eggdrop Tcl Script</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Writing a Basic Eggdrop Module</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#module-header">Module Header</a></li>
<li class="toctree-l2"><a class="reference internal" href="#required-code">Required Code</a></li>
<li class="toctree-l2"><a class="reference internal" href="#adding-a-partyline-command">Adding a Partyline Command</a></li>
<li class="toctree-l2"><a class="reference internal" href="#adding-a-tcl-command">Adding a Tcl Command</a></li>
<li class="toctree-l2"><a class="reference internal" href="#adding-a-tcl-bind">Adding a Tcl Bind</a></li>
</ul>
</li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Eggdrop Modules</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../modules/index.html">Eggdrop Module Information</a></li>
<li class="toctree-l1"><a class="reference internal" href="../modules/included.html">Modules included with Eggdrop</a></li>
<li class="toctree-l1"><a class="reference internal" href="../modules/writing.html">How to Write an Eggdrop Module</a></li>
<li class="toctree-l1"><a class="reference internal" href="../modules/internals.html">Eggdrop Bind Internals</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">About Eggdrop</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../about/about.html">About Eggdrop</a></li>
<li class="toctree-l1"><a class="reference internal" href="../about/legal.html">Boring legal stuff</a></li>
</ul>
<div role="search">
<h3 style="margin-top: 1.5em;">Search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="writing-a-basic-eggdrop-module">
<h1>Writing a Basic Eggdrop Module<a class="headerlink" href="#writing-a-basic-eggdrop-module" title="Link to this heading">¶</a></h1>
<p>An Eggdrop module is a piece of C code that can be loaded (or unloaded) onto the core Eggdrop code. A module differs from a Tcl script in that modules must be compiled and then loaded, whereas scripts can be edited and loaded directly. Importantly, a module can be written to create new Eggdrop-specific Tcl commands and binds that a user can then use in a Tcl script. For example, the server module loaded by Eggdrop is what creates the “jump” Tcl command, which causes tells the Eggdrop to jump to the next server in its server list.</p>
<p>There are a few required functions a module must perform in order to properly work with Eggdrop</p>
<section id="module-header">
<h2>Module Header<a class="headerlink" href="#module-header" title="Link to this heading">¶</a></h2>
<p>A module should include license information. This tells other open source users how they are allowed to use the code. Eggdrop uses GPL 2.0 licensing, and our license information looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/*</span>
<span class="o">*</span> <span class="n">This</span> <span class="n">program</span> <span class="ow">is</span> <span class="n">free</span> <span class="n">software</span><span class="p">;</span> <span class="n">you</span> <span class="n">can</span> <span class="n">redistribute</span> <span class="n">it</span> <span class="ow">and</span><span class="o">/</span><span class="ow">or</span>
<span class="o">*</span> <span class="n">modify</span> <span class="n">it</span> <span class="n">under</span> <span class="n">the</span> <span class="n">terms</span> <span class="n">of</span> <span class="n">the</span> <span class="n">GNU</span> <span class="n">General</span> <span class="n">Public</span> <span class="n">License</span>
<span class="o">*</span> <span class="k">as</span> <span class="n">published</span> <span class="n">by</span> <span class="n">the</span> <span class="n">Free</span> <span class="n">Software</span> <span class="n">Foundation</span><span class="p">;</span> <span class="n">either</span> <span class="n">version</span> <span class="mi">2</span>
<span class="o">*</span> <span class="n">of</span> <span class="n">the</span> <span class="n">License</span><span class="p">,</span> <span class="ow">or</span> <span class="p">(</span><span class="n">at</span> <span class="n">your</span> <span class="n">option</span><span class="p">)</span> <span class="nb">any</span> <span class="n">later</span> <span class="n">version</span><span class="o">.</span>
<span class="o">*</span>
<span class="o">*</span> <span class="n">This</span> <span class="n">program</span> <span class="ow">is</span> <span class="n">distributed</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">hope</span> <span class="n">that</span> <span class="n">it</span> <span class="n">will</span> <span class="n">be</span> <span class="n">useful</span><span class="p">,</span>
<span class="o">*</span> <span class="n">but</span> <span class="n">WITHOUT</span> <span class="n">ANY</span> <span class="n">WARRANTY</span><span class="p">;</span> <span class="n">without</span> <span class="n">even</span> <span class="n">the</span> <span class="n">implied</span> <span class="n">warranty</span> <span class="n">of</span>
<span class="o">*</span> <span class="n">MERCHANTABILITY</span> <span class="ow">or</span> <span class="n">FITNESS</span> <span class="n">FOR</span> <span class="n">A</span> <span class="n">PARTICULAR</span> <span class="n">PURPOSE</span><span class="o">.</span> <span class="n">See</span> <span class="n">the</span>
<span class="o">*</span> <span class="n">GNU</span> <span class="n">General</span> <span class="n">Public</span> <span class="n">License</span> <span class="k">for</span> <span class="n">more</span> <span class="n">details</span><span class="o">.</span>
<span class="o">*</span>
<span class="o">*</span> <span class="n">You</span> <span class="n">should</span> <span class="n">have</span> <span class="n">received</span> <span class="n">a</span> <span class="n">copy</span> <span class="n">of</span> <span class="n">the</span> <span class="n">GNU</span> <span class="n">General</span> <span class="n">Public</span> <span class="n">License</span>
<span class="o">*</span> <span class="n">along</span> <span class="k">with</span> <span class="n">this</span> <span class="n">program</span><span class="p">;</span> <span class="k">if</span> <span class="ow">not</span><span class="p">,</span> <span class="n">write</span> <span class="n">to</span> <span class="n">the</span> <span class="n">Free</span> <span class="n">Software</span>
<span class="o">*</span> <span class="n">Foundation</span><span class="p">,</span> <span class="n">Inc</span><span class="o">.</span><span class="p">,</span> <span class="mi">59</span> <span class="n">Temple</span> <span class="n">Place</span> <span class="o">-</span> <span class="n">Suite</span> <span class="mi">330</span><span class="p">,</span> <span class="n">Boston</span><span class="p">,</span> <span class="n">MA</span> <span class="mi">02111</span><span class="o">-</span><span class="mi">1307</span><span class="p">,</span> <span class="n">USA</span><span class="o">.</span>
<span class="o">*/</span>
</pre></div>
</div>
</section>
<section id="required-code">
<h2>Required Code<a class="headerlink" href="#required-code" title="Link to this heading">¶</a></h2>
<p>For this section, you don’t necessarily need to understand what it is doing, but this code is required for a module to function. If you want to learn more about this, check out <a class="reference internal" href="../modules/writing.html#writing-module"><span class="std std-ref">How to Write an Eggdrop Module</span></a></p>
<p>You’ll next want to name your module:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">#define MODULE_NAME "woobie"</span>
</pre></div>
</div>
<p>Declare your own function tables (again, you don’t need to understand this part; you just need to copy/paste it):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">#undef global</span>
<span class="n">static</span> <span class="n">Function</span> <span class="o">*</span><span class="k">global</span> <span class="o">=</span> <span class="n">NULL</span><span class="p">,</span> <span class="o">*</span><span class="n">server_funcs</span> <span class="o">=</span> <span class="n">NULL</span><span class="p">;</span>
<span class="n">EXPORT_SCOPE</span> <span class="n">char</span> <span class="o">*</span><span class="n">woobie_start</span><span class="p">();</span>
</pre></div>
</div>
<p>Next are two memory-related functions used by the core Eggdrop .status and .module commands:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>static int woobie_expmem()
{
int size = 0;
return size;
}
static void woobie_report(int idx, int details)
{
if (details) {
int size = woobie_expmem();
dprintf(idx, " Using %d byte%s of memory\n", size,
(size != 1) ? "s" : "");
}
}
</pre></div>
</div>
<p>This function is called when Eggdrop loads the module:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>char *woobie_start(Function *global_funcs)
{
global = global_funcs;
/* Register the module. */
module_register(MODULE_NAME, woobie_table, 2, 1);
/* ^--- minor module version
* ^------ major module version
* ^-------------------- module function table
* ^--------------------------------- module name
*/
if (!module_depend(MODULE_NAME, "eggdrop", 108, 0)) {
module_undepend(MODULE_NAME);
return "This module requires Eggdrop 1.8.0 or later.";
}
</pre></div>
</div>
<p>This next function is used to unload the module:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="n">char</span> <span class="o">*</span><span class="n">woobie_close</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">module_undepend</span><span class="p">(</span><span class="n">MODULE_NAME</span><span class="p">);</span>
<span class="k">return</span> <span class="n">NULL</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This creates a function table that is exported to Eggdrop. In other words, these are commands that are made available to the Eggdrop core and other modules. At minimum, the following functions must be exported:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="n">Function</span> <span class="n">woobie_table</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="p">(</span><span class="n">Function</span><span class="p">)</span> <span class="n">woobie_start</span><span class="p">,</span>
<span class="p">(</span><span class="n">Function</span><span class="p">)</span> <span class="n">woobie_close</span><span class="p">,</span>
<span class="p">(</span><span class="n">Function</span><span class="p">)</span> <span class="n">woobie_expmem</span><span class="p">,</span>
<span class="p">(</span><span class="n">Function</span><span class="p">)</span> <span class="n">woobie_report</span><span class="p">,</span>
<span class="p">};</span>
</pre></div>
</div>
<p>At this point, you should have a module that compiles and can be loaded by Eggdrop- but doesn’t really do anything yet. We’ll change that in the next section!</p>
</section>
<section id="adding-a-partyline-command">
<h2>Adding a Partyline Command<a class="headerlink" href="#adding-a-partyline-command" title="Link to this heading">¶</a></h2>
<p>A partyline command function accepts three arguments- a pointer to the user record of the user that called the command; the idx the user was on when calling the command; and a pointer to the arguments appended to the command. A command should immediately log that it was called to the LOG_CMDS log level, and then run its desired code. This simple example prints “WOOBIE” to the partyline idx of the user that called it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="nb">int</span> <span class="n">cmd_woobie</span><span class="p">(</span><span class="n">struct</span> <span class="n">userrec</span> <span class="o">*</span><span class="n">u</span><span class="p">,</span> <span class="nb">int</span> <span class="n">idx</span><span class="p">,</span> <span class="n">char</span> <span class="o">*</span><span class="n">par</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">putlog</span><span class="p">(</span><span class="n">LOG_CMDS</span><span class="p">,</span> <span class="s2">"*"</span><span class="p">,</span> <span class="s2">"#</span><span class="si">%s</span><span class="s2"># woobie"</span><span class="p">,</span> <span class="n">dcc</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span><span class="o">.</span><span class="n">nick</span><span class="p">);</span>
<span class="n">dprintf</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span> <span class="s2">"WOOBIE!</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If you add partyline commands, you need to create a table which links the new command name to the function it should call. This can be done like so:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="n">cmd_t</span> <span class="n">mywoobie</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="o">/*</span> <span class="n">command</span> <span class="n">flags</span> <span class="n">function</span> <span class="n">tcl</span><span class="o">-</span><span class="n">name</span> <span class="o">*/</span>
<span class="p">{</span><span class="s2">"woobie"</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="n">cmd_woobie</span><span class="p">,</span> <span class="n">NULL</span><span class="p">},</span>
<span class="p">{</span><span class="n">NULL</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="n">NULL</span><span class="p">}</span> <span class="o">/*</span> <span class="n">Mark</span> <span class="n">end</span><span class="o">.</span> <span class="o">*/</span>
<span class="p">};</span>
</pre></div>
</div>
<p>The tcl-name field can be a name for a Tcl command that will also call the partyline command, or it can be left as NULL.</p>
</section>
<section id="adding-a-tcl-command">
<h2>Adding a Tcl Command<a class="headerlink" href="#adding-a-tcl-command" title="Link to this heading">¶</a></h2>
<p>Eggdrop uses the Tcl C API library to interact with the Tcl interpreter. Learning this API is outside the scope of this tutorial, but this example Tcl command will echo the provided argument:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="nb">int</span> <span class="n">tcl_echome</span> <span class="n">STDVAR</span> <span class="p">{</span>
<span class="n">BADARGS</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">" arg"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"llama"</span><span class="p">)</span> <span class="p">{</span>
<span class="n">Tcl_AppendResult</span><span class="p">(</span><span class="n">irp</span><span class="p">,</span> <span class="s2">"You said: "</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">NULL</span><span class="p">);</span>
<span class="k">return</span> <span class="n">TCL_OK</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">Tcl_AppendResult</span><span class="p">(</span><span class="n">irp</span><span class="p">,</span> <span class="s2">"illegal word!"</span><span class="p">);</span>
<span class="k">return</span> <span class="n">TCL_ERROR</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>A few notes on this example. BADARGS is a macro that checks the input provided to the Tcl command. The first argument BADARGS accepts is the minimum number of parameters the Tcl command must accept (including the command itself). The second argument is the maximum number of parameters that BADARGS will accept. The third argument is the help text that will be displayed if these boundaries are exceeded. For example, BADARGS(2, 4, “ name ?date? ?place?”) requires at least one argument to be passed, and a maximum of three arguments. Eggdrop code style is to enclose optional arguments between qusetion marks in the help text.</p>
<p>Similar to adding a partyline command, you also have to create a function table for a new Tcl command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="n">tcl_cmds</span> <span class="n">mytcl</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="p">{</span><span class="s2">"echome"</span><span class="p">,</span> <span class="n">tcl_echome</span><span class="p">},</span>
<span class="p">{</span><span class="n">NULL</span><span class="p">,</span> <span class="n">NULL</span><span class="p">}</span> <span class="o">/*</span> <span class="n">Required</span> <span class="n">to</span> <span class="n">mark</span> <span class="n">end</span> <span class="n">of</span> <span class="n">table</span> <span class="o">*/</span>
<span class="p">};</span>
</pre></div>
</div>
<p>And now the newly-created Tcl command ‘echome’ is available for use in a script!</p>
</section>
<section id="adding-a-tcl-bind">
<h2>Adding a Tcl Bind<a class="headerlink" href="#adding-a-tcl-bind" title="Link to this heading">¶</a></h2>
<p>A Tcl bind is a command that is activated when a certain condition is met. With Eggdrop, these are usually linked to receiving messages or other IRC events. To create a bind, you must first register the bind type with Eggdrop when the module is loaded (you added the woobie_start() and woobie_close functions earlier, you still need all that earlier code in here as well):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="n">p_tcl_bind_list</span> <span class="n">H_woob</span><span class="p">;</span>
<span class="o">...</span>
<span class="n">char</span> <span class="o">*</span><span class="n">woobie_start</span><span class="p">(</span><span class="n">Function</span> <span class="o">*</span><span class="n">global_funcs</span><span class="p">)</span>
<span class="p">{</span>
<span class="o">...</span>
<span class="n">H_woob</span> <span class="o">=</span> <span class="n">add_bind_table</span><span class="p">(</span><span class="s2">"woobie"</span><span class="p">,</span> <span class="n">HT_STACKABLE</span><span class="p">,</span> <span class="n">woobie_2char</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>And then remove the binds when the module is unloaded:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="n">char</span> <span class="o">*</span><span class="n">woobie_close</span><span class="p">()</span>
<span class="p">{</span>
<span class="o">...</span>
<span class="n">del_bind_table</span><span class="p">(</span><span class="n">H_woob</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Here, “woobie” is the name of the bind (similar to the PUB, MSG, JOIN types of binds you already see in tcl-commands.doc). HT_STACKABLE means you can have multiple binds of this type. “woobie_2char” defines how many arguments the bind will take, and we’ll talk about that next.</p>
<section id="defining-bind-arguments">
<h3>Defining bind arguments<a class="headerlink" href="#defining-bind-arguments" title="Link to this heading">¶</a></h3>
<p>The following code example defines a bind that will take two arguments:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="nb">int</span> <span class="n">woobie_2char</span> <span class="n">STDVAR</span>
<span class="p">{</span>
<span class="n">Function</span> <span class="n">F</span> <span class="o">=</span> <span class="p">(</span><span class="n">Function</span><span class="p">)</span> <span class="n">cd</span><span class="p">;</span>
<span class="n">BADARGS</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="s2">" nick chan"</span><span class="p">);</span>
<span class="n">CHECKVALIDITY</span><span class="p">(</span><span class="n">woobie_2char</span><span class="p">);</span>
<span class="n">F</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
<span class="k">return</span> <span class="n">TCL_OK</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>And this example defines a bind that will take three arguments:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="nb">int</span> <span class="n">woobie_3char</span> <span class="n">STDVAR</span>
<span class="p">{</span>
<span class="n">Function</span> <span class="n">F</span> <span class="o">=</span> <span class="p">(</span><span class="n">Function</span><span class="p">)</span> <span class="n">cd</span><span class="p">;</span>
<span class="n">BADARGS</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">" foo bar moo"</span><span class="p">);</span>
<span class="n">CHECKVALIDITY</span><span class="p">(</span><span class="n">woobie_3char</span><span class="p">);</span>
<span class="n">F</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="k">return</span> <span class="n">TCL_OK</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Like before, BADARGS still checks that the number of arguments passed is correct, and outputs help text if it is not. The rest is boilerplate code to pass the arguments when the bind is called.</p>
</section>
<section id="calling-the-bind">
<h3>Calling the Bind<a class="headerlink" href="#calling-the-bind" title="Link to this heading">¶</a></h3>
<p>To call the bind, Eggdrop coding style is to name that function “check_tcl_bindname”. So here, whenever we reach a point in code that should trigger the bind, we’ll call check_tcl_woobie() and pass the arguments we defined- in this case, two arguments that woobie_2char was created to handle. Here is some sample code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>check_tcl_woobie(chan, nick);
static int check_tcl_woobie(char *chan, char *nick, char *userhost) {
int x;
char mask[1024];
struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
snprintf(mask, sizeof mask, "%s %s!%s",
chan, nick, userhost);
Tcl_SetVar(interp, "_woob1", nick ? (char *) nick : "", 0);
Tcl_SetVar(interp, "_woob2", chan, 0);
x = check_tcl_bind(H_woob, mask, &fr, " $_woob1 $_woob2",
MATCH_MASK | BIND_STACKABLE);
return (x == BIND_EXEC_LOG);
}
</pre></div>
</div>
<p>Now that we have encountered a condition that triggers the bind type (in code by calling <code class="docutils literal notranslate"><span class="pre">check_tcl_woobie()</span></code> ), we need to check it against the binds the user has loaded in scripts and see if it matches those conditions. This is done with <code class="docutils literal notranslate"><span class="pre">check_tcl_bind()</span></code>, called with the bind type, the userhost of the user, the flag record of the user if it exists, the bind arguments, and bind options. We can configure how we want to check the triggering action against the bind, and we can further use the return value from <code class="docutils literal notranslate"><span class="pre">check_tcl_bind()</span></code> to take additional action by Eggdrop. You can read more about the specific values used in <code class="docutils literal notranslate"><span class="pre">check_tcl_bind</span></code> in <a class="reference internal" href="../modules/internals.html#triggering-any-bind"><span class="std std-ref">Triggering any Bind</span></a></p>
</section>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
</div>
<div class="footer-wrapper">
<div class="footer">
<div class="left">
<div role="navigation" aria-label="related navigaton">
<a href="firstscript.html" title="Writing an Eggdrop Tcl Script"
>previous</a> |
<a href="../modules/index.html" title="Eggdrop Module Information"
>next</a>
</div>
<div role="note" aria-label="source link">
</div>
</div>
<div class="right">
<div class="footer" role="contentinfo">
© Copyright 2025, Eggheads.
Last updated on Aug 15, 2025.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
</div>
</div>
<div class="clearer"></div>
</div>
</div>
</body>
</html>
|