Xbot › Modules
From Botdom Documentation
- The correct title of this article is xbot/Modules. The initial letter is capitalized due to technical limitations.
Last updated at version 1.2
Contents |
What are modules?
A module is a directory (of the same name) which contains a collection of PHP instructions which work together (via the xbot system) to achieve some goal.
The modules system of xbot allows for commands, triggers and a bunch of other cool stuff. Read on for more details. :D An example module can be found in ~/modules/example/
There are three types of modules:
- Normal (priority 0): Can be deactivated/reactivated during runtime.
- Core (priority 1): Cannot be deactivated during runtime, but can be set as initially deactivated.
- System (priority 2): Cannot be deactivated. Will pop up a WARNING notice if not found.
System modules are considered a part of xbot. For typical use, you can create normal or core modules, both of which follow the same format, except for differing in how their init/config files are named.
Modules are loaded into xbot through the load script, which checks each module directory for an init file, either modinit.php (module) or sysinit.php (core module), and loads the module accordingly. If there is no init file, the whole directory is ignored.
The load script will also check for the existence of a config file, either modcfg.php or ~/modules/MODULE_NAME.modcfg.php (which overrides the former), which contains settings for the module (made available in this file at the discretion of the module developer).
During runtime, your module can be activated/deactivated by using the command "module [on|off] [MODULE_NAME]".
To access your module and its module functions in the bot, you can use global $sys_mod; $sys_mod[MODULE_NAME]->FUNCTION()_OR_PROPERTY.
Init file
Generally, an init file follows this form:
<?php $sys_mod[$m] = new Module($m); $sys_mod[$m]->setInfo(AUTHORS,TITLE,VERSION[,DESCRIPTION]); // module settings and behaviour // any other things you need to do at startup, // such as including new classes / functions / data structures etc ?>
- $sys_mod is the global array which contains all the module objects.
- $m is the MODULE_NAME.
- AUTHORS is a comma delimited list of authors. Eg, "infinity0, electrinet".
- For the DECSRIPTION, the strings "%auth%", "%devauth%", "%title%", "%v%" will be replaced by (a comma delimited list of authors), (a comma delimited list of authors with links to their dA pages), (module title) and (module version) respectively. The default value of DESCRIPTION is "{title} {v} by {devauth}.".
- This config file is only ever run once, in ~/system/load.php
You MUST NOT change any instances of $m. When the script is run, its value at that time would be the name of the folder of the module. This ensures the uniqueness of the module. For consistency and ease of coding, the name of the module will always be the folder it's kept in. You can, however, change the title of your module with setInfo().
Adding commands
A command is a special type of event (see below), and is treated separately from other event types. It's triggered by user-input which starts with the bot's trigger. For example, if your bot's trigger is "!", then !test would trigger the script assigned to the command "test".
To assign scripts to commands, use the following in your module config file.
$sys_mod[$m]->addCmd(COMMAND_NAME,COMMAND_FILE[,LOWEST_USER_PERMISSION[,DEFAULT_STATUS]); $sys_mod[$m]->addCmdInfo(COMMAND_NAME,DESCRIPTION,SYNTAX);
- LOWEST_USER_PERMISSION is an integer as defined in the $sys_privs array. Its default value is 'df', which is equivalent to the system default privclass. Setting it to null will enable the event for all access levels (including those below the default access level).
- DEFAULT_STATUS is the status this command or event will have when the module is loaded or activated as a whole, by setStatus(1). It is TRUE by default.
- The addCmdInfo() function may be omitted but this is not recommended as the extra information given would be helpful to coders and users alike. SYNTAX is a string that gets displayed in the "!command info [command]" command. The string is exploded on occurences of "||" and each substring syntax is displayed on their own line. Alternatively, if DESCRIPTION equals "aliasfor" then the actual description and syntax is retrieved from the command with the name SYNTAX.
As an example, to set the file "example.php" to run whenever an admin of the bot (permission level = 99) types "!example1", you would use:
$sys_mod[$m]->addCmd('example1','example',99);
Only one command can be registered to any file, and vice versa.
Conflicting commands
Different commands may be assigned the same file, so that typing "!example1" and "!example2" both result in "example.php" being run. However, only one file can be assigned to one command in ALL MODULES. This is to avoid unexpected results in the bot.
Commands which cause conflict are negotiated in the following order:
- ~/modules/A/sysconfig.php
- ~/modules/Z/sysconfig.php
- ~/modules/a/sysconfig.php
- ~/modules/z/sysconfig.php
- ~/modules/A/config.php
- ~/modules/Z/config.php
- ~/modules/a/config.php
- ~/modules/z/config.php
The first module to contain the command (when modules are listed in the above order) takes priority. A notice will be displayed in the console whenever a command causes a conflict, so that it may be fixed.
xbot DOES NOT throw a special error if the conflicting command is part of a core module, so it is UP TO YOU to make sure that any commands in a module you have marked as being core do not conflict with any existing core modules. Obviously, the default core modules included with xbot do not have any conflicting commands,
Adding events
An event is an action triggered by anything which the bot may come across during usage. The default list of triggers are in the $sys_evt array in bot.php; in most cases the usage of the trigger is obvious by its name, but if you are unsure, you can see where exactly they run in the code by searching for the trigger-name in ~/system/*.php.
To assign scripts to events, use the following in your module config file.
$sys_mod[$m]->addEvt(TRIGGER_NAME,COMMAND_FILE[,LOWEST_USER_PERMISSION[,DEFAULT_STATUS]]); $sys_mod[$m]->addEvtInfo(TRIGGER_NAME,COMMAND_FILE,DESCRIPTION);
- TRIGGER_NAME is the name of the trigger as defined in the $sys_evt array in bot.php.
- LOWEST_USER_PERMISSION is an integer as defined in the $access array in bot.php. Its default value is 'd', which is equivalent to the system default privclass. Setting it to null will enable the event for all access levels (including those below the default access level).
- DEFAULT_STATUS is the status this command or event will have when the module is loaded or activated as a whole, by setStatus(1). It is TRUE by default.
- The addEvtInfo() function may be omitted but this is not recommended as the extra information given would be helpful to coders and users alike.
As an example, to set the file "example.php" to run whenever someone joins the room, you would use:
$sys_mod[$m]->addEvt('recv-join','example');
Multiple event triggers can be registered with the same file, and vice versa.
Config files
Generally, a config file follows this form:
<?php $sys_mod[$m]->status = 1; // default starting status (activated / deactivated) // any data which is to be adapted to the module user's particular needs ?>
Ie. the content of the config file is whatever you need/want for your module. It's done this way to separate solid data (init) and volatile (config) data, so that it's easier to edit the latter without editing the former.
It's recommended to keep a default config file at modcfg.php with the actual used config file at ~/modules/MODULE_NAME.modcfg.php. This allows you to prepare the module for distribution more easily.
On *nix systems, this also allows you to keep one copy of a module and run it with different settings in multiple bots simultaneously, so that you only have to edit one copy when you're developing. See #Custom config files
Module development
Accessing event data
When an event is triggered, it will set the global variables $mod and $sys_trg['mod'] to the name of the module to which the event/command belongs to, so that you can access your own module with $sys_mod[$mod].
Data of the current packet being processed is always available from $sys_cl->data and $sys_cl->pkt as a string and an array respectively. In PHP code which is ran as part of a module, "$sys_cl" can be replaced by "$this".
Some of the more commonly required (trigger-specific) packet data is copied from $sys_cl->pkt into $sys_trg, and then to scalar variables (whose names corresponding to the keys of $sys_trg) for easy access. $sys_trg is global, but these scalar variables can only be accessed through code directly linked to the module itself (through addCmd/addEvt), and not from eg. functions or objects. The variables are listed below.
Commands
Variables you may access from any command are:
- $mod
- module of command. Copied from $sys_trg['mod'].
- $from
- subject of command. Copied from $sys_trg['subj'].
- $chan
- channel of command. Copied from $sys_trg['chan'].
- $command
- name of command. Copied from $sys_trg['cmd'].
- $args
- arguments of command. Copied from $sys_trg['args'].
Events
Variables you may access from any event are:
- $trigger
- type of event. Copied from $sys_trg['type'].
- $mod
- module of event. Copied from $sys_trg['mod'].
- $from
- subject of event. Copied from $sys_trg['subj']. (for kick/privchg, this is the kickee/privchangee)
- $target
- object of event. Copied from $sys_trg['obj']. (for kick/privchg, this is the kickER/privchangER)
- $chan
- channel of event. Copied from $sys_trg['chan'].
- $args
- arguments of event. Copied from $sys_trg['args']. (for details, see ~/system/process.php)
Saving/loading file data
Use $sys_mod[$mod]->savedata(ARRAY,FILE,SERIALISE) or ->loaddata(FILE,SERIALISE). (If $mod is unavailable, use $sys_trg['mod'].)
FILE will automatically be saved as/loaded from ~/savedata/MODULENAME/FILE. You cannot access other module files via this method.
Some cunning hacks involving modules
Saving data between commands
You can do whatever you wish with $sys_mod[$mod]->data. (If $mod is unavailable, use $sys_trg['mod'].)
Sometimes you need to store data in between commands. If you don't want/need to save the data to a file, you can do this instead:
- User types !commandA
- CommandA sets data[key] to valueA
- User types !commandA
- CommandA does something different because data[key]==valueA
Just be sure to eg. make sure the users are the same, if that's a necessary behaviour.
Efficient error catching
You can (de)activate individual events/commands using $sys_mod[$mod]->setCmdStatus(COMMAND,STATUS) or ->setEvtStatus(EVENTTYPE,FILE,STATUS). (If $mod is unavailable, use $sys_trg['mod'].)
You can use this to more efficiently catch errors, by having your error-catching scripts only run when they are relevant, eg:
- User types !commandA
- CommandA sets EvtA:FILE to ON, and sends out a request for more data from dAmn.
- The data is received from dAmn, and triggers EvtA:FILE.
- EvtA:FILE does the necessary stuff, then sets itself OFF.
The need to set EvtA:FILE to ON and OFF might seem redundant, but other modules (or you yourself) may want to send out the same request for more data to dAmn WITHOUT triggering EvtA:FILE.
Multiple instances of a module
This works only on a filesystem which supports symlinks (should also work with hardlinks but nobody uses those for good reasons).
- Put your module in a folder away from ~/modules/.
- Now, you can repeat the following for as many bots as you want, without copying the core module files.
- Create a symlink directory called MODULE_NAME in ~/modules/ to said module
- Copy (not symlink) the config file to ~/modules/MODULE_NAME.modcfg.php
- Edit the config file as you wish. This will only apply to the current bot.
And that's how it's done.
Custom events
You can even create your own triggers for an event, although this involves editing the bot's core files. To register a trigger with the bot, insert the following into the global $sys_evt array in ~/system/class.modules.php
TRIGGER_NAME => array(),
This TRIGGER_NAME can be anything you like, as long as it doesn't conflict with the other triggers.
Now you need to set where the trigger runs. To set the run point of the trigger, place the following at the desired point in the bot's code.
$sys_cl->event(TRIGGER_NAME,SUBJECT,OBJECT,CHANNEL,ARGS); // any of these may be blank, but that wouldn't be useful, now would it? :P
Now you'll be able to use this trigger for an event in a module. Use the same format as before:
$sys_mod[$m]->addEvt(TRIGGER_NAME,COMMAND_FILE[,LOWEST_USER_PERMISSION[,DEFAULT_STATUS]]);

