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