This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats/dl/modules.txt
2004-03-08 22:14:39 +00:00

426 lines
15 KiB
Text

************************************************************************
** NeoStats - IRC Statistical Services **
** Copyright (c) 1999-2003 NeoStats Group. All Rights Reserved. **
** This program and all associated documentation is free but **
** copyrighted software; see the file COPYING for details. **
** Homepage: http://www.neostats.net/ **
************************************************************************
How to Write a NeoStats Module, and not stuff it all up! Version 2.5.6
----------------------------------------------------------------------
This document explains how to write modules for NeoStats.
The module instructions apply to versions 2.5.6 and higher. For older
versions you must refer to the documentation which comes with that
version since older versions had a different API specification.
This document also includes a section at the end for upgrading your
modules to the improved system available in 2.5.6. The new system
is backwards compatible with the 2.5.x system but since the old
system will eventually be removed, we recommend uprading your module
as soon as possible.
Modules are not simple but we are trying to make the API as simple as
possible so that they are easy to write. We suggest you use the source
of other modules as examples as well as this document.
2.5.x includes a feature that will help you with your modules. This
feature is aimed at all the bad coders out there that write buggy code.
Basically, if your module executes an instruction that would cause a
segfault, NeoStats will unload your modules and return itself to its
state before your module was called. But, it has one drawback, it can't
handle buffer overflows and so on. It might detect a segfault in your
module, but if your module has been overflowing memory left right and
center, then chances are that NeoStats will still crash. If I can find
a solution to this problem (without copying the entire NeoStats memory
before each call) then I'll implement it.
So, you're feeling very very lucky, and want to write your own wiz bang
Services? Ok... Get out the aspirin, cause this is going to be fun....
-----------------------------------<>-----------------------------------
Anything that the Server receives from users, or other servers can be
intercepted by a module. This basically means that you can do what ever
you want in your modules.
In order to help you learn how to make a module, we have included an
example basic module layout in template/template.c. We will use that
file in our disucssion of how to setup the module.
-----------------------------------<>-----------------------------------
First we must include the header file which gives our code access to the
NeoStats API:
#include "neostats.h"
Next we have to export a definition which include specific information
about our module. This is required.
ModuleInfo __module_info = {
"example",
"example Module Description",
"version 1.0"
__DATE__,
__TIME__
};
This structure contains:
module_name - A string for the module name
(one word e.g. "example")
module_description - A string short description of the module
(e.g. "My example module")
module_version - A string containing a version number
(e.g. "1,0", "Version 1.0" etc)
module_build_date - The build date of the module. The macro
__DATE__ allows us to create this automatically
module_build_time - The build time of the module. The macro
__TIME__ allows us to create this automatically
This information is used to report back to users on what modules and
what versions are loaded and can be used by the core and other modules
to check that they are compatible.
We also need to export a list of any responses to IRCd commands sent by
users to our modules that we wish to support e.g. /VERSION mymodule. This
is optional.
******************************** WARNING ********************************
This table is optional but depreciated. You should respond to module
events to be portable across all ircds and only use this table as a
last resort if a module event is not available. This table will be
removed from operation in a future release. If you need to use this
table for anything, tell us so we can add an appropiate event handler.
******************************** WARNING ********************************
NeoStats, and many IRCD's use tokens now, and the strings differ between
IRCds so a hard coded string such as "VERSION" might not always work.
For easy CrossIRCD support, we provide macros for all the available
commands such as MSG_VERSION and TOK_VERSION. These will make your module
more portable if you wish to release it. e.g.
Functions __module_functions[] = {
{MSG_VERSION, new_m_version, 1} ,
#ifdef GOTTOKENSUPPORT
{TOK_VERSION, new_m_version, 1} ,
#endif
{NULL, NULL, 0}
};
The table entries are:
- the server command you want to respond to (e.g. MSG_VERSION)
- the function to call when this happens (e.g. new_m_version)
- Flag to say whether to process
only local server commands (0) or
network commands (1)
Each function in this table is passed 2 variables: char **av and int ac.
av is a array containing the parsed command, ac contains the number of
elements.
The array must be NULL terminated, so set the final command and function
fields to NULL and the flag to 0.
We can also have a table for any events on IRC that we wish to process.
This is optional.
EventFnList __module_events[] = {
{ EVENT_ONLINE, Online},
{ NULL, NULL}
};
The table contains the event we want to process (e.g. ONLINE) and the
function to call when it happens (e.g. Online). Events signify both
server actions (e.g. the ONLINE event is triggered when NeoStats
connects to the network) and user actions (e.g. SIGNON is triggered when
a user joins the network).
The array must be NULL terminated with both event string and function
fields set to NULL.
We provide macros for each event which are listed with descriptions and
available parameters in "events.h". The header file is automatically
included by "stats.h" so you do not need to worry about including it in
your module.
-----------------------------------<>-----------------------------------
Although that is all you need for a working module, there are a number
of other functions to further extend your module's capability.
__ModInit is called when a module is first loaded so can be used to
initialise settings for your module. It must not be used to start
anything which will try to send commands to the IRC network such
as starting a bot since you may not be connected to a network when
this function is called. It is mainly useful for processing
configuration and starting databases.
int __ModInit(int modnum, int apiver)
{
if(apiver<API_VER)
return -1;
s_my_bot_name = "NeoBot";
return 1;
}
The function is passed two parameters
- the module number ...
- the api version. You should use this to check that your module is
compatible with the version of NeoStats loading your module using
the api version. The API_VER value is used to determine this.
You should return 1 for success or -1 one for failure (for example the
api version is incompatible.
__ModFini is called when a module is unloaded so is useful for saving
databases.
void __ModFini()
{
};
-----------------------------------<>-----------------------------------
You cannot use commands like "NICK" and "PRIVMSG" and "NOTICE" are
handled through specific NeoStats calls. Following are functions that
you will use to talk to the network and register bots on it.
init_bot allows you to create and initialize a bot to introduce for your
module. This is the only way to reguster your bot on the network.
init_bot(nick, ident, hostname, realname, modes,
__module_info.module_name);
init bot will return 1 on success, or -1 if there is a failure. A
failure might be that the nickname already exists on the network,
in which case, you would have to try a different nickname.
bot_nick_change is used to change the nickname used for your bot.
bot_nick_change(currentnick, newnick);
The function will return 1 on success, or -1 if the nickname is already
registered on the network.
del_bot allows you to remove your bot from the network.
del_bot(nick, reason);
The function will returns 1 on success or -1 otherwise for example if
you try to delete a nickname that isn't registered,
__Bot_Message is called whenever a message is sent to your bot, e.g.
/msg yourbotname or /notice yourbotname.
int __Bot_Message(char *origin, char **av, int ac)
The parameters are as follows:
origin - who sent the message to you. It could be a user nickname
or could be a server message
av - an array of the message, starting with the bots name.
So the message:
/msg NeoStats Help would be:
av[0] = "NeoStats";
av[1] = "help";
ac - the number of elements in the array.
(e.g. the above would be 2)
You can process any custom commands for your bot inside this function
e.g. to process /msg yourbotname help, you would check av[1] for the
string "help" and perform whatever task you desire.
-----------------------------------<>-----------------------------------
Timers are available to register for your module.
To add a timer:
add_mod_timer(function name, timername,
__module_info.module_name, interval);
function name - the function you want to trigger when this timer
is triggered
timername - a descriptive name of the timer
module_name - must be the same as that defined in your ModuleInfo
structure so we recommend you use
__module_info.module_name
interval - interval in seconds that this function is to be
called.
Note, this interval is not precise. NeoStats will check the timers and
if at least interval has passed, will call your routine. Since NeoStats
is single threaded, it runs in a continuous loop, meaning that if
NeoStats itself, or another module held up that loop, then the timers
are not going to run until that piece of code completes. Therefore an
interval of 60 seconds might be called after 65 seconds.
To delete a timer:
int del_mod_timer(timername)
timername - the name the timer created with in add_mod_timer
-----------------------------------<>-----------------------------------
TODO:
int __Chan_Message(char *origin, char **argv, int argc)
-----------------------------------<>-----------------------------------
TODO:
Sockets. They can make outgoing tcp connections to other servers (i.e.,
web, email, etc)
-----------------------------------<>-----------------------------------
TODO:
Call other functions in other modules.
-----------------------------------<>-----------------------------------
TODO:
Document any other APIs for modules, kptool etc.
-----------------------------------<>-----------------------------------
Caveats:
Not every platform supporting dynamic libraries so we are working on
support for static libraries but that might take a while. For now, if
your host does not support dynamic libraries, we suggest that you try to
find one that does if you really want to run NeoStats.
Don't bug me about it...
-----------------------------------<>-----------------------------------
Upgrading modules from 2.5.x to 2.5.6
-------------------------------------
Although we retain backwards compatibility with the original 2.5.x API,
we will eventually only support the newer API so you should upgrade
your module to use the new system. This is quite quick and easy to do.
1) Module Info:
Old System:
const char exversion_date[] = __DATE__;
const char exversion_time[] = __TIME__;
Module_Info my_info[] = { {
"example",
"example Module Description",
"version 1.0"
} };
Module_Info *__module_get_info() {
return my_info;
}
New System:
1) rename your info structure to be exactly as follows:
ModuleInfo __module_info = {
"example",
"example Module Description",
"version 1.0"
__DATE__,
__TIME__
};
2) Delete the function __module_get_info since it is not longer needed.
3) Change all occurences of exversion_date and exversion_time to
__module_info.module_build_date and __module_info.module_build_time
4) Change all references to my_info[0] to be __module_info
2) Module functions:
Old System:
Functions my_fn_list[] = {
{ "VERSION", new_m_version, 1 },
{ NULL, NULL, 0 }
};
Functions *__module_get_functions() {
return my_fn_list;
};
New System:
1) rename your Functions structure as follows:
Functions __module_functions[] = {
{ "VERSION", new_m_version, 1 },
{ NULL, NULL, 0 }
};
2) Delete the function __module_get_functions since it is not longer
needed.
3) Events:
Old System:
EventFnList my_event_list[] = {
{ NULL, NULL}
};
EventFnList *__module_get_events() {
return my_event_list;
};
New System:
1) rename your Events structure as follows:
EventFnList __module_events[] = {
{ NULL, NULL, 0 }
};
2) Delete the function __module_get_events since it is not longer
needed.
4) _init and _fini
These were optional functions in the original system so you may not have
them. If you do, please update as follows:
Old System:
void _init()
{
}
void _fini()
{
}
New System:
1) replace _init with
int __ModInit(int modnum, int apiver)
{
if(apiver<API_VER)
return -1;
return 1;
}
You should include a check for the apiver and fail if your module was
compiled with a different version using the define as in the example.
return 1 for success or -1 one for any failure.
2) replace _fini with
void __ModFini()
{
};
That is all you need to do to update to the 2.5.6 module API.
-----------------------------------<>-----------------------------------
That's about it.
The module API is constantly reviewed and is updated and added to from
time to time. We try to maintain backwards compatibility where it is
possible for a short time after we make any major changes. Your modules
should always work with all releases of the 2.5.x series, but you may
find that in version 2.6, you have to make a few changes to support
new features and API changes.
If you have any questions, comments or suggestions about our module API
or this document, please post on our message boards at www.neostats.net.
************************************************************************
** This document was last updated on October 8th, 2003 by M and is **
** based on documents originally created by Fish. **
************************************************************************