Limnoria/docs/CAPABILITIES

119 lines
6.7 KiB
Plaintext

Ok, some explanation of the capabilities system is probably in
order. With most IRC bots (including the ones I've written myself
prior to this one) "what a user can do" is set in one of two ways. On
the *really* simple bots, each user has a numeric "level" and commands
check to see if a user has a "high enough level" to perform some
operation. On bots that are slightly more complicated, users have a
list of "flags" whose meanings are hardcoded, and the bot checks to
see if a user possesses the necessary flag before performing some
operation. Both methods, IMO, are rather arbitrary, and force the
user and the programmer to be unduly confined to less expressive
constructs.
This bot is different. Every user has a set of "capabilities" that is
consulted every time they give the bot a command. Commands, rather
than checking for a user level of 100, or checking if the user has an
"o" flag, are instead able to check if a user has the "owner"
capability. At this point such a difference might not seem
revolutionary, but at least we can already tell that this method is
self-documenting, and easier for users and developers to understand
what's truly going on.
If that was all, well, the capability system would be "cool", but not
many people would say it was "awesome". But it *is* awesome! Several
things are happening behind the scene that make it awesome, and these
are things that couldn't happen if the bot was using numeric
userlevels or single-character flags. First, whenever a user issues
the bot a command, the command dispatcher checks to make sure the user
doesn't have the "anticapability" for that command. An anticapability
is a capability that, instead of saying "what a user can do", says
what a user *cannot* do. It's formed rather simply by adding a dash
("-") to the beginning of a capability; "rot13" is a capability, and
"-rot13" is an anticapability. Anyway, when a user issues the bot a
command, perhaps "calc" or "help", the bot first checks to make sure
the user doesn't have the "-calc" or the "-help" capabilities before
even considering responding to the user. So commands can be turned on
or off on a *per user* basis, offering fine-grained control not often
(if at all!) seen in other bots.
But that's not all! The capabilities system also supports *Channel*
capabilities, which are capabilities that only apply to a specific
channel; they're of the form "#channel,capability". Whenever a user
issues a command to the bot in a channel, the command dispatcher also
checks to make sure the user doesn't have the anticapability for that
command *in that channel*, and if the user does, the bot won't respond
to the user in the channel. Thus now, in addition to having the
ability to turn individual commands on or off for an individual user,
we can now turn commands on or off for an individual user on an
individual channel!
So when a user "foo" sends a command "bar" to the bot on channel
"#baz", first the bot checks to see if the user has the anticapability
for the command by itself, "-bar". If so, it returns right then and
there, completely ignoring the fact that the user issued that command
to it. If the user doesn't have that anticapability, then the bot
checks to see if the user issued the command over a channel, and if
so, checks to see if the user has the antichannelcapability for that
command, "#baz,-bar". If so, again, he returns right then and there
and doesn't even think about responding to the bot. If neither of
these anticapabilities are present, then the bot just responds to the
user like normal.
From a programming perspective, capabilties are easy to use and
flexible. Any command can check if a user has any capability, even
ones not thought of when the bot was originally written.
Commands/Callbacks can add their own capabilities -- it's as easy as
just checking for a capability and documenting somewhere that a user
needs that capability to do something.
From an end-user perspective, capabilities remove a lot of the mystery
and esotery of bot control, in addition to giving the user absolutely
finegrained control over what users are allowed to do with the bot.
Additionally, defaults can be set by the end-user for both individual
channels and for the bot as a whole, letting an end-user set the
policy he wants the bot to follow for users that haven't yet
registered in his user database. It's really a revolution!
There are several default capabilities the bot uses. The most
important of these is the "owner" capability. This capability allows
the person having it to use *any* command. It's best to keep this
capability reserved to people who actually have access to the shell
the bot is running on.
There is also the "admin" capability for non-owners that are highly
trusted to administer the bot appropriately. They can do things such
as change the bot's nick, globally enable/disable commands, cause the
bot to ignore a given user, set the prefixchar, report bugs, etc.
They generally cannot do administration related to channels, which is
reserved for people with the next capability.
People who are to administer channels with the bot should have the
#channel,op capability -- whatever channel they are to administrate,
they should have that channel capability for "op". For example, since
I want inkedmn to be an administrator in #supybot, I'll give him the
#supybot,op capability. This is in addition to his admin capability,
since the admin capability doesn't give the person having it control
over channels. #channel,op is used for such things as
giving/receiving ops, kickbanning people, lobotomizing the bot,
ignoring users in the channel, and managing the channel capabilities.
The #channel,op capability is also basically the equivalent of the
owner capability for capabilities involving #channel -- basically
anyone with the #channel,op capability is considered to have all
positive capabilities and no negative capabilities for #channel.
One other globally important capability exists: "trusted". This is a
command that basically says "This user can be trusted not to try and
crash the bot." It allows users to call commands like Math.icalc,
which potentially could cause the bot to begin a calculation that
could potentially never return (a calculation like 10**10**10**10).
Another command that requires the trusted capability is Utilties.re,
which (due to the regular expression implementation in Python (and any
other language that uses NFA regular expressions, like Perl or Ruby or
Lua or ...) which can allow a regular expression to take exponential
time to process). Consider what would happen if someone gave the
bot the command 're [format join "" s/./ [dict go] /] [dict go]'
Other plugins may require different capabilities; the Factoids plugin
requires #channel,factoids, the Topic plugin requires #channel,topic,
etc.