mirror of
				https://github.com/Mikaela/Limnoria.git
				synced 2025-11-04 01:27:21 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			108 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
Ok, some 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 finegrained 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, compltely 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 programmatical 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 admin capability doesn't give the
 | 
						|
person having it control over channels.  #channel.op is object 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 the someone gave
 | 
						|
the bot the command 're [strjoin "" s/./ [dict go] /] [dict go]'
 | 
						|
 | 
						|
Other plugins may require different capabilities; the Factoids plugin requires
 | 
						|
#channel.capability, the Topic plugin requires #channel.topic, etc.
 |