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
2002-03-11 21:11:48 +00:00

271 lines
11 KiB
Text

How to Write a NeoStats Module, and not stuff it all up! Version 2.5
------------------------------------------------------------------------------
This document attempts to explain how to write Modules for NeoStats
(Versions greater than 2.5, older versions had a different API specification)
Modules are not simple :) I really suggest you use the source or
some other modules as examples as well as this document.
We have added in 2.5 a new 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 a 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 NeoStats
will still crash. If I can find a solution to this problem (without coping
the entire Neostats memory before each call) then I'll implement it.
So, your feeling very very lucky, and want to write your own wiz bang
Services? Ok... Get out the asprin, cause this is gonna be fun....
______________________________________________________________________________
Anything that the Server recieves from users, or other servers can be
intercepted by a Module... This basically means you can do what ever you
want in Modules.
Lets use example.c as example here... I'll detail each part of it....
#include <stdio.h>
#include "dl.h"
#include "stats.h"
ok, Firstly, you have to include a few files.
"dl.h" is mandatory, needed for the Module API...
"stats.h" is also a pretty good idea, if you want to use some of the
Internal Functions of NeoStats. If your Module is going to have a Bot in it,
then its Mandatory as well...
Module_Info my_info[] = { {
"example",
"example Module Description",
"version 1.0"
} };
Module_Info *__module_get_info() {
return my_info;
};
ok, a pretty lame coding style, but hey, it works, so who cares at the
moment.
Every Module must be able to return a array describing the Module Name, a
Short Description and a *Text* based version number.
The First field is used when refercing modules (eg, unloading a Module) the
second field is the description... the third field is a Version number...
Like I said, its text based, but could be just numbers for all you care.. it
can be used by other modules that might rely on it to make sure if version
compatible...
Functions my_fn_list[] = {
{ "VERSION", new_m_version, 1 }
{ NULL, NULL, 0 }
};
Functions *__module_get_functions() {
return my_fn_list;
};
ok, here is where we define what commands we want to be routed to this
Module. In this case, if a user typed /version <NeoStats Server name> then
this Module would intercept it... (note that with most commands, the Base
NeoStats also would intercept it) so in this case, both the NeoStats and
Module would return information. again. my_fn_list[] is a array. the first
field is what command you want to intercept it Could be "NICK" or
whatever... the Second field is the name of the function in the module that
will get this command... and finally the third field helps identify if you
want to see commands that come from the locally connected servers (eg, if it
squits NeoStats) or if you want to see commands that come form the network
in General. In this case, 1 means that we want Network Commands...
Remember, NeoStats, and many IRCD's use tokens now, so VERSION might not
always work. You should also try "+" as thats the token for version. For
easy CrossIRCD
support, I suggest you use the MSG_VERSION and TOK_VERSION defines
(for example in Unreal.h) as they will be implemented in all CrossIRCD
version, and make your module more portable if you wish to release it.
the function new_m_version is passed 2 variables: char **av and int ac.
av is a array containing the parsed command, ac contains the number of
elements.
the end of the array must be NULL terminated, meaning that the TEXT fields
must be null, and the numeric fields must be 0.
EventFnList my_event_list[] = {
{ "ONLINE", Online},
{ NULL, NULL}
};
EventFnList *__module_get_events() {
return my_event_list;
};
Ok, this is Internal Functions Lists that you want to trigger on. Examples
of them are ONLINE, trigged when NeoStats is Connected to the IRC network,
or SIGNON when a new user signs on... This list is pretty small at the
moment, but will grow as we add more features. Again, the
first field is the event you want to monitor, second is the function to
trigger when this event is activated. Again, NULL terminate the array.
The Events that are in the current version (2.5Alpha4.7) are:
ONLINE
This event is called when NeoStats connects to the Network. Can be used to
init bots, and so on.
SIGNON
Called when a new user signs onto the network. the User Structure User is
passed as a param, so you can see who it was that signed on.
SIGNOFF
Called when a user quits the network. The User structure User
is passed as a param, so you can see who it was that signed off.
KILL
Called when a user is killed on the network. the user structure User
is passed as a param, so you can see who was killed (You would have to use
the recbuf global variable to see who killed them though)
BOTKILL
Called if one of the NeoStats bots gets killed. You would use it
to Re-Initilize the Bot.
NEWSERVER
Called when a server connects to the network. the server structure Server
is passed as a param so you can see details about the new server
DELSERVER
Called when a server leaves the network.
SQUIT
Called when a server squits the network (ED: whats the diff with above?)
NETINFO
Called when the connection to the network is synced.
UMODE
Called when a user changes Umodes. (eg, /mode +o fish) the
User Structure User is passed as a param.
Thats it for events right at the moment. As we have just added Channel
support though, I suspect many more events are about to be
added. For a complete and uptodate list of Events, I suggest "grep
Event_Module *" in the source directory, to find out what Events are now
available.
void _fini() {
log("unloading Spam");
};
void _init() {
log("Loaded Module");
}
Two Special Functions that can be helpfull if you have to initilize
databases or close them down (or whatever else you might need to do)
NOTE: DO NOT USE _init to start up bots or whatever. NeoStats might not even
be connected to a IRC network when _init is fired. Basically, Don't use init
to start anything that is going to try to send commands to the IRC network.
use it to Initilize a database, or read in a config file... _init is called
even before the module is fully loaded....
_fini is called when the module is unloaded, probably the very last thing
that happens, so if you need to close log files, or flush out a database
cache then here is the place to do it...
now, some special functions to use as well, like init and fini:
init_bot(nick, ident, hostname, realname, modes, my_info[0].module_name);
init_bot is a function in the Main program that Registers a Bot on the
network for you. DON'T just think that you can send a "NICK mybot" out to
the network cause it won't work. PRIVMSG's and NOTICES are handled in a
special way, and each module has to register its bots via this interface.
init bot will return 1 on success, or if there is a failure of somereason,
then it will return -1. A failure might be that the nickname already exists
on the network, in which case, you would have to try a new Nick.
bot_nick_change(currentnick, newnick)
Bot_nick is used to change the Nickname of a bot. Because the Bot Nicknames
are registered internally in NeoStats, you must call this function to change
the nickname... again, will return 1 on success, or -1 if the nickname is
already registered on the network.
del_bot(nick, reason)
This functions makes your Bot Quit from the Network, and unregisters the
name with NeoStats.. if you try to LOG off a nickname that isn't registered,
then it will return -1 otherwise on success, it returns 1
int __Bot_Message(char *origin, char **av, int ac)
This function in your Module is called whenever a bot that has been
registered like above recieves a message from the Network. If you are
programing a Bot, this this is the Interface for all PRIVMSG's and NOTICE's
the Variables passed to it are as follows:
origin -> who sent the Message to you.. It could be a Nick 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. (eg, the above would be 2)
add_mod_timer(function name, timername, my_info[0].module_name, interval);
Ahh, have a need for Timers in your Module.. Well here is how you do them...
again, you have to register your function with NeoStats, just like you would
with a Bot.
the variables are:
Function name -> the Name of the function you want to trigger when this
timer is triggered
timername -> a descriptive name of the Timer...
my_info[0].module_name -> must be the same as what you passed to NeoStats
for the module name... to stop muckups, I use the actual Variable I passed.
interval -> The Interval in Seconds that this Function can be run...
A word of Warning about timers.. These are not precision timers. when I say
Interval, all it does is say, "has this many seconds passed since I last ran
this function. If you specified 60 seconds for the Function, it might not
get run till 66 seconds. Because NeoStats is Single Threaded, it runs in a
continues loop, meaning that if NeoStats itself, or another Module held up
that loop, then the timers are not going to run untill that peice of code
gives up...
int del_mod_timer(char *timername)
ahhh, finished running your timers, and want to delete them, then just call
this function with the timername u used above, and volia, the timer will be
deleted.
This is the Main API for Modules in a Nutshell.. I really suggest you read
the source to get a good understanding of the modules, or email me
if you have questions. Modules are pretty flexable and
powerfull, but can also be the source of a lot of problems.
Other things that modules can do:
Sockets. They can make outgoing tcp connections to other servers (ie, web,
email, etc)
Call other functions in other modules.
at the moment, I know of the issue of not every platform supporting Dynamic
Libaries... So I'm going to work on linking in static libaries... but that
could take me a while... so if your host doesn't have Dynamic Libary suport,
then find one that does if you really want to run NeoStats... Don't bug me
about it...
Thats about it...
Comments and suggestions are welcome at: fish@dynam.ac
or you can find me on one of these networks occasionally: