
Her hair glistened in the rain like nose hair after a sneeze. |
|
|
Perl-fu is an IRC bot written in POE::Component::IRC. It is loosely based on the infobots available for download at http://www.infobot.org/. The original goal of the 'Perl-fu project' was to write a superior infobot. Perl-fu and most of Perl-fu's core plug-ins were written by Jinzougen (http://www.jinzougen.net). Who is usually found in #perlhelp on efnet. So any complements, praise, comments, suggestions, life-stories and/or death threats should be sent to him via that website. The first time you start Perl-fu, you're going to have to make some configuration decisions. After Perl-fu runs once, these configuration options will be remembered in Perl-fu's conf file. You may however go back and change any of these options anytime you start the bot (or at runtime by using one of the newer "set option" commands in the Corecmd plug-in). These options are defined/changed via command line switches. At the time this document was written, Perl-fu had 12 switches. They are used via the syntax --switchname=value. Each switch and a description of each switch is listed below.
After Perl-fu is ran. It will create a file called perlfu.conf. If you wish, you can edit the file directly and change the values there. But if you, be careful to preserve the exact format. Perl-fu writes to that file a certain way and expects to read from it the same way. Before running Perl-fu for the first time it's a good idea to set yourself up as an operator. That way you can use all of Corecmd's commands that control the bot. When you first download Perl-fu, there should be a file called Corecmd.ops in the main folder. When you first download it, it has one nick and a mask that'll match anything. What you have to do is think of a nickname that only you will be using for the next few minutes. Then type that (in all caps) in the place of "YOUR_NICK_HERE". Start up the bot. Then, under that nick, use the bot's internal op adding/delete commands to add yourself and any other trusted persons to the op list, then remove the temporary one you are using. For help on Corecmd commands, just use the command 'help'. As of version 1.05, Perl-fu comes with a documentation-only plug-in that explains factoids. Use the command "fudoc factoids" to access it. 2.4 - Installing Perl-fu Plug-ins Perl-fu has a plug-in architecture that makes installing plug-ins as easy as putting them in the right directory. And that folder is Perlfu/Plugin/ relative to where perlfu.pl is. So for example, if you put perlfu.pl in the directory /home/downloads/perlfu/, then the plug-in directory would be /home/downloads/perlfu/Perlfu/Plugin/. Note that since so far I've been too lazy to have Perl-fu depend on the CWD, you'll have to cd to Perl-fu's directory before running it. I'll get to the CWD thing in time. Perl-fu was written on Perl version 5.6.1. So if you have version 5.6.0 or higher you should be ok. The only non-standard modules it uses are POE, and POE::Component::IRC. These will have be installed. Also note that any of Perl-fu's plug-ins is capable of using whichever modules they want, so reach your plug-ins' documentation to make sure you have all the right modules. perlfu.pl is the main program responsible for connect to an IRC server and maintaining that connection. It's responsible for loading and using the plug-ins, parsing messages and managing factoid operations. I can't really think of too much about perlfu.pl that is relevant to this document. If you want to learn about it, check out the source. 3.2 - Understanding Perl-fu Plug-ins When Perl-fu starts up, after initializing itself with command line switches and it's conf file and all that madness, it loads the plug-ins. It does this by scanning the plug_dir for files ending in ".pm". It performs a do on each file to get the class name, makes a new object of that class and gets the plug-ins' active and passive event handlers from the appropriate methods (this is all described in more detail in the next section). To make a long story short, Perl-fu ends up with two hashes, %Active_Plugins and %Passive_Plugins. %Active_Plugins describes which plug-in/method to call based on a matched regex, and %Passive_Plugins describes which events plug-ins want passive access to. If this all blew by your head, don't worry, I go a little more in-depth in the next section. (This was just to scare the newbies :-) 4.1 - Required Plug-in Elements In order to adhere to Perl-fu's design, any plug-in you write needs to have a few specific parts. We'll go through a checklist of plug-in components and talk a little about what each part is for. 1.) Package: First of all, your plug-in must have a valid package name. It should be "Perlfu::Plugin::Yourpluginname". At the very bottom of your plug-in, you should have this package name in a string as well. This is so Perl-fu can tell what package your plug-in is in by doing it. 2.) Subclass: For safety's sake, or in case you forget any of these elements, you should subclass your plug-in via: our @ISA = qw(Perlfu::Plugin); 3.) Contructor: You have to have a contructor called new. It will be executed when Perl-fu is starting or reloading the plug-ins. You should do all your initialization, if any, here. It's class name will be passed into it and it must return a bless reference to your plug-in's class. 4.) Passive Events: Passive and active events are explained later in this section. But as far as the checklist goes, you need to have a method called passive. It must return a list of irc events (in the correct naming scheme which is also described later) that your plug-in want's to passively handle. 5.) Active Events: Passive and active events are explained later in this section. But as far as the checklist goes, you need to have a method called active. It must return a hash reference that will serve as your active handler. The keys are qr//'ed regexes that the command line must match, and the values are strings representing the method to call when the key is matched. 6.) Methods: Make sure that any events you define in passive() and/or active() have corresponding methods. Event naming schemes only deals with passive events(), which are described next. Basically Perl-fu calls your plug-in on passive events based on the event that occurred. And the way you name these events and methods to go with them is pretty simple. To figure out how to name an event/method, look up the corresponding event in the POE::Component::IRC docs. You'll find they are all named like "irc_eventname". Well the Perl-fu way of doing it is by dropping the "irc_" prefix, and uppercasing all the rest. So for an "irc_nick" event, the Perl-fu event would be called "NICK". "irc_public" is "PUBLIC" and so on. Even P::C::I events that have more than one underscore, such as the ctcp ones are exactly the same, so "irc_ctcp_ping" is "CTCP_PING". Perl-fu plug-ins have two different ways they are called. These two ways are active and passive. The difference between the two is that active events are used for methods that give output and passive ones are used for events that simply use the event data but give no output. This is best described with an example. Say I wanted to write a Karma plug-in. This plug-in will keep track of people's karma by watching the channel for nick++ and nick--'s. So every time someone said nick++ or nick--, the plug-in would increment/decrement the karma for that nick. These events don't generate any output and would therefore be passive. However, you also want to be able to tell someone what the karma for someone is. So if someone said perhaps "karma for nick", you'd want to catch that command and spit out that person's karma right? this would be active. Each public/private message can only activate ONE active event. This is to prevent the bot saying multiple things that correspond to different plug-ins. As soon as one active event is matched, it skips checking the rest, and since there is no real way of knowing in which order the events are checked, you have to make your events as specific as possible. Let's take a look at exactly how to use active and passive events. One of your plug-in's required elements is a method called "passive". This method returns a list of events it passively wants to handle. For example, if I wanted to passively handle public and private message events, my passive method would return a list like qw(PUBLIC MSG). Note that these are properly formatted names because the corresponding P::C::I events for each are irc_public and irc_msg respectively. Now, whenever an irc_public event happens, it will call a method named "PUBLIC" in your plug-in. This method is sent all the data that the event produced and it is passed in the same order as it was recieved from P::C::I starting with ARG0. Look up the P::C::I documentation to find what exactly these values are, but for an example, @_ in your PUBLIC method would probably look like my($self, $nickmask, $recip, $text) = @_;. Note that a reference to the poe_kernel is not passed. This is to discourage you from trying to use it in a passive method, because only active methods are ment to give output. However since some plugins may require the use of more advanced IRC messages, the POE kernel reference can always be found at $POE::Kernel::poe_kernel. The other kind of event is of the "active" sort. These events are meant to give output and only one line of output. First of all, the "active" method in your plug-in must return a hash reference. the keys to this hash are qr//'ed regexes. The way Perl-fu uses these regexes is like this. Whenever a public/private message event occurs, Perl-fu goes through it's own parsing to determine whether or not it's a request for a factoid, a command to set/overwrite/forget a factoid, or a possible command for a plug-in. And this regex is used to test if it actually _is_ a command for your plug-in. Perl-fu takes care of the addressing and everything so all you need to do is worry about what the command part will look like. Here's an example: <Android18>perl-fu, commandname arg1 arg2 arg3 Perl-fu will try to match "commandname arg1 arg2 arg3" in the first case and "What's up?" in the second case against each of your regexes. (Note that the second one would only actually produce a plug-in call if --addr_cmd is false (see the switches section at the beginning). So if you wanted to capture say a command that was known as "commandname". Your active method might return a hash reference that looks like this: {qr/^commandname (.+)/i => 'commandname_method'} Now there are many things to pick up about this key/value pair. For one thing, note that there is the ^ anchor. This is important since you want to make sure "commandname" is the first thing in the command. Also notice how the .+ is captured. Capturing parts of the regex is how you pass values to your method! So in this case, it would capture "arg1 arg2 arg3". And sure enough, a scalar containing "arg1 arg2 arg3" will be passed to your method when someone uses the command. This is not the only thing passed to the method though. In every one of your
methods you describe, this is the order of things passed to it: $self is your blessed reference, $nick and $mask are the nickname and addressmask of the person that generated the event, $denizen is true if the person is in one of the same channels Perl-fu is in, false if they are not, and @args is an array of everything you captured in the regex. In our example, we only captured on thing, so @args only has one element and it is "arg1 arg2 arg3". So this is all fine and dandy.. so how do you generate this output anyway? You do it via the return command. Your active plug-in should return a list of two elements. That list should look something like (replytype => "output"). Reply type is, in reality, the second argument passed to $POE::Kernel::poe_kernel->post(). Most of the time this will be 'privmsg'. However if you wanted to produce a ctcp action, you might say: return(ctcp => "ACTION output"). No matter how you do it, Perl-fu will take care of sending it to the right channel in the case of a public message or nick in the case of a private one. If you want to learn more about privmsg and ctcp and the POE Kernel, read the POE and POE::Component::IRC documentation. 4.4 - Implementing Fudocumentation Version 1.05 introduces a new, standard method of plug-in documentation, Fudoc. Having your plug-in support Fudocumentation isn't required but is highly encouraged. It's very easy. All you do is add an object method called "fudoc" to your plugin. This sub is responsible for telling the Fudoc plug-in your plug-in's documentation when requested. It is called as an object method so a blessed reference will be first in @_. Along with that reference, the nickname of the user who requested documentation is also passed.. just incase you want to customize the docs for that user. Fudoc maintains it's own private plug-in objects so if you use the blessed reference to access data, make sure all that data is set up in the new() method, since no other interaction will happen with Fudoc. Your fudoc() sub is expected to return a reference to an array of lines to display. Here's a simple example plug-in to encompass everything we've discussed. package Perlfu::Plugin::MyPlug; Eh.. There are probably a few... There might even be something that crashes the program entirely I don't know.. I'll be glad to work on fixing whichever ones you find. You can reach me, Jinzougen, at jinzougen@jinzougen.net. And you can probably find me online in #perlhelp on EFnet under one of the following names: jinzougen, or android-. |
Copyright © 2003 - Brandon Beamer (all rights reserved).