mirror of https://github.com/Mikaela/Limnoria.git
textwidth=70 reformatting along with some documentation fixes that I noticed
This commit is contained in:
parent
940a934f6e
commit
5deb99192e
|
@ -1,107 +1,118 @@
|
||||||
Ok, some some explanation of the capabilities system is probably in order.
|
Ok, some some explanation of the capabilities system is probably in
|
||||||
With most IRC bots (including the ones I've written myself prior to this one)
|
order. With most IRC bots (including the ones I've written myself
|
||||||
"what a user can do" is set in one of two ways. On the *really* simple bots,
|
prior to this one) "what a user can do" is set in one of two ways. On
|
||||||
each user has a numeric "level" and commands check to see if a user has a "high
|
the *really* simple bots, each user has a numeric "level" and commands
|
||||||
enough level" to perform some operation. On bots that are slightly more
|
check to see if a user has a "high enough level" to perform some
|
||||||
complicated, users have a list of "flags" whose meanings are hardcoded, and the
|
operation. On bots that are slightly more complicated, users have a
|
||||||
bot checks to see if a user possesses the necessary flag before performing some
|
list of "flags" whose meanings are hardcoded, and the bot checks to
|
||||||
operation. Both methods, IMO, are rather arbitrary, and force the user and the
|
see if a user possesses the necessary flag before performing some
|
||||||
programmer to be unduly confined to less expressive constructs.
|
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
|
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
|
consulted every time they give the bot a command. Commands, rather
|
||||||
checking for a user level of 100, or checking if the user has an "o" flag, are
|
than checking for a user level of 100, or checking if the user has an
|
||||||
instead able to check if a user has the "owner" capability. At this point such
|
"o" flag, are instead able to check if a user has the "owner"
|
||||||
a difference might not seem revolutionary, but at least we can already tell
|
capability. At this point such a difference might not seem
|
||||||
that this method is self-documenting, and easier for users and developers to
|
revolutionary, but at least we can already tell that this method is
|
||||||
understand what's truly going on.
|
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
|
If that was all, well, the capability system would be "cool", but not
|
||||||
people would say it was "awesome". But it *is* awesome! Several things are
|
many people would say it was "awesome". But it *is* awesome! Several
|
||||||
happening behind the scene that make it awesome, and these are things that
|
things are happening behind the scene that make it awesome, and these
|
||||||
couldn't happen if the bot was using numeric userlevels or single-character
|
are things that couldn't happen if the bot was using numeric
|
||||||
flags. First, whenever a user issues the bot a command, the command dispatcher
|
userlevels or single-character flags. First, whenever a user issues
|
||||||
checks to make sure the user doesn't have the "anticapability" for that
|
the bot a command, the command dispatcher checks to make sure the user
|
||||||
command. An anticapability is a capability that, instead of saying "what a
|
doesn't have the "anticapability" for that command. An anticapability
|
||||||
user can do", says what a user *cannot* do. It's formed rather simply by
|
is a capability that, instead of saying "what a user can do", says
|
||||||
adding a dash ("-") to the beginning of a capability; "rot13" is
|
what a user *cannot* do. It's formed rather simply by adding a dash
|
||||||
a capability, and "-rot13" is an anticapability. Anyway, when a user issues
|
("-") to the beginning of a capability; "rot13" is a capability, and
|
||||||
the bot a command, perhaps "calc" or "help", the bot first checks to make sure
|
"-rot13" is an anticapability. Anyway, when a user issues the bot a
|
||||||
the user doesn't have the "-calc" or the "-help" capabilities before even
|
command, perhaps "calc" or "help", the bot first checks to make sure
|
||||||
considering responding to the user. So commands can be turned on or off on a
|
the user doesn't have the "-calc" or the "-help" capabilities before
|
||||||
*per user* basis, offering finegrained control not often (if at all!) seen in
|
even considering responding to the user. So commands can be turned on
|
||||||
other bots.
|
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*
|
But that's not all! The capabilities system also supports *Channel*
|
||||||
capabilities, which are capabilities that only apply to a specific channel;
|
capabilities, which are capabilities that only apply to a specific
|
||||||
they're of the form "#channel.capability". Whenever a user issues a command to
|
channel; they're of the form "#channel,capability". Whenever a user
|
||||||
the bot in a channel, the command dispatcher also checks to make sure the user
|
issues a command to the bot in a channel, the command dispatcher also
|
||||||
doesn't have the anticapability for that command *in that channel*, and if the
|
checks to make sure the user doesn't have the anticapability for that
|
||||||
user does, the bot won't respond to the user in the channel. Thus now, in
|
command *in that channel*, and if the user does, the bot won't respond
|
||||||
addition to having the ability to turn individual commands on or off for an
|
to the user in the channel. Thus now, in addition to having the
|
||||||
individual user, we can now turn commands on or off for an individual user on
|
ability to turn individual commands on or off for an individual user,
|
||||||
an individual channel!
|
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
|
So when a user "foo" sends a command "bar" to the bot on channel
|
||||||
the bot checks to see if the user has the anticapability for the command by
|
"#baz", first the bot checks to see if the user has the anticapability
|
||||||
itself, "-bar". If so, it returns right then and there, compltely ignoring the
|
for the command by itself, "-bar". If so, it returns right then and
|
||||||
fact that the user issued that command to it. If the user doesn't have that
|
there, compltely ignoring the fact that the user issued that command
|
||||||
anticapability, then the bot checks to see if the user issued the command over
|
to it. If the user doesn't have that anticapability, then the bot
|
||||||
a channel, and if so, checks to see if the user has the antichannelcapability
|
checks to see if the user issued the command over a channel, and if
|
||||||
for that command, "#baz.-bar". If so, again, he returns right then and there
|
so, checks to see if the user has the antichannelcapability for that
|
||||||
and doesn't even think about responding to the bot. If neither of these
|
command, "#baz,-bar". If so, again, he returns right then and there
|
||||||
anticapabilities are present, then the bot just responds to the user like
|
and doesn't even think about responding to the bot. If neither of
|
||||||
normal.
|
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.
|
From a programmatical perspective, capabilties are easy to use and
|
||||||
Any command can check if a user has any capability, even ones not thought of
|
flexible. Any command can check if a user has any capability, even
|
||||||
when the bot was originally written. Commands/Callbacks can add their own
|
ones not thought of when the bot was originally written.
|
||||||
capabilities -- it's as easy as just checking for a capability and documenting
|
Commands/Callbacks can add their own capabilities -- it's as easy as
|
||||||
somewhere that a user needs that capability to do something.
|
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
|
From an end-user perspective, capabilities remove a lot of the mystery
|
||||||
esotery of bot control, in addition to giving the user absolutely finegrained
|
and esotery of bot control, in addition to giving the user absolutely
|
||||||
control over what users are allowed to do with the bot. Additionally, defaults
|
finegrained control over what users are allowed to do with the bot.
|
||||||
can be set by the end-user for both individual channels and for the bot as a
|
Additionally, defaults can be set by the end-user for both individual
|
||||||
whole, letting an end-user set the policy he wants the bot to follow for users
|
channels and for the bot as a whole, letting an end-user set the
|
||||||
that haven't yet registered in his user database.
|
policy he wants the bot to follow for users that haven't yet
|
||||||
It's really a revolution!
|
registered in his user database. It's really a revolution!
|
||||||
|
|
||||||
There are several default capabilities the bot uses. The most important of
|
There are several default capabilities the bot uses. The most
|
||||||
these is the "owner" capability. This capability allows the person having it
|
important of these is the "owner" capability. This capability allows
|
||||||
to use *any* command. It's best to keep this capability reserved to people
|
the person having it to use *any* command. It's best to keep this
|
||||||
who actually have access to the shell the bot is running on.
|
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
|
There is also the "admin" capability for non-owners that are highly
|
||||||
to administer the bot appropriately. They can do things such as change the
|
trusted to administer the bot appropriately. They can do things such
|
||||||
bot's nick, globally enable/disable commands, cause the bot to ignore a given
|
as change the bot's nick, globally enable/disable commands, cause the
|
||||||
user, set the prefixchar, report bugs, etc. They generally cannot do
|
bot to ignore a given user, set the prefixchar, report bugs, etc.
|
||||||
administration related to channels, which is reserved for people with the
|
They generally cannot do administration related to channels, which is
|
||||||
next capability.
|
reserved for people with the next capability.
|
||||||
|
|
||||||
People who are to administer channels with the bot should have the #channel.op
|
People who are to administer channels with the bot should have the
|
||||||
capability -- whatever channel they are to administrate, they should have that
|
#channel,op capability -- whatever channel they are to administrate,
|
||||||
channel capability for "op". For example, since I want inkedmn to be an
|
they should have that channel capability for "op". For example, since
|
||||||
administrator in #supybot, I'll give him the #supybot.op capability. This is
|
I want inkedmn to be an administrator in #supybot, I'll give him the
|
||||||
in addition to his admin capability, since the admin capability doesn't give
|
#supybot,op capability. This is in addition to his admin capability,
|
||||||
the person having it control over channels. #channel.op is used for such
|
since the admin capability doesn't give the person having it control
|
||||||
things as giving/receiving ops, kickbanning people, lobotomizing the bot,
|
over channels. #channel,op is used for such things as
|
||||||
ignoring users in the channel, and managing the channel capabilities. The
|
giving/receiving ops, kickbanning people, lobotomizing the bot,
|
||||||
#channel.op capability is also basically the equivalent of the owner capability
|
ignoring users in the channel, and managing the channel capabilities.
|
||||||
for capabilities involving #channel -- basically anyone with the #channel.op
|
The #channel,op capability is also basically the equivalent of the
|
||||||
capability is considered to have all positive capabilities and no negative
|
owner capability for capabilities involving #channel -- basically
|
||||||
capabilities for #channel.
|
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
|
One other globally important capability exists: "trusted". This is a
|
||||||
that basically says "This user can be trusted not to try and crash the bot."
|
command that basically says "This user can be trusted not to try and
|
||||||
It allows users to call commands like Math.icalc, which potentially could
|
crash the bot." It allows users to call commands like Math.icalc,
|
||||||
cause the bot to begin a calculation that could potentially never return (a
|
which potentially could cause the bot to begin a calculation that
|
||||||
calculation like 10**10**10**10). Another command that requires the trusted
|
could potentially never return (a calculation like 10**10**10**10).
|
||||||
capability is Utilties.re, which (due to the regular expression implementation
|
Another command that requires the trusted capability is Utilties.re,
|
||||||
in Python (and any other language that uses NFA regular expressions, like
|
which (due to the regular expression implementation in Python (and any
|
||||||
Perl or Ruby or Lua or ...) which can allow a regular expression to take
|
other language that uses NFA regular expressions, like Perl or Ruby or
|
||||||
exponential time to process). Consider what would happen if the someone gave
|
Lua or ...) which can allow a regular expression to take exponential
|
||||||
the bot the command 're [strjoin "" s/./ [dict go] /] [dict go]'
|
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
|
Other plugins may require different capabilities; the Factoids plugin
|
||||||
#channel.factoids, the Topic plugin requires #channel.topic, etc.
|
requires #channel,factoids, the Topic plugin requires #channel,topic,
|
||||||
|
etc.
|
||||||
|
|
|
@ -40,8 +40,8 @@ our example.
|
||||||
Using the Config plugin, you can list the values in a subgroup and get
|
Using the Config plugin, you can list the values in a subgroup and get
|
||||||
or set any of the values anywhere in the configuration hierarchy. For
|
or set any of the values anywhere in the configuration hierarchy. For
|
||||||
example, let's say you wanted to see what configuration values were
|
example, let's say you wanted to see what configuration values were
|
||||||
under the "supybot" (the base group) hierarchy. You would simply issue
|
under the "supybot" (the base group) hierarchy. You would simply
|
||||||
this command:
|
issue this command:
|
||||||
|
|
||||||
<jemfinch|lambda> @config list supybot
|
<jemfinch|lambda> @config list supybot
|
||||||
<supybot> jemfinch|lambda: nick, ident, user, server,
|
<supybot> jemfinch|lambda: nick, ident, user, server,
|
||||||
|
@ -80,25 +80,25 @@ modifying the configuration values. It's important to know that when
|
||||||
you provide the group argument to config list that you must always
|
you provide the group argument to config list that you must always
|
||||||
provide the full name of the group. For example, "config list
|
provide the full name of the group. For example, "config list
|
||||||
commands" would be incorrect, even though we see "commands" in the
|
commands" would be incorrect, even though we see "commands" in the
|
||||||
listing above. Remember, we just shorten the names by the group
|
listing above. Remember, we just shorten the names by the group we're
|
||||||
we're listing so we can fit more such names in a single message. In
|
listing so we can fit more such names in a single message. In this
|
||||||
this case, that would be "supybot", so to list everything in
|
case, that would be "supybot", so to list everything in the commands
|
||||||
the commands subgroup of supybot, we do:
|
subgroup of supybot, we do:
|
||||||
|
|
||||||
<jemfinch|lambda> @config list supybot.commands
|
<jemfinch|lambda> @config list supybot.commands
|
||||||
<supybot> jemfinch|lambda: defaultPlugins
|
<supybot> jemfinch|lambda: defaultPlugins
|
||||||
|
|
||||||
Okay, now that you've used the Config plugin to list configuration
|
Okay, now that you've used the Config plugin to list configuration
|
||||||
variables, it's time that we start looking at individual variables
|
variables, it's time that we start looking at individual variables and
|
||||||
and their values.
|
their values.
|
||||||
|
|
||||||
The first (and perhaps most important) thing you should know about
|
The first (and perhaps most important) thing you should know about
|
||||||
each configuration variable is that they all have an associated help
|
each configuration variable is that they all have an associated help
|
||||||
string to tell you what they represent. So the first command we'll
|
string to tell you what they represent. So the first command we'll
|
||||||
cover is "config help". To see the help string for any value or
|
cover is "config help". To see the help string for any value or
|
||||||
group, simply use the "config help" command. For example, to see
|
group, simply use the "config help" command. For example, to see what
|
||||||
what this "supybot.prefixChars" configuration variable is all about,
|
this "supybot.prefixChars" configuration variable is all about, we'd
|
||||||
we'd do this:
|
do this:
|
||||||
|
|
||||||
<jemfinch|lambda> @config help supybot.prefixChars
|
<jemfinch|lambda> @config help supybot.prefixChars
|
||||||
<supybot> jemfinch|lambda: Determines what prefix
|
<supybot> jemfinch|lambda: Determines what prefix
|
||||||
|
@ -126,12 +126,11 @@ Now, check this out:
|
||||||
<jemfinch|lambda> $config supybot.prefixChars
|
<jemfinch|lambda> $config supybot.prefixChars
|
||||||
<supybot> jemfinch|lambda: '@$'
|
<supybot> jemfinch|lambda: '@$'
|
||||||
|
|
||||||
Note that we used $ as our prefix character, and that the value of
|
Note that we used $ as our prefix character, and that the value of the
|
||||||
the configuration variable changed. If I were to use the "flush"
|
configuration variable changed. If I were to use the "flush" command
|
||||||
command now, this change would be flushed to the registry file on
|
now, this change would be flushed to the registry file on disk (this
|
||||||
disk (this would also happen if I made the bot quit, or pressed
|
would also happen if I made the bot quit, or pressed Ctrl-C in the
|
||||||
Ctrl-C in the terminal the bot was running in). Instead, I'll
|
terminal the bot was running in). Instead, I'll revert the change:
|
||||||
revert the change:
|
|
||||||
|
|
||||||
<jemfinch|lambda> $config supybot.prefixChars @
|
<jemfinch|lambda> $config supybot.prefixChars @
|
||||||
<supybot> jemfinch|lambda: The operation succeeded.
|
<supybot> jemfinch|lambda: The operation succeeded.
|
||||||
|
@ -153,9 +152,9 @@ simply say:
|
||||||
|
|
||||||
Simple, eh?
|
Simple, eh?
|
||||||
|
|
||||||
Now, let's say you want to find all configuration variables that
|
Now, let's say you want to find all configuration variables that might
|
||||||
might be even remotely related to opping. For that, you'll want the
|
be even remotely related to opping. For that, you'll want the "config
|
||||||
"config search" command. Check this out:
|
search" command. Check this out:
|
||||||
|
|
||||||
<jemfinch|lambda> @config search op
|
<jemfinch|lambda> @config search op
|
||||||
<supybot> jemfinch|lambda:
|
<supybot> jemfinch|lambda:
|
||||||
|
@ -174,16 +173,16 @@ there's no way for the bot to know what configuration variables it
|
||||||
registers.
|
registers.
|
||||||
|
|
||||||
Some people might like editing their registry file directly rather
|
Some people might like editing their registry file directly rather
|
||||||
than manipulating all these things through the bot. For those
|
than manipulating all these things through the bot. For those people,
|
||||||
people, we offer the "config reload" command, which reloads both
|
we offer the "config reload" command, which reloads both registry
|
||||||
registry configuration and user/channel/ignore database
|
configuration and user/channel/ignore database configuration. Just
|
||||||
configuration. Just edit the interesting files and then give the bot
|
edit the interesting files and then give the bot the "config reload"
|
||||||
the "config reload" command and it'll work as expected. Do note,
|
command and it'll work as expected. Do note, however, that Supybot
|
||||||
however, that Supybot flushes his configuration files and databases
|
flushes his configuration files and databases to disk every hour or
|
||||||
to disk every hour or so, and if this happens after you've edited
|
so, and if this happens after you've edited your configuration files
|
||||||
your configuration files but before you reload your changes, you
|
but before you reload your changes, you could lose the changes you
|
||||||
could lose the changes you made. To prevent this, set the
|
made. To prevent this, set the supybot.flush value to Off, and no
|
||||||
supybot.flush value to Off, and no automatic flushing will occur.
|
automatic flushing will occur.
|
||||||
|
|
||||||
Anyway, that's about it for configuration. Have fun, and enjoy your
|
Anyway, that's about it for configuration. Have fun, and enjoy your
|
||||||
configurable bot!
|
configurable bot!
|
||||||
|
|
33
docs/EXAMPLE
33
docs/EXAMPLE
|
@ -111,10 +111,10 @@ You'll probably want to change the copyright notice to be your name.
|
||||||
It wouldn't stick even if you kept my name, so you might as well :)
|
It wouldn't stick even if you kept my name, so you might as well :)
|
||||||
|
|
||||||
Describe what you want the plugin to do in the docstring. This is
|
Describe what you want the plugin to do in the docstring. This is
|
||||||
used in supybot-wizard in order to explain to the user the purpose
|
used in supybot-wizard in order to explain to the user the purpose of
|
||||||
of the module. It's also returned when someone asks the bot for help
|
the module. It's also returned when someone asks the bot for help for
|
||||||
for a given module (instead of help for a certain command). We'll
|
a given module (instead of help for a certain command). We'll change
|
||||||
change this one to "Lots of stuff relating to random numbers."
|
this one to "Lots of stuff relating to random numbers."
|
||||||
|
|
||||||
Then there are the imports. The callbacks module is used (the class
|
Then there are the imports. The callbacks module is used (the class
|
||||||
you're given subclasses callbacks.Privmsg) but the privmsgs module
|
you're given subclasses callbacks.Privmsg) but the privmsgs module
|
||||||
|
@ -176,8 +176,8 @@ And we save two lines of code and make our code a little more clear :)
|
||||||
Now that we have an RNG, we need some way to get random numbers. So
|
Now that we have an RNG, we need some way to get random numbers. So
|
||||||
first, we'll add a command that simply gets the next random number and
|
first, we'll add a command that simply gets the next random number and
|
||||||
gives it back to the user. It takes no arguments, of course (what
|
gives it back to the user. It takes no arguments, of course (what
|
||||||
would you give it?). Here's the command, and I'll follow that with the
|
would you give it?). Here's the command, and I'll follow that with
|
||||||
explanation of what each part means.
|
the explanation of what each part means.
|
||||||
|
|
||||||
def random(self, irc, msg, args):
|
def random(self, irc, msg, args):
|
||||||
"""takes no arguments
|
"""takes no arguments
|
||||||
|
@ -342,9 +342,9 @@ checking for missing arguments and whatnot so we don't have to.
|
||||||
The Random object we're using offers us a "sample" method that takes a
|
The Random object we're using offers us a "sample" method that takes a
|
||||||
sequence and a number (we'll call it N) and returns a list of N items
|
sequence and a number (we'll call it N) and returns a list of N items
|
||||||
taken randomly from the sequence. So I'll show you an example that
|
taken randomly from the sequence. So I'll show you an example that
|
||||||
takes advantage of multiple arguments but doesn't use
|
takes advantage of multiple arguments but doesn't use privmsgs.getArgs
|
||||||
privmsgs.getArgs (and thus has to handle its own errors if the number
|
(and thus has to handle its own errors if the number of arguments
|
||||||
of arguments isn't right). Here's the code:
|
isn't right). Here's the code:
|
||||||
|
|
||||||
def sample(self, irc, msg, args):
|
def sample(self, irc, msg, args):
|
||||||
"""<number of items> [<text> ...]
|
"""<number of items> [<text> ...]
|
||||||
|
@ -373,12 +373,11 @@ than through getArgs. Since we already have the arguments in a list,
|
||||||
it doesn't make any sense to have privmsgs.getArgs smush them all
|
it doesn't make any sense to have privmsgs.getArgs smush them all
|
||||||
together into a big long string that we'll just have to re-split. But
|
together into a big long string that we'll just have to re-split. But
|
||||||
we still want the nice error handling of privmsgs.getArgs. So what do
|
we still want the nice error handling of privmsgs.getArgs. So what do
|
||||||
we do? We raise callbacks.ArgumentError! That's the secret juju
|
we do? We raise callbacks.ArgumentError! That's the secret juju that
|
||||||
that privmsgs.getArgs is doing; now we're just doing it ourself.
|
privmsgs.getArgs is doing; now we're just doing it ourself. Someone
|
||||||
Someone up our callchain knows how to handle it so a neat error
|
up our callchain knows how to handle it so a neat error message is
|
||||||
message is returned. So in this function, if .pop(0) fails, we
|
returned. So in this function, if .pop(0) fails, we weren't given
|
||||||
weren't given enough arguments and thus need to tell the user how to
|
enough arguments and thus need to tell the user how to call us.
|
||||||
call us.
|
|
||||||
|
|
||||||
So we have the args, we have the number, we do a simple call to
|
So we have the args, we have the number, we do a simple call to
|
||||||
random.sample and then we do this funky utils.commaAndify to it.
|
random.sample and then we do this funky utils.commaAndify to it.
|
||||||
|
@ -417,8 +416,8 @@ important, though, is the first thing you'll notice that's different:
|
||||||
the privmsg.getArgs call. Here we're offering a default argument in
|
the privmsg.getArgs call. Here we're offering a default argument in
|
||||||
case the user is too lazy to supply one (or just wants a nice,
|
case the user is too lazy to supply one (or just wants a nice,
|
||||||
standard six-sided die :)) privmsgs.getArgs supports that; we'll just
|
standard six-sided die :)) privmsgs.getArgs supports that; we'll just
|
||||||
tell it that we don't *need* any arguments (via required=0) and that we
|
tell it that we don't *need* any arguments (via required=0) and that
|
||||||
*might like* one argument (optional=1). If the user provides an
|
we *might like* one argument (optional=1). If the user provides an
|
||||||
argument, we'll get it -- if they don't, we'll just get an empty
|
argument, we'll get it -- if they don't, we'll just get an empty
|
||||||
string. Hence the "if not n: n = 6", where we provide the default.
|
string. Hence the "if not n: n = 6", where we provide the default.
|
||||||
|
|
||||||
|
|
67
docs/FAQ
67
docs/FAQ
|
@ -4,13 +4,12 @@ Q: Why does my bot not recognize me or tell me that I don't have the
|
||||||
A: Because you're not given it anything to recognize you from!
|
A: Because you're not given it anything to recognize you from!
|
||||||
You'll need to identify with the bot ("help identify" to see how
|
You'll need to identify with the bot ("help identify" to see how
|
||||||
that works) or add your hostmask to your user record ("help
|
that works) or add your hostmask to your user record ("help
|
||||||
addhostmask" to see how that works) for it to know that you're
|
addhostmask" to see how that works) for it to know that you're you.
|
||||||
you. You may wish to note that addhostmask can accept a password;
|
You may wish to note that addhostmask can accept a password; rather
|
||||||
rather than identify, you can send the command "addhostmask
|
than identify, you can send the command "addhostmask myOwnerUser
|
||||||
myOwnerUser [hostmask] myOwnerUserPassword" and the bot will add
|
[hostmask] myOwnerUserPassword" and the bot will add your current
|
||||||
your current hostmask to your owner user (of course, you should
|
hostmask to your owner user (of course, you should change
|
||||||
change myOwnerUser and myOwnerUserPassword appropriately for your
|
myOwnerUser and myOwnerUserPassword appropriately for your bot).
|
||||||
bot).
|
|
||||||
|
|
||||||
|
|
||||||
Q: How do I make my Supybot op my users?
|
Q: How do I make my Supybot op my users?
|
||||||
|
@ -21,10 +20,10 @@ A: First, you'll have to make sure that your users register with the
|
||||||
Use the "channel addcapability" command to do this. After that,
|
Use the "channel addcapability" command to do this. After that,
|
||||||
your users should be able to use the "op" command to get ops.
|
your users should be able to use the "op" command to get ops.
|
||||||
|
|
||||||
If you want your users to be auto-opped when they join the
|
If you want your users to be auto-opped when they join the channel,
|
||||||
channel, you'll need to load the Enforcer plugin and turn its
|
you'll need to load the Enforcer plugin and turn its autoOp
|
||||||
autoOp configuration variable on. Use the "config" command to do
|
configuration variable on. Use the "config" command to do so.
|
||||||
so. Here's an example of how to do these steps:
|
Here's an example of how to do these steps:
|
||||||
|
|
||||||
<jemfinch|lambda> I'm going to make an example session for giving
|
<jemfinch|lambda> I'm going to make an example session for giving
|
||||||
you auto-ops, for our FAQ.
|
you auto-ops, for our FAQ.
|
||||||
|
@ -60,12 +59,11 @@ Q: Can users with the "admin" capability change configuration
|
||||||
|
|
||||||
A: Currently, no. Since this is the first release of Supybot that
|
A: Currently, no. Since this is the first release of Supybot that
|
||||||
uses the registry, we wanted to stay on the conservative side and
|
uses the registry, we wanted to stay on the conservative side and
|
||||||
require the "owner" capability for changing all
|
require the "owner" capability for changing all non-channel-related
|
||||||
non-channel-related configuration variables. Feel free to make
|
configuration variables. Feel free to make your case to us as to
|
||||||
your case to us as to why a certain configuration variable should
|
why a certain configuration variable should only require the
|
||||||
only require the "admin" capability instead of the "owner"
|
"admin" capability instead of the "owner" capability, and if we
|
||||||
capability, and if we agree with you, we'll change it for the next
|
agree with you, we'll change it for the next release.
|
||||||
release.
|
|
||||||
|
|
||||||
|
|
||||||
Q: How do I make my Supybot connect to multiple servers?
|
Q: How do I make my Supybot connect to multiple servers?
|
||||||
|
@ -75,10 +73,10 @@ A: You'll need to use the Relay plugin. As long as you don't call
|
||||||
channels (even if the bot is on the same channel on different
|
channels (even if the bot is on the same channel on different
|
||||||
networks). In order to use the Relay plugin, you'll want to first
|
networks). In order to use the Relay plugin, you'll want to first
|
||||||
call the "relay start" command, followed by the "relay connect"
|
call the "relay start" command, followed by the "relay connect"
|
||||||
command. These commands are (unfortunately) not persistent at
|
command. These commands are (unfortunately) not persistent at this
|
||||||
this time, so you'll need to give them to the bot anytime you
|
time, so you'll need to give them to the bot anytime you start it
|
||||||
start it up. We'll probably have this lack of persistence
|
up. We'll probably have this lack of persistence rectified before
|
||||||
rectified before the next release.
|
the next release.
|
||||||
|
|
||||||
|
|
||||||
Q: Can Supybot do factoids?
|
Q: Can Supybot do factoids?
|
||||||
|
@ -89,10 +87,10 @@ A: Supybot most certainly can! In fact, we offer two full-fledged
|
||||||
Factoids (written by jemfinch) is Supybot's original
|
Factoids (written by jemfinch) is Supybot's original
|
||||||
factoids-related plugin. It offers full integration with Supybot's
|
factoids-related plugin. It offers full integration with Supybot's
|
||||||
nested commands as well as a complete 1:n key to factoid ratio,
|
nested commands as well as a complete 1:n key to factoid ratio,
|
||||||
with lookup by individual number. Factoids also uses
|
with lookup by individual number. Factoids also uses a
|
||||||
a channel-specific database instead of a global database, although
|
channel-specific database instead of a global database, although in
|
||||||
in the future it will likely be a configuration option whether to
|
the future it will likely be a configuration option whether to use
|
||||||
use channel-specific or global databases for such plugins.
|
channel-specific or global databases for such plugins.
|
||||||
|
|
||||||
MoobotFactoids (written by Strike) is much more full-featured,
|
MoobotFactoids (written by Strike) is much more full-featured,
|
||||||
offering users the ability to define factoids in a slightly more
|
offering users the ability to define factoids in a slightly more
|
||||||
|
@ -103,11 +101,10 @@ A: Supybot most certainly can! In fact, we offer two full-fledged
|
||||||
beginning)). If you're accustomed to Moobot's factoids or
|
beginning)). If you're accustomed to Moobot's factoids or
|
||||||
Blootbot's factoids, then this is the Factoids plugin for you.
|
Blootbot's factoids, then this is the Factoids plugin for you.
|
||||||
Unfortunately, due to the more natural definition syntax (required
|
Unfortunately, due to the more natural definition syntax (required
|
||||||
to be compatible with Moobot) you can't define Factoids with
|
to be compatible with Moobot) you can't define Factoids with nested
|
||||||
nested commands; you'll have to evaluate the command first and
|
commands; you'll have to evaluate the command first and then copy
|
||||||
then copy the result into your factoid definition. MoobotFactoids
|
the result into your factoid definition. MoobotFactoids uses a
|
||||||
uses a global database, so the factoids are the same for all
|
global database, so the factoids are the same for all channels.
|
||||||
channels.
|
|
||||||
|
|
||||||
In the future, we plan to have a compatibility plugin for Infobot,
|
In the future, we plan to have a compatibility plugin for Infobot,
|
||||||
but as of present we've not yet written one.
|
but as of present we've not yet written one.
|
||||||
|
@ -119,9 +116,9 @@ A: As of present, we have no automated way to do so. Strike has
|
||||||
written a few scripts for importing a Moobot database into
|
written a few scripts for importing a Moobot database into
|
||||||
MoobotFactoids, however, so you'll want to talk to him about
|
MoobotFactoids, however, so you'll want to talk to him about
|
||||||
helping you with that. We're certainly happy to help you convert
|
helping you with that. We're certainly happy to help you convert
|
||||||
such databases; if you can provide us with such a database
|
such databases; if you can provide us with such a database exported
|
||||||
exported to a flat file, we can probably do the rest of the work
|
to a flat file, we can probably do the rest of the work to write a
|
||||||
to write a script that imports it into a database for one of our
|
script that imports it into a database for one of our
|
||||||
factoids-related plugins.
|
factoids-related plugins.
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,8 +139,8 @@ A: Submit it on Sourceforge through our Sourceforge project page:
|
||||||
log entry). We'd also like to see the commands that caused the
|
log entry). We'd also like to see the commands that caused the
|
||||||
bug, or happened around the time you saw the bug. If the bug
|
bug, or happened around the time you saw the bug. If the bug
|
||||||
involved a database, we'd love to see the database. Remember, it's
|
involved a database, we'd love to see the database. Remember, it's
|
||||||
always worse to send us too much information in a bug report than
|
always worse to send us too little information in a bug report than
|
||||||
too little.
|
too much.
|
||||||
|
|
||||||
|
|
||||||
Q: Karma doesn't seem to work for me.
|
Q: Karma doesn't seem to work for me.
|
||||||
|
|
|
@ -28,15 +28,15 @@ like being asked many questions, just run supybot with no arguments
|
||||||
and it'll ask you only the questions necessary to run a bot.
|
and it'll ask you only the questions necessary to run a bot.
|
||||||
|
|
||||||
So after running either of those two programs, you've got a nice
|
So after running either of those two programs, you've got a nice
|
||||||
registry file handy. If you're not satisfied with your answers to
|
registry file handy. If you're not satisfied with your answers to any
|
||||||
any of the questions you were asked, feel free to run the program
|
of the questions you were asked, feel free to run the program again
|
||||||
again until you're satisfied with all your answers. Once you're
|
until you're satisfied with all your answers. Once you're satisfied,
|
||||||
satisfied, though, run the "supybot" program with the registry file
|
though, run the "supybot" program with the registry file you created
|
||||||
you created as an argument. This will start the bot; unless you
|
as an argument. This will start the bot; unless you turned off
|
||||||
turned off logging to stdout, you'll see some nice log messages
|
logging to stdout, you'll see some nice log messages describing what
|
||||||
describing what the bot is doing at any particular moment; it may
|
the bot is doing at any particular moment; it may pause for a
|
||||||
pause for a significant amount of time after saying "Connecting
|
significant amount of time after saying "Connecting to ..." while the
|
||||||
to ..." while the server tries to check its ident.
|
server tries to check its ident.
|
||||||
|
|
||||||
Ok, so let's assume your bot connected to the server fine and joined
|
Ok, so let's assume your bot connected to the server fine and joined
|
||||||
the channels you told it to join. For now we'll assume you named your
|
the channels you told it to join. For now we'll assume you named your
|
||||||
|
@ -60,16 +60,14 @@ supybot: list Misc
|
||||||
Will list all the commands in the Misc plugin. If you want to see the
|
Will list all the commands in the Misc plugin. If you want to see the
|
||||||
help for any command, just use the help command:
|
help for any command, just use the help command:
|
||||||
|
|
||||||
supybot: help help
|
supybot: help help supybot: help list supybot: help load
|
||||||
supybot: help list
|
|
||||||
supybot: help load
|
|
||||||
|
|
||||||
Sometimes more than one plugin will have a given command; for
|
Sometimes more than one plugin will have a given command; for
|
||||||
instance, the "list" command exists in both the Misc and Config
|
instance, the "list" command exists in both the Misc and Config
|
||||||
plugins (both loaded by default). List, in this case, defaults to
|
plugins (both loaded by default). List, in this case, defaults to the
|
||||||
the Misc plugin, but you may want to get the help for the list
|
Misc plugin, but you may want to get the help for the list command in
|
||||||
command in the Config plugin. In that case, you'll want to give your
|
the Config plugin. In that case, you'll want to give your command
|
||||||
command like this:
|
like this:
|
||||||
|
|
||||||
supybot: help config list
|
supybot: help config list
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
So here's a general *programming* introduction to what the different modules do
|
So here's a general *programming* introduction to what the different
|
||||||
and what services they provide. It is, however, only an introduction. Read
|
modules do and what services they provide. It is, however, only an
|
||||||
the modules themselves for a much more detailed explanation :)
|
introduction. Read the modules themselves for a much more detailed
|
||||||
|
explanation :)
|
||||||
|
|
||||||
fix.py: Stuff that Python should (but doesn't) include by default.
|
fix.py: Stuff that Python should (but doesn't) include by default.
|
||||||
|
|
||||||
cdb.py: A constant database library, translated from C (and my O'Caml version)
|
cdb.py: A constant database library, translated from C (and my O'Caml
|
||||||
More information available at http://cr.yp.to/cdb.html. Not
|
version) More information available at
|
||||||
currently used since we switched to PySQLite.
|
http://cr.yp.to/cdb.html. Not currently used since we
|
||||||
|
switched to PySQLite.
|
||||||
|
|
||||||
ansi.py: Contains different ANSI color sequences.
|
ansi.py: Contains different ANSI color sequences.
|
||||||
Mostly used by the debug module.
|
Mostly used by the debug module.
|
||||||
|
|
||||||
debug.py: Functions for handling bugs and errors in a consistent manner
|
conf.py: The configuration file for the bot -- it sets a lot of
|
||||||
throughout the bot.
|
variables that other modules check for when they have
|
||||||
|
questions about what they need to do.
|
||||||
|
|
||||||
conf.py: The configuration file for the bot -- it sets a lot of variables that
|
world.py: Just a dropping off place for some globals that need to be
|
||||||
other modules check for when they have questions about what they need
|
shared among all the modules. It's obviously not used *a
|
||||||
to do.
|
lot*, but some things seem to fit better here than anywhere
|
||||||
|
else.
|
||||||
world.py: Just a dropping off place for some globals that need to be shared
|
|
||||||
among all the modules. It's obviously not used *a lot*, but some
|
|
||||||
things seem to fit better here than anywhere else.
|
|
||||||
|
|
||||||
template.py: A template used by setup.py to create customized runnable
|
template.py: A template used by setup.py to create customized runnable
|
||||||
Python scripts for individual bots.
|
Python scripts for individual bots.
|
||||||
|
@ -28,21 +28,22 @@ template.py: A template used by setup.py to create customized runnable
|
||||||
privmsgs.py: Basic stuff relating to callbacks.Privmsg, the base class
|
privmsgs.py: Basic stuff relating to callbacks.Privmsg, the base class
|
||||||
for most plugins.
|
for most plugins.
|
||||||
|
|
||||||
callbacks.py: A few basic callbacks providing significant functionality.
|
callbacks.py: A few basic callbacks providing significant
|
||||||
You'll likely be inheriting from Privmsg quite a bit.
|
functionality. You'll likely be inheriting from Privmsg
|
||||||
|
quite a bit.
|
||||||
|
|
||||||
ircdb.py: The users and channels databases are here, as well as the
|
ircdb.py: The users and channels databases are here, as well as the
|
||||||
IrcUser and IrcChannel classes. Look here when you want to
|
IrcUser and IrcChannel classes. Look here when you want to
|
||||||
restrict a command to only certain users.
|
restrict a command to only certain users.
|
||||||
|
|
||||||
irclib.py: Provides the most important class in the irclib, Irc. It represents
|
irclib.py: Provides the most important class in the irclib, Irc. It
|
||||||
a connection to an IRC server, but it's entirely separate from the
|
represents a connection to an IRC server, but it's entirely
|
||||||
network implementation. It's connected to the network (or whatever
|
separate from the network implementation. It's connected
|
||||||
else drives it) by a "driver" module which uses its feedMsg/takeMsg
|
to the network (or whatever else drives it) by a "driver"
|
||||||
functions.
|
module which uses its feedMsg/takeMsg functions.
|
||||||
|
|
||||||
drivers.py: The baseclass (IrcDriver) for various drivers to drive irclib.Irc
|
drivers.py: The baseclass (IrcDriver) for various drivers to drive
|
||||||
classes. Also, the driving mechanism.
|
irclib.Irc classes. Also, the driving mechanism.
|
||||||
|
|
||||||
asyncoreDrivers.py: The asyncore-based drivers for use with the bot.
|
asyncoreDrivers.py: The asyncore-based drivers for use with the bot.
|
||||||
|
|
||||||
|
@ -52,12 +53,12 @@ socketDrivers.py: The plain old socket-based drivers for use with the
|
||||||
twistedDrivers.py: The Twisted <http://www.twistedmatrix.com/> drivers
|
twistedDrivers.py: The Twisted <http://www.twistedmatrix.com/> drivers
|
||||||
for use with the bot.
|
for use with the bot.
|
||||||
|
|
||||||
ircmsgs.py: The IrcMsg class (get to know it :)) and various functions for
|
ircmsgs.py: The IrcMsg class (get to know it :)) and various functions
|
||||||
making the creation of IrcMsgs easier.
|
for making the creation of IrcMsgs easier.
|
||||||
|
|
||||||
ircutils.py: Various utility functions for Irc -- read the module to see what
|
ircutils.py: Various utility functions for Irc -- read the module to
|
||||||
goodies are there :)
|
see what goodies are there :)
|
||||||
|
|
||||||
schedule.py: A schedule driver (which is automatically registered with the
|
schedule.py: A schedule driver (which is automatically registered with
|
||||||
drivers module) to run things at a particular time, or at
|
the drivers module) to run things at a particular time,
|
||||||
specified periods of time.
|
or at specified periods of time.
|
||||||
|
|
70
docs/STYLE
70
docs/STYLE
|
@ -1,5 +1,5 @@
|
||||||
Read PEP 8 (Guido's Style Guide) and know that we use almost all the same style
|
Read PEP 8 (Guido's Style Guide) and know that we use almost all the
|
||||||
guidelines.
|
same style guidelines.
|
||||||
|
|
||||||
Maximum line length is 79 characters. 78 is a safer bet, though.
|
Maximum line length is 79 characters. 78 is a safer bet, though.
|
||||||
|
|
||||||
|
@ -10,29 +10,31 @@ They're just easier to type.
|
||||||
|
|
||||||
Triple double quotes (""") are always used for docstrings.
|
Triple double quotes (""") are always used for docstrings.
|
||||||
|
|
||||||
Spaces go around all operators (except around '=' in default arguments to
|
Spaces go around all operators (except around '=' in default arguments
|
||||||
functions) and after all commas (unless doing so keeps a line within the 79
|
to functions) and after all commas (unless doing so keeps a line
|
||||||
character limit).
|
within the 79 character limit).
|
||||||
|
|
||||||
Class names are StudlyCaps. Method and function names are camelCaps
|
Class names are StudlyCaps. Method and function names are camelCaps
|
||||||
(StudlyCaps with an initial lowercase letter). If variable and attribute
|
(StudlyCaps with an initial lowercase letter). If variable and
|
||||||
names can maintain readability without being camelCaps, then they should be
|
attribute names can maintain readability without being camelCaps, then
|
||||||
entirely in lowercase, otherwise they should also use camelCaps. Plugin names
|
they should be entirely in lowercase, otherwise they should also use
|
||||||
are StudlyCaps.
|
camelCaps. Plugin names are StudlyCaps.
|
||||||
|
|
||||||
Imports should always happen at the top of the module, one import per line
|
Imports should always happen at the top of the module, one import per
|
||||||
(so if imports need to be added or removed later, it can be done easily).
|
line (so if imports need to be added or removed later, it can be done
|
||||||
|
easily).
|
||||||
|
|
||||||
A blank line should be between all consecutive method declarations in a
|
A blank line should be between all consecutive method declarations in
|
||||||
class definition. Two blank lines should be between all consecutive class
|
a class definition. Two blank lines should be between all consecutive
|
||||||
definitions in a file. Comments are even better than blank lines for
|
class definitions in a file. Comments are even better than blank
|
||||||
separating classes.
|
lines for separating classes.
|
||||||
|
|
||||||
Database filenames should generally begin with the name of the plugin and the
|
Database filenames should generally begin with the name of the plugin
|
||||||
extension should be 'db'. baseplugin.DBHandler does this already.
|
and the extension should be 'db'. baseplugin.DBHandler does this
|
||||||
|
already.
|
||||||
|
|
||||||
Whenever creating a file descriptor or socket, keep a reference around and be
|
Whenever creating a file descriptor or socket, keep a reference around
|
||||||
sure to close it. There should be no code like this:
|
and be sure to close it. There should be no code like this:
|
||||||
s = urllib2.urlopen('url').read()
|
s = urllib2.urlopen('url').read()
|
||||||
Instead, do this:
|
Instead, do this:
|
||||||
fd = urllib2.urlopen('url')
|
fd = urllib2.urlopen('url')
|
||||||
|
@ -44,31 +46,33 @@ All plugins should include a docstring decsribing what the plugin
|
||||||
does. This docstring will be returned when the user wants help on a
|
does. This docstring will be returned when the user wants help on a
|
||||||
plugin.
|
plugin.
|
||||||
|
|
||||||
Method docstrings in classes deriving from callbacks.Privmsg should include an
|
Method docstrings in classes deriving from callbacks.Privmsg should
|
||||||
argument list as their first line, and after that a blank line followed by
|
include an argument list as their first line, and after that a blank
|
||||||
a longer description of what the command does. The argument list is used by
|
line followed by a longer description of what the command does. The
|
||||||
the 'syntax' command, and the longer description is used by the 'help' command.
|
argument list is used by the 'syntax' command, and the longer
|
||||||
|
description is used by the 'help' command.
|
||||||
|
|
||||||
Whenever joining more than two strings, use string interpolation, not addition:
|
Whenever joining more than two strings, use string interpolation, not
|
||||||
|
addition:
|
||||||
s = x + y + z # Bad.
|
s = x + y + z # Bad.
|
||||||
s = '%s%s%s' % (x, y, z) # Good.
|
s = '%s%s%s' % (x, y, z) # Good.
|
||||||
s = ''.join([x, y, z]) # Best, but not as general.
|
s = ''.join([x, y, z]) # Best, but not as general.
|
||||||
This has to do with efficiency; the intermediate string x+y is made (and thus
|
This has to do with efficiency; the intermediate string x+y is made
|
||||||
copied) before x+y+z is made, so it's less efficient.
|
(and thus copied) before x+y+z is made, so it's less efficient.
|
||||||
|
|
||||||
When writing strings that have formatting characters in them, don't
|
When writing strings that have formatting characters in them, don't
|
||||||
use anything but %s unless you absolutely must. In particular, %d
|
use anything but %s unless you absolutely must. In particular, %d
|
||||||
should never be used, it's less general than %s and serves no useful
|
should never be used, it's less general than %s and serves no useful
|
||||||
purpose.
|
purpose.
|
||||||
|
|
||||||
Use the debug module to its fullest; when you need to print some values to
|
Use the log module to its fullest; when you need to print some values
|
||||||
debug, use debug.printf to do so, and leave those print statements in the code
|
to debug, use self.log.debug to do so, and leave those print
|
||||||
(commented out) so they can later be re-enabled. Remember that once
|
statements in the code (commented out) so they can later be
|
||||||
code is buggy, it tends to have more bugs, and you'll probably need those print
|
re-enabled. Remember that once code is buggy, it tends to have more
|
||||||
statements again.
|
bugs, and you'll probably need those print statements again.
|
||||||
|
|
||||||
SQL table names should be all-lowercase and include underscores to separate
|
SQL table names should be all-lowercase and include underscores to
|
||||||
words. This is because SQL itself is case-insensitive.
|
separate words. This is because SQL itself is case-insensitive.
|
||||||
|
|
||||||
SQL statements in code should put SQL words in ALL CAPS:
|
SQL statements in code should put SQL words in ALL CAPS:
|
||||||
SELECT quote FROM quotes ORDER BY random() LIMIT 1
|
SELECT quote FROM quotes ORDER BY random() LIMIT 1
|
||||||
|
|
Loading…
Reference in New Issue