mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-02-18 14:40:51 +01:00
The "DocBook is fun" commit. We now have a whole new DTD and stylesheets to
use, as well as all the docs being in SGML now.
This commit is contained in:
parent
8ea62d2503
commit
151b2f829b
@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
<!DOCTYPE article SYSTEM "supybot.dtd">
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
<articleinfo>
|
<articleinfo>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
<revision>
|
<revision>
|
||||||
<revnumber>0.1</revnumber>
|
<revnumber>0.1</revnumber>
|
||||||
<date>18 Feb 2004</date>
|
<date>18 Feb 2004</date>
|
||||||
<revremark>Initial revision</revremark>
|
<revremark>Initial Docbook translation</revremark>
|
||||||
</revision>
|
</revision>
|
||||||
</revhistory>
|
</revhistory>
|
||||||
</articleinfo>
|
</articleinfo>
|
||||||
@ -48,7 +48,7 @@
|
|||||||
the bot a command. Commands, rather than checking for a user
|
the bot a command. Commands, rather than checking for a user
|
||||||
level of 100, or checking if the user has an <varname>o</varname>
|
level of 100, or checking if the user has an <varname>o</varname>
|
||||||
flag, are instead able to check if a user has the
|
flag, are instead able to check if a user has the
|
||||||
<varname>owner</varname> capability. At this point such a
|
<capability>owner</capability> capability. At this point such a
|
||||||
difference might not seem revolutionary, but at least we can
|
difference might not seem revolutionary, but at least we can
|
||||||
already tell that this method is self-documenting, and easier for
|
already tell that this method is self-documenting, and easier for
|
||||||
users and developers to understand what's truly going on.
|
users and developers to understand what's truly going on.
|
||||||
@ -68,49 +68,49 @@
|
|||||||
“anticapability” for that command. An anticapability is
|
“anticapability” for that command. An anticapability is
|
||||||
a capability that, instead of saying “what a user can
|
a capability that, instead of saying “what a user can
|
||||||
do”, says what a user <emphasis>cannot</emphasis> do. It's
|
do”, says what a user <emphasis>cannot</emphasis> do. It's
|
||||||
formed rather simply by adding a dash (“-”) to the
|
formed rather simply by adding a dash (“-”) to the
|
||||||
beginning of a capability; <varname>rot13</varname> is a
|
beginning of a capability; <botcommand>rot13</botcommand> is a
|
||||||
capability, and <varname>-rot13</varname> is an anticapability.
|
capability, and <botcommand>-rot13</botcommand> is an
|
||||||
Anyway, when a user issues the bot a command, perhaps
|
anticapability. Anyway, when a user issues the bot a command,
|
||||||
<function>calc</function> or <function>help</function> the bot
|
perhaps <botcommand>calc</botcommand> or
|
||||||
first checks to make sure the user doesn't have the
|
<botcommand>help</botcommand>, the bot first checks to make sure
|
||||||
<varname>-calc</varname> or the <varname>-help</varname>
|
the user doesn't have the <capability>-calc</capability> or the
|
||||||
capabilities before even considering responding to the user. So
|
<capability>-help</capability> capabilities before even
|
||||||
commands can be turned on or off on a <emphasis>per
|
considering responding to the user. So commands can be turned on
|
||||||
user</emphasis> basis, offering finegrained control not often (if
|
or off on a <emphasis>per user</emphasis> basis, offering
|
||||||
at all!) seen in other bots.
|
finegrained control not often (if at all!) seen in other bots.
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Channel capabilities</title>
|
<title>Channel capabilities</title>
|
||||||
<para>
|
<para>
|
||||||
But that's not all! The capabilities system also supports
|
But that's not all! The capabilities system also supports
|
||||||
<emphasis>Channel</emphasis> capabilities, which are
|
<emphasis>Channel</emphasis> capabilities, which are
|
||||||
capabilities that only apply to a specific channel; they're of
|
capabilities that only apply to a specific channel; they're of
|
||||||
the form <varname>#channel.capability</varname>. Whenever a
|
the form <capability>#channel.capability</capability>.
|
||||||
user issues a command to the bot in a channel, the command
|
Whenever a user issues a command to the bot in a channel, the
|
||||||
dispatcher also checks to make sure the user doesn't have the
|
command dispatcher also checks to make sure the user doesn't
|
||||||
anticapability for that command <emphasis>in that
|
have the anticapability for that command <emphasis>in that
|
||||||
channel</emphasis> and if the user does, the bot won't respond
|
channel</emphasis> and if the user does, the bot won't respond
|
||||||
to the user in the channel. Thus now, in addition to having
|
to the user in the channel. Thus now, in addition to having
|
||||||
the ability to turn individual commands on or off for an
|
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, we can now turn commands on or off for an
|
||||||
individual user on an individual channel!
|
individual user on an individual channel!
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
So when a user <varname>foo</varname> sends a command
|
So when a user <nick>foo</nick> sends a command
|
||||||
<function>bar</function> to the bot on channel
|
<botcommand>bar</botcommand> to the bot on channel
|
||||||
<varname>#baz</varname>, first the bot checks to see if the
|
<channel>#baz</channel>, first the bot checks to see if the
|
||||||
user has the anticapability for the command by itself,
|
user has the anticapability for the command by itself,
|
||||||
<varname>-bar</varname>. If so, it returns right then and
|
<capability>-bar</capability>. If so, it returns right then
|
||||||
there, compltely ignoring the fact that the user issued that
|
and there, compltely ignoring the fact that the user issued
|
||||||
command to it. If the user doesn't have that anticapability,
|
that command to it. If the user doesn't have that
|
||||||
then the bot checks to see if the user issued the command over
|
anticapability, then the bot checks to see if the user issued
|
||||||
a channel, and if so, checks to see if the user has the
|
the command over a channel, and if so, checks to see if the
|
||||||
antichannelcapability for that command,
|
user has the antichannelcapability for that command,
|
||||||
<varname>#baz.-bar</varname>. If so, again, he returns right
|
<capability>#baz.-bar</capability>. If so, again, he returns
|
||||||
then and there and doesn't even think about responding to the
|
right then and there and doesn't even think about responding
|
||||||
bot. If neither of these anticapabilities are present, then
|
to the bot. If neither of these anticapabilities are present,
|
||||||
the bot just responds to the user like normal.
|
then the bot just responds to the user like normal.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
@ -148,14 +148,14 @@
|
|||||||
<title>Hard-coded supybot capabilities</title>
|
<title>Hard-coded supybot capabilities</title>
|
||||||
<para>
|
<para>
|
||||||
There are several default capabilities the bot uses. The most
|
There are several default capabilities the bot uses. The most
|
||||||
important of these is the <varname>owner</varname> capability.
|
important of these is the <capability>owner</capability>
|
||||||
This capability allows the person having it to use
|
capability. This capability allows the person having it to use
|
||||||
<emphasis>any</emphasis> command. It's best to keep this
|
<emphasis>any</emphasis> command. It's best to keep this
|
||||||
capability reserved to people who actually have access to the
|
capability reserved to people who actually have access to the
|
||||||
shell the bot is running on.
|
shell the bot is running on.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
There is also the <varname>admin</varname> capability for
|
There is also the <capability>admin</capability> capability for
|
||||||
non-owners that are highly trusted to administer the bot
|
non-owners that are highly trusted to administer the bot
|
||||||
appropriately. They can do things such as change the bot's nick,
|
appropriately. They can do things such as change the bot's nick,
|
||||||
globally enable/disable commands, cause the bot to ignore a given
|
globally enable/disable commands, cause the bot to ignore a given
|
||||||
@ -164,40 +164,41 @@
|
|||||||
people with the next capability.
|
people with the next capability.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
People who are to administer channels with the bot should have the
|
People who are to administer channels with the bot should have the
|
||||||
<varname>#channel.op</varname> capability -- whatever channel they
|
<capability>#channel.op</capability> capability -- whatever
|
||||||
are to administrate, they should have that channel capability for
|
channel they are to administrate, they should have that channel
|
||||||
<varname>op</varname>. For example, since I want
|
capability for <capability>op</capability>. For example, since I
|
||||||
<varname>inkedmn</varname> to be an administrator in
|
want <nick>inkedmn</nick> to be an administrator in
|
||||||
<varname>#supybot</varname>, I'll give him the
|
<channel>#supybot</channel>, I'll give him the
|
||||||
<varname>#supybot.op</varname> capability. This is in addition to
|
<capability>#supybot.op</capability> capability. This is in
|
||||||
his <varname>admin</varname> capability, since the
|
addition to his <capability>admin</capability> capability, since
|
||||||
<varname>admin</varname> capability doesn't give the person having
|
the <capability>admin</capability> capability doesn't give the
|
||||||
it control over channels. <varname>#channel.op</varname> is used
|
person having it control over channels.
|
||||||
for such things as giving/receiving ops, kickbanning people,
|
<capability>#channel.op</capability> is used for such things as
|
||||||
lobotomizing the bot, ignoring users in the channel, and managing
|
giving/receiving ops, kickbanning people, lobotomizing the bot,
|
||||||
the channel capabilities. The <varname>#channel.op</varname>
|
ignoring users in the channel, and managing the channel
|
||||||
capability is also basically the equivalent of the owner
|
capabilities. The <capability>#channel.op</capability> capability
|
||||||
capability for capabilities involving <varname>#channel</varname>
|
is also basically the equivalent of the owner capability for
|
||||||
– basically anyone with the <varname>#channel.op</varname>
|
capabilities involving <channel>#channel</channel> –
|
||||||
capability is considered to have all positive capabilities and no
|
basically anyone with the <capability>#channel.op</capability>
|
||||||
negative capabilities for <varname>#channel</varname>.
|
capability is considered to have all positive capabilities and no
|
||||||
|
negative capabilities for <channel>#channel</channel>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
One other globally important capability exists:
|
One other globally important capability exists:
|
||||||
<varname>trusted</varname>. This is a command that basically says
|
<capability>trusted</capability>. This is a command that
|
||||||
“This user can be trusted not to try and crash the
|
basically says “This user can be trusted not to try and
|
||||||
bot.” It allows users to call commands like
|
crash the bot.” It allows users to call commands like
|
||||||
<function>Math.icalc</function>, which potentially could cause the
|
<botcommand>Math.icalc</botcommand>, which potentially could cause the
|
||||||
bot to begin a calculation that could potentially never return (a
|
bot to begin a calculation that could potentially never return (a
|
||||||
calculation like 10**10**10**10). Another command that requires
|
calculation like 10**10**10**10). Another command that requires
|
||||||
the trusted capability is <function>Utilties.re</function>, which
|
the trusted capability is <botcommand>Utilties.re</botcommand>, which
|
||||||
(due to the regular expression implementation in Python (and any
|
(due to the regular expression implementation in Python (and any
|
||||||
other language that uses NFA regular expressions, like Perl or
|
other language that uses NFA regular expressions, like Perl or
|
||||||
Ruby or Lua or …) which can allow a regular expression to
|
Ruby or Lua or …) which can allow a regular expression to
|
||||||
take exponential time to process). Consider what would happen if
|
take exponential time to process). Consider what would happen if
|
||||||
the someone gave the bot the command <literal>re [strjoin "" s/./
|
the someone gave the bot the command <literal>re [strjoin "" s/./
|
||||||
[dict go] /] [dict go]</literal>.
|
[dict go] /] [dict go]</literal>.
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
</article>
|
</article>
|
||||||
|
311
docs/DocBook/configuration.sgml
Normal file
311
docs/DocBook/configuration.sgml
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
<!DOCTYPE article SYSTEM "supybot.dtd">
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<articleinfo>
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>Jeremiah</firstname>
|
||||||
|
<surname>Fincher</surname>
|
||||||
|
</author>
|
||||||
|
<author>
|
||||||
|
<firstname>Daniel</firstname>
|
||||||
|
<surname>DiPaolo</surname>
|
||||||
|
</author>
|
||||||
|
<editor>
|
||||||
|
<firstname>Daniel</firstname>
|
||||||
|
<surname>DiPaolo</surname>
|
||||||
|
<contrib>DocBook translator</contrib>
|
||||||
|
</editor>
|
||||||
|
</authorgroup>
|
||||||
|
<title>Supybot configuration system explanation</title>
|
||||||
|
<revhistory>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.1</revnumber>
|
||||||
|
<date>18 Feb 2004</date>
|
||||||
|
<revremark>Initial Docbook translation</revremark>
|
||||||
|
</revision>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.2</revnumber>
|
||||||
|
<date>26 Feb 2004</date>
|
||||||
|
<revremark>Conversion to Supybot DTD</revremark>
|
||||||
|
</revision>
|
||||||
|
</revhistory>
|
||||||
|
</articleinfo>
|
||||||
|
<sect1>
|
||||||
|
<title>Introduction</title>
|
||||||
|
<para>
|
||||||
|
So you've got your Supybot up and running and there are some
|
||||||
|
things you don't like about it. Fortunately for you, chances are
|
||||||
|
that these things are configurable, and this document is here to
|
||||||
|
tell you how to configure them.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Configuration of Supybot is handled via the
|
||||||
|
<plugin>Config</plugin> plugin, which controls runtime access to
|
||||||
|
Supybot's registry (the configuration file generated by the
|
||||||
|
<script>supybot-wizard</script> program you ran). The
|
||||||
|
<plugin>Config</plugin> plugin provides a way to get or set
|
||||||
|
variables, to list the available variables, and even to get help
|
||||||
|
for certain variables. Take a moment now to read the help for
|
||||||
|
each of those commands: <botcommand>get</botcommand>,
|
||||||
|
<botcommand>set</botcommand>, <botcommand>list</botcommand>, and
|
||||||
|
<botcommand>help</botcommand>. If you don't know how to get help on
|
||||||
|
those commands, go ahead and read our
|
||||||
|
<filename>GETTING_STARTED</filename> document before this one.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Supybot's registry</title>
|
||||||
|
<para>
|
||||||
|
Now, if you're used to the Windows registry, don't worry,
|
||||||
|
Supybot's registry is completely different. For one, it's
|
||||||
|
completely plain text. There's no binary database sensitive to
|
||||||
|
corruption, it's not necessary to use another program to edit it
|
||||||
|
– all you need is a simple text editor. But there is at
|
||||||
|
least one good idea in Windows' registry: hierarchical
|
||||||
|
configuration. Supybot's configuration variables are organized in
|
||||||
|
a hierarchy: variables having to do with the way Supybot makes
|
||||||
|
replies all start with
|
||||||
|
<registrygroup>supybot.reply</registrygroup>; variables having to
|
||||||
|
do with the way a plugin works all start with
|
||||||
|
<registrygroup>supybot.plugins.Plugin</registrygroup> (where
|
||||||
|
<plugin>Plugin</plugin> is the name of the plugin in question).
|
||||||
|
This hierarchy is nice because it means the user isn't inundated
|
||||||
|
with hundreds of unrelated and unsorted configuration variables.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some of the more important configuration values are located
|
||||||
|
directly under the base group,
|
||||||
|
<registrygroup>supybot</registrygroup>. Things like the bot's
|
||||||
|
nick, its ident, etc. Along with these config values are a few
|
||||||
|
subgroups that contain other values. Some of the more prominent
|
||||||
|
subgroups are: <registrygroup>plugins</registrygroup> (where all
|
||||||
|
the plugin-specific configuration is held),
|
||||||
|
<registrygroup>reply</registrygroup> (where variables affecting
|
||||||
|
the way a Supybot makes its replies resides),
|
||||||
|
<registrygroup>replies</registrygroup> (where all the specific
|
||||||
|
standard replies are kept), and
|
||||||
|
<registrygroup>directories</registrygroup> (where all the
|
||||||
|
directories a Supybot uses are defined). There are other
|
||||||
|
subgroups as well, but these are the ones we'll use in our
|
||||||
|
example.
|
||||||
|
</para>
|
||||||
|
<sect2>
|
||||||
|
<title>Config plugin commands</title>
|
||||||
|
<sect3>
|
||||||
|
<title>Listing registry contents</title>
|
||||||
|
<para>
|
||||||
|
Using the <plugin>Config</plugin> plugin, you can list
|
||||||
|
the values in a subgroup and get or set any of the values
|
||||||
|
anywhere in the configuration hierarchy. For example,
|
||||||
|
let's say you wanted to see what configuration values were
|
||||||
|
under the <registrygroup>supybot</registrygroup> (the base
|
||||||
|
group) hierarchy. You would simply issue this command:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config list supybot
|
||||||
|
<supybot> jemfinch|lambda: nick, ident, user, server, password,
|
||||||
|
channels, prefixChars, defaultCapabilities, defaultAllow, defaultIgnore,
|
||||||
|
humanTimestampFormat, externalIP, pipeSyntax,
|
||||||
|
followIdentificationThroughNickChanges, alwaysJoinOnInvite,
|
||||||
|
showSimpleSyntax, maxHistoryLength, nickmods, throttleTime,
|
||||||
|
snarfThrottle, threadAllCommands, pingServer, pingInterval,
|
||||||
|
upkeepInterval, flush, httpPeekSize, and defaultSocketTimeout
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
These are all the configuration values you can set which
|
||||||
|
are under the base <registrygroup>supybot</registrygroup>
|
||||||
|
group. Actually, their full names would each have a
|
||||||
|
“supybot.” appended on to the front of them,
|
||||||
|
but it is omitted in the listing in order to shorten the
|
||||||
|
output.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Now, to see all of the available configuration groups
|
||||||
|
under the base <registrygroup>supybot</registrygroup>
|
||||||
|
group, we simply use the <flag>--groups</flag> flag to
|
||||||
|
<botcommand>config list</botcommand>:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config list --groups supybot
|
||||||
|
<supybot> jemfinch|lambda: commands, databases, directories, drivers,
|
||||||
|
log, plugins, replies, and reply
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
These are all the subgroups of
|
||||||
|
<registrygroup>supybot</registrygroup>. Again, the full
|
||||||
|
name of these would have “supybot.” prepended
|
||||||
|
to them. So really, we have
|
||||||
|
<registrygroup>supybot.commands</registrygroup>,
|
||||||
|
<registrygroup>supybot.databases</registrygroup>, etc.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
An item can show up in both lists if it is a group
|
||||||
|
that itself has a value. For example, all plugins
|
||||||
|
fall under this category, as their value is a boolean
|
||||||
|
value determining whether or not that plugin is to be
|
||||||
|
loaded when the bot is started.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect3>
|
||||||
|
<sect3>
|
||||||
|
<title>Dealing with registry values</title>
|
||||||
|
<para>
|
||||||
|
Okay, now that you've used the <plugin>Config</plugin>
|
||||||
|
plugin to list configuration variables, it's time that we
|
||||||
|
start looking at individual variables and their values.
|
||||||
|
</para>
|
||||||
|
<sect4>
|
||||||
|
<title>Built-in help for registry values</title>
|
||||||
|
<para>
|
||||||
|
The first (and perhaps most important) thing you
|
||||||
|
should know about each configuration variable is that
|
||||||
|
they all have an associated help string to tell you
|
||||||
|
what they represent. So the first command we'll cover
|
||||||
|
is <botcommand>config help</botcommand>. To see the
|
||||||
|
help string for any value or group, simply use the
|
||||||
|
<botcommand>config help</botcommand> command. For
|
||||||
|
example, to see what this
|
||||||
|
<registrygroup>supybot.prefixChars</registrygroup>
|
||||||
|
configuration variable is all about, we'd do this:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config help supybot.prefixChars
|
||||||
|
<supybot> jemfinch|lambda: Determines what prefix characters the bot
|
||||||
|
will reply to. A prefix character is a single character that the bot will
|
||||||
|
use to determine what messages are addressed to it; when there are no
|
||||||
|
prefix characters set, it just uses its nick.
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Pretty simple, eh?
|
||||||
|
</para>
|
||||||
|
</sect4>
|
||||||
|
<sect4>
|
||||||
|
<title>Getting/setting registry values</title>
|
||||||
|
<para>
|
||||||
|
Now, if you're curious what the current value of a
|
||||||
|
configuration variable is, you'll use the
|
||||||
|
<botcommand>config</botcommand> command with one
|
||||||
|
argument, the name of the variable you want to see the
|
||||||
|
value of:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config supybot.prefixChars
|
||||||
|
<supybot> jemfinch|lambda: '@'
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
To set this value, just stick an extra argument after
|
||||||
|
the name:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config supybot.prefixChars @$
|
||||||
|
<supybot> jemfinch|lambda: The operation succeeded.
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Now, check this out:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> $config supybot.prefixChars
|
||||||
|
<supybot> jemfinch|lambda: '@$'
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Note that we used <literal>$</literal> as our prefix
|
||||||
|
character, and that the value of the configuration
|
||||||
|
variable changed. If I were to use the
|
||||||
|
<botcommand>flush</botcommand> command now, this
|
||||||
|
change would be flushed to the registry file on disk
|
||||||
|
(this would also happen if I made the bot quit, or
|
||||||
|
pressed
|
||||||
|
<keycombo>
|
||||||
|
<keycap>Ctrl</keycap>
|
||||||
|
<keycap>C</keycap>
|
||||||
|
</keycombo>
|
||||||
|
in the terminal the bot was running in). Instead,
|
||||||
|
I'll revert the change:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> $config supybot.prefixChars @
|
||||||
|
<supybot> jemfinch|lambda: The operation succeeded.
|
||||||
|
<jemfinch|lambda> $note that this makes no response.
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
If you're ever curious what the default for a given
|
||||||
|
configuration variable is, use the <botcommand>config
|
||||||
|
default</botcommand> command:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config default supybot.prefixChars
|
||||||
|
<supybot> jemfinch|lambda: ''
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Thus, to reset a configuration variable to its default
|
||||||
|
value, you can simply say:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config supybot.prefixChars [config default
|
||||||
|
supybot.prefixChars]
|
||||||
|
<supybot> jemfinch|lambda: The operation succeeded.
|
||||||
|
<jemfinch|lambda> @note that this does nothing
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Simple, eh?
|
||||||
|
</para>
|
||||||
|
</sect4>
|
||||||
|
</sect3>
|
||||||
|
<sect3>
|
||||||
|
<title>Searching the registry</title>
|
||||||
|
<para>
|
||||||
|
Now, let's say you want to find all configuration
|
||||||
|
variables that might be even remotely related to opping.
|
||||||
|
For that, you'll want the <botcommand>config
|
||||||
|
search</botcommand> command. Check this out:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> @config search op
|
||||||
|
<supybot> jemfinch|lambda: supybot.plugins.Enforcer.autoOp,
|
||||||
|
supybot.plugins.Enforcer.autoOp.#supybot,
|
||||||
|
supybot.plugins.Enforcer.autoHalfop,
|
||||||
|
supybot.plugins.Enforcer.cycleToGetOps, supybot.plugins.Topic,
|
||||||
|
supybot.plugins.Topic.separator, and supybot.plugins.Relay.topicSync
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Sure, it showed up all the topic-related stuff in there,
|
||||||
|
but it also showed you all the op-related stuff, too. Do
|
||||||
|
note, however, that you can only see configuration
|
||||||
|
variables for plugins that you have loaded or that you
|
||||||
|
loaded in the past; if you've never loaded a plugin,
|
||||||
|
there's no way for the bot to know what configuration
|
||||||
|
variables it registers.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some people might like editing their registry file
|
||||||
|
directly rather than manipulating all these things through
|
||||||
|
the bot. For those people, we offer the
|
||||||
|
<botcommand>config reload</botcommand> command, which
|
||||||
|
reloads both registry configuration and
|
||||||
|
user/channel/ignore database configuration. Just edit the
|
||||||
|
interesting files and then give the bot the
|
||||||
|
<botcommand>config reload</botcommand> command and it'll
|
||||||
|
work as expected. Do note, however, that Supybot flushes
|
||||||
|
his configuration files and databases to disk every hour
|
||||||
|
or so, and if this happens after you've edited your
|
||||||
|
configuration files but before you reload your changes,
|
||||||
|
you could lose the changes you made. To prevent this, set
|
||||||
|
the <registrygroup>supybot.flush</registrygroup> value to
|
||||||
|
<literal>Off</literal>, and no automatic flushing will
|
||||||
|
occur.
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>All done!</title>
|
||||||
|
<para>
|
||||||
|
Anyway, that's about it for configuration. Have fun, and enjoy
|
||||||
|
your configurable bot!
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
<!DOCTYPE article SYSTEM "supybot.dtd">
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
<articleinfo>
|
<articleinfo>
|
||||||
@ -32,6 +32,11 @@
|
|||||||
Updated to match EXAMPLE included with 0.75.0
|
Updated to match EXAMPLE included with 0.75.0
|
||||||
</revremark>
|
</revremark>
|
||||||
</revision>
|
</revision>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.4</revnumber>
|
||||||
|
<date>26 Feb 2004</date>
|
||||||
|
<revremark>Converted to use Supybot DTD</revremark>
|
||||||
|
</revision>
|
||||||
</revhistory>
|
</revhistory>
|
||||||
</articleinfo>
|
</articleinfo>
|
||||||
<sect1>
|
<sect1>
|
||||||
@ -56,13 +61,12 @@
|
|||||||
<title>Creating your own plugin</title>
|
<title>Creating your own plugin</title>
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>
|
<title>
|
||||||
Using <application>scripts/newplugin.py</application>
|
Using <script>scripts/newplugin.py</script>
|
||||||
</title>
|
</title>
|
||||||
<para>
|
<para>
|
||||||
First, the easiest way to start writing a module is to use the
|
First, the easiest way to start writing a module is to use the
|
||||||
wizard provided,
|
wizard provided, <script>scripts/newplugin.py</script>.
|
||||||
<application>scripts/newplugin.py</application>. Here's an
|
Here's an example session:
|
||||||
example session:
|
|
||||||
</para>
|
</para>
|
||||||
<screen>
|
<screen>
|
||||||
functor% scripts/newplugin.py
|
functor% scripts/newplugin.py
|
||||||
@ -169,7 +173,7 @@ Class = Random
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Describe what you want the plugin to do in the docstring.
|
Describe what you want the plugin to do in the docstring.
|
||||||
This is used in <application>scripts/setup.py</application> in
|
This is used in <script>scripts/setup.py</script> in
|
||||||
order to explain to the user the purpose of the module. It's
|
order to explain to the user the purpose of the module. It's
|
||||||
also returned when someone asks the bot for help for a given
|
also returned when someone asks the bot for help for a given
|
||||||
module (instead of help for a certain command). We'll change
|
module (instead of help for a certain command). We'll change
|
||||||
@ -177,17 +181,18 @@ Class = Random
|
|||||||
numbers."</literal>
|
numbers."</literal>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Then there are the imports. The <varname>callbacks</varname>
|
Then there are the imports. The
|
||||||
|
<module>callbacks</module>
|
||||||
module is used (the class you're given subclasses
|
module is used (the class you're given subclasses
|
||||||
<varname>callbacks.Privmsg</varname>) but the
|
<classname>callbacks.Privmsg</classname>) but the
|
||||||
<varname>privmsgs</varname> module isn't used. That's
|
<module>privmsgs</module> module isn't used. That's
|
||||||
alright; we can almost guarantee you'll use it, so we go ahead
|
alright; we can almost guarantee you'll use it, so we go ahead
|
||||||
and add the import to the template.
|
and add the import to the template.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Then you see a <function>configure</function> function. This
|
Then you see a <function>configure</function> function. This
|
||||||
the function that's called when users decide to add your
|
the function that's called when users decide to add your
|
||||||
module in <application>scripts/setup.py</application>. You'll
|
module in <script>scripts/setup.py</script>. You'll
|
||||||
note that by default it simply adds <literal>"load
|
note that by default it simply adds <literal>"load
|
||||||
Example"</literal> (where 'Example' is the name you provided
|
Example"</literal> (where 'Example' is the name you provided
|
||||||
as the name of your plugin, so in our case it is
|
as the name of your plugin, so in our case it is
|
||||||
@ -204,8 +209,8 @@ Class = Random
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
What you're given is a skeleton: a simple subclass of
|
What you're given is a skeleton: a simple subclass of
|
||||||
<varname>callbacks.Privmsg</varname> for you to start with.
|
<classname>callbacks.Privmsg</classname> for you to start
|
||||||
Now let's add a command.
|
with. Now let's add a command.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
I don't know what you know about random number generators, but
|
I don't know what you know about random number generators, but
|
||||||
@ -213,7 +218,7 @@ Class = Random
|
|||||||
seed) and they continue (via some somewhat
|
seed) and they continue (via some somewhat
|
||||||
complicated/unpredictable algorithm) from there. This seed
|
complicated/unpredictable algorithm) from there. This seed
|
||||||
(and the rest of the sequence, really) is all nice and
|
(and the rest of the sequence, really) is all nice and
|
||||||
packaged up in Python's <varname>random</varname> module, the
|
packaged up in Python's <module>random</module> module, the
|
||||||
<varname>Random</varname> object. So the first thing we're
|
<varname>Random</varname> object. So the first thing we're
|
||||||
going to have to do is give our plugin a
|
going to have to do is give our plugin a
|
||||||
<varname>Random</varname> object.
|
<varname>Random</varname> object.
|
||||||
@ -225,8 +230,8 @@ Class = Random
|
|||||||
be careful of is that you call the superclass
|
be careful of is that you call the superclass
|
||||||
<function>__init__</function> method at the end of your own
|
<function>__init__</function> method at the end of your own
|
||||||
<function>__init__</function>. So to add this
|
<function>__init__</function>. So to add this
|
||||||
<varname>random.Random</varname> object to our plugin, we can
|
<classname>random.Random</classname> object to our plugin, we
|
||||||
replace the <function>pass</function> statement with
|
can replace the <keyword>pass</keyword> statement with
|
||||||
this:
|
this:
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
@ -285,40 +290,40 @@ def __init__(self):
|
|||||||
<para>
|
<para>
|
||||||
And that's it! Pretty simple, huh? Anyway, you're probably
|
And that's it! Pretty simple, huh? Anyway, you're probably
|
||||||
wondering what all that <emphasis>means</emphasis>. We'll
|
wondering what all that <emphasis>means</emphasis>. We'll
|
||||||
start with the <function>def</function> statement:
|
start with the <keyword>def</keyword> statement:
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
def random(self, irc, msg, args):
|
def random(self, irc, msg, args):
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
What that does is define a command
|
What that does is define a command
|
||||||
<function>random</function>. You can call it by saying
|
<function>random</function>. You can call it by saying
|
||||||
"@random" (or whatever prefix character your specific bot
|
"@random" (or whatever prefix character your specific bot
|
||||||
uses). The arguments are a bit less obvious.
|
uses). The arguments are a bit less obvious.
|
||||||
<varname>self</varname> is self-evident (hah!).
|
<varname>self</varname> is self-evident (hah!).
|
||||||
<varname>irc</varname> is the <varname>Irc</varname> object
|
<varname>irc</varname> is the <classname>Irc</classname>
|
||||||
passed to the command; <varname>msg</varname> is the original
|
object passed to the command; <varname>msg</varname> is the
|
||||||
<varname>IrcMsg</varname> object. But you're really not going
|
original <classname>IrcMsg</classname> object. But you're
|
||||||
to have to deal with either of these too much (with the
|
really not going to have to deal with either of these too much
|
||||||
exception of calling <function>irc.reply</function> or
|
(with the exception of calling <function>irc.reply</function>
|
||||||
<function>irc.error</function>). What you're
|
or <function>irc.error</function>). What you're
|
||||||
<emphasis>really</emphasis> interested in is the
|
<emphasis>really</emphasis> interested in is the
|
||||||
<varname>args</varname> arg. That if a list of all the
|
<varname>args</varname> arg. That if a list of all the
|
||||||
arguments passed to your command, pre-parsed and already
|
arguments passed to your command, pre-parsed and already
|
||||||
evaluated (i.e., you never have to worry about nested
|
evaluated (i.e., you never have to worry about nested
|
||||||
commands, or handling double quoted strings, or splitting on
|
commands, or handling double quoted strings, or splitting on
|
||||||
whitespace -- the work has already been done for you). You
|
whitespace -- the work has already been done for you). You
|
||||||
can read about the <varname>Irc</varname> object in
|
can read about the <classname>Irc</classname> object in
|
||||||
<filename>irclib.py</filename> (you won't find
|
<filename>irclib.py</filename> (you won't find
|
||||||
<function>.reply</function> or <function>.error</function>
|
<function>.reply</function> or <function>.error</function>
|
||||||
there, though, because you're actually getting an
|
there, though, because you're actually getting an
|
||||||
<varname>IrcObjectProxy</varname>, but that's beyond the level
|
<classname>IrcObjectProxy</classname>, but that's beyond the
|
||||||
we want to describe here :)). You can read about the
|
level we want to describe here :)). You can read about the
|
||||||
<varname>msg</varname> object in
|
<varname>msg</varname> object in
|
||||||
<filename>ircmsgs.py</filename>. But again, aside from
|
<filename>ircmsgs.py</filename>. But again, aside from
|
||||||
calling <function>irc.reply</function> or
|
calling <function>irc.reply</function> or
|
||||||
<function>irc.error</function>, you'll very rarely be using
|
<function>irc.error</function>, you'll very rarely be using
|
||||||
these objects.
|
these objects.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
(In case you're curious, the answer is yes, you
|
(In case you're curious, the answer is yes, you
|
||||||
@ -342,13 +347,13 @@ def __init__(self):
|
|||||||
<emphasis>is</emphasis> the help! Given the above docstring,
|
<emphasis>is</emphasis> the help! Given the above docstring,
|
||||||
this is what a supybot does:
|
this is what a supybot does:
|
||||||
</para>
|
</para>
|
||||||
<screen>
|
<ircsession>
|
||||||
<angryman> jemfinch: random takes no arguments (for more help
|
<angryman> jemfinch: random takes no arguments (for more help
|
||||||
use the morehelp command)
|
use the morehelp command)
|
||||||
<jemfinch> $morehelp random
|
<jemfinch> $morehelp random
|
||||||
<angryman> jemfinch: Returns the next random number from the
|
<angryman> jemfinch: Returns the next random number from the
|
||||||
current random number generator.
|
current random number generator.
|
||||||
</screen>
|
</ircsession>
|
||||||
<para>
|
<para>
|
||||||
'help <command>' replies with the command name followed
|
'help <command>' replies with the command name followed
|
||||||
by the first line of the command's docstring; there should be
|
by the first line of the command's docstring; there should be
|
||||||
@ -361,21 +366,22 @@ def __init__(self):
|
|||||||
irc.reply(msg, str(self.rng.random()))
|
irc.reply(msg, str(self.rng.random()))
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
<function>irc.reply</function> takes two arguments, an
|
<function>irc.reply</function> takes two arguments, an
|
||||||
<varname>IrcMsg</varname> (like the one passed into your
|
<classname>IrcMsg</classname> (like the one passed into your
|
||||||
function) and a string. The <varname>IrcMsg</varname> is used
|
function) and a string. The <classname>IrcMsg</classname> is
|
||||||
to determine who the reply should go to and whether or not it
|
used to determine who the reply should go to and whether or
|
||||||
should be sent in private message (commands sent in private
|
not it should be sent in private message (commands sent in
|
||||||
are replied to in private). The string is the reply to be
|
private are replied to in private). The string is the reply
|
||||||
sent. Don't worry about length restrictions or anything -- if
|
to be sent. Don't worry about length restrictions or anything
|
||||||
the string you want to send is too big for an IRC message (and
|
-- if the string you want to send is too big for an IRC
|
||||||
oftentimes that turns out to be the case :)) the supybot
|
message (and oftentimes that turns out to be the case :)) the
|
||||||
framework handles that entirely transparently to you. Do make
|
supybot framework handles that entirely transparently to you.
|
||||||
sure, however, that you give <function>irc.reply</function> a
|
Do make sure, however, that you give
|
||||||
string. It doesn't take anything else (sometimes even unicode
|
<function>irc.reply</function> a string. It doesn't take
|
||||||
fails!). That's why we have "str(self.rng.random())" instead
|
anything else (sometimes even unicode fails!). That's why we
|
||||||
of simply "self.rng.random()" -- we had to give
|
have "str(self.rng.random())" instead of simply
|
||||||
<function>irc.reply</function> a string.
|
"self.rng.random()" -- we had to give
|
||||||
|
<function>irc.reply</function> a string.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Anyway, now that we have an RNG, we have a need for seed! Of
|
Anyway, now that we have an RNG, we have a need for seed! Of
|
||||||
@ -422,7 +428,7 @@ def __init__(self):
|
|||||||
arguments are returned in a tuple/list). Yes, we could've
|
arguments are returned in a tuple/list). Yes, we could've
|
||||||
just said "seed = args[0]" and gotten the first argument, but
|
just said "seed = args[0]" and gotten the first argument, but
|
||||||
what if the user didn't pass us an argument at all? Then
|
what if the user didn't pass us an argument at all? Then
|
||||||
we've got to catch the <varname>IndexError</varname> from
|
we've got to catch the <classname>IndexError</classname> from
|
||||||
<varname>args[0]</varname> and complain to the user about it.
|
<varname>args[0]</varname> and complain to the user about it.
|
||||||
<function>privmsgs.getArgs</function>, on the other hand,
|
<function>privmsgs.getArgs</function>, on the other hand,
|
||||||
handles all that for us. If the user didn't give us enough
|
handles all that for us. If the user didn't give us enough
|
||||||
@ -440,7 +446,7 @@ def __init__(self):
|
|||||||
sure to remind the user that an error has been encountered
|
sure to remind the user that an error has been encountered
|
||||||
(currently, that means it puts "Error: " at the beginning of
|
(currently, that means it puts "Error: " at the beginning of
|
||||||
the message). After erroring, we return. It's important to
|
the message). After erroring, we return. It's important to
|
||||||
remember this <function>return</function> here; otherwise,
|
remember this <keyword>return</keyword> here; otherwise,
|
||||||
we'll just keep going down through the function and try to use
|
we'll just keep going down through the function and try to use
|
||||||
this "seed" variable that never got assigned. A good general
|
this "seed" variable that never got assigned. A good general
|
||||||
rule of thumb is that any time you use
|
rule of thumb is that any time you use
|
||||||
@ -500,9 +506,9 @@ def __init__(self):
|
|||||||
to.
|
to.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The <varname>Random</varname> object we're using offers us a
|
The <classname>Random</classname> object we're using offers us
|
||||||
"sample" method that takes a sequence and a number (we'll call
|
a "sample" method that takes a sequence and a number (we'll
|
||||||
it <varname>N</varname>) and returns a list of
|
call it <varname>N</varname>) and returns a list of
|
||||||
<varname>N</varname> items taken randomly from the sequence.
|
<varname>N</varname> items taken randomly from the sequence.
|
||||||
So I'll show you an example that takes advantage of multiple
|
So I'll show you an example that takes advantage of multiple
|
||||||
arguments but doesn't use
|
arguments but doesn't use
|
||||||
@ -542,13 +548,13 @@ def __init__(self):
|
|||||||
into a big long string that we'll just have to re-split. But
|
into a big long string that we'll just have to re-split. But
|
||||||
we still want the nice error handling of
|
we still want the nice error handling of
|
||||||
<function>privmsgs.getArgs</function>. So what do we do? We
|
<function>privmsgs.getArgs</function>. So what do we do? We
|
||||||
raise <varname>callbacks.ArgumentError</varname>! That's the
|
raise <classname>callbacks.ArgumentError</classname>! That's
|
||||||
secret juju that <function>privmsgs.getArgs</function> is
|
the secret juju that <function>privmsgs.getArgs</function> is
|
||||||
doing; now we're just doing it ourself. Someone up our
|
doing; now we're just doing it ourself. Someone up our
|
||||||
callchain knows how to handle it so a neat error message is
|
callchain knows how to handle it so a neat error message is
|
||||||
returned. So in this function, if
|
returned. So in this function, if
|
||||||
<function>.pop(0)</function> fails, we weren't given enough
|
<function>.pop(0)</function> fails, we weren't given enough
|
||||||
arguments and thus need to tell the user how to call us.
|
arguments and thus need to tell the user how to call us.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
So we have the args, we have the number, we do a simple call
|
So we have the args, we have the number, we do a simple call
|
||||||
@ -607,22 +613,22 @@ def __init__(self):
|
|||||||
<para>
|
<para>
|
||||||
Later, though, you'll see something other than
|
Later, though, you'll see something other than
|
||||||
<function>irc.reply</function>. This is
|
<function>irc.reply</function>. This is
|
||||||
<function>irc.queueMsg</function>, the general interface for
|
<function>irc.queueMsg</function>, the general interface for
|
||||||
sending messages to the server. It's what
|
sending messages to the server. It's what
|
||||||
<function>irc.reply</function> is using under the covers. It
|
<function>irc.reply</function> is using under the covers. It
|
||||||
takes an <varname>IrcMsg</varname> object. Fortunately,
|
takes an <classname>IrcMsg</classname> object. Fortunately,
|
||||||
that's exactly what's returned by
|
that's exactly what's returned by
|
||||||
<function>ircmsgs.action</function>. An action message, just
|
<function>ircmsgs.action</function>. An action message, just
|
||||||
in case you don't know, is a /me kind of message.
|
in case you don't know, is a /me kind of message.
|
||||||
<function>ircmsgs.action</function> is a helper function that
|
<function>ircmsgs.action</function> is a helper function that
|
||||||
takes a target (a place to send the message, either a channel
|
takes a target (a place to send the message, either a channel
|
||||||
or a person) and a payload (the thing to /me) and returns the
|
or a person) and a payload (the thing to /me) and returns the
|
||||||
appropriate <varname>IrcMsg</varname> object.
|
appropriate <classname>IrcMsg</classname> object.
|
||||||
<function>ircutils.replyTo</function> simply takes an
|
<function>ircutils.replyTo</function> simply takes an
|
||||||
<varname>IrcMsg</varname> and returns where we should reply
|
<classname>IrcMsg</classname> and returns where we should
|
||||||
to; if the message was originally sent to a channel, we'll
|
reply to; if the message was originally sent to a channel,
|
||||||
reply to there, if it was originally sent to us privately,
|
we'll reply to there, if it was originally sent to us
|
||||||
we'll reply in private.
|
privately, we'll reply in private.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
At the end, you might be surprised by the "raise
|
At the end, you might be surprised by the "raise
|
||||||
@ -646,7 +652,7 @@ def __init__(self):
|
|||||||
<title>Finishing touches</title>
|
<title>Finishing touches</title>
|
||||||
<para>
|
<para>
|
||||||
Let's take a look at that <function>configure</function>
|
Let's take a look at that <function>configure</function>
|
||||||
function <application>scripts/newplugin.py</application> made
|
function <script>scripts/newplugin.py</script> made
|
||||||
for us. Here it is, in case you've forgotten:
|
for us. Here it is, in case you've forgotten:
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
@ -660,10 +666,10 @@ def configure(onStart, afterConnect, advanced):
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
You remember when you first started running supybot and ran
|
You remember when you first started running supybot and ran
|
||||||
<application>scripts/setup.py</application> and it asked you
|
<script>scripts/setup.py</script> and it asked you
|
||||||
all those questions? Well, now's your chance to ask other
|
all those questions? Well, now's your chance to ask other
|
||||||
users some questions of your own. In our case, with our
|
users some questions of your own. In our case, with our
|
||||||
<varname>Random</varname> plugin, it might be nice to offer
|
<plugin>Random</plugin> plugin, it might be nice to offer
|
||||||
the user the ability to specify a seed to use whenever the
|
the user the ability to specify a seed to use whenever the
|
||||||
plugin is loaded. So let's ask him if he wants to do that,
|
plugin is loaded. So let's ask him if he wants to do that,
|
||||||
and if so, let's ask him what the seed should be.
|
and if so, let's ask him what the seed should be.
|
||||||
@ -684,7 +690,7 @@ def configure(onStart, afterConnect, advanced):
|
|||||||
onStart.append('seed %s' % seed)
|
onStart.append('seed %s' % seed)
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
As you can see, what the <varname>questions</varname> module
|
As you can see, what the <module>questions</module> module
|
||||||
does is fairly self-evident: <function>yn</function> returns
|
does is fairly self-evident: <function>yn</function> returns
|
||||||
either 'y' or 'n'; <function>something</function> returns
|
either 'y' or 'n'; <function>something</function> returns
|
||||||
<emphasis>something</emphasis> (but not nothing; for nothing,
|
<emphasis>something</emphasis> (but not nothing; for nothing,
|
||||||
@ -694,12 +700,12 @@ def configure(onStart, afterConnect, advanced):
|
|||||||
<varname>onStart</varname> is a list of the commands to run
|
<varname>onStart</varname> is a list of the commands to run
|
||||||
when the bot starts; we're just throwing our little piece into
|
when the bot starts; we're just throwing our little piece into
|
||||||
it. These commands will then be written into the template
|
it. These commands will then be written into the template
|
||||||
<application>scripts/setup.py</application> creates for the bot.
|
<script>scripts/setup.py</script> creates for the bot.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
We've written our own plugin from scratch (well, from the
|
We've written our own plugin from scratch (well, from the
|
||||||
boilerplate that we got from
|
boilerplate that we got from
|
||||||
<application>scripts/newplugin.py</application> :)) and
|
<script>scripts/newplugin.py</script> :)) and
|
||||||
survived! Now go write more plugins for supybot, and send
|
survived! Now go write more plugins for supybot, and send
|
||||||
them to me so I can use them too :)
|
them to me so I can use them too :)
|
||||||
</para>
|
</para>
|
||||||
|
284
docs/DocBook/faq.sgml
Normal file
284
docs/DocBook/faq.sgml
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
<!DOCTYPE article SYSTEM "supybot.dtd">
|
||||||
|
<article class="faq">
|
||||||
|
<articleinfo>
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>Jeremiah</firstname>
|
||||||
|
<surname>Fincher</surname>
|
||||||
|
</author>
|
||||||
|
<editor>
|
||||||
|
<firstname>Daniel</firstname>
|
||||||
|
<surname>DiPaolo</surname>
|
||||||
|
<contrib>DocBook translator</contrib>
|
||||||
|
</editor>
|
||||||
|
</authorgroup>
|
||||||
|
<title>Supybot Frequently Asked Questions</title>
|
||||||
|
<revhistory>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.1</revnumber>
|
||||||
|
<date>18 Feb 2004</date>
|
||||||
|
<revremark>Initial Docbook translation</revremark>
|
||||||
|
</revision>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.2</revnumber>
|
||||||
|
<date>26 Feb 2004</date>
|
||||||
|
<revremark>Changed to Supybot DTD</revremark>
|
||||||
|
</revision>
|
||||||
|
</revhistory>
|
||||||
|
</articleinfo>
|
||||||
|
<qandaset defaultlabel="qanda">
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
Why does my bot not recognize me or tell me that I don't
|
||||||
|
have the <capability>owner</capability> capability?
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
Because you're not given it anything to recognize you
|
||||||
|
from! You'll need to identify with the bot
|
||||||
|
(<botcommand>help identify</botcommand> to see how that
|
||||||
|
works) or add your hostmask to your user record
|
||||||
|
(<botcommand>help addhostmask</botcommand> to see how that
|
||||||
|
works) for it to know that you're you. You may wish to
|
||||||
|
note that <botcommand>addhostmask</botcommand> can accept
|
||||||
|
a password; rather than identify, you can send the command
|
||||||
|
<botcommand>addhostmask myOwnerUser [hostmask]
|
||||||
|
myOwnerUserPassword</botcommand> and the bot will add your
|
||||||
|
current hostmask to your owner user (of course, you should
|
||||||
|
change <literal>myOwnerUser</literal> and
|
||||||
|
<literal>myOwnerUserPassword</literal> appropriately for
|
||||||
|
your bot).
|
||||||
|
</para>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
How do I make Supybot op my users?
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
First, you'll have to make sure that your users register
|
||||||
|
with the bot. They can do this with the
|
||||||
|
<botcommand>register</botcommand> command. After they do
|
||||||
|
so, you'll want to add the
|
||||||
|
<capability>#channel,op</capability> capability to their
|
||||||
|
user. Use the <botcommand>channel
|
||||||
|
addcapability</botcommand> command to do this. After
|
||||||
|
that, your users should be able to use the
|
||||||
|
<botcommand>op</botcommand> command to get ops.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you want your users to be auto-opped when they join the
|
||||||
|
channel, you'll need to load the <plugin>Enforcer</plugin>
|
||||||
|
plugin and turn its <registrygroup>autoOp</registrygroup>
|
||||||
|
configuration variable on. Use the
|
||||||
|
<botcommand>config</botcommand> command to do so. Here's
|
||||||
|
an example of how to do these steps:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch|lambda> I'm going to make an example session for giving
|
||||||
|
you auto-ops, for our FAQ.
|
||||||
|
<dunk1> ah ok ;]
|
||||||
|
<jemfinch|lambda> First, I need you to register with supybot, using
|
||||||
|
the "register" command (remember to send it in private).
|
||||||
|
<dunk1> done
|
||||||
|
<jemfinch|lambda> what name are you registered under?
|
||||||
|
<dunk1> dunk1
|
||||||
|
<jemfinch|lambda> ok, cool.
|
||||||
|
<jemfinch|lambda> @channel addcapability dunk1 op
|
||||||
|
<supybot> jemfinch|lambda: The operation succeeded.
|
||||||
|
<jemfinch|lambda> now use the "op" command to get ops.
|
||||||
|
<dunk1> @op
|
||||||
|
— supybot gives channel operator status to dunk1
|
||||||
|
<dunk1> works!
|
||||||
|
<dunk1> ;]
|
||||||
|
<jemfinch|lambda> @load Enforcer
|
||||||
|
<supybot> jemfinch|lambda: The operation succeeded.
|
||||||
|
<jemfinch|lambda> @config supybot.plugins.Enforcer.autoOp.#supybot On
|
||||||
|
<supybot> jemfinch|lambda: The operation succeeded.
|
||||||
|
<jemfinch|lambda> ok, now cycle the channel (part and then rejoin)
|
||||||
|
<– dunk1 (dunker@freebsd.nl) has left #supybot
|
||||||
|
–> dunk1 (dunker@freebsd.nl) has joined #supybot
|
||||||
|
— supybot gives channel operator status to dunk1
|
||||||
|
<jemfinch|lambda> cool, thanks :)
|
||||||
|
</ircsession>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
Can users with the <capability>admin</capability>
|
||||||
|
capability change configuration variables?
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
Currently, no. Since this is the first release of Supybot
|
||||||
|
that uses the registry, we wanted to stay on the
|
||||||
|
conservative side and require the
|
||||||
|
<capability>owner</capability> capability for changing all
|
||||||
|
non-channel-related configuration variables. Feel free to
|
||||||
|
make your case to us as to why a certain configuration
|
||||||
|
variable should only require the
|
||||||
|
<capability>admin</capability> capability instead of the
|
||||||
|
<capability>owner</capability> capability, and if we agree
|
||||||
|
with you, we'll change it for the next release.
|
||||||
|
</para>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
How do I make my Supybot connect to multiple servers?
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
You'll need to use the <plugin>Relay</plugin> plugin. As
|
||||||
|
long as you don't call the <botcommand>relay
|
||||||
|
join</botcommand> command, it won't actually do any
|
||||||
|
relaying between 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 call the <botcommand>relay
|
||||||
|
start</botcommand> command, followed by the
|
||||||
|
<botcommand>relay connect</botcommand> command. These
|
||||||
|
commands are (unfortunately) not persistent at this time,
|
||||||
|
so you'll need to give them to the bot anytime you start
|
||||||
|
it up. We'll probably have this lack of persistence
|
||||||
|
rectified before the next release.
|
||||||
|
</para>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
Can Supybot do factoids?
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
Supybot most certainly can! In fact, we offer two
|
||||||
|
full-fledged factoids-related plugins!
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<plugin>Factoids</plugin> (written by
|
||||||
|
<nick>jemfinch</nick>) is Supybot's original
|
||||||
|
factoids-related plugin. It offers full integration with
|
||||||
|
Supybot's nested commands as well as a complete 1:n key to
|
||||||
|
factoid ratio, with lookup by individual number.
|
||||||
|
<plugin>Factoids</plugin> also uses a channel-specific
|
||||||
|
database instead of a global database, although in the
|
||||||
|
future it will likely be a configuration option whether to
|
||||||
|
use channel-specific or global databases for such plugins.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<plugin>MoobotFactoids</plugin> (written by
|
||||||
|
<nick>Strike</nick>) is much more full-featured, offering
|
||||||
|
users the ability to define factoids in a slightly more
|
||||||
|
user-friendly way, as well as parsing factoids to handle
|
||||||
|
<reply>, <action>, "see", and alternations
|
||||||
|
(defining a factoid "test" as "<reply>(foo|bar|baz)"
|
||||||
|
will make the bot send "foo" or "bar" or "baz" to the
|
||||||
|
channel (without the normal "test is " at the beginning)).
|
||||||
|
If you're accustomed to Moobot's factoids or Blootbot's
|
||||||
|
factoids, then this is the Factoids plugin for you.
|
||||||
|
Unfortunately, due to the more natural definition syntax
|
||||||
|
(required to be compatible with Moobot) you can't define
|
||||||
|
Factoids with nested commands; you'll have to evaluate the
|
||||||
|
command first and then copy the result into your factoid
|
||||||
|
definition. <plugin>MoobotFactoids</plugin> uses a global
|
||||||
|
database, so the factoids are the same for all channels.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In the future, we plan to have a compatibility plugin for
|
||||||
|
Infobot, but as of present we've not yet written one.
|
||||||
|
</para>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
Can I import my Infobot/Blootbot/Moobot factoids into
|
||||||
|
Supybot?
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
As of present, we have no automated way to do so.
|
||||||
|
<nick>Strike</nick> has written a few scripts for
|
||||||
|
importing a Moobot database into
|
||||||
|
<plugin>MoobotFactoids</plugin>, however, so you'll want
|
||||||
|
to talk to him about helping you with that. We're
|
||||||
|
certainly happy to help you convert such databases; if you
|
||||||
|
can provide us with such a database exported to a flat
|
||||||
|
file, we can probably do the rest of the work to write a
|
||||||
|
script that imports it into a database for one of our
|
||||||
|
factoids-related plugins.
|
||||||
|
</para>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
I found a bug, what do I do?
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
Submit it on Sourceforge through our Sourceforge project
|
||||||
|
page:
|
||||||
|
<ulink
|
||||||
|
url="http://sourceforge.net/tracker/?group_id=58965&atid=489447">
|
||||||
|
http://sourceforge.net/tracker/?group_id=58965&atid=489447
|
||||||
|
</ulink>. If Sourceforge happens to be down when you try
|
||||||
|
to submit your bug, then post it in the "Supybot Developer
|
||||||
|
Discussion" forum at our forums at
|
||||||
|
<ulink url="http://forums.supybot.org">
|
||||||
|
http://forums.supybot.org/
|
||||||
|
</ulink>. If that doesn't work, email
|
||||||
|
<email>supybot-bugs@lists.sourceforge.net</email>. If
|
||||||
|
that doesn't work, email
|
||||||
|
<email>jemfinch@supybot.org</email>. If that doesn't
|
||||||
|
work, find yourself some carrier pigeons and … hah!
|
||||||
|
You thought I was serious!
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Anyway, when you submit your bug, we'll need several
|
||||||
|
things. If the bug involved an uncaught exception, we
|
||||||
|
need the traceback (basically the stuff from
|
||||||
|
“Uncaught exception in …” to the next
|
||||||
|
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 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 too little.
|
||||||
|
</para>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
<qandaentry>
|
||||||
|
<question>
|
||||||
|
<para>
|
||||||
|
Karma doesn't seem to work for me.
|
||||||
|
</para>
|
||||||
|
</question>
|
||||||
|
<answer>
|
||||||
|
<para>
|
||||||
|
<plugin>Karma</plugin> by default doesn't acknowledge
|
||||||
|
karma updates. If you check the karma of whatever you
|
||||||
|
increased/decreased, you'll note that your increment or
|
||||||
|
decrement still took place. If you'd rather
|
||||||
|
<plugin>Karma</plugin> acknowledge karma updates, change
|
||||||
|
the
|
||||||
|
<registrygroup>supybot.plugins.Karma.response</registrygroup>
|
||||||
|
configuration variable to <literal>On</literal>.
|
||||||
|
</para>
|
||||||
|
</answer>
|
||||||
|
</qandaentry>
|
||||||
|
</qandaset>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
|
297
docs/DocBook/getting_started.sgml
Normal file
297
docs/DocBook/getting_started.sgml
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<!DOCTYPE article SYSTEM "supybot.dtd">
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<articleinfo>
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>Jeremiah</firstname>
|
||||||
|
<surname>Fincher</surname>
|
||||||
|
</author>
|
||||||
|
<editor>
|
||||||
|
<firstname>Daniel</firstname>
|
||||||
|
<surname>DiPaolo</surname>
|
||||||
|
<contrib>DocBook translator</contrib>
|
||||||
|
</editor>
|
||||||
|
</authorgroup>
|
||||||
|
<title>Getting started with Supybot</title>
|
||||||
|
<revhistory>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.1</revnumber>
|
||||||
|
<date>18 Feb 2004</date>
|
||||||
|
<revremark>Initial Docbook translation</revremark>
|
||||||
|
</revision>
|
||||||
|
</revhistory>
|
||||||
|
</articleinfo>
|
||||||
|
<sect1>
|
||||||
|
<title>Introduction</title>
|
||||||
|
<para>
|
||||||
|
Ok, so you've decided to try out Supybot. That's great! The more
|
||||||
|
people who use Supybot, the more people can submit bugs and help
|
||||||
|
us to make it the best IRC bot in the world :)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
First things first: Supybot <emphasis>requires</emphasis> Python
|
||||||
|
2.3. There ain't no getting around it. If you're a Python
|
||||||
|
developer, you probably know how superior 2.3 is to previous
|
||||||
|
incarnations. If you're not, just think about the difference
|
||||||
|
between a bowl of plain vanilla ice cream and a banana split. Or
|
||||||
|
something like that. Either way, <emphasis>we're</emphasis>
|
||||||
|
Python developers and we like banana splits.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Installing the bot and its utilities</title>
|
||||||
|
<para>
|
||||||
|
So what do you do? First thing you'll want to do is run (with
|
||||||
|
root/admin privileges) <application>python setup.py
|
||||||
|
install</application>. This will install Supybot globally. If
|
||||||
|
you need to install locally for whatever reason, see this <ulink
|
||||||
|
url="http://tinyurl.com/2tb37">forum post</ulink> on how to do so.
|
||||||
|
You'll then have several new programs installed where Python
|
||||||
|
scripts are normally installed on your system
|
||||||
|
(<filename>/usr/bin</filename> or
|
||||||
|
<filename>/usr/local/bin</filename> are common on UNIX systems;
|
||||||
|
<filename>C:\Python23\Scripts</filename> is a common place on
|
||||||
|
Windows; and (watch out, this is a long one :))
|
||||||
|
<filename>/System/Library/Frameworks/Python.framework/Versions/2.3/bin</filename>
|
||||||
|
is a common place on MacOS X.). The two that might be of
|
||||||
|
particular interest to you, the new user, are
|
||||||
|
<script>supybot</script> and
|
||||||
|
<script>supybot-wizard</script> The former
|
||||||
|
(<script>supybot</script> is the script to run an actual
|
||||||
|
bot; the latter (<script>supybot-wizard</script> is an
|
||||||
|
in-depth wizard that provides a nice user interface for creating
|
||||||
|
configuration files for your bot. We'd prefer you to the use
|
||||||
|
<script>supybot-wizard</script>, but if you're in a
|
||||||
|
hurry or don't feel like being asked many questions, just run
|
||||||
|
supybot with no arguments and it'll ask you only the questions
|
||||||
|
necessary ")to run a bot.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Firing up the bot for the first time</title>
|
||||||
|
<para>
|
||||||
|
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 any of the questions you were asked, feel free to run the
|
||||||
|
program again until you're satisfied with all your answers. Once
|
||||||
|
you're satisfied, though, run the
|
||||||
|
<script>supybot</script> program with the
|
||||||
|
registry file you created as an argument. This will start the
|
||||||
|
bot; unless you turned off logging to stdout, you'll see some nice
|
||||||
|
log messages describing what the bot is doing at any particular
|
||||||
|
moment; it may pause for a significant amount of time after saying
|
||||||
|
"Connecting to ..." while the server tries to check its ident.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Your first interactions with the bot</title>
|
||||||
|
<para>
|
||||||
|
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 bot <nick>supybot</nick> (you probably didn't,
|
||||||
|
but it'll make it much clearer in the examples that follow to
|
||||||
|
assume that you did). We'll also assume that you told it to join
|
||||||
|
<channel>#channel</channel> (a nice generic name for a channel,
|
||||||
|
isn't it? :)) So what do you do with this bot that you just made
|
||||||
|
to join your channel? Try this in the channel:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
supybot: list
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Replacing <nick>supybot</nick> with the actual name you
|
||||||
|
picked for your bot, of course. Your bot should reply with a list
|
||||||
|
of the plugins he currently has loaded. At least
|
||||||
|
<plugin>Admin</plugin>, <plugin>Channel</plugin>,
|
||||||
|
<plugin>Config</plugin>, <plugin>Misc</plugin>,
|
||||||
|
<plugin>Owner</plugin>, and <plugin>User</plugin> should be
|
||||||
|
there; if you used <script>supybot-wizard</script> to
|
||||||
|
create your configuration file you may have many more plugins
|
||||||
|
loaded. The <botcommand>list</botcommand> command can also be used to
|
||||||
|
list the commands in a given plugin:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
supybot: list Misc
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Will list all the commands in the <plugin>Misc</plugin> plugin.
|
||||||
|
</para>
|
||||||
|
<sect2>
|
||||||
|
<title>Accessing the bot's online help</title>
|
||||||
|
<para>
|
||||||
|
If you want to see the help for any command, just use
|
||||||
|
the <botcommand>help</botcommand> command:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
supybot: help help
|
||||||
|
supybot: help list
|
||||||
|
supybot: help load
|
||||||
|
</ircsession>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title>Dealing with ambiguous commands</title>
|
||||||
|
<para>
|
||||||
|
Sometimes more than one plugin will have a given command; for
|
||||||
|
instance, the <botcommand>list</botcommand> command exists in both
|
||||||
|
the <plugin>Misc</plugin> and <plugin>Config</plugin>
|
||||||
|
plugins (both loaded by default). <plugin>List</plugin>, in
|
||||||
|
this case, defaults to the <plugin>Misc</plugin> plugin, but
|
||||||
|
you may want to get the help for the
|
||||||
|
<botcommand>list</botcommand>
|
||||||
|
command in the <plugin>Config</plugin> plugin. In that
|
||||||
|
case, you'll want to give your command like this:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
supybot: help config list
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Anytime your bot tells you that a given command is defined in
|
||||||
|
several plugins, you'll want to use this syntax
|
||||||
|
(<botcommand>plugin command</botcommand>) to disambiguate which
|
||||||
|
plugin's command you wish to call. For instance, if you
|
||||||
|
wanted to call the <plugin>Config</plugin> plugin's
|
||||||
|
<botcommand>list</botcommand> command, then you'd need to say:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
supybot: config list
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Rather than just <botcommand>list</botcommand>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title>Loading plugins</title>
|
||||||
|
<para>
|
||||||
|
Now that you know how to deal with plugins having commands
|
||||||
|
with the same name, let's take a look at loading other
|
||||||
|
plugins. If you didn't use
|
||||||
|
<script>supybot-wizard</script>, though, you might
|
||||||
|
do well to try it before playing around with loading plugins
|
||||||
|
yourself: each plugin has its own
|
||||||
|
<function>configure</function> function that the wizard uses
|
||||||
|
to setup the appropriate registry entries if the plugin
|
||||||
|
requires any.
|
||||||
|
</para>
|
||||||
|
<sect3>
|
||||||
|
<title>Identifying yourself as the bot owner</title>
|
||||||
|
<para>
|
||||||
|
Now, if you do want to play around with loading plugins,
|
||||||
|
you're going to need to have the
|
||||||
|
<capability>owner</capability>
|
||||||
|
capability. If you ran the wizard, then chances are you
|
||||||
|
already added an owner user for yourself. If not,
|
||||||
|
however, you can add one via the handy-dandy
|
||||||
|
<script>supybot-adduser</script> script. You'll
|
||||||
|
want to run it while the bot is not running (otherwise it
|
||||||
|
could overwrite
|
||||||
|
<script>supybot-adduser</script>'s changes to
|
||||||
|
your user database before you get a chance to reload
|
||||||
|
them). Just follow the prompts, and when it asks if you
|
||||||
|
want to give the user any capabilities, say yes and then
|
||||||
|
give yourself the <capability>owner</capability> capability
|
||||||
|
(without the quotes), restart the bot and you'll be ready
|
||||||
|
to load some plugins!
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Now, in order for the bot to recognize you as your owner
|
||||||
|
user, you'll have to identify with the bot. Open up a
|
||||||
|
query window in your irc client (/query should do it; if
|
||||||
|
not, just know that you can't identify in a channel
|
||||||
|
because it requires sending your password to the bot).
|
||||||
|
Then type this:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
help identify
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
And follow the instructions; the command you send will
|
||||||
|
probably look like this, with your owner user and password
|
||||||
|
replaced:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
identify myowneruser myuserpassword
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
The bot will tell you that “The operation
|
||||||
|
succeeded” if you got the right name and password.
|
||||||
|
Now that you're identified, you can do anything that
|
||||||
|
requires any privilege: that includes all the commands in
|
||||||
|
the <plugin>Owner</plugin> and <plugin>Admin</plugin>
|
||||||
|
plugins, which you may want to take a look at (using the
|
||||||
|
<botcommand>list</botcommand> and
|
||||||
|
<botcommand>help</botcommand>
|
||||||
|
commands, of course). One command in particular that you
|
||||||
|
might want to use (it's from the <plugin>User</plugin>
|
||||||
|
plugin) is the <botcommand>addhostmask</botcommand> command: it
|
||||||
|
lets you add a hostmask to your user record so the bot
|
||||||
|
recognizes you by your hostmask instead of requiring you
|
||||||
|
to always identify with it before it recognizes you. Use
|
||||||
|
the <botcommand>help</botcommand> command to see how this
|
||||||
|
command works. Here's how I often use it:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
addhostmask myuser [hostmask] mypassword
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
You may not have seen that "[hostmask]" syntax before.
|
||||||
|
Supybot allows nested commands, which means that any
|
||||||
|
command's output can be nested as an argument to another
|
||||||
|
command. The hostmask command from the
|
||||||
|
<plugin>Misc</plugin> plugin returns the hostmask of a
|
||||||
|
given nick, but if given no arguments, it returns the
|
||||||
|
hostmask of the person giving the command. So the command
|
||||||
|
above adds the hostmask I'm currently using to my user's
|
||||||
|
list of recognized hostmasks. I'm only required to give
|
||||||
|
<literal>mypassword</literal> if I'm not already
|
||||||
|
identified with the bot.
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title>The <botcommand>more</botcommand> command</title>
|
||||||
|
<para>
|
||||||
|
Another command you might find yourself needing somewhat often
|
||||||
|
is the <botcommand>more</botcommand> command. The IRC protocol
|
||||||
|
limits messages to 512 bytes, 60 or so of which must be
|
||||||
|
devoted to some bookkeeping. Sometimes, however, Supybot
|
||||||
|
wants to send a message that's longer than that. What it
|
||||||
|
does, then, is break it into "chunks" and send the first one,
|
||||||
|
following it with "(X more messages)" where X is how many more
|
||||||
|
chunks there are. To get to these chunks, use the more
|
||||||
|
command. One way to try is to look at the listing of
|
||||||
|
configuration groups for the bot (more on this in the
|
||||||
|
CONFIGURATION document) by giving the command "config list
|
||||||
|
supybot". Last I checked, it'll overflow into a second chunk.
|
||||||
|
When you invoke this command, you should see output like:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<supybot> nick, ident, user, server, password, channels, prefixChars,
|
||||||
|
defaultCapabilities, defaultAllow, defaultIgnore,
|
||||||
|
humanTimestampFormat, externalIP, bracketSyntax, pipeSyntax,
|
||||||
|
followIdentificationThroughNickChanges, alwaysJoinOnInvite,
|
||||||
|
showSimpleSyntax, maxHistoryLength, nickmods, throttleTime,
|
||||||
|
snarfThrottle, threadAllCommands, pingServer, pingInterval,
|
||||||
|
upkeepInterval, flush, (1 more message)
|
||||||
|
</ircsession>
|
||||||
|
<para>
|
||||||
|
Now, to see the rest of the output, simply give the command
|
||||||
|
<botcommand>more</botcommand>, and it will show you the rest:
|
||||||
|
</para>
|
||||||
|
<ircsession>
|
||||||
|
<jemfinch> more
|
||||||
|
<supybot> httpPeekSize, and defaultSocketTimeout
|
||||||
|
</ircsession>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>You're ready!</title>
|
||||||
|
<para>
|
||||||
|
You should now have a solid foundation for using Supybot. Be sure
|
||||||
|
to check the help that is built-in to the bot itself if you have
|
||||||
|
any questions, and enjoy using Supybot!
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
|
585
docs/DocBook/interfaces.sgml
Normal file
585
docs/DocBook/interfaces.sgml
Normal file
@ -0,0 +1,585 @@
|
|||||||
|
<!DOCTYPE article SYSTEM "supybot.dtd">
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<articleinfo>
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>Jeremiah</firstname>
|
||||||
|
<surname>Fincher</surname>
|
||||||
|
</author>
|
||||||
|
<editor>
|
||||||
|
<firstname>Daniel</firstname>
|
||||||
|
<surname>DiPaolo</surname>
|
||||||
|
<contrib>DocBook translator</contrib>
|
||||||
|
</editor>
|
||||||
|
</authorgroup>
|
||||||
|
<title>Supybot developer interfaces</title>
|
||||||
|
<revhistory>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.1</revnumber>
|
||||||
|
<date>19 Feb 2004</date>
|
||||||
|
<revremark>Initial Docbook translation</revremark>
|
||||||
|
</revision>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.2</revnumber>
|
||||||
|
<date>26 Feb 2004</date>
|
||||||
|
<revremark>Converted to Supybot DTD</revremark>
|
||||||
|
</revision>
|
||||||
|
</revhistory>
|
||||||
|
</articleinfo>
|
||||||
|
<sect1>
|
||||||
|
<title>Available interfaces</title>
|
||||||
|
<para>
|
||||||
|
These are the interfaces for some of the objects you'll deal with
|
||||||
|
if you code for Supybot.
|
||||||
|
</para>
|
||||||
|
<sect2>
|
||||||
|
<title><classname>ircmsgs.IrcMsg</classname>
|
||||||
|
<para>
|
||||||
|
This is the object that represents an IRC message. It has
|
||||||
|
several methods and attributes. The most important thing
|
||||||
|
about this class, however, is that it <emphasis>is</emphasis>
|
||||||
|
hashable, and thus <emphasis>cannot</emphasis> be modified.
|
||||||
|
Do not change any attributes; any code that modifies an IRC
|
||||||
|
message is <emphasis>broken</emphasis> and should not exist.
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<title>Interesting methods</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>__init__</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
One of the more complex initializers in a class.
|
||||||
|
It can be used in three different ways:
|
||||||
|
</para>
|
||||||
|
<orderedlist numeration="arabic" spacing="normal">
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
It can be given a string, as one received
|
||||||
|
from the server, which it will then parse
|
||||||
|
into its separate components and
|
||||||
|
instantiate the class with those
|
||||||
|
components as attributes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
It can be given a command, some (optional)
|
||||||
|
arguments, and a (optional) prefix, and
|
||||||
|
will instantiate the class with those
|
||||||
|
components as attributes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
It can be given, in addition to any of the
|
||||||
|
above arguments, a <varname>msg</varname>
|
||||||
|
keyword argument that will use the
|
||||||
|
attributes of msg as defaults. This
|
||||||
|
exists to make it easier to copy messages,
|
||||||
|
since the class is immutable.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>__str__</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This returns the message in a string form suitable
|
||||||
|
for sending to a server.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>__repr__</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This returns the message in a form suitable for
|
||||||
|
<function>eval()</function>, assuming the name
|
||||||
|
<varname>IrcMsg</varname> is in your namespace and
|
||||||
|
is bound to this class.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
<para>
|
||||||
|
The following attributes are the meat of this class. These
|
||||||
|
are generally what you'll be looking at with
|
||||||
|
<varname>IrcMsg</varname>s.
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<title>Interesting attributes</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>command</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This is the command of the
|
||||||
|
<varname>IrcMsg</varname> –
|
||||||
|
<literal>PRIVMSG</literal>,
|
||||||
|
<literal>NOTICE</literal>,
|
||||||
|
<literal>WHOIS</literal>,
|
||||||
|
etc.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>args</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This is a tuple of the arguments to the
|
||||||
|
<varname>IrcMsg</varname>. Some messages have
|
||||||
|
arguments, some don't, depending on what command
|
||||||
|
they are. You are, of course, always assured that
|
||||||
|
<varname>args</varname> exists and is a tuple,
|
||||||
|
though it might be empty.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>prefix</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This is the hostmask of the person/server the
|
||||||
|
message is from. In general, you won't be setting
|
||||||
|
this on your outgoing messages, but incoming
|
||||||
|
messages will always have one. This is the whole
|
||||||
|
hostmask; if the message was received from a
|
||||||
|
server, it'll be the server's hostmask; if the
|
||||||
|
message was received from a user, it'll be the
|
||||||
|
whole user hostmask. In that case, however, it's
|
||||||
|
also parsed out into the
|
||||||
|
<varname>nick</varname>/<varname>user</varname>/<varname>host</varname>
|
||||||
|
attributes, which are probably more useful to
|
||||||
|
check for many purposes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>nick</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If the message was sent by a user, this will be
|
||||||
|
the nick of the user. If it was sent by a server,
|
||||||
|
this will be the server's name (something like
|
||||||
|
<literal>calvino.freenode.net</literal> or
|
||||||
|
similar).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>user</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If the message was sent by a user, this will be
|
||||||
|
the user string of the user – what they put
|
||||||
|
into their IRC client for their "full name." If
|
||||||
|
it was sent by a server, it'll be the server's
|
||||||
|
name, again.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>host</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If the message was sent by a user, this will be
|
||||||
|
the host portion of their hostmask. If it was
|
||||||
|
sent by a server, it'll be the server's name (yet
|
||||||
|
again :))
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title><classname>irclib.Irc</classname>
|
||||||
|
<para>
|
||||||
|
This is the object to handle everything about IRC except the
|
||||||
|
actual connection to the server itself.
|
||||||
|
(<emphasis>NOTE</emphasis> that the object actually received
|
||||||
|
by commands in subclasses of
|
||||||
|
<classname>callbacks.Privmsg</classname> is an
|
||||||
|
<classname>IrcObjectProxy</classname>, which is described
|
||||||
|
later. It augments the following interface with several
|
||||||
|
methods of its own to help plugin authors.)
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<title>Interesting methods</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>queueMsg</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Queues a message for sending to the server. The
|
||||||
|
queue is generally FIFO, but it does prioritize
|
||||||
|
messages based on their command.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>sendMsg</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Queues a message for sending to the server prior
|
||||||
|
to any messages in the normal queue. This is
|
||||||
|
exactly a FIFO queue, no reordering is done at
|
||||||
|
all.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<!--<note>
|
||||||
|
<para>
|
||||||
|
The following two methods are the most important for
|
||||||
|
people writing new <varname>IrcDriver</varname>s.
|
||||||
|
Otherwise, you really don't need to pay attention to
|
||||||
|
them.
|
||||||
|
</para>
|
||||||
|
</note>-->
|
||||||
|
<varlistentry>
|
||||||
|
<term>feedMsg</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Feeds the <varname>Irc</varname> object a message
|
||||||
|
for it handle appropriately, as well as passing it
|
||||||
|
on to callbacks.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>takeMsg</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If the <varname>Irc</varname> object has a message
|
||||||
|
it's ready to send to the server, this will return
|
||||||
|
it. Otherwise, it will return
|
||||||
|
<literal>None</literal>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<!--<note>
|
||||||
|
<para>
|
||||||
|
The next several methods are of far more marginal
|
||||||
|
utility. But someone may need them, so they're
|
||||||
|
documented here.
|
||||||
|
</para>
|
||||||
|
</note>-->
|
||||||
|
<varlistentry>
|
||||||
|
<term>addCallback</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Takes a callback to add to the list of callbacks
|
||||||
|
in the <varname>Irc</varname> object. See the
|
||||||
|
interface for <varname>IrcCallback</varname> for
|
||||||
|
more information.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>getCallback</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Gets a callback by name, if it is in the
|
||||||
|
<varname>Irc</varname> object's list of callbacks.
|
||||||
|
If it it isn't, returns <literal>None</literal>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>removeCallback</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Removes a callback by name. Returns a list of the
|
||||||
|
callbacks removed (since it is technically
|
||||||
|
possible to have multiple callbacks with the same
|
||||||
|
name. This list may be empty.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>__init__</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Requires a <varname>nick</varname>. Optional
|
||||||
|
arguments include <varname>user</varname> and
|
||||||
|
<varname>ident</varname>, which default to the
|
||||||
|
nick given, <varname>password</varname>, which
|
||||||
|
defaults to the empty password, and
|
||||||
|
<varname>callbacks</varname>, a list of callbacks
|
||||||
|
(which defaults to nothing, an empty list).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>reset</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Resets the <varname>Irc</varname> object to its
|
||||||
|
original state, as well as sends a
|
||||||
|
<function>reset()</function> to every callbacks.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>die</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Kills the IRC object and all its callbacks.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
<variablelist>
|
||||||
|
<title>Interesting attributes</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>nick</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The current nick of the bot.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>prefix</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The current prefix of the bot.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>server</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The current server the bot is connected to.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>network</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The current network name the bot is connected to.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>afterConnect</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>False</literal> until the bot has
|
||||||
|
received a command sent after the connection is
|
||||||
|
finished – 376, 377, or 422.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>state</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
An <varname>IrcState</varname> object for this
|
||||||
|
particular connection. See the interface for the
|
||||||
|
<varname>IrcState</varname> object for more
|
||||||
|
information.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title><classname>irclib.IrcCallback</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<title>Interesting Methods</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>name</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Returns the name of the callback. The default
|
||||||
|
implementation simply returns the name of the
|
||||||
|
class.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>__call__</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Called by the <varname>Irc</varname> object with
|
||||||
|
itself and the message whenever a message is fed
|
||||||
|
to the <varname>Irc</varname> object. Nothing is
|
||||||
|
done with the return value.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>inFilter</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Called by the <varname>Irc</varname> object with
|
||||||
|
itself and the message whenever a message is fed
|
||||||
|
to the <varname>Irc</varname> object. The return
|
||||||
|
value should be an <varname>IrcMsg</varname>
|
||||||
|
object to be passed to the next callback in the
|
||||||
|
<varname>Irc</varname>'s list of callbacks. If
|
||||||
|
<literal>None</literal> is returned, all
|
||||||
|
processing stops. This gives callbacks an
|
||||||
|
oppurtunity to "filter" incoming messages before
|
||||||
|
general callbacks are given them.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>outFilter</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Basically equivalent to
|
||||||
|
<varname>inFilter</varname>, except instead of
|
||||||
|
being called on messages as they enter the
|
||||||
|
<varname>Irc</varname> object, it's called on
|
||||||
|
messages as they leave the <varname>Irc</varname>
|
||||||
|
object.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>die</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Called when the parent <varname>Irc</varname> is
|
||||||
|
told to die. This gives callbacks an oppurtunity
|
||||||
|
to close open files, network connections, or
|
||||||
|
databases before they're deleted.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>reset</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Called when the parent <varname>Irc</varname> is
|
||||||
|
told to reset (which is generally when
|
||||||
|
reconnecting to the server). Most callbacks don't
|
||||||
|
need to define this.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
<variablelist>
|
||||||
|
<title>Interesting attributes</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>priority</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Determines the priority of the callback in the
|
||||||
|
<varname>Irc</varname> object's list of callbacks.
|
||||||
|
Defaults to <literal>99</literal>; the valid range
|
||||||
|
includes <literal>0</literal> through
|
||||||
|
<literal>sys.maxint-1</literal> (don't use
|
||||||
|
<literal>sys.maxint</literal> itself, that's
|
||||||
|
reserved for the <varname>Misc</varname> plugin).
|
||||||
|
The lower the number, the higher the priority.
|
||||||
|
High priority callbacks are called earlier in the
|
||||||
|
<varname>inFilter</varname> cycle, earlier in the
|
||||||
|
<varname>__call__</varname> cycle, and later in
|
||||||
|
the <varname>outFilter</varname> cycle –
|
||||||
|
basically, they're given the first chances on the
|
||||||
|
way in and the last chances on the way out.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title><classname>callbacks.IrcObjectProxy</classname></title>
|
||||||
|
<para>
|
||||||
|
<classname>IrcObjectProxy</classname> is a proxy for an
|
||||||
|
<classname>irclib.Irc</classname> instance that serves to
|
||||||
|
provide a much fuller interface for handling replies and
|
||||||
|
errors as well as to handle the nesting of commands. This is
|
||||||
|
what you'll be dealing with almost all the time when writing
|
||||||
|
commands; when writing <function>doCommand</function> methods
|
||||||
|
(the kind you read about in the interface description of
|
||||||
|
<classname>irclib.IrcCallback</classname>) you'll be dealing
|
||||||
|
with plain old <classname>irclib.Irc</classname> objects.
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<title>Interesting methods</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>reply</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Called to reply to the current message with a
|
||||||
|
string that is to be the reply. Uses the
|
||||||
|
<function>queueMsg</function> command discussed in
|
||||||
|
the <classname>irclib.Irc</classname> section.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>replySuccess</term>
|
||||||
|
<term>replyError</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
These reply with the configured responses for
|
||||||
|
success and generic error, respectively. If an
|
||||||
|
additional argument is given, it's (intelligently)
|
||||||
|
appended to the generic message to be more
|
||||||
|
specific.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>error</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Called to send an error reply to the current
|
||||||
|
message; not only does the response indicate an
|
||||||
|
error, but commands that error out break the
|
||||||
|
nested-command chain, which is generally useful
|
||||||
|
for not confusing the user :)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>errorNoCapability</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Like <function>error</function>, except it accepts
|
||||||
|
the capability that's missing and integrates it
|
||||||
|
into the configured error message for such things.
|
||||||
|
Also accepts an additional string for a more
|
||||||
|
descriptive message, if that's what you want.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>errorPossibleBug</term>
|
||||||
|
<term>errorNotRegistered</term>
|
||||||
|
<term>errorNoUser</term>
|
||||||
|
<term>errorRequiresPrivacy</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
These methods reply with the appropriate
|
||||||
|
configured error message for the conditions in
|
||||||
|
their names; they all take an additional arguments
|
||||||
|
to be more specific about the conditions they
|
||||||
|
indicate, but this argument is very rarely
|
||||||
|
necessary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>getRealIrc</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Returns the actual <classname>Irc</classname>
|
||||||
|
object being proxied for.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
|
46
docs/DocBook/supybot-html.dsl
Normal file
46
docs/DocBook/supybot-html.dsl
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
(define %stylesheet% "../stylesheets/supybot.css")
|
||||||
|
|
||||||
|
(element botcommand
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "botcommand"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element plugin
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "plugin"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element flag
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "flag"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element nick
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "nick"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element capability
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "capability"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element registrygroup
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "registrygroup"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element ircsession
|
||||||
|
(make element gi: "pre"
|
||||||
|
attributes: '(("class" "ircsession"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element script
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "script"))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element channel
|
||||||
|
(make element gi: "span"
|
||||||
|
attributes: '(("class" "channel"))
|
||||||
|
(process-children)))
|
43
docs/DocBook/supybot-print.dsl
Normal file
43
docs/DocBook/supybot-print.dsl
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
(define %mono-font-family% "Courier New")
|
||||||
|
|
||||||
|
(element botcommand
|
||||||
|
(make sequence
|
||||||
|
font-family-name: %mono-font-family%))
|
||||||
|
|
||||||
|
(element plugin
|
||||||
|
(make sequence
|
||||||
|
font-weight: 'bold))
|
||||||
|
|
||||||
|
(element flag
|
||||||
|
(make sequence
|
||||||
|
font-posture: 'italic))
|
||||||
|
|
||||||
|
(element nick
|
||||||
|
(make sequence
|
||||||
|
font-family-name: %mono-font-family%))
|
||||||
|
|
||||||
|
(element capability
|
||||||
|
(make sequence
|
||||||
|
font-weight: 'bold))
|
||||||
|
|
||||||
|
(element registrygroup
|
||||||
|
(make sequence
|
||||||
|
font-weight: 'bold))
|
||||||
|
|
||||||
|
(element ircsession
|
||||||
|
(make paragraph
|
||||||
|
font-family-name: %mono-font-family%
|
||||||
|
space-before: 12pt
|
||||||
|
space-after: 12pt
|
||||||
|
start-indent: 6pt
|
||||||
|
lines: 'asis
|
||||||
|
input-whitespace-treatment: 'preserve))
|
||||||
|
|
||||||
|
(element script
|
||||||
|
(make sequence
|
||||||
|
font-family-name: %mono-font-family%))
|
||||||
|
|
||||||
|
(element channel
|
||||||
|
(make sequence
|
||||||
|
font-weight: 'bold))
|
||||||
|
|
23
docs/DocBook/supybot.dsl
Normal file
23
docs/DocBook/supybot.dsl
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
|
||||||
|
<!ENTITY print-ss PUBLIC
|
||||||
|
"-//Norman Walsh//DOCUMENT DocBook Print Stylesheet//EN" CDATA DSSSL>
|
||||||
|
<!ENTITY html-ss PUBLIC
|
||||||
|
"-//Norman Walsh//DOCUMENT DocBook HTML Stylesheet//EN" CDATA DSSSL>
|
||||||
|
<!ENTITY supybot-print SYSTEM "supybot-print.dsl">
|
||||||
|
<!ENTITY supybot-html SYSTEM "supybot-html.dsl">
|
||||||
|
]>
|
||||||
|
|
||||||
|
<style-sheet>
|
||||||
|
<style-specification id="print" use="print-stylesheet">
|
||||||
|
<style-specification-body>
|
||||||
|
&supybot-print;
|
||||||
|
</style-specification-body>
|
||||||
|
</style-specification>
|
||||||
|
<style-specification id="html" use="html-stylesheet">
|
||||||
|
<style-specification-body>
|
||||||
|
&supybot-html;
|
||||||
|
</style-specification-body>
|
||||||
|
</style-specification>
|
||||||
|
<external-specification id="print-stylesheet" document="print-ss">
|
||||||
|
<external-specification id="html-stylesheet" document="html-ss">
|
||||||
|
</style-sheet>
|
137
docs/DocBook/supybot.dtd
Normal file
137
docs/DocBook/supybot.dtd
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<!-- Segregate all of our stuff into its own class for possible extension
|
||||||
|
later and just because I wanted to write my own class :) -->
|
||||||
|
<!ENTITY % local.supybot.class "">
|
||||||
|
<!ENTITY % supybot.class "BotCommand|Plugin|Flag|Nick|Capability
|
||||||
|
|RegistryGroup|Registry|Script
|
||||||
|
|Channel %local.supybot.class;">
|
||||||
|
|
||||||
|
<!-- Stuff that isn't supybot-specific, but it's python-related and no
|
||||||
|
suitable element exists in the DocBook DTD -->
|
||||||
|
<!ENTITY % local.python.class "">
|
||||||
|
<!ENTITY % python.class "Module|Keyword %local.python.class;">
|
||||||
|
|
||||||
|
<!-- Pretty much all of our stuff fits where stuff in the tech.char class
|
||||||
|
goes, so we simply add our stuff using the local extension -->
|
||||||
|
<!ENTITY % local.tech.char.class "|%supybot.class;|%python.class;">
|
||||||
|
|
||||||
|
<!-- linespecific is the same class as things like screen and programlisting,
|
||||||
|
so it's added here to fit with the DocBook stuff (i.e., so putting an
|
||||||
|
ircsession in where one of those previous two elements would be is a
|
||||||
|
valid operation -->
|
||||||
|
<!ENTITY % local.linespecific.class "|IrcSession">
|
||||||
|
|
||||||
|
<!-- Source the original DocBook DTD -->
|
||||||
|
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||||
|
%DocBookDTD;
|
||||||
|
|
||||||
|
<!ELEMENT BotCommand - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.botcommand.attrib "">
|
||||||
|
<!ENTITY % botcommand.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST BotCommand
|
||||||
|
%common.attrib;
|
||||||
|
%local.botcommand.attrib;
|
||||||
|
%botcommand.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Plugin - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.plugin.attrib "">
|
||||||
|
<!ENTITY % plugin.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Plugin
|
||||||
|
%common.attrib;
|
||||||
|
%local.plugin.attrib;
|
||||||
|
%plugin.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Flag - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.flag.attrib "">
|
||||||
|
<!ENTITY % flag.role.attrib
|
||||||
|
"
|
||||||
|
flagtype (arg|noarg) #IMPLIED
|
||||||
|
%role.attrib;"
|
||||||
|
>
|
||||||
|
<!ATTLIST Flag
|
||||||
|
%common.attrib;
|
||||||
|
%local.flag.attrib;
|
||||||
|
%flag.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Nick - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.nick.attrib "">
|
||||||
|
<!ENTITY % nick.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Nick
|
||||||
|
%common.attrib;
|
||||||
|
%local.nick.attrib;
|
||||||
|
%nick.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Capability - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.capability.attrib "">
|
||||||
|
<!ENTITY % capability.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Capability
|
||||||
|
%common.attrib;
|
||||||
|
%local.capability.attrib;
|
||||||
|
%capability.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Comment - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.comment.attrib "">
|
||||||
|
<!ENTITY % comment.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Comment
|
||||||
|
%common.attrib;
|
||||||
|
%local.comment.attrib;
|
||||||
|
%comment.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT RegistryGroup - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.registrygroup.attrib "">
|
||||||
|
<!ENTITY % registrygroup.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST RegistryGroup
|
||||||
|
%common.attrib;
|
||||||
|
%local.registrygroup.attrib;
|
||||||
|
%registrygroup.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Registry - - ((RegistryGroup|Comment)+)>
|
||||||
|
<!ENTITY % local.registry.attrib "">
|
||||||
|
<!ENTITY % registry.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Registry
|
||||||
|
%common.attrib;
|
||||||
|
%local.registry.attrib;
|
||||||
|
%registry.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT IrcSession - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.ircsession.attrib "">
|
||||||
|
<!ENTITY % ircsession.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST IrcSession
|
||||||
|
%common.attrib;
|
||||||
|
%local.ircsession.attrib;
|
||||||
|
%ircsession.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Script - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.script.attrib "">
|
||||||
|
<!ENTITY % script.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Script
|
||||||
|
%common.attrib;
|
||||||
|
%local.script.attrib;
|
||||||
|
%script.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Channel - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.channel.attrib "">
|
||||||
|
<!ENTITY % channel.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Channel
|
||||||
|
%common.attrib;
|
||||||
|
%local.channel.attrib;
|
||||||
|
%channel.role.attrib;
|
||||||
|
>
|
||||||
|
|
||||||
|
<!ELEMENT Module - - ((%smallcptr.char.mix)+)>
|
||||||
|
<!ENTITY % local.module.attrib "">
|
||||||
|
<!ENTITY % module.role.attrib "%role.attrib;">
|
||||||
|
<!ATTLIST Module
|
||||||
|
%common.attrib;
|
||||||
|
%local.module.attrib;
|
||||||
|
%module.role.attrib;
|
||||||
|
>
|
Loading…
x
Reference in New Issue
Block a user