Do You Want To Make Modifications to RookChat?
Are you interested in writing new features or bots for RookChat? Because RookChat is open-source, including the bots, those who are interested in mucking about with the code may certainly do so. RookChat is released under the GNU Public License. If you have any questions about what this license permits or prohibits you to do with the program, visit the GNU Public License FAQ. In a nutshell, you can make modifications to the software, but if you make the program available to anyone, you must also distribute (freely) the source code of the modified version under the GNU Public License. This modified version must have your name on it, to distinguish it from the "official" distribution of RookChat, while preserving the copyright notices from the original code.
Should you make a modification to RookChat, whether a simple bug fix or a new command or bot or whatever, it is also requested that you make the modification available to me. I may want to include your new feature in the main distribution or link to it from a mods page (as yet forthcoming), but in any case I would like to see your work.
How the RookChat Code Is Organized
Directory | Files | Description |
---|---|---|
src/ | controller.py, actions.py, views.py | controller.py
is the "main" routine. Generally, all this
does is keep track of what basic actions and views are recognized and
makes appropriate calls to the
actions.py module and the
views.py module, in that order.
For each possible action, there is one method in each of actions.py and views.py. actions.py takes care of effecting any required changes, while views.py returns the HTML that should be viewed as a result. |
src/ | *methods.py | All modules that end in methods.py are interfaces to data files. Rather than accessing data files directly, the methods of these files should be called. This ensures that data files are not corrupted because two separate pieces of code are handling the same files differently. They also implement data caching features that help reduce disk usage. |
src/ | auth.py, bots.py, display.py, help.py, ip.py, msgs.py, op.py, permissions.py, rooms.py, users.py | These modules perform higher level operations than the *methods.py modules do. Many of the operations covered in these modules make use of multiple *methods.py modules. Rather than handling data storage, as the *methods.py modules do, these modules have more of an understanding of the logic of how the program needs to run. |
src/ | commands.py, executor.py | These modules handle the execution of commands issued by users logged into RookChat (the commands that begin with a slash and are typed right into the browser window). The commands.py module contains information about what commands are available, what arguments each command takes, help information about the commands, etc. executor.py contains the code that actually gets run when a command is issued. |
src/ | stream.py | Code for the streaming update method. When the chat is run in streaming mode, the messages frame, rather than refreshing periodically to get new messages, stays open and gets new messages as they appear. Consequently, the CGI process for the messages frame sticks around on the server, rather than simply displaying data real quick and exiting, as is normally the case for CGI programs. This lingering process is called the streamer, and stream.py contains the code it runs. |
botlib/ | botlib.py | This is the bot toolkit. Bots should only ever call functions defined in this module -- it should not be making direct calls to anything in the src/ directory. |
How To Add New Features To RookChat
RookChat was designed to be reasonably easy to extend with new views, commands, bots, etc. Here is a brief overview about how to make the most common types of extensions to RookChat's functionality. Unless the changes you wish to make involve the very infrastructure of RookChat, the information below will probably help you.
Adding a new view to RookChat.
Here is how you can add a new view (or screen) to RookChat. Each type of page or frame served by the RookChat scripts is a view, e.g., the login page or the user list frame.
First, assign the new view a keyword and insert this into the __actions dictionary given in controller.py. Then define two methods, one in actions.py and one in views.py, that have this same name. The actions.py method should return '1' if no errors have occurred; otherwise, a tuple with the first element being whatever you want (usually 0) and the second being an error code. The error codes are located in rcerrors.py. This method should perform all actions associated with the view (for example, loading the user list frame updates your idle time, among other things) but not display anything. In most cases, you will want this method to authenticate the user at the very least. This requires making an appropriate call to a function in auth.py and immediately returning an error if it fails. You can check the other methods of actions.py to see how this is done.
The method in views.py receives the return value of the actions.py method as an argument. The first thing you should do is check this argument for an error and act accordingly. Frequently, the first three lines of code will be exactly this:
if ain != 1: self.__error(ain[1]) return
After that, you can start printing out the HTML code for the view by making calls to display.py or just printing directly. Note that if you need to display a URL, you should use rcfiles.script_filename to refer to the name of the RookChat script, and methods in the query.py module to display the query string portion of the URL. Be sure not to display any English text directly; to allow for internationalization, add a tagged message to the language0.py modules (in the language/ directory) instead. (If you know the foreign translations for the string, add it to the other language?.py modules as well.)
Adding a new command to RookChat.
To add a new command to RookChat, add an entry to commands.py with the command name, arguments, and help information. You'll have to add tagged strings to the language0.py module (in the language/ directory) for the help text. Also remember to add the new command to the "see also" lists of related commands. If the new command is part of a new command category (important only for the help text), then be sure to include the name of this new command category at the top of the list_of_commands_category() function in help.py and to insert a new help_category_* string in the language files.
Next, add a method to executor.py that matches the name of the command. This method should do what is required to execute the command. If the new command is not one all users can run, this method should check permissions first. This method can make calls to a variety of modules to get its job done, including users.py, rooms.py, msgs.py, bots.py, permissions.py, rcfilter.py, and any of the *methods.py modules. Make sure that you update the user's idle time if and only if the command does something publicly visible. Also make sure any text displayed anywhere gets sent through rcfilter.py, to guard against HTML code, bad words, long messages, etc, being displayed inappropriately.
Adding a new option or profile field to RookChat.
To add a new option or profile field to RookChat, add an entry to the beginning of optionmethods.py, where the options and profile fields are listed. There are a lot of possible fields for each option, so you might want to start by copying the most similar existing option. Take note of the comments in code, as they explain some of the less intuitive fields.
Next, edit the language0.py and add a translation for opt_newoptiontag (for a new option) or prof_newoptiontag (for a new profile field), where newoptiontag is the value you put for the "tag" field in optionmethods.py. This should be set to the displayed name of the new option or profile field. If this option or profile field is a "select" type (i.e., a drop-down box that allows the user to choose between a pre-determined set of values), then you must also supply a language translation for each value, in the form of opt_newoptiontag_value or prof_newoptiontag_value. As an example, look at the translations available for the "smileys" option.
If you are adding a new profile field, that's all you need to do; if you're adding a new option, you'll of course need to write whatever code consults and acts upon the value of the option.
Adding a new bot to RookChat.
First create a BotName.cgi file for the bot in the bots/ directory. This filename should be case-sensitive according to how the bot name should be displayed. All it should do is import botname.py, where botname is an all lower-case version of the bot name. This script should have all the bot code in it. It should only make calls to functions in botlib.py to get its job done, i.e., it should never import anything from the src/ directory. If you need to interact with the RookChat code base in any way, and botlib.py doesn't already have a method that supplies your needs, then add one.
The control flow for the botname.py module is a callback system, where methods are called as events occur. Your best bet is to copy an existing bot, one that more or less matches your needs from a structural standpoint, and make changes, rather than starting from scratch.
Adding a new language to RookChat.
Note: The following instructions only valid for version 1.00.04 and later. If you're working on a version of RookChat earlier than 1.00.04, your best bet is to upgrade to the latest version before going any further.
To add support for a new language to RookChat, you must add a new subdirectory to the languages/ directory whose name will function as a tag for the new language. Copy all the files from the english-american/ subdirectory into this new directory. Rename english_american.py to have the same name as the new directory, but with .py added to the end.
The language files come in three different formats, and the rules for formatting them are slightly different:
- The *.py file maps tags (which must not be touched) to string values (which should be translated). The percent codes in some of the string values must be preserved, and, moreover, the order of the percent codes within individual string values must be preserved.
- The possess* files contain lines that replace what users type when they have been taken over by the /possess command. They are newline-sensitive. All text in these files should get translated, but the location of newlines should be preserved, even if that means individual lines are more than 80 characters long. Note that these possession strings only ever appear in the default language for any given RookChat installation; they don't change based on the option settings of individual users.
- All other files are plain text files with HTML codes and some percent codes. The only trick with these is to preserve the various percent codes ( %s, %pc), but it is not necessary to keep them in the same relative order, as it is with the strings in the *.py file.
Note that commands cannot be changed, so if, for example, there is a reference to the /rose command, it must stay the way it is and not be translated. This is also true of parameters to commands -- for example, the strings fixed, normal, mod, op, admin, owner, public, open, moderated, and restricted are parameters to the /userlevel, /newmemolist, and other commands. These have to stay as they are.
However, the visual display of, for example, [mod], [op], [admin], and [owner] tags can be translated into the new language: in fact, the *.py files contain a string for each of them. So be conscientious about this distinction as you translate.
Lastly, you have to add a line in all of the other *.py files in the other language directories. In each of these files, search for opt_language_, and you'll see a translation string for each language in the system. Add a translation string for the new language, completing the tag opt_language_ with the tag for your new language.
After the new directory and the new files are in place, RookChat should recognize the existence of the new language automatically; to test this, see if the new language now appears in the "Change Language" drop-down list on the main page.
Adding a new smiley to RookChat.
Simply put the new smiley image in the smileys/ directory and modify the src/smileys.py file by adding a new entry for the new smiley.