diff --git a/locale/fr/LC_MESSAGES/contribute.po b/locale/fr/LC_MESSAGES/contribute.po new file mode 100644 index 0000000..ee7d1ff --- /dev/null +++ b/locale/fr/LC_MESSAGES/contribute.po @@ -0,0 +1,346 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2003-2015, the Limnoria/Gribble/Supybot contributors +# This file is distributed under the same license as the Limnoria package. +# FIRST AUTHOR , 2016. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Limnoria 0.83\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-02-24 17:46+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.2.0\n" + +#: ../../contribute/develop.rst:5 +msgid "Contributing to Limnoria as a developer" +msgstr "" + +#: ../../contribute/develop.rst:9 +msgid "This page is still a draft and is not complete." +msgstr "" + +#: ../../contribute/develop.rst:14 +msgid "About the policy about repository access" +msgstr "" + +#: ../../contribute/develop.rst:16 +msgid "" +"For the moment, I decided to give write access to my repository to " +"nobody, because I want to check everything that is pushed in it. If " +"someone pushes a bad update, it may be dangerous for users and I do not " +"want that." +msgstr "" + +#: ../../contribute/develop.rst:20 +#, python-format +msgid "" +"On the other side, I am **very** open to pull requests, that's to say, if" +" you ask me to merge some changes you made, there are 99% changes I will " +"merge this changes. That's why I suggest you to fork my repository on " +"GitHub, make your modifications, and click the \"Pull requests\" button " +"in my repository." +msgstr "" + +#: ../../contribute/develop.rst:27 +msgid "Using Git" +msgstr "" + +#: ../../contribute/develop.rst:29 +msgid "" +"If you are a developer, I assume that you know how to use Git. If you " +"don't, I suggest you to learn how to use it, at least the basics (clone, " +"checkout, branch, commit, push/pull, add/rm, log, show, reset, revert)." +msgstr "" + +#: ../../contribute/develop.rst:33 +msgid "" +"I learnt how to use Git with an ebook, also available as a real book: " +"`Pro Git`_." +msgstr "" + +#: ../../contribute/develop.rst:36 +msgid "" +"Our prefered way of contributing is through GitHub pull requests to " +"`Limnoria's repository`_. Please send your pull requests to the `testing`" +" branch." +msgstr "" + +#: ../../contribute/develop.rst:44 +msgid "Where to start" +msgstr "" + +#: ../../contribute/develop.rst:46 +msgid "" +"If you are not an experienced Python and/or Limnoria developper, you can " +"start with solving `issues tagged as easy`_. I believe they are likely to" +" be easy to solve even without a lot of experience." +msgstr "" + +#: ../../contribute/develop.rst:50 +msgid "" +"If you need help solving an issue (tagged as easy or not) or want to find" +" an issue that matches your skills, please ask on IRC, we will be glad to" +" help you." +msgstr "" + +#: ../../contribute/develop.rst:57 +msgid "Code style" +msgstr "" + +#: ../../contribute/develop.rst:59 +msgid "Read the doc in the source code (docs/STYLE.rst)." +msgstr "" + +#: ../../contribute/index.rst:5 +msgid "Contributing to Limnoria" +msgstr "" + +#: ../../contribute/translate.rst:7 +msgid "Translating Limnoria" +msgstr "" + +#: ../../contribute/translate.rst:9 +msgid "" +"I already wrote a `guide on how to translate`_ plugins. So, this page " +"will only explain how to translate the core and push your translations to" +" Limnoria." +msgstr "" + +#: ../../contribute/translate.rst:16 +msgid "The best way: using Git yourself" +msgstr "" + +#: ../../contribute/translate.rst:18 +msgid "" +"As I said in the :ref:`policy about developer's contributions " +"`, I don't give write access to my repo for " +"the moment, but I accept pull requests." +msgstr "" + +#: ../../contribute/translate.rst:22 +msgid "" +"As you are a translator, you don't need to know all the technical details" +" about development, so I write a simplified doc here." +msgstr "" + +#: ../../contribute/translate.rst:26 +msgid "Preparing git" +msgstr "" + +#: ../../contribute/translate.rst:28 +msgid "" +"First you should install git. It's usually package ``git`` in your OS, or" +" you can download it from `their homepage`_ or download GitHub client for" +" `Windows`_ or `OS X`_" +msgstr "" + +#: ../../contribute/translate.rst:32 +msgid "" +"Then you should tell GitHub who you are and what is your email address. " +"This information is attached to commits and GitHub uses it to get your " +"gravatar::" +msgstr "" + +#: ../../contribute/translate.rst:39 +msgid "" +"If you are going to use the ``https``, you probably want git to remember " +"your GitHub password for some time so you don't have to write it " +"continuosly::" +msgstr "" + +#: ../../contribute/translate.rst:46 +msgid "" +"This would make git remember your password for hour. It can be changed by" +" changing 3600 to any other amount of seconds." +msgstr "" + +#: ../../contribute/translate.rst:50 +msgid "Cloning the repository" +msgstr "" + +#: ../../contribute/translate.rst:52 +msgid "" +"You first need an account on `GitHub`_; I think you don't need " +"explaination for that." +msgstr "" + +#: ../../contribute/translate.rst:55 +msgid "" +"Then, go on `Limnoria repository`_ and click the *Fork* button. This will" +" create you a copy of my repository where you will have write access (and" +" I won't have this write access)." +msgstr "" + +#: ../../contribute/translate.rst:59 +msgid "" +"Then, open a console, and write (replace *YourName* by the name of your " +"GitHub account)::" +msgstr "" + +#: ../../contribute/translate.rst:64 +msgid "" +"If you are experienced with git, you can ``git clone " +"git@github.com:/Limnoria.git --branch=testing`` instead." +msgstr "" + +#: ../../contribute/translate.rst:68 +msgid "" +"This will create a new directory, called *Limnoria*, where all the code " +"and project history are copied. Now, cd to the directory::" +msgstr "" + +#: ../../contribute/translate.rst:73 +msgid "" +"The things below affect to you only if you didn't specify the branch in " +"the git clone command." +msgstr "" + +#: ../../contribute/translate.rst:76 +msgid "" +"Then, you need to checkout the *testing* branch. What does that mean? It " +"means that there is differents stages in Limnoria: all changes are made " +"in testing, and when I think *testing* is stable, I merge it into " +"*master*. So, checking out *testing* means Git will use the code in " +"*testing*, you will translate strings that are in *testing*, and changes " +"you make will be in *testing*. Now, do it::" +msgstr "" + +#: ../../contribute/translate.rst:85 +msgid "Git will reply you that it understood what you mean by *testing*." +msgstr "" + +#: ../../contribute/translate.rst:87 +msgid "Ok, now, you can translate." +msgstr "" + +#: ../../contribute/translate.rst:90 +msgid "Pushing translations" +msgstr "" + +#: ../../contribute/translate.rst:92 +msgid "" +"Once you have done some translations (let's say you translated Alias), " +"you have to commit your changes. That mean you tell Git \"Ok, I've made " +"some changes, and I want to take a snapshot (either to be able to roll " +"back or to publish your changes)." +msgstr "" + +#: ../../contribute/translate.rst:97 +msgid "" +"First, you need to tell Git what files you want to be committed (let's " +"say you are the Finnish translator, so you updated Alias's fi.po)::" +msgstr "" + +#: ../../contribute/translate.rst:102 +msgid "" +"Then, you can commit your files. Depending on what you made, you can use " +"one of this commands (not all of them!)::" +msgstr "" + +#: ../../contribute/translate.rst:109 +msgid "" +"By the way, the text that follow -m is a message that will be readed by " +"**humans**, so you can write anything you want, but I think it's better " +"that everybody use the same kind of messages." +msgstr "" + +#: ../../contribute/translate.rst:113 +msgid "" +"Ok, then, Git knows you have done something. But you didn't send your " +"work on Internet yet. To send it, run::" +msgstr "" + +#: ../../contribute/translate.rst:118 +msgid "Simple, isn't it?" +msgstr "" + +#: ../../contribute/translate.rst:120 +msgid "" +"Now, go back to GitHub and your forked repository, and click the *Pull " +"request* button. Then, set *testing* on the both side, and run *Update " +"Commit Range*. I will by mailed that you asked me to merge your changes, " +"and I will do it soon." +msgstr "" + +#: ../../contribute/translate.rst:126 +msgid "Getting updates" +msgstr "" + +#: ../../contribute/translate.rst:128 +msgid "As you may know, I do some updates in Limnoria repository. ;)" +msgstr "" + +#: ../../contribute/translate.rst:130 +msgid "" +"You need to have the latest version of the *messages.pot* files. So, you " +"need to teach Git how to get this updates::" +msgstr "" + +#: ../../contribute/translate.rst:135 +msgid "Now, every time you want to download updates, run::" +msgstr "" + +#: ../../contribute/translate.rst:141 +msgid "Another way: mailing me your translations" +msgstr "" + +#: ../../contribute/translate.rst:143 +msgid "" +"I think this is the simplest way for you. You only have to follow the " +"translation guide and send me your .po files by mail." +msgstr "" + +#: ../../contribute/translate.rst:146 +msgid "You can choose either one of this way to do it." +msgstr "" + +#: ../../contribute/translate.rst:149 +msgid "Mikaela's way" +msgstr "" + +#: ../../contribute/translate.rst:151 +msgid "" +"Send the fi.po (or whatever the name is) files one by one as an " +"attachment. Don't forget to tell me what plugin it is." +msgstr "" + +#: ../../contribute/translate.rst:154 +msgid "I (Mikaela) have moved to git long time ago though." +msgstr "" + +#: ../../contribute/translate.rst:157 +msgid "skizzhg's way" +msgstr "" + +#: ../../contribute/translate.rst:159 +msgid "" +"Do many translations. Put them in a tarball/zipball/whatever (but not a " +"RAR archive, I can't read them because is a proprietary format)." +msgstr "" + +#: ../../contribute/translate.rst:162 +msgid "I prefer that you choose this architecture:" +msgstr "" + +#: ../../contribute/translate.rst:164 +msgid "FirstPlugin/locales/it.po" +msgstr "" + +#: ../../contribute/translate.rst:165 +msgid "SecondPlugin/locales/it.po" +msgstr "" + +#: ../../contribute/translate.rst:166 +msgid "ThirdPlugin/locales/it.po" +msgstr "" + +#: ../../contribute/translate.rst:168 +msgid "Because I can extract everything with one click." +msgstr "" + diff --git a/locale/fr/LC_MESSAGES/develop.po b/locale/fr/LC_MESSAGES/develop.po new file mode 100644 index 0000000..ef978c6 --- /dev/null +++ b/locale/fr/LC_MESSAGES/develop.po @@ -0,0 +1,5201 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2003-2015, the Limnoria/Gribble/Supybot contributors +# This file is distributed under the same license as the Limnoria package. +# FIRST AUTHOR , 2016. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Limnoria 0.83\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-02-24 17:46+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.2.0\n" + +#: ../../develop/advanced_plugin_config.rst:3 +msgid "Advanced Plugin Config" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:4 +msgid "" +"This tutorial covers some of the more advanced plugin config features " +"available to Supybot plugin authors." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:8 +msgid "What's This Tutorial For?" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:9 +msgid "Brief overview of what this tutorial covers and the target audience." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:11 +msgid "" +"Want to know the crazy advanced features available to you, the Supybot " +"plugin author? Well, this is the tutorial for you. This article assumes " +"you've read the Supybot plugin author tutorial since all the basics of " +"plugin config are handled there first." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:16 +msgid "In this tutorial we'll cover:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:18 +msgid "" +"Using the configure function more effectively by using the functions " +"provided in supybot.questions" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:20 +msgid "" +"Creating config variable groups and config variables underneath those " +"groups." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:22 +msgid "" +"The built-in config variable types (\"registry types\") for use with " +"config variables" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:24 +msgid "" +"Creating custom registry types to handle config variable values more " +"effectively" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:28 +msgid "Using 'configure' effectively" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:29 +msgid "" +"How to use 'configure' effectively using the functions from " +"'supybot.questions'" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:32 +msgid "" +"In the original Supybot plugin author tutorial you'll note that we gloss " +"over the configure portion of the config.py file for the sake of keeping " +"the tutorial to a reasonable length. Well, now we're going to cover it in" +" more detail." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:37 +msgid "" +"The supybot.questions module is a nice little module coded specifically " +"to help clean up the configure section of every plugin's config.py. The " +"boilerplate config.py code imports the four most useful functions from " +"that module:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:41 +msgid "" +"\"expect\" is a very general prompting mechanism which can specify " +"certain inputs that it will accept and also specify a default response. " +"It takes the following arguments:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:45 +#: ../../develop/advanced_plugin_config.rst:57 +#: ../../develop/advanced_plugin_config.rst:62 +#: ../../develop/advanced_plugin_config.rst:69 +msgid "prompt: The text to be displayed" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:46 +msgid "possibilities: The list of possible responses (can be the empty list, [])" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:48 +msgid "" +"default (optional): Defaults to None. Specifies the default value to use " +"if the user enters in no input." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:50 +msgid "" +"acceptEmpty (optional): Defaults to False. Specifies whether or not to " +"accept no input as an answer." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:53 +msgid "" +"\"anything\" is basically a special case of expect which takes anything " +"(including no input) and has no default value specified. It takes only " +"one argument:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:59 +msgid "" +"\"something\" is also a special case of expect, requiring some input and " +"allowing an optional default. It takes the following arguments:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:63 +msgid "" +"default (optional): Defaults to None. The default value to use if the " +"user doesn't input anything." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:66 +msgid "" +"\"yn\" is for \"yes or no\" questions and basically forces the user to " +"input a \"y\" for yes, or \"n\" for no. It takes the following arguments:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:70 +msgid "" +"default (optional): Defaults to None. Default value to use if the user " +"doesn't input anything." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:73 +msgid "" +"All of these functions, with the exception of \"yn\", return whatever " +"string results as the answer whether it be input from the user or " +"specified as the default when the user inputs nothing. The \"yn\" " +"function returns True for \"yes\" answers and False for \"no\" answers." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:78 +msgid "" +"For the most part, the latter three should be sufficient, but we expose " +"expect to anyone who needs a more specialized configuration." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:81 +msgid "" +"Let's go through a quick example configure that covers all four of these " +"functions. First I'll give you the code, and then we'll go through it, " +"discussing each usage of a supybot.questions function just to make sure " +"you realize what the code is actually doing. Here it is::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:107 +msgid "" +"As you can see, this is the WorldDom plugin, which I am currently working" +" on. The first thing our configure function checks is to see whether or " +"not the bot owner would like the world domination commands in this plugin" +" to be available to everyone. If they say yes, we set the " +"globalWorldDominationRequires configuration variable to the empty string," +" signifying that no specific capabilities are necessary. If they say no, " +"we prompt them for a specific capability to check for, defaulting to the " +"\"Admin\" capability. Here they can create their own custom capability to" +" grant to folks which this plugin will check for if they want, but " +"luckily for the bot owner they don't really have to do this since " +"Supybot's capabilities system can be flexed to take care of this." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:118 +msgid "" +"Lastly, we check to find out what direction they want to attack from as " +"they venture towards world domination. I prefer \"death from above!\", so" +" I made that the default response, but the more boring cardinal " +"directions are available as choices as well." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:124 +msgid "Using Config Groups" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:125 +msgid "A brief overview of how to use config groups to organize config variables" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:128 +msgid "Supybot's Hierarchical Configuration" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:130 +msgid "" +"Supybot's configuration is inherently hierarchical, as you've probably " +"already figured out in your use of the bot. Naturally, it makes sense to " +"allow plugin authors to create their own hierarchies to organize their " +"configuration variables for plugins that have a lot of plugin options. If" +" you've taken a look at the plugins that Supybot comes with, you've " +"probably noticed that several of them take advantage of this. In this " +"section of this tutorial we'll go over how to make your own config " +"hierarchy for your plugin." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:138 +msgid "" +"Here's the brilliant part about Supybot config values which makes " +"hierarchical structuring all that much easier - values are groups. That " +"is, any config value you may already defined in your plugins can already " +"be treated as a group, you simply need to know how to add items to that " +"group." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:143 +msgid "" +"Now, if you want to just create a group that doesn't have an inherent " +"value you can do that as well, but you'd be surprised at how rarely you " +"have to do that. In fact if you look at most of the plugins that Supybot " +"comes with, you'll only find that we do this in a handful of spots yet we" +" use the \"values as groups\" feature quite a bit." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:150 +msgid "Creating a Config Group" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:152 +msgid "" +"As stated before, config variables themselves are groups, so you can " +"create a group simply by creating a configuration variable::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:159 +msgid "" +"As you probably know by now this creates the config variable " +"supybot.plugins.WorldDom.globalWorldDominationRequires which you can " +"access/set using the Config plugin directly on the running bot. What you " +"may not have known prior to this tutorial is that that variable is also a" +" group. Specifically, it is now the " +"WorldDom.globalWorldDominationRequires group, and we can add config " +"variables to it! Unfortunately, this particular bit of configuration " +"doesn't really require anything underneath it, so let's create a new " +"group which does using the \"create only a group, not a value\" command." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:168 +msgid "" +"Let's create a configurable list of targets for different types of " +"attacks (land, sea, air, etc.). We'll call the group attackTargets. " +"Here's how you create just a config group alone with no value assigned::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:174 +msgid "" +"The first argument is just the group under which you want to create your " +"new group (and we got WorldDom from conf.registerPlugin which was in our " +"boilerplate code from the plugin creation wizard). The second argument " +"is, of course, the group name. So now we have WorldDom.attackTargets (or," +" fully, supybot.plugins.WorldDom.attackTargets)." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:181 +msgid "Adding Values to a Group" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:183 +msgid "" +"Actually, you've already done this several times, just never to a custom " +"group of your own. You've always added config values to your plugin's " +"config group. With that in mind, the only slight modification needed is " +"to simply point to the new group::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:192 +msgid "" +"And now we have a nice list of air targets! You'll notice that the first " +"argument is WorldDom.attackTargets, our new group. Make sure that the " +"conf.registerGroup call is made before this one or else you'll get a " +"nasty AttributeError." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:198 +msgid "Variations" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:201 +msgid "Channel-specific values" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:203 +msgid "" +"A very handy feature is channel-specific variables, which allows bot " +"administrators to set a global value (as for non-channel-specific values " +"AND another value for specific channels)." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:207 +msgid "" +"The syntax is pretty much like the previous one, except we use " +"`registerChannelValue` instead of `registerGlobalValue`::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:215 +msgid "Private values" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:217 +msgid "" +"Variable type also take an optional argument, for setting a configuration" +" variable to private (useful for passwords, authentication tokens, api " +"keys, …)::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:227 +msgid "Accessing the configuration registry" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:229 +msgid "Of course, you can access the variables in your plugins." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:231 +msgid "" +"If it is a variable created by your plugin, you can do it like this (if " +"the configuration variable's name is `air`)::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:236 +msgid "" +"and it will return data of the right type (in this case, a list of " +"string, as we declarated it above as a " +"`registry.SpaceSeparatedListOfStrings`)." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:239 +msgid "" +"If it is a channel-specific variable, you can get the value on `#channel`" +" like this (if the variable is not defined on this channel, it defaults " +"to the global one)::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:246 +msgid "" +"You can also set configuration variables (either globally or for a single" +" channel)::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:254 +msgid "" +"You can also access other configuration variables (or your own if you " +"want) via the ``supybot.conf`` module::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:264 +msgid "The Built-in Registry Types" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:265 +msgid "" +"A rundown of all of the built-in registry types available for use with " +"config variables." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:268 +msgid "" +"The \"registry\" module defines the following config variable types for " +"your use (I'll include the 'registry.' on each one since that's how " +"you'll refer to it in code most often). Most of them are fairly self-" +"explanatory, so excuse the boring descriptions:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:273 +msgid "" +"registry.Boolean - A simple true or false value. Also accepts the " +"following for true: \"true\", \"on\" \"enable\", \"enabled\", \"1\", and " +"the following for false: \"false\", \"off\", \"disable\", \"disabled\", " +"\"0\"," +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:277 +msgid "registry.Integer - Accepts any integer value, positive or negative." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:279 +msgid "registry.NonNegativeInteger - Will hold any non-negative integer value." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:281 +msgid "" +"registry.PositiveInteger - Same as above, except that it doesn't accept 0" +" as a value." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:284 +msgid "registry.Float - Accepts any floating point number." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:286 +msgid "registry.PositiveFloat - Accepts any positive floating point number." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:288 +msgid "" +"registry.Probability - Accepts any floating point number between 0 and 1 " +"(inclusive, meaning 0 and 1 are also valid)." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:291 +msgid "registry.String - Accepts any string that is not a valid Python command" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:293 +msgid "" +"registry.NormalizedString - Accepts any string (with the same exception " +"above) but will normalize sequential whitespace to a single space.." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:296 +msgid "" +"registry.StringSurroundedBySpaces - Accepts any string but assures that " +"it has a space preceding and following it. Useful for configuring a " +"string that goes in the middle of a response." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:300 +msgid "" +"registry.StringWithSpaceOnRight - Also accepts any string but assures " +"that it has a space after it. Useful for configuring a string that begins" +" a response." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:304 +msgid "registry.Regexp - Accepts only valid (Perl or Python) regular expressions" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:306 +msgid "" +"registry.SpaceSeparatedListOfStrings - Accepts a space-separated list of " +"strings." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:309 +msgid "" +"There are a few other built-in registry types that are available but are " +"not usable in their current state, only by creating custom registry " +"types, which we'll go over in the next section." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:314 +msgid "Custom Registry Types" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:315 +msgid "" +"How to create and use your own custom registry types for use in " +"customizing plugin config variables." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:319 +msgid "Why Create Custom Registry Types?" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:321 +msgid "" +"For most configuration, the provided types in the registry module are " +"sufficient. However, for some configuration variables it's not only " +"convenient to use custom registry types, it's actually recommended. " +"Customizing registry types allows for tighter restrictions on the values " +"that get set and for greater error-checking than is possible with the " +"provided types." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:328 +msgid "What Defines a Registry Type?" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:330 +msgid "" +"First and foremost, it needs to subclass one of the existing registry " +"types from the registry module, whether it be one of the ones in the " +"previous section or one of the other classes in registry specifically " +"designed to be subclassed." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:334 +msgid "" +"Also it defines a number of other nice things: a custom error message for" +" your type, customized value-setting (transforming the data you get into " +"something else if wanted), etc." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:339 +msgid "Creating Your First Custom Registry Type" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:341 +msgid "" +"As stated above, priority number one is that you subclass one of the " +"types in the registry module. Basically, you just subclass one of those " +"and then customize whatever you want. Then you can use it all you want in" +" your own plugins. We'll do a quick example to demonstrate." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:346 +msgid "" +"We already have registry.Integer and registry.PositiveInteger, but let's " +"say we want to accept only negative integers. We can create our own " +"NegativeInteger registry type like so::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:357 +msgid "" +"All we need to do is define a new error message for our custom registry " +"type (specified by the docstring for the class), and customize the " +"setValue function. Note that all you have to do when you want to signify " +"that you've gotten an invalid value is to call self.error(). Finally, we " +"call the parent class's setValue to actually set the value." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:364 +msgid "What Else Can I Customize?" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:366 +msgid "" +"Well, the error string and the setValue function are the most useful " +"things that are available for customization, but there are other things. " +"For examples, look at the actual built-in registry types defined in " +"registry.py (in the src directory distributed with the bot)." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:372 +msgid "What Subclasses Can I Use?" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:374 +msgid "" +"Chances are one of the built-in types in the previous section will be " +"sufficient, but there are a few others of note which deserve mention:" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:377 +msgid "" +"registry.Value - Provides all the core functionality of registry types " +"(including acting as a group for other config variables to reside " +"underneath), but nothing more." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:381 +msgid "" +"registry.OnlySomeStrings - Allows you to specify only a certain set of " +"strings as valid values. Simply override validStrings in the inheriting " +"class and you're ready to go." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:385 +msgid "" +"registry.SeparatedListOf - The generic class which is the parent class to" +" registry.SpaceSeparatedListOfStrings. Allows you to customize four " +"things: the type of sequence it is (list, set, tuple, etc.), what each " +"item must be (String, Boolean, etc.), what separates each item in the " +"sequence (using custom splitter/joiner functions), and whether or not the" +" sequence is to be sorted. Look at the definitions of " +"registry.SpaceSeparatedListOfStrings and " +"registry.CommaSeparatedListOfStrings at the bottom of registry.py for " +"more information. Also, there will be an example using this in the " +"section below." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:397 +msgid "Using My Custom Registry Type" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:399 +msgid "" +"Using your new registry type is relatively straightforward. Instead of " +"using whatever registry built-in you might have used before, now use your" +" own custom class. Let's say we define a registry type to handle a comma-" +"separated list of probabilities::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:410 +msgid "" +"Now, to use that type we simply have to specify it whenever we create a " +"config variable using it::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:417 +msgid "" +"Note that we initialize it just the same as we do any other registry " +"type, with two arguments: the default value, and then the description of " +"the config variable." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:424 +msgid "Configuration hooks" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:427 +msgid "" +"Until stock Supybot or Gribble merge this feature, this section only " +"applies to Limnoria." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:430 +msgid "" +"It is possible to get a function called when a configuration variable is " +"changed. While this is usually not useful (you get the value whenever you" +" need it), some plugins do use it, for instance for caching results or " +"for pre-fetching data." +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:435 +msgid "" +"Let's say you want to write a plugin that prints `nick changed` in the " +"logs when `supybot.nick` is edited. You can do it like this::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:449 +msgid "" +"As not all Supybot versions support it (yet), it can be a good idea to " +"show a warning instead of crashing on those versions::" +msgstr "" + +#: ../../develop/advanced_plugin_config.rst:469 +msgid "" +"For the moment, the `name` parameter is never given when the callback is " +"called. However, in the future, it will be set to the name of the " +"variable that has been changed (useful if you want to use the same " +"callback for multiple variable), so it is better to allow this parameter." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:3 +msgid "Advanced Plugin Testing" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:4 +msgid "The complete guide to writing tests for your plugins." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:7 +msgid "Why Write Tests?" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:8 +msgid "Why should I write tests for my plugin? Here's why." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:10 +msgid "" +"For those of you asking \"Why should I write tests for my plugin? I tried" +" it out, and it works!\", read on. For those of you who already realize " +"that Testing is Good (TM), skip to the next section." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:14 +msgid "Here are a few quick reasons why to test your Supybot plugins." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:16 +msgid "" +"When/if we rewrite or change certain features in Supybot, tests make sure" +" your plugin will work with these changes. It's much easier to run " +"supybot-test MyPlugin after upgrading the code and before even reloading " +"the bot with the new code than it is to load the bot with new code and " +"then load the plugin only to realize certain things don't work. You may " +"even ultimately decide you want to stick with an older version for a " +"while as you patch your custom plugin. This way you don't have to rush a " +"patch while restless users complain since you're now using a newer " +"version that doesn't have the plugin they really like." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:26 +msgid "" +"Running the automated tests takes a few seconds, testing plugins in IRC " +"on a live bot generally takes quite a bit longer. We make it so that " +"writing tests generally doesn't take much time, so a small initial " +"investment adds up to lots of long-term gains." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:31 +msgid "" +"If you want your plugin to be included in any of our releases (the core " +"Supybot if you think it's worthy, or our supybot-plugins package), it has" +" to have tests. Period." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:35 +msgid "For a bigger list of why to write unit tests, check out this article:" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:37 +msgid "http://www.onjava.com/pub/a/onjava/2003/04/02/javaxpckbk.html" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:39 +msgid "" +"and also check out what the Extreme Programming folks have to say about " +"unit tests:" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:42 +msgid "http://www.extremeprogramming.org/rules/unittests.html" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:45 +msgid "Plugin Tests" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:46 +msgid "How to write tests for commands in your plugins." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:49 +#: ../../develop/advanced_plugin_testing.rst:239 ../../develop/httpserver.rst:8 +#: ../../develop/plugin_tutorial.rst:6 ../../develop/using_wrap.rst:8 +msgid "Introduction" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:51 +msgid "" +"This tutorial assumes you've read through the plugin author tutorial, and" +" that you used supybot-plugin-create to create your plugin (as everyone " +"should). So, you should already have all the necessary imports and all " +"that boilerplate stuff in test.py already, and you have already seen what" +" a basic plugin test looks like from the plugin author tutorial. Now " +"we'll go into more depth about what plugin tests are available to Supybot" +" plugin authors." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:59 +msgid "Plugin Test Case Classes" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:61 +msgid "" +"Supybot comes with two plugin test case classes, PluginTestCase and " +"ChannelPluginTestCase. The former is used when it doesn't matter whether " +"or not the commands are issued in a channel, and the latter is used for " +"when it does. For the most part their API is the same, so unless there's " +"a distinction between the two we'll treat them as one and the same when " +"discussing their functionality." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:69 +msgid "The Most Basic Plugin Test Case" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:71 +msgid "At the most basic level, a plugin test case requires three things:" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:73 +msgid "" +"the class declaration (subclassing PluginTestCase or " +"ChannelPluginTestCase)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:75 +msgid "" +"a list of plugins that need to be loaded for these tests (does not " +"include Owner, Misc, or Config, those are always automatically loaded) - " +"often this is just the name of the plugin that you are writing tests for" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:78 +msgid "some test methods" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:80 +msgid "" +"Here's what the most basic plugin test case class looks like (for a " +"plugin named MyPlugin)::" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:89 +msgid "" +"Your plugin test case should be named TestCase as you see above, though " +"it doesn't necessarily have to be named that way (supybot-plugin-create " +"puts that in place for you anyway). As you can see we elected to subclass" +" PluginTestCase because this hypothetical plugin apparently doesn't do " +"anything channel-specific." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:95 +msgid "" +"As you probably noticed, the plugins attribute of the class is where the " +"list of necessary plugins goes, and in this case just contains the plugin" +" that we are testing. This will be the case for probably the majority of " +"plugins. A lot of the time test writers will use a bot function that " +"performs some function that they don't want to write code for and they " +"will just use command nesting to feed the bot what they need by using " +"that plugin's functionality. If you choose to do this, only do so with " +"core bot plugins as this makes distribution of your plugin simpler. After" +" all, we want people to be able to run your plugin tests without having " +"to have all of your plugins!" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:105 +msgid "" +"One last thing to note before moving along is that each of the test " +"methods should describe what they are testing. If you want to test that " +"your plugin only responds to registered users, don't be afraid to name " +"your test method testOnlyRespondingToRegisteredUsers or " +"testNotRespondingToUnregisteredUsers. You may have noticed some rather " +"long and seemingly unwieldy test method names in our code, but that's " +"okay because they help us know exactly what's failing when we run our " +"tests. With an ambiguously named test method we may have to crack open " +"test.py after running the tests just to see what it is that failed. For " +"this reason you should also test only one thing per test method. Don't " +"write a test method named testFoobarAndBaz. Just write two test methods, " +"testFoobar and testBaz. Also, it is important to note that test methods " +"must begin with test and that any method within the class that does begin" +" with test will be run as a test by the supybot-test program. If you want" +" to write utility functions in your test class that's fine, but don't " +"name them something that begins with test or they will be executed as " +"tests." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:122 +msgid "Including Extra Setup" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:124 +msgid "" +"Some tests you write may require a little bit of setup. For the most part" +" it's okay just to include that in the individual test method itself, but" +" if you're duplicating a lot of setup code across all or most of your " +"test methods it's best to use the setUp method to perform whatever needs " +"to be done prior to each test method." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:130 +msgid "" +"The setUp method is inherited from the whichever plugin test case class " +"you chose for your tests, and you can add whatever functionality you want" +" to it. Note the important distinction, however: you should be adding to " +"it and not overriding it. Just define setUp in your own plugin test case " +"class and it will be run before all the test methods are invoked." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:136 +msgid "" +"Let's do a quick example of one. Let's write a setUp method which " +"registers a test user for our test bot::" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:146 +msgid "" +"Now notice how the first line calls the parent class's setUp method " +"first? This must be done first. Otherwise several problems are likely to " +"arise. For one, you wouldn't have an irc object at self.irc that we use " +"later on nor would self.nick be set." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:151 +msgid "" +"As for the rest of the method, you'll notice a few things that are " +"available to the plugin test author. self.prefix refers to the hostmask " +"of the hypothetical test user which will be \"talking\" to the bot, " +"issuing commands. We set it to some generically fake hostmask, and then " +"we use feedMsg to send a private message (using the bot's nick, " +"accessible via self.nick) to the bot registering the username \"tester\" " +"with the password \"moo\". We have to do it this way (rather than what " +"you'll find out is the standard way of issuing commands to the bot in " +"test cases a little later) because registration must be done in private. " +"And lastly, since feedMsg doesn't dequeue any messages from the bot after" +" being fed a message, we perform a getMsg to get the response. You're not" +" expected to know all this yet, but do take note of it since using these " +"methods in test-writing is not uncommon. These utility methods as well as" +" all of the available assertions are covered in the next section." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:165 +msgid "" +"So, now in any of the test methods we write, we'll be able to count on " +"the fact that there will be a registered user \"tester\" with a password " +"of \"moo\", and since we changed our prefix by altering self.prefix and " +"registered after doing so, we are now identified as this user for all " +"messages we send unless we specify that they are coming from some other " +"prefix." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:172 +msgid "The Opposite of Setting-up: Tearing Down" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:174 +msgid "" +"If you did some things in your setUp that you want to clean up after, " +"then this code belongs in the tearDown method of your test case class. " +"It's essentially the same as setUp except that you probably want to wait " +"to invoke the parent class's tearDown until after you've done all of your" +" tearing down. But do note that you do still have to invoke the parent " +"class's tearDown method if you decide to add in your own tear-down stuff." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:182 +msgid "Setting Config Variables for Testing" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:184 +msgid "" +"Before we delve into all of the fun assertions we can use in our test " +"methods it's worth noting that each plugin test case can set custom " +"values for any Supybot config variable they want rather easily. Much like" +" how we can simply list the plugins we want loaded for our tests in the " +"plugins attribute of our test case class, we can set config variables by " +"creating a mapping of variables to values with the config attribute." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:191 +msgid "" +"So if, for example, we wanted to disable nested commands within our " +"plugin testing for some reason, we could just do this::" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:200 +msgid "" +"And now you can be assured that supybot.commands.nested is going to be " +"off for all of your test methods in this test case class." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:204 +msgid "Temporarily setting a configuration variable" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:206 +msgid "" +"Sometimes we want to change a configuration variable only in a test (or " +"in a part of a test), and keep the original value for other tests. The " +"historical way to do it is::" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:221 +msgid "But there is a more compact syntax, using context managers::" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:231 +msgid "" +"Until stock Supybot or Gribble merge the second syntax, only Limnoria " +"will support it." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:235 +msgid "Plugin Test Methods" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:236 +msgid "The full list of test methods and how to use them." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:241 +msgid "" +"You know how to make plugin test case classes and you know how to do just" +" about everything with them except to actually test stuff. Well, listed " +"below are all of the assertions used in tests. If you're unfamiliar with " +"what an assertion is in code testing, it is basically a requirement of " +"something that must be true in order for that test to pass. It's a " +"necessary condition. If any assertion within a test method fails the " +"entire test method fails and it goes on to the next one." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:250 +msgid "Assertions" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:252 +msgid "" +"All of these are methods of the plugin test classes themselves and hence " +"are accessed by using self.assertWhatever in your test methods. These are" +" sorted in order of relative usefulness." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:260 +msgid "assertResponse(query, expectedResponse)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:257 +msgid "" +"Feeds query to the bot as a message and checks to make sure the response " +"is expectedResponse. The test fails if they do not match (note that " +"prefixed nicks in the response do not need to be included in the " +"expectedResponse)." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:264 +msgid "assertError(query)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:263 +msgid "" +"Feeds query to the bot and expects an error in return. Fails if the bot " +"doesn't return an error." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:269 +msgid "assertNotError(query)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:267 +msgid "" +"The opposite of assertError. It doesn't matter what the response to query" +" is, as long as it isn't an error. If it is not an error, this test " +"passes, otherwise it fails." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:275 +msgid "assertRegexp(query, regexp, flags=re.I)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:272 +msgid "" +"Feeds query to the bot and expects something matching the regexp (no m// " +"required) in regexp with the supplied flags. Fails if the regexp does not" +" match the bot's response." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:280 +msgid "assertNotRegexp(query, regexp, flags=re.I)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:278 +msgid "" +"The opposite of assertRegexp. Fails if the bot's output matches regexp " +"with the supplied flags." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:284 +msgid "assertHelp(query)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:283 +msgid "" +"Expects query to return the help for that command. Fails if the command " +"help is not triggered." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:289 +msgid "assertAction(query, expectedResponse=None)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:287 +msgid "" +"Feeds query to the bot and expects an action in response, specifically " +"expectedResponse if it is supplied. Otherwise, the test passes for any " +"action response." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:294 +msgid "assertActionRegexp(query, regexp, flags=re.I)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:292 +msgid "" +"Basically like assertRegexp but carries the extra requirement that the " +"response must be an action or the test will fail." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:297 +msgid "Utilities" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:303 +msgid "feedMsg(query, to=None, frm=None)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:300 +msgid "" +"Simply feeds query to whoever is specified in to or to the bot itself if " +"no one is specified. Can also optionally specify the hostmask of the " +"sender with the frm keyword. Does not actually perform any assertions." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:306 +msgid "getMsg(query)" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:306 +msgid "Feeds query to the bot and gets the response." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:309 +msgid "Other Tests" +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:310 +msgid "" +"If you had to write helper code for a plugin and want to test it, here's " +"how." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:313 +msgid "" +"Previously we've only discussed how to test stuff in the plugin that is " +"intended for IRC. Well, we realize that some Supybot plugins will require" +" utility code that doesn't necessarily require all of the overhead of " +"setting up IRC stuff, and so we provide a more lightweight test case " +"class, SupyTestCase, which is a very very light wrapper around " +"unittest.TestCase (from the standard unittest module) that basically just" +" provides a little extra logging. This test case class is what you should" +" use for writing those test cases which test things that are independent " +"of IRC." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:322 +msgid "" +"For example, in the MoobotFactoids plugin there is a large chunk of " +"utility code dedicating to parsing out random choices within a factoid " +"using a class called OptionList. So, we wrote the OptionListTestCase as a" +" SupyTestCase for the MoobotFactoids plugin. The setup for test methods " +"is basically the same as before, only you don't have to define plugins " +"since this is independent of IRC." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:329 +msgid "" +"You still have the choice of using setUp and tearDown if you wish, since " +"those are inherited from unittest.TestCase. But, the same rules about " +"calling the setUp or tearDown method from the parent class still apply." +msgstr "" + +#: ../../develop/advanced_plugin_testing.rst:333 +msgid "" +"With all this in hand, now you can write great tests for your Supybot " +"plugins!" +msgstr "" + +#: ../../develop/callbacks.rst:5 +msgid "supybot.callbacks" +msgstr "" + +#: ../../develop/callbacks.rst:10 +msgid "Plugin" +msgstr "" + +#: of supybot.callbacks.Plugin:1 +msgid "" +"Bases: :class:`supybot.callbacks.PluginMixin`, " +":class:`supybot.callbacks.Commands`" +msgstr "" + +#: of supybot.callbacks.Plugin.callPrecedence:1 +#: supybot.irclib.IrcCallback.callPrecedence:1 +msgid "" +"Returns a pair of (callbacks to call before me, callbacks to call after " +"me)" +msgstr "" + +#: of supybot.callbacks.Plugin.die:1 supybot.irclib.IrcCallback.die:1 +msgid "Makes the callback die. Called when the parent Irc object dies." +msgstr "" + +#: of supybot.callbacks.Plugin.dispatchCommand:1 +#: supybot.irclib.Irc.dispatchCommand:1 +#: supybot.irclib.IrcState.dispatchCommand:1 +#: supybot.irclib.IrcCommandDispatcher.dispatchCommand:1 +msgid "Given a string 'command', dispatches to doCommand." +msgstr "" + +#: of supybot.callbacks.Plugin.getCommandMethod:1 +#: supybot.callbacks.Commands.getCommandMethod:1 +msgid "Gets the given command from this plugin." +msgstr "" + +#: of supybot.callbacks.Plugin.inFilter:1 supybot.irclib.IrcCallback.inFilter:1 +msgid "Used for filtering/modifying messages as they're entering." +msgstr "" + +#: of supybot.callbacks.Plugin.inFilter:3 supybot.irclib.IrcCallback.inFilter:3 +msgid "" +"ircmsgs.IrcMsg objects are immutable, so this method is expected to " +"return another ircmsgs.IrcMsg object. Obviously the same IrcMsg can be " +"returned." +msgstr "" + +#: of supybot.callbacks.Plugin.isCommand:1 +#: supybot.callbacks.Commands.isCommand:1 +msgid "Convenience, backwards-compatibility, semi-deprecated." +msgstr "" + +#: of supybot.callbacks.Plugin.isCommandMethod:1 +#: supybot.callbacks.Commands.isCommandMethod:1 +msgid "Returns whether a given method name is a command in this plugin." +msgstr "" + +#: of supybot.callbacks.Plugin.outFilter:1 +#: supybot.irclib.IrcCallback.outFilter:1 +msgid "Used for filtering/modifying messages as they're leaving." +msgstr "" + +#: of supybot.callbacks.Plugin.outFilter:3 +#: supybot.irclib.IrcCallback.outFilter:3 +msgid "As with inFilter, an IrcMsg is returned." +msgstr "" + +#: of supybot.callbacks.Plugin.reset:1 supybot.irclib.IrcCallback.reset:1 +msgid "Resets the callback. Called when reconnecting to the server." +msgstr "" + +#: ../../develop/callbacks.rst:19 +msgid "PluginRegexp" +msgstr "" + +#: of supybot.callbacks.PluginRegexp:1 +msgid "Bases: :class:`supybot.callbacks.Plugin`" +msgstr "" + +#: of supybot.callbacks.PluginRegexp:1 +msgid "" +"Same as Plugin, except allows the user to also include regexp-based " +"callbacks. All regexp-based callbacks must be specified in the set (or " +"list) attribute \"regexps\", \"addressedRegexps\", or " +"\"unaddressedRegexps\" depending on whether they should always be " +"triggered, triggered only when the bot is addressed, or triggered only " +"when the bot isn't addressed." +msgstr "" + +#: of supybot.callbacks.PluginRegexp.addressedRegexps:1 +msgid "" +"'addressedRegexps' methods are called only when the message is addressed," +" and then, only with the payload (i.e., what is returned from the " +"'addressed' function." +msgstr "" + +#: of supybot.callbacks.PluginRegexp.regexps:1 +msgid "'regexps' methods are called whether the message is addressed or not." +msgstr "" + +#: of supybot.callbacks.PluginRegexp.unaddressedRegexps:1 +msgid "" +"'unaddressedRegexps' methods are called only when the message is *not* " +"addressed." +msgstr "" + +#: ../../develop/callbacks.rst:28 +msgid "tokenize" +msgstr "" + +#: of supybot.callbacks.tokenize:1 +msgid "A utility function to create a Tokenizer and tokenize a string." +msgstr "" + +#: ../../develop/callbacks.rst:34 ../../develop/irclib.rst:60 +msgid "Other classes" +msgstr "" + +#: of supybot.callbacks:1 +msgid "This module contains the basic callbacks for handling PRIVMSGs." +msgstr "" + +#: of supybot.callbacks.ArgumentError:1 supybot.callbacks.SilentError:1 +msgid "Bases: :class:`supybot.callbacks.Error`" +msgstr "" + +#: of supybot.callbacks.ArgumentError:1 +msgid "The bot replies with a help message when this is raised." +msgstr "" + +#: of supybot.callbacks.BasePlugin:1 supybot.callbacks.DisabledCommands:1 +#: supybot.callbacks.RichReplyMethods:1 supybot.callbacks.Tokenizer:1 +#: supybot.commands.context:1 supybot.commands.Spec:1 +#: supybot.irclib.IrcCommandDispatcher:1 supybot.irclib.IrcMsgQueue:1 +#: supybot.ircmsgs.IrcMsg:1 +msgid "Bases: :class:`object`" +msgstr "" + +#: of supybot.callbacks.CanonicalNameDict:1 +msgid "Bases: :class:`supybot.utils.gen.InsensitivePreservingDict`" +msgstr "" + +#: of supybot.callbacks.CanonicalNameSet:1 +msgid "Bases: :class:`supybot.utils.gen.NormalizingSet`" +msgstr "" + +#: of supybot.callbacks.CanonicalString:1 +msgid "Bases: :class:`supybot.registry.NormalizedString`" +msgstr "" + +#: of supybot.callbacks.CommandProcess:1 +msgid "Bases: :class:`supybot.world.SupyProcess`" +msgstr "" + +#: of supybot.callbacks.CommandProcess:1 +msgid "" +"Just does some extra logging and error-recovery for commands that need to" +" run in processes." +msgstr "" + +#: of supybot.callbacks.CommandThread:1 +msgid "Bases: :class:`supybot.world.SupyThread`" +msgstr "" + +#: of supybot.callbacks.CommandThread:1 +msgid "" +"Just does some extra logging and error-recovery for commands that need to" +" run in threads." +msgstr "" + +#: of supybot.callbacks.Commands:1 +msgid "" +"Bases: :class:`supybot.callbacks.BasePlugin`, " +":class:`supybot.utils.python.SynchronizedAndFirewalled`" +msgstr "" + +#: of supybot.callbacks.Disabled:1 +msgid "Bases: :class:`supybot.registry.SpaceSeparatedListOf`" +msgstr "" + +#: of supybot.callbacks.Error:1 +msgid "Bases: :class:`Exception`" +msgstr "" + +#: of supybot.callbacks.Error:1 +msgid "Generic class for errors in Privmsg callbacks." +msgstr "" + +#: of supybot.callbacks.MetaSynchronizedAndFirewalled:1 +msgid "" +"Bases: :class:`supybot.log.MetaFirewall`, " +":class:`supybot.utils.python.MetaSynchronized`" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy:1 +msgid "Bases: :class:`supybot.callbacks.ReplyIrcProxy`" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy:1 +msgid "A proxy object to allow proper nesting of commands (even threaded ones)." +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.findCallbacksForArgs:1 +msgid "" +"Returns a two-tuple of (command, plugins) that has the command (a list of" +" strings) and the plugins for which it was a command." +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:1 +msgid "Keyword arguments:" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:3 +msgid "`noLengthCheck=False`: True if the length shouldn't be checked" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:4 +msgid "(used for 'more' handling)" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:5 +msgid "`prefixNick=True`: False if the nick shouldn't be prefixed to the" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:6 +msgid "reply." +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:7 +msgid "`action=False`: True if the reply should be an action." +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:8 +msgid "`private=False`: True if the reply should be in private." +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:9 +msgid "`notice=False`: True if the reply should be noticed when the" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:10 +msgid "bot is configured to do so." +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:11 +msgid "`to=`: The nick or channel the reply should go to." +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:12 +msgid "Defaults to msg.args[0] (or msg.nick if private)" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:14 +msgid "`sendImmediately=False`: True if the reply should use sendMsg() which" +msgstr "" + +#: of supybot.callbacks.NestedCommandsIrcProxy.reply:14 +msgid "" +"bypasses conf.supybot.protocols.irc.throttleTime and gets sent before any" +" queued messages" +msgstr "" + +#: of supybot.callbacks.PluginMixin:1 +msgid "" +"Bases: :class:`supybot.callbacks.BasePlugin`, " +":class:`supybot.irclib.IrcCallback`" +msgstr "" + +#: of supybot.callbacks.ReplyIrcProxy:1 +msgid "Bases: :class:`supybot.callbacks.RichReplyMethods`" +msgstr "" + +#: of supybot.callbacks.ReplyIrcProxy:1 +msgid "" +"This class is a thin wrapper around an irclib.Irc object that gives it " +"the reply() and error() methods (as well as everything in " +"RichReplyMethods, based on those two)." +msgstr "" + +#: of supybot.callbacks.ReplyIrcProxy.getRealIrc:1 +msgid "Returns the real irclib.Irc object underlying this proxy chain." +msgstr "" + +#: of supybot.callbacks.RichReplyMethods:1 +msgid "" +"This is a mixin so these replies need only be defined once. It operates " +"under several assumptions, including the fact that 'self' is an Irc " +"object of some sort and there is a self.msg that is an IrcMsg." +msgstr "" + +#: of supybot.callbacks.SilentError:1 +msgid "An error that we should not notify the user." +msgstr "" + +#: of supybot.callbacks.addressed:1 +msgid "" +"If msg is addressed to 'name', returns the portion after the address. " +"Otherwise returns the empty string." +msgstr "" + +#: of supybot.callbacks.canonicalName:1 +msgid "Turn a command into its canonical form." +msgstr "" + +#: of supybot.callbacks.canonicalName:3 +msgid "" +"Currently, this makes everything lowercase and removes all dashes and " +"underscores." +msgstr "" + +#: of supybot.callbacks.error:1 +msgid "Makes an error reply to msg with the appropriate error payload." +msgstr "" + +#: ../../develop/capabilities.rst:3 +msgid "Capabilities" +msgstr "" + +#: ../../develop/capabilities.rst:6 +msgid "" +"I wrote this section with the little knowledge I have of the capabilities" +" system; I work mainly by testing different possibilities until I get " +"what I want. As for all the documentation, feel free to contact me to " +"correct/enhance it." +msgstr "" + +#: ../../develop/capabilities.rst:12 +msgid "" +"First, you should know how capabilities work :ref:`on the user side " +"`." +msgstr "" + +#: ../../develop/capabilities.rst:16 +msgid "Checking for a capability given its name" +msgstr "" + +#: ../../develop/capabilities.rst:18 +msgid "You only have to use ``ircdb.checkCapability(prefix, 'capability')``." +msgstr "" + +#: ../../develop/capabilities.rst:20 +msgid "" +"You can also override some behavior of the capability system. Here is the" +" complete documentation of ``ircdb.checkCapabiltiy``:" +msgstr "" + +#: of supybot.ircdb.checkCapability:1 +msgid "Checks that the user specified by name/hostmask has the capability given." +msgstr "" + +#: of supybot.ircdb.checkCapability:3 +msgid "" +"``users`` and ``channels`` default to ``ircdb.users`` and " +"``ircdb.channels``." +msgstr "" + +#: of supybot.ircdb.checkCapability:6 +msgid "" +"``ignoreOwner``, ``ignoreChannelOp``, and ``ignoreDefaultAllow`` are used" +" to override default behavior of the capability system in special cases " +"(actually, in the AutoMode plugin):" +msgstr "" + +#: of supybot.ircdb.checkCapability:10 +msgid "``ignoreOwner`` disables the behavior \"owners have all capabilites\"" +msgstr "" + +#: of supybot.ircdb.checkCapability:11 +msgid "" +"``ignoreChannelOp`` disables the behavior \"channel ops have all channel " +"capabilities\"" +msgstr "" + +#: of supybot.ircdb.checkCapability:13 +msgid "" +"``ignoreDefaultAllow`` disables the behavior \"if a user does not have a " +"capability or the associated anticapability, then they have the " +"capability\"" +msgstr "" + +#: ../../develop/capabilities.rst:27 +msgid "Manipulating capability names" +msgstr "" + +#: ../../develop/capabilities.rst:29 +msgid "" +"Althrough you can manipulate capability names with string operations, " +"Supybot provides a few methods to do that “in the abstract” (could be " +"useful if we change the capability syntax one day…):" +msgstr "" + +#: of supybot.ircdb.makeChannelCapability:1 +msgid "Makes a channel capability given a channel and a capability." +msgstr "" + +#: of supybot.ircdb.isChannelCapability:1 +msgid "Returns True if capability is a channel capability; False otherwise." +msgstr "" + +#: of supybot.ircdb.makeAntiCapability:1 +msgid "Returns the anticapability of a given capability." +msgstr "" + +#: of supybot.ircdb.unAntiCapability:1 +msgid "Takes an anticapability and returns the non-anti form." +msgstr "" + +#: of supybot.ircdb.invertCapability:1 +msgid "Make a capability into an anticapability and vice versa." +msgstr "" + +#: of supybot.ircdb.isAntiCapability:1 +msgid "Returns True if capability is an anticapability; False otherwise." +msgstr "" + +#: ../../develop/commands.rst:5 +msgid "supybot.commands" +msgstr "" + +#: of supybot.commands:1 +msgid "Includes wrappers for commands." +msgstr "" + +#: of supybot.commands.any:1 supybot.commands.additional:1 +#: supybot.commands.rest:1 supybot.commands.getopts:1 supybot.commands.first:1 +#: supybot.commands.reverse:1 supybot.commands.commalist:1 +msgid "Bases: :class:`supybot.commands.context`" +msgstr "" + +#: of supybot.commands.many:1 +msgid "Bases: :class:`supybot.commands.any`" +msgstr "" + +#: of supybot.commands.optional:1 +msgid "Bases: :class:`supybot.commands.additional`" +msgstr "" + +#: of supybot.commands.getopts:1 +msgid "" +"The empty string indicates that no argument is taken; None indicates that" +" there is no converter for the argument." +msgstr "" + +#: of supybot.commands.urlSnarfer:1 +msgid "Protects the snarfer from loops (with other bots) and whatnot." +msgstr "" + +#: of supybot.commands.thread:1 +msgid "Makes sure a command spawns a thread when called." +msgstr "" + +#: of supybot.commands.wrap:1 +msgid "Useful wrapper for plugin commands." +msgstr "" + +#: of supybot.commands.wrap:3 +msgid "" +"Valid converters are: admin, anything, banmask, boolean, " +"callerInGivenChannel, capability, channel, channelDb, channelOrGlobal, " +"checkCapability, checkCapabilityButIgnoreOwner, checkChannelCapability, " +"color, commandName, email, expiry, filename, float, glob, halfop, " +"haveHalfop, haveHalfop+, haveOp, haveOp+, haveVoice, haveVoice+, " +"hostmask, httpUrl, id, inChannel, index, int, ip, isGranted, letter, " +"literal, long, lowered, matches, networkIrc, nick, nickInChannel, nonInt," +" nonNegativeInt, now, onlyInChannel, op, otherUser, owner, plugin, " +"positiveInt, private, public, regexpMatcher, regexpMatcherMany, " +"regexpReplacer, seenNick, something, somethingWithoutSpaces, text, to, " +"url, user, validChannel, voice." +msgstr "" + +#: of supybot.commands.wrap:5 +msgid "A command, taking (self, irc, msg, args, ...) as arguments" +msgstr "" + +#: of supybot.commands.wrap:6 +msgid "A list of converters and contexts" +msgstr "" + +#: of supybot.commands.process:1 +msgid "Runs a function in a subprocess." +msgstr "" + +#: of supybot.commands.process:3 +msgid "" +"Several extra keyword arguments can be supplied. , the pluginname, " +"and , the command name, are strings used to create the process name, " +"for identification purposes. , if supplied, limits the length of" +" execution of target function to seconds." +msgstr "" + +#: of supybot.commands.regexp_wrapper:1 +msgid "A convenient wrapper to stuff regexp search queries through a subprocess." +msgstr "" + +#: of supybot.commands.regexp_wrapper:3 +msgid "" +"This is used because specially-crafted regexps can use exponential time " +"and hang the bot." +msgstr "" + +#: ../../develop/events.rst:3 +msgid "Special methods and catching events" +msgstr "" + +#: ../../develop/events.rst:5 +msgid "" +"This page is a non-exhaustive list of special plugin method names and " +"events catchable via those methods (other events include " +":ref:`configuration hooks ` and :ref:`HTTP server " +"callbacks `)" +msgstr "" + +#: ../../develop/events.rst:10 +msgid "" +"All methods here are defined in ``supybot-callbacks-plugin``. You may " +"override them if you need, but make sure you call the parent's one unless" +" you actually don't want to do it." +msgstr "" + +#: ../../develop/events.rst:14 +msgid "" +"In case multiple plugins implement the same special methods, the order " +"they are called depends on the ``callAfter`` and ``callBefore`` (lists of" +" plugin names) attributes of the plugins, if they are set." +msgstr "" + +#: ../../develop/events.rst:19 +msgid "Loading and unloading" +msgstr "" + +#: ../../develop/events.rst:21 +msgid "" +"The ``__init__`` method gets called with an Irc object as a parameter " +"when a plugin is loaded (or has just been reloaded). Make sure you always" +" call the parent's ``__init__``." +msgstr "" + +#: ../../develop/events.rst:25 +msgid "" +"When a plugin is unloaded (or is to be reloaded), the ``die`` method is " +"called (with no parameter). Also make sure you always call the parent's " +"``die``." +msgstr "" + +#: ../../develop/events.rst:30 +msgid "Commands and numerics" +msgstr "" + +#: ../../develop/events.rst:32 +msgid "" +"You can catch commands directly with “do-methods”: when the bot receives " +"a ``PRIVMSG``, all ``doPrivmsg`` methods are called; when it gets a " +"``437`` message, all ``do437`` methods are called, etc." +msgstr "" + +#: ../../develop/events.rst:36 +msgid "" +"Those command take two commands: an :ref:`Irc object ` and a :ref:`IrcMsg object `." +msgstr "" + +#: ../../develop/events.rst:39 +msgid "To get a list of all possible messages, check IRC RFCs." +msgstr "" + +#: ../../develop/events.rst:42 +msgid "Filters" +msgstr "" + +#: ../../develop/events.rst:44 +msgid "" +"The ``inFilter`` and ``outFilter`` methods allow you to “intercept” " +"messages between the bot and the network and to alter them." +msgstr "" + +#: ../../develop/events.rst:47 +msgid "" +"``inFilter`` gets messages just after they are parsed from network; and " +"its return value is fed to the bot. ``outFilter`` does the opposite: it " +"get any message the bot is about the send, and returns a message (which " +"may be the same) that will be sent instead." +msgstr "" + +#: ../../develop/events.rst:57 +msgid "Commands handling" +msgstr "" + +#: ../../develop/events.rst:60 +msgid "Command dispatching" +msgstr "" + +#: ../../develop/events.rst:63 +msgid "" +"I wrote this subsection with the little knowledge I have of the commands " +"handling (all I know comes from hacks I made to write the Aka plugin), so" +" keep in mind some informations might be wrong. As for all the " +"documentation, feel free to contact me to correct/enhance it." +msgstr "" + +#: ../../develop/events.rst:70 +msgid "" +"``isCommandMethod`` takes a command name as a string (which may contain " +"spaces) and returns a boolean telling if the plugin provides this " +"command." +msgstr "" + +#: ../../develop/events.rst:72 +msgid "" +"``listCommands`` returns a list of command names as strings (which may " +"contain spaces)" +msgstr "" + +#: ../../develop/events.rst:74 +msgid "" +"``getCommand`` takes a potential command name as a list of strings, and " +"returns a truncated list corresponding to the name of a command provided " +"by the plugin. If no command match, it returns an empty list." +msgstr "" + +#: ../../develop/events.rst:77 +msgid "" +"``getCommandMethod`` takes a command name as a list of strings and " +"returns the corresponding method/function." +msgstr "" + +#: ../../develop/events.rst:79 +msgid "" +"``callCommand`` gets a command name as a list of strings, an irc object, " +"an msg object, and extra arguments (with `*args` and `**kwargs`), calls " +"``getCommandMethod`` to get the command method, and calls it with the " +"arguments. It also calls the functions in ``pre_command_callback``." +msgstr "" + +#: ../../develop/events.rst:86 +msgid "Pre-command-call callbacks" +msgstr "" + +#: ../../develop/events.rst:89 +msgid "" +"Until stock Supybot and Gribble merge this feature, this section only " +"applies to Limnoria" +msgstr "" + +#: ../../develop/events.rst:92 +msgid "" +"If you want a function of your plugin to be called before every command " +"call, you can add it to the ``pre_command_callback`` attribute of your " +"plugin (actually, it is a static class attribute, so make sure you *add* " +"it to the list and don't touch other items of the list)." +msgstr "" + +#: ../../develop/events.rst:97 +msgid "" +"At every command call, *all* callbacks are called, and if *any* of them " +"returns ``True``, the command is not called." +msgstr "" + +#: ../../develop/events.rst:101 +msgid "Other command-related events" +msgstr "" + +#: ../../develop/events.rst:103 +msgid "" +"all ``invalidCommand`` methods get called (with an Irc object, an IrcMsg " +"objet, and a list of token) when a user calls a command that no plugin " +"provides." +msgstr "" + +#: ../../develop/events.rst:109 +msgid "Regular expression triggered events" +msgstr "" + +#: ../../develop/events.rst:111 +msgid "" +"The :class:`supybot.callbacks.PluginRegexp` class provides some utilities" +" for creating plugins that act on regular expression matching." +msgstr "" + +#: ../../develop/httpserver.rst:5 +msgid "Using Limnoria's HTTP server in your plugins" +msgstr "" + +#: ../../develop/httpserver.rst:11 +msgid "" +"Until stock Supybot or Gribble merge the HTTP server, this documentation " +"only applies to Limnoria." +msgstr "" + +#: ../../develop/httpserver.rst:14 +msgid "" +"Limnoria provides an HTTP server to plugins. This is not relevant for " +"most plugins, but some of them have to start a server (either for serving" +" a website or for being remotely called). The HTTP server provided by " +"Limnoria aims at starting a single server for all of them, which means " +"less used port and less resources usage." +msgstr "" + +#: ../../develop/httpserver.rst:20 +msgid "" +"Some example plugins are `Factoids`_, `WebStats`_, `GitHub`_, UfrPaste, " +"and `WebDoc`_" +msgstr "" + +#: ../../develop/httpserver.rst:30 +msgid "Using the HTTP server in a plugin" +msgstr "" + +#: ../../develop/httpserver.rst:32 +msgid "" +"Let's try to make a basic dictionary about Supybot! We'll call it " +"Supystory." +msgstr "" + +#: ../../develop/httpserver.rst:34 +msgid "" +"We want to get plain text information about Supybot, Gribble, and " +"Limnoria when accessing http://localhost:8080/supystory/supybot, " +"http://localhost:8080/supystory/gribble, and " +"http://localhost:8080/supystory/limnoria, an index page, and an HTML " +"error page if the page is not found" +msgstr "" + +#: ../../develop/httpserver.rst:41 +msgid "Importing the HTTP server" +msgstr "" + +#: ../../develop/httpserver.rst:43 +msgid "On only have to add this line::" +msgstr "" + +#: ../../develop/httpserver.rst:48 +msgid "Creating a callback" +msgstr "" + +#: ../../develop/httpserver.rst:50 +msgid "" +"If you are familiar with `BaseHTTPServer`, you will recognize the design," +" except you don't need to subclass BaseHTTPServer, because I already did " +"it in *supybot.httpserver*." +msgstr "" + +#: ../../develop/httpserver.rst:54 +msgid "" +"Now, you have to subclass `httpserver.SupyHTTPServerCallback`. A callback" +" is pretty much like an handler, but this is not an handler, because a " +"callback is called by the handler." +msgstr "" + +#: ../../develop/httpserver.rst:58 +msgid "Here is how to do it::" +msgstr "" + +#: ../../develop/httpserver.rst:63 +msgid "" +"Now, you have to register the callback, because the HTTP server does not " +"know what subdirectory it should assign to your callback. Do it with " +"adding a *__init__* to your plugin (read Supybot's docs about it, for " +"more informations)::" +msgstr "" + +#: ../../develop/httpserver.rst:78 +msgid "" +"By the way, don't forget to unhook your callback when unloading your " +"plugin, unless what it will be impossible to reload the plugin! Append " +"this code to the following::" +msgstr "" + +#: ../../develop/httpserver.rst:89 +msgid "" +"Now, you can load your plugin, and you'll see on the server a beautiful " +"link to `/supystory` called `Supystory`." +msgstr "" + +#: ../../develop/httpserver.rst:93 +msgid "Overriding the default error message" +msgstr "" + +#: ../../develop/httpserver.rst:95 +msgid "" +"But our plugin does not do anything for the moment. If click the link, " +"you'll get this message::" +msgstr "" + +#: ../../develop/httpserver.rst:102 +msgid "" +"That mean your browser sent a GET request, but you didn't teach your " +"plugin how to handle it. First, we'll change this error message. Here is " +"a new code for your callback::" +msgstr "" + +#: ../../develop/httpserver.rst:111 +msgid "" +"Now, you'll get your customized message. But your plugin still doesn't " +"work. You need to implement the GET request." +msgstr "" + +#: ../../develop/httpserver.rst:115 +msgid "Implementing the GET request" +msgstr "" + +#: ../../develop/httpserver.rst:117 +msgid "" +"As I said before, callbacks are pretty much like handlers. In order to " +"handle GET requests, you have to implement a method called... `doGet` (if" +" you used BaseHTTPServer, you will notice this is not do_GET, because " +"doGet is more homogeneous with Supybot naming style: `doPrivmsg`, " +"`doPing`, and so on)." +msgstr "" + +#: ../../develop/httpserver.rst:122 +msgid "" +"You will get the handler and the URI as arguments. The handler is a " +"`BaseHTTPRequestHandler`_, and the URI is a string." +msgstr "" + +#: ../../develop/httpserver.rst:127 +msgid "Here is the code of the callback... pretty much simple, as ever::" +msgstr "" + +#: ../../develop/httpserver.rst:192 +msgid "Using templates" +msgstr "" + +#: ../../develop/httpserver.rst:194 +msgid "" +"You may also want to allow your plugin's users to customize the web pages" +" without editing the source code of the plugin itself." +msgstr "" + +#: ../../develop/httpserver.rst:197 +msgid "" +"Limnoria provides a template facility, which takes a file name, returns " +"the content of a file from the file system if it exists (the user-defined" +" template), and a default one otherwise (the developer's default " +"template). does not exist." +msgstr "" + +#: ../../develop/httpserver.rst:202 +msgid "" +"In our case, we will do it only for the home page and the error page " +"(which are the only 'big' pages), like this::" +msgstr "" + +#: ../../develop/httpserver.rst:275 +msgid "" +"Then, the user can change the template by copying " +"`data/web/supystory/index.html.example` to " +"`data/web/supystory/index.html` and editing it. (Same for `error.html`.)" +msgstr "" + +#: ../../develop/index.rst:5 +msgid "Developing plugins for Limnoria" +msgstr "" + +#: ../../develop/index.rst:8 +msgid "Generic documentation" +msgstr "" + +#: ../../develop/index.rst:20 +msgid "Specific documentation" +msgstr "" + +#: ../../develop/index.rst:31 +msgid "Library reference" +msgstr "" + +#: ../../develop/irclib.rst:5 +msgid "supybot.irclib" +msgstr "" + +#: ../../develop/irclib.rst:10 +msgid "Irc" +msgstr "" + +#: ../../develop/irclib.rst:12 +msgid "It is usually the `irc` object given to plugin commands." +msgstr "" + +#: of supybot.irclib.Irc:1 supybot.irclib.IrcState:1 +#: supybot.irclib.IrcCallback:1 +msgid "" +"Bases: :class:`supybot.irclib.IrcCommandDispatcher`, " +":class:`supybot.log.Firewalled`" +msgstr "" + +#: of supybot.irclib.Irc:1 +msgid "The base class for an IRC connection." +msgstr "" + +#: of supybot.irclib.Irc:3 +msgid "Handles PING commands already." +msgstr "" + +#: ../../develop/irclib.rst:20 +msgid "Whether or not this object represents a living IRC connection." +msgstr "" + +#: ../../develop/irclib.rst:22 +msgid "bool" +msgstr "" + +#: ../../develop/irclib.rst:26 +msgid "The name of the network this object is connected to." +msgstr "" + +#: ../../develop/irclib.rst:28 +msgid "str" +msgstr "" + +#: ../../develop/irclib.rst:32 +msgid "float" +msgstr "" + +#: of supybot.irclib.Irc.addCallback:1 +msgid "Adds a callback to the callbacks list." +msgstr "" + +#: of supybot.irclib.Irc.addCallback:3 +msgid "A callback object" +msgstr "" + +#: of supybot.irclib.Irc.die:1 +msgid "" +"Makes the Irc object *promise* to die -- but it won't die (of its own " +"volition) until all its queues are clear. Isn't that cool?" +msgstr "" + +#: of supybot.irclib.Irc.do002:1 +msgid "Logs the ircd version." +msgstr "" + +#: of supybot.irclib.Irc.do670:1 +msgid "STARTTLS accepted." +msgstr "" + +#: of supybot.irclib.Irc.do691:1 +msgid "STARTTLS refused." +msgstr "" + +#: of supybot.irclib.Irc.doError:1 +msgid "Handles ERROR messages." +msgstr "" + +#: of supybot.irclib.Irc.doNick:1 +msgid "Handles NICK messages." +msgstr "" + +#: of supybot.irclib.Irc.doPing:1 +msgid "Handles PING messages." +msgstr "" + +#: of supybot.irclib.Irc.doPong:1 +msgid "Handles PONG messages." +msgstr "" + +#: of supybot.irclib.Irc.feedMsg:1 +msgid "Called by the IrcDriver; feeds a message received." +msgstr "" + +#: of supybot.irclib.Irc.getCallback:1 +msgid "Gets a given callback by name." +msgstr "" + +#: of supybot.irclib.Irc.isChannel:1 +msgid "" +"Helper function to check whether a given string is a channel on the " +"network this Irc object is connected to." +msgstr "" + +#: of supybot.irclib.Irc.monitor:1 +msgid "" +"Increment a counter of how many callbacks monitor each target; and send a" +" MONITOR + to the server if the target is not yet monitored." +msgstr "" + +#: of supybot.irclib.Irc.queueMsg:1 +msgid "Queues a message to be sent to the server." +msgstr "" + +#: of supybot.irclib.Irc.removeCallback:1 +msgid "Removes a callback from the callback list." +msgstr "" + +#: of supybot.irclib.Irc.reset:1 +msgid "Resets the Irc object. Called when the driver reconnects." +msgstr "" + +#: of supybot.irclib.Irc.sendMsg:1 +msgid "Queues a message to be sent to the server *immediately*" +msgstr "" + +#: of supybot.irclib.Irc.takeMsg:1 +msgid "Called by the IrcDriver; takes a message to be sent." +msgstr "" + +#: of supybot.irclib.Irc.unmonitor:1 +msgid "" +"Decrements a counter of how many callbacks monitor each target; and send " +"a MONITOR - to the server if the counter drops to 0." +msgstr "" + +#: ../../develop/irclib.rst:38 +msgid "IrcState" +msgstr "" + +#: ../../develop/irclib.rst:40 +msgid "" +"Used mainly as the `state` attribute of :py:class:`supybot.irclib.Irc` " +"objects." +msgstr "" + +#: of supybot.irclib.IrcState:1 +msgid "Maintains state of the Irc connection. Should also become smarter." +msgstr "" + +#: of supybot.irclib.IrcState.addMsg:1 +msgid "Updates the state based on the irc object and the message." +msgstr "" + +#: of supybot.irclib.IrcState.do004:1 +msgid "Handles parsing the 004 reply" +msgstr "" + +#: of supybot.irclib.IrcState.do004:3 +msgid "Supported user and channel modes are cached" +msgstr "" + +#: of supybot.irclib.IrcState.getTopic:1 +msgid "Returns the topic for a given channel." +msgstr "" + +#: of supybot.irclib.IrcState.nickToHostmask:1 +msgid "Returns the hostmask for a given nick." +msgstr "" + +#: of supybot.irclib.IrcState.reset:1 +msgid "Resets the state to normal, unconnected state." +msgstr "" + +#: ../../develop/irclib.rst:50 +msgid "ChannelState" +msgstr "" + +#: ../../develop/irclib.rst:52 +msgid "" +"Used mainly as the `channels['#chan']` attribute of " +":py:class:`supybot.irclib.Irc` objects." +msgstr "" + +#: of supybot.irclib.ChannelState:1 +msgid "Bases: :class:`supybot.utils.python.Object`" +msgstr "" + +#: of supybot.irclib.ChannelState.addUser:1 +msgid "Adds a given user to the ChannelState. Power prefixes are handled." +msgstr "" + +#: of supybot.irclib.ChannelState.removeUser:1 +msgid "Removes a given user from the channel." +msgstr "" + +#: of supybot.irclib.ChannelState.replaceUser:1 +msgid "Changes the user oldNick to newNick; used for NICK changes." +msgstr "" + +#: of supybot.irclib.Batch:1 +msgid "Bases: :class:`tuple`" +msgstr "" + +#: of supybot.irclib.Batch.arguments:1 +msgid "Alias for field number 1" +msgstr "" + +#: of supybot.irclib.Batch.messages:1 +msgid "Alias for field number 2" +msgstr "" + +#: of supybot.irclib.Batch.type:1 +msgid "Alias for field number 0" +msgstr "" + +#: of supybot.irclib.IrcCallback:1 +msgid "Base class for standard callbacks." +msgstr "" + +#: of supybot.irclib.IrcCallback:3 +msgid "" +"Callbacks derived from this class should have methods of the form " +"\"doCommand\" -- doPrivmsg, doNick, do433, etc. These will be called on " +"matching messages." +msgstr "" + +#: of supybot.irclib.IrcCallback.name:1 +msgid "Returns the name of the callback." +msgstr "" + +#: of supybot.irclib.IrcCommandDispatcher:1 +msgid "Base class for classes that must dispatch on a command." +msgstr "" + +#: of supybot.irclib.IrcMsgQueue:1 +msgid "Class for a queue of IrcMsgs. Eventually, it should be smart." +msgstr "" + +#: of supybot.irclib.IrcMsgQueue:3 +msgid "" +"Probably smarter than it is now, though it's gotten quite a bit smarter " +"than it originally was. A method to \"score\" methods, and a heapq to " +"maintain a priority queue of the messages would be the ideal way to do " +"intelligent queuing." +msgstr "" + +#: of supybot.irclib.IrcMsgQueue:8 +msgid "" +"As it stands, however, we simply keep track of 'high priority' messages, " +"'low priority' messages, and normal messages, and just make sure to " +"return the 'high priority' ones before the normal ones before the 'low " +"priority' ones." +msgstr "" + +#: of supybot.irclib.IrcMsgQueue.dequeue:1 +msgid "Dequeues a given message." +msgstr "" + +#: of supybot.irclib.IrcMsgQueue.enqueue:1 +msgid "Enqueues a given message." +msgstr "" + +#: of supybot.irclib.IrcMsgQueue.reset:1 +msgid "Clears the queue." +msgstr "" + +#: ../../develop/ircmsgs.rst:5 +msgid "supybot.ircmsgs" +msgstr "" + +#: of supybot.ircmsgs:1 +msgid "" +"This module provides the basic IrcMsg object used throughout the bot to " +"represent the actual messages. It also provides several helper functions" +" to construct such messages in an easier way than the constructor for the" +" IrcMsg object (which, as you'll read later, is quite...full-featured :))" +msgstr "" + +#: of supybot.ircmsgs.IrcMsg:1 +msgid "Class to represent an IRC message." +msgstr "" + +#: of supybot.ircmsgs.IrcMsg:3 +msgid "" +"As usual, ignore attributes that begin with an underscore. They simply " +"don't exist. Instances of this class are *not* to be modified, since " +"they are hashable. Public attributes of this class are .prefix, " +".command, .args, .nick, .user, and .host." +msgstr "" + +#: of supybot.ircmsgs.IrcMsg:8 +msgid "" +"The constructor for this class is pretty intricate. It's designed to " +"take any of three major (sets of) arguments." +msgstr "" + +#: of supybot.ircmsgs.IrcMsg:11 +msgid "" +"Called with no keyword arguments, it takes a single string that is a raw " +"IRC message (such as one taken straight from the network)." +msgstr "" + +#: of supybot.ircmsgs.IrcMsg:14 +msgid "" +"Called with keyword arguments, it *requires* a command parameter. Args " +"is optional, but with most commands will be necessary. Prefix is " +"obviously optional, since clients aren't allowed (well, technically, they" +" are, but only in a completely useless way) to send prefixes to the " +"server." +msgstr "" + +#: of supybot.ircmsgs.IrcMsg:19 +msgid "" +"Since this class isn't to be modified, the constructor also accepts a " +"'msg' keyword argument representing a message from which to take all the " +"attributes not provided otherwise as keyword arguments. So, for " +"instance, if a programmer wanted to take a PRIVMSG they'd gotten and " +"simply redirect it to a different source, they could do this:" +msgstr "" + +#: of supybot.ircmsgs.IrcMsg:25 +msgid "IrcMsg(prefix='', args=(newSource, otherMsg.args[1]), msg=otherMsg)" +msgstr "" + +#: of supybot.ircmsgs.IrcMsg.tag:1 +msgid "Affect a key:value pair to this message." +msgstr "" + +#: of supybot.ircmsgs.IrcMsg.tagged:1 +msgid "Get the value affected to a tag." +msgstr "" + +#: of supybot.ircmsgs.action:1 +msgid "Returns a PRIVMSG ACTION to recipient with the message msg." +msgstr "" + +#: of supybot.ircmsgs.ban:1 +msgid "Returns a MODE to ban nick on channel." +msgstr "" + +#: of supybot.ircmsgs.bans:1 +msgid "Returns a MODE to ban each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.dehalfop:1 +msgid "Returns a MODE to dehalfop nick on channel." +msgstr "" + +#: of supybot.ircmsgs.dehalfops:1 +msgid "Returns a MODE to dehalfop each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.deop:1 +msgid "Returns a MODE to deop nick on channel." +msgstr "" + +#: of supybot.ircmsgs.deops:1 +msgid "Returns a MODE to deop each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.devoice:1 +msgid "Returns a MODE to devoice nick on channel." +msgstr "" + +#: of supybot.ircmsgs.devoices:1 +msgid "Returns a MODE to devoice each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.halfop:1 +msgid "Returns a MODE to halfop nick on channel." +msgstr "" + +#: of supybot.ircmsgs.halfops:1 +msgid "Returns a MODE to halfop each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.invite:1 +msgid "Returns an INVITE for nick." +msgstr "" + +#: of supybot.ircmsgs.isAction:1 +msgid "A predicate returning true if the PRIVMSG in question is an ACTION" +msgstr "" + +#: of supybot.ircmsgs.isCtcp:1 +msgid "Returns whether or not msg is a CTCP message." +msgstr "" + +#: of supybot.ircmsgs.join:1 +msgid "Returns a JOIN to a channel" +msgstr "" + +#: of supybot.ircmsgs.joins:1 +msgid "Returns a JOIN to each of channels." +msgstr "" + +#: of supybot.ircmsgs.kick:1 +msgid "Returns a KICK to kick nick from channel with the message msg." +msgstr "" + +#: of supybot.ircmsgs.kicks:1 +msgid "Returns a KICK to kick each of nicks from channel with the message msg." +msgstr "" + +#: of supybot.ircmsgs.modes:1 +msgid "Returns a MODE to quiet each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.nick:1 +msgid "Returns a NICK with nick nick." +msgstr "" + +#: of supybot.ircmsgs.notice:1 +msgid "Returns a NOTICE to recipient with the message msg." +msgstr "" + +#: of supybot.ircmsgs.op:1 +msgid "Returns a MODE to op nick on channel." +msgstr "" + +#: of supybot.ircmsgs.ops:1 +msgid "Returns a MODE to op each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.part:1 +msgid "Returns a PART from channel with the message msg." +msgstr "" + +#: of supybot.ircmsgs.parts:1 +msgid "Returns a PART from each of channels with the message msg." +msgstr "" + +#: of supybot.ircmsgs.password:1 +msgid "Returns a PASS command for accessing a server." +msgstr "" + +#: of supybot.ircmsgs.ping:1 +msgid "Takes a payload and returns the proper PING IrcMsg." +msgstr "" + +#: of supybot.ircmsgs.pong:1 +msgid "Takes a payload and returns the proper PONG IrcMsg." +msgstr "" + +#: of supybot.ircmsgs.prettyPrint:1 +msgid "Provides a client-friendly string form for messages." +msgstr "" + +#: of supybot.ircmsgs.prettyPrint:3 +msgid "IIRC, I copied BitchX's (or was it XChat's?) format for messages." +msgstr "" + +#: of supybot.ircmsgs.privmsg:1 +msgid "Returns a PRIVMSG to recipient with the message msg." +msgstr "" + +#: of supybot.ircmsgs.quit:1 +msgid "Returns a QUIT with the message msg." +msgstr "" + +#: of supybot.ircmsgs.topic:1 +msgid "Returns a TOPIC for channel with the topic topic." +msgstr "" + +#: of supybot.ircmsgs.unAction:1 +msgid "Returns the payload (i.e., non-ACTION text) of an ACTION msg." +msgstr "" + +#: of supybot.ircmsgs.unban:1 +msgid "Returns a MODE to unban nick on channel." +msgstr "" + +#: of supybot.ircmsgs.unbans:1 +msgid "Returns a MODE to unban each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.user:1 +msgid "Returns a USER with ident ident and user user." +msgstr "" + +#: of supybot.ircmsgs.voice:1 +msgid "Returns a MODE to voice nick on channel." +msgstr "" + +#: of supybot.ircmsgs.voices:1 +msgid "Returns a MODE to voice each of nicks on channel." +msgstr "" + +#: of supybot.ircmsgs.who:1 +msgid "Returns a WHO for the hostmask or channel hostmaskOrChannel." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:3 +msgid "Writing Your First Supybot Plugin" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:7 +msgid "" +"Ok, so you want to write a plugin for Supybot. Good, then this is the " +"place to be. We're going to start from the top (the highest level, where " +"Supybot code does the most work for you) and move lower after that." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:11 +msgid "" +"So have you used Supybot? If not, you need to go use it. This will help " +"you understand crucial things like the way the various commands work and " +"it is essential prior to embarking upon the plugin-development excursion " +"detailed in the following pages. If you haven't used Supybot, come back " +"to this document after you've used it for a while and gotten a feel for " +"it." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:17 +msgid "" +"So, now that we know you've used Supybot, we'll start getting into " +"details. We'll go through this tutorial by actually writing a new plugin," +" named Random with just a few simple commands." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:21 +msgid "" +"Caveat: you'll need to have Supybot installed on the machine you intend " +"to develop plugins on. This will not only allow you to test the plugins " +"with a live bot, but it will also provide you with several nice scripts " +"which aid the development of plugins. Most notably, it provides you with " +"the supybot-plugin-create script which we will use in the next section..." +" Creating a minimal plugin This section describes using the 'supybot-" +"plugin-create' script to create a minimal plugin which we will enhance in" +" later sections." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:30 +msgid "" +"The recommended way to start writing a plugin is to use the wizard " +"provided, :command:`supybot-plugin-create`. Run this from within your " +"local plugins directory, so we will be able to load the plugin and test " +"it out." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:34 +msgid "" +"It's very easy to follow, because basically all you have to do is answer " +"three questions. Here's an example session::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:52 +msgid "" +"It's that simple! Well, that part of making the minimal plugin is that " +"simple. You should now have a directory with a few files in it, so let's " +"take a look at each of those files and see what they're used for." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:57 +msgid "README.md" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:58 +msgid "" +"Open the file with notepad just as if it was a .txt file. In `README.md` " +"you put exactly what the boilerplate text says to put in there:" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:61 +msgid "" +"Insert a description of your plugin here, with any notes, etc. about " +"using it." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:64 +msgid "" +"A brief overview of exactly what the purpose of the plugin is supposed to" +" do is really all that is needed here. Also, if this plugin requires any " +"third-party Python modules, you should definitely mention those here. You" +" don't have to describe individual commands or anything like that, as " +"those are defined within the plugin code itself as you'll see later. You " +"also don't need to acknowledge any of the developers of the plugin as " +"those too are handled elsewhere." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:71 +msgid "For our Random plugin, let's make :file:`README.md` say this:" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:73 +msgid "" +"This plugin contains commands relating to random numbers, and includes: a" +" simple random number generator, the ability to pick a random number from" +" within a range, a command for returning a random sampling from a list of" +" items, and a simple dice roller." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:78 +msgid "" +"And now you know what's in store for the rest of this tutorial, we'll be " +"writing all of that in one Supybot plugin, and you'll be surprised at " +"just how simple it is!" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:83 +msgid "__init__.py" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:84 +msgid "" +"The next file we'll look at is :file:`__init__.py`. If you're familiar " +"with the Python import mechanism, you'll know what this file is for. If " +"you're not, think of it as sort of the \"glue\" file that pulls all the " +"files in this directory together when you load the plugin. It's also " +"where there are a few administrative items live that you really need to " +"maintain." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:90 +msgid "" +"Let's go through the file. For the first 30 lines or so, you'll see the " +"copyright notice that we use for our plugins, only with your name in " +"place (as prompted in :command:`supybot-plugin-create`). Feel free to use" +" whatever license you choose, we don't feel particularly attached to the " +"boilerplate code so it's yours to license as you see fit even if you " +"don't modify it. For our example, we'll leave it as is." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:97 +msgid "" +"The plugin docstring immediately follows the copyright notice and it " +"(like :file:`README.txt`) tells you precisely what it should contain:" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:100 +msgid "" +"Add a description of the plugin (to be presented to the user inside the " +"wizard) here. This should describe *what* the plugin does." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:103 +msgid "" +"The \"wizard\" that it speaks of is the :command:`supybot-wizard` script " +"that is used to create working Supybot config file. I imagine that in " +"meeting the prerequisite of \"using a Supybot\" first, most readers will " +"have already encountered this script. Basically, if the user selects to " +"look at this plugin from the list of plugins to load, it prints out that " +"description to let the user know what it does, so make sure to be clear " +"on what the purpose of the plugin is. This should be an abbreviated " +"version of what we put in our :file:`README.txt`, so let's put this::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:114 +msgid "" +"Next in :file:`__init__.py` you see a few imports which are necessary, " +"and then four attributes that you need to modify for your bot and " +"preferably keep up with as you develop it: ``__version__``, " +"``__author__``, ``__contributors__``, ``__url__``." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:119 +msgid "" +"``__version__`` is just a version string representing the current working" +" version of the plugin, and can be anything you want. If you use some " +"sort of RCS, this would be a good place to have it automatically " +"increment the version string for any time you edit any of the files in " +"this directory. We'll just make ours \"0.1\"." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:125 +msgid "" +"``__author__`` should be an instance of the :class:`supybot.Author` " +"class. A :class:`supybot.Author` is simply created by giving it a full " +"name, a short name (preferably IRC nick), and an e-mail address (all of " +"these are optional, though at least the second one is expected). So, for " +"example, to create my Author user (though I get to cheat and use " +"supybot.authors.strike since I'm a main dev, muahaha), I would do::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:135 +msgid "Keep this in mind as we get to the next item..." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:137 +msgid "" +"``__contributors__`` is a dictionary mapping supybot.Author instances to " +"lists of things they contributed. If someone adds a command named foo to " +"your plugin, the list for that author should be ``[\"foo\"]``, or perhaps" +" even ``[\"added foo command\"]``. The main author shouldn't be " +"referenced here, as it is assumed that everything that wasn't contributed" +" by someone else was done by the main author. For now we have no " +"contributors, so we'll leave it blank." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:144 +msgid "" +"Lastly, the ``__url__`` attribute should just reference the download URL " +"for the plugin. Since this is just an example, we'll leave this blank." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:147 +msgid "" +"The rest of :file:`__init__.py` really shouldn't be touched unless you " +"are using third-party modules in your plugin. If you are, then you need " +"to take special note of the section that looks like this::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:158 +msgid "" +"As the comment says, this is one place where you need to make sure you " +"import the third-party modules, and that you call :func:`reload` on them " +"as well. That way, if we are reloading a plugin on a running bot it will " +"actually reload the latest code. We aren't using any third-party modules," +" so we can just leave this bit alone." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:164 +msgid "" +"We're almost through the \"boring\" part and into the guts of writing " +"Supybot plugins, let's take a look at the next file." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:168 +msgid "config.py" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:169 +msgid "" +":file:`config.py` is, unsurprisingly, where all the configuration stuff " +"related to your plugin goes. If you're not familiar with Supybot's " +"configuration system, I recommend reading the config tutorial before " +"going any further with this section." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:174 +msgid "So, let's plow through config.py line-by-line like we did the other files." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:176 +msgid "" +"Once again, at the top is the standard copyright notice. Again, change it" +" to how you see fit." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:179 +msgid "Then, some standard imports which are necessary." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:181 +msgid "" +"Now, the first peculiar thing we get to is the configure function. This " +"function is what is called by the supybot-wizard whenever a plugin is " +"selected to be loaded. Since you've used the bot by now (as stated on the" +" first page of this tutorial as a prerequisite), you've seen what this " +"script does to configure plugins. The wizard allows the bot owner to " +"choose something different from the default plugin config values without " +"having to do it through the bot (which is still not difficult, but not as" +" easy as this). Also, note that the advanced argument allows you to " +"differentiate whether or not the person configuring this plugin considers" +" himself an advanced Supybot user. Our plugin has no advanced features, " +"so we won't be using it." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:192 +msgid "" +"So, what exactly do we do in this configure function for our plugin? " +"Well, for the most part we ask questions and we set configuration values." +" You'll notice the import line with supybot.questions in it. That " +"provides some nice convenience functions which are used to (you guessed " +"it) ask questions. The other line in there is the conf.registerPlugin " +"line which registers our plugin with the config and allows us to create " +"configuration values for the plugin. You should leave these two lines in " +"even if you don't have anything else to put in here. For the vast " +"majority of plugins, you can leave this part as is, so we won't go over " +"how to write plugin configuration functions here (that will be handled in" +" a separate article). Our plugin won't be using much configuration, so " +"we'll leave this as is." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:204 +msgid "" +"Next, you'll see a line that looks very similar to the one in the " +"configure function. This line is used not only to register the plugin " +"prior to being called in configure, but also to store a bit of an alias " +"to the plugin's config group to make things shorter later on. So, this " +"line should read::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:211 +msgid "" +"Now we get to the part where we define all the configuration groups and " +"variables that our plugin is to have. Again, many plugins won't require " +"any configuration so we won't go over it here, but in a separate article " +"dedicated to sprucing up your config.py for more advanced plugins. Our " +"plugin doesn't require any config variables, so we actually don't need to" +" make any changes to this file at all." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:218 +msgid "" +"Configuration of plugins is handled in depth at the Advanced Plugin " +"Config Tutorial" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:222 +msgid "plugin.py" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:223 +msgid "" +"Here's the moment you've been waiting for, the overview of plugin.py and " +"how to make our plugin actually do stuff." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:226 +msgid "" +"At the top, same as always, is the standard copyright block to be used " +"and abused at your leisure." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:229 +msgid "" +"Next, some standard imports. Not all of them are used at the moment, but " +"you probably will use many (if not most) of them, so just let them be. " +"Since we'll be making use of Python's standard 'random' module, you'll " +"need to add the following line to the list of imports::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:236 +msgid "" +"Now, the plugin class itself. What you're given is a skeleton: a simple " +"subclass of callbacks.Plugin for you to start with. The only real content" +" it has is the boilerplate docstring, which you should modify to reflect " +"what the boilerplate text says - it should be useful so that when someone" +" uses the plugin help command to determine how to use this plugin, " +"they'll know what they need to do. Ours will read something like::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:251 +msgid "" +"It's basically a \"guide to getting started\" for the plugin. Now, to " +"make the plugin do something. First of all, to get any random numbers " +"we're going to need a random number generator (RNG). Pretty much " +"everything in our plugin is going to use it, so we'll define it in the " +"constructor of our plugin, __init__. Here we'll also seed it with the " +"current time (standard practice for RNGs). Here's what our __init__ looks" +" like::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:264 +msgid "" +"Now, the first two lines may look a little daunting, but it's just " +"administrative stuff required if you want to use a custom __init__. If we" +" didn't want to do so, we wouldn't have to, but it's not uncommon so I " +"decided to use an example plugin that did. For the most part you can just" +" copy/paste those lines into any plugin you override the __init__ for and" +" just change them to use the plugin name that you are working on instead." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:271 +msgid "" +"So, now we have a RNG in our plugin, let's write a command to get a " +"random number. We'll start with a simple command named random that just " +"returns a random number from our RNG and takes no arguments. Here's what " +"that looks like::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:284 +msgid "And that's it. Now here are the important points." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:286 +msgid "" +"First and foremost, all plugin commands must have all-lowercase function " +"names. If they aren't all lowercase they won't show up in a plugin's list" +" of commands (nor will they be useable in general). If you look through a" +" plugin and see a function that's not in all lowercase, it is not a " +"plugin command. Chances are it is a helper function of some sort, and in " +"fact using capital letters is a good way of assuring that you don't " +"accidentally expose helper functions to users as commands." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:294 +msgid "" +"You'll note the arguments to this class method are (self, irc, msg, " +"args). This is what the argument list for all methods that are to be used" +" as commands must start with. If you wanted additional arguments, you'd " +"append them onto the end, but since we take no arguments we just stop " +"there. I'll explain this in more detail with our next command, but it is " +"very important that all plugin commands are class methods that start with" +" those four arguments exactly as named." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:301 +msgid "" +"Next, in the docstring there are two major components. First, the very " +"first line dictates the argument list to be displayed when someone calls " +"the help command for this command (i.e., help random). Then you leave a " +"blank line and start the actual help string for the function. Don't worry" +" about the fact that it's tabbed in or anything like that, as the help " +"command normalizes it to make it look nice. This part should be fairly " +"brief but sufficient to explain the function and what (if any) arguments " +"it requires. Remember that this should fit in one IRC message which is " +"typically around a 450 character limit." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:310 +msgid "" +"Then we have the actual code body of the plugin, which consists of a " +"single line: irc.reply(str(self.rng.random())). The irc.reply function " +"issues a reply to wherever the PRIVMSG it received the command from with " +"whatever text is provided. If you're not sure what I mean when I say " +"\"wherever the PRIVMSG it received the command from\", basically it " +"means: if the command is issued in a channel the response is sent in the " +"channel, and if the command is issued in a private dialog the response is" +" sent in a private dialog. The text we want to display is simply the next" +" number from our RNG (self.rng). We get that number by calling the random" +" function, and then we str it just to make sure it is a nice printable " +"string." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:321 +msgid "" +"Lastly, all plugin commands must be 'wrap'ed. What the wrap function does" +" is handle argument parsing for plugin commands in a very nice and very " +"powerful way. With no arguments, we simply need to just wrap it. For more" +" in-depth information on using wrap check out the wrap tutorial (The " +"astute Python programmer may note that this is very much like a " +"decorator, and that's precisely what it is. However, we developed this " +"before decorators existed and haven't changed the syntax due to our " +"earlier requirement to stay compatible with Python 2.3. As we now " +"require Python 2.4 or greater, this may eventually change to support work" +" via decorators.)" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:331 +msgid "" +"Now let's create a command with some arguments and see how we use those " +"in our plugin commands. Let's allow the user to seed our RNG with their " +"own seed value. We'll call the command seed and take just the seed value " +"as the argument (which we'll require be a floating point value of some " +"sort, though technically it can be any hashable object). Here's what this" +" command looks like::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:347 +msgid "" +"You'll notice first that argument list now includes an extra argument, " +"seed. If you read the wrap tutorial mentioned above, you should " +"understand how this arg list gets populated with values. Thanks to wrap " +"we don't have to worry about type-checking or value-checking or anything " +"like that. We just specify that it must be a float in the wrap portion " +"and we can use it in the body of the function." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:354 +msgid "" +"Of course, we modify the docstring to document this function. Note the " +"syntax on the first line. Arguments go in <> and optional arguments " +"should be surrounded by [] (we'll demonstrate this later as well)." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:358 +msgid "" +"The body of the function should be fairly straightforward to figure out, " +"but it introduces a new function - irc.replySuccess. This is just a " +"generic \"I succeeded\" command which responds with whatever the bot " +"owner has configured to be the success response (configured in " +"supybot.replies.success). Note that we don't do any error-checking in the" +" plugin, and that's because we simply don't have to. We are guaranteed " +"that seed will be a float and so the call to our RNG's seed is guaranteed" +" to work." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:366 +msgid "" +"Lastly, of course, the wrap call. Again, read the wrap tutorial for " +"fuller coverage of its use, but the basic premise is that the second " +"argument to wrap is a list of converters that handles argument validation" +" and conversion and it then assigns values to each argument in the arg " +"list after the first four (required) arguments. So, our seed argument " +"gets a float, guaranteed." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:372 +msgid "" +"With this alone you'd be able to make some pretty usable plugin commands," +" but we'll go through two more commands to introduce a few more useful " +"ideas. The next command we'll make is a sample command which gets a " +"random sample of items from a list provided by the user::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:393 +msgid "" +"This plugin command introduces a few new things, but the general " +"structure should look fairly familiar by now. You may wonder why we only " +"have two extra arguments when obviously this plugin can accept any number" +" of arguments. Well, using wrap we collect all of the remaining arguments" +" after the first one into the items argument. If you haven't caught on " +"yet, wrap is really cool and extremely useful." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:400 +msgid "" +"Next of course is the updated docstring. Note the use of [] to denote the" +" optional items after the first item." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:403 +msgid "" +"The body of the plugin should be relatively easy to read. First we check " +"and make sure that n (the number of items the user wants to sample) is " +"not larger than the actual number of items they gave. If it does, we call" +" irc.error with the error message you see. irc.error is kind of like " +"irc.replySuccess only it gives an error message using the configured " +"error format (in supybot.replies.error). Otherwise, we use the sample " +"function from our RNG to get a sample, then we sort it, and we reply with" +" the 'utils.str.commaAndify'ed version. The utils.str.commaAndify " +"function basically takes a list of strings and turns it into \"item1, " +"item2, item3, item4, and item5\" for an arbitrary length. More details on" +" using the utils module can be found in the utils tutorial." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:415 +msgid "" +"Now for the last command that we will add to our plugin.py. This last " +"command will allow the bot users to roll an arbitrary n-sided die, with " +"as many sides as they so choose. Here's the code for this command::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:429 +msgid "" +"The only new thing learned here really is that the irc.reply method " +"accepts an optional argument action, which if set to True makes the reply" +" an action instead. So instead of just crudely responding with the " +"number, instead you should see something like * supybot rolls a 5. You'll" +" also note that it uses a more advanced wrap line than we have used to " +"this point, but to learn more about wrap, you should refer to the wrap " +"tutorial" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:436 +msgid "" +"And now that we're done adding plugin commands you should see the " +"boilerplate stuff at the bottom, which just consists of::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:441 +msgid "" +"And also some vim modeline stuff. Leave these as is, and we're finally " +"done with plugin.py!" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:445 +msgid "test.py" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:446 +msgid "" +"Now that we've gotten our plugin written, we want to make sure it works. " +"Sure, an easy way to do a somewhat quick check is to start up a bot, load" +" the plugin, and run a few commands on it. If all goes well there, " +"everything's probably okay. But, we can do better than \"probably okay\"." +" This is where written plugin tests come in. We can write tests that not " +"only assure that the plugin loads and runs the commands fine, but also " +"that it produces the expected output for given inputs. And not only that," +" we can use the nifty supybot-test script to test the plugin without even" +" having to have a network connection to connect to IRC with and most " +"certainly without running a local IRC server." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:456 +msgid "" +"The boilerplate code for test.py is a good start. It imports everything " +"you need and sets up RandomTestCase which will contain all of our tests. " +"Now we just need to write some test methods. I'll be moving fairly " +"quickly here just going over very basic concepts and glossing over " +"details, but the full plugin test authoring tutorial has much more detail" +" to it and is recommended reading after finishing this tutorial." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:463 +msgid "" +"Since we have four commands we should have at least four test methods in " +"our test case class. Typically you name the test methods that simply " +"checks that a given command works by just appending the command name to " +"test. So, we'll have testRandom, testSeed, testSample, and testDiceRoll. " +"Any other methods you want to add are more free-form and should describe " +"what you're testing (don't be afraid to use long names)." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:470 +msgid "First we'll write the testRandom method::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:476 +msgid "" +"Since we can't predict what the output of our random number generator is " +"going to be, it's hard to specify a response we want. So instead, we just" +" make sure we don't get an error by calling the random command, and " +"that's about all we can do." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:481 +msgid "" +"Next, testSeed. In this method we're just going to check that the command" +" itself functions. In another test method later on we will check and make" +" sure that the seed produces reproducible random numbers like we would " +"hope it would, but for now we just test it like we did random in " +"'testRandom'::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:490 +msgid "" +"Now for testSample. Since this one takes more arguments it makes sense " +"that we test more scenarios in this one. Also this time we have to make " +"sure that we hit the error that we coded in there given the right " +"conditions::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:500 +msgid "" +"So first we check and make sure trying to take a 20-element sample of a " +"1-element list gives us an error. Next we just check and make sure we get" +" the right number of elements and that they are formatted correctly when " +"we give 1, 2, or 3 element lists." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:505 +msgid "" +"And for the last of our basic \"check to see that it works\" functions, " +"testDiceRoll::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:511 +msgid "" +"We know that diceroll should return an action, and that with no arguments" +" it should roll a single-digit number. And that's about all we can test " +"reliably here, so that's all we do." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:515 +msgid "" +"Lastly, we wanted to check and make sure that seeding the RNG with seed " +"actually took effect like it's supposed to. So, we write another test " +"method::" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:528 +msgid "" +"So we seed the RNG with 20, store the message, and then seed it at 20 " +"again. We grab that message, and unless they are the same number when we " +"compare the two, we fail. And then just to make sure our RNG is producing" +" random numbers, we get another random number and make sure it is " +"distinct from the prior one." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:534 +msgid "Conclusion" +msgstr "" + +#: ../../develop/plugin_tutorial.rst:535 +msgid "" +"You are now very well-prepared to write Supybot plugins. Now for a few " +"words of wisdom with regards to Supybot plugin-writing." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:538 +msgid "" +"Read other people's plugins, especially the included plugins and ones by " +"the core developers. We (the Supybot dev team) can't possibly document " +"all the awesome things that Supybot plugins can do, but we try. " +"Nevertheless there are some really cool things that can be done that " +"aren't very well-documented." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:544 +msgid "" +"Hack new functionality into existing plugins first if writing a new " +"plugin is too daunting." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:547 +msgid "" +"Come ask us questions in #supybot on Freenode or OFTC. Going back to the " +"first point above, the developers themselves can help you even more than " +"the docs can (though we prefer you read the docs first)." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:551 +msgid "" +"Share your plugins with the world and make Supybot all that more " +"attractive for other users so they will want to write their plugins for " +"Supybot as well." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:555 +msgid "Read, read, read all the documentation." +msgstr "" + +#: ../../develop/plugin_tutorial.rst:557 +msgid "And of course, have fun writing your plugins." +msgstr "" + +#: ../../develop/style.rst:3 +msgid "Style Guidelines" +msgstr "" + +#: ../../develop/style.rst:5 +msgid "" +"**Note:** Code not following these style guidelines fastidiously is " +"likely (*very* likely) not to be accepted into the Supybot core." +msgstr "" + +#: ../../develop/style.rst:8 +msgid "" +"Read :pep:`8` (Guido's Style Guide) and know that we use almost all the " +"same style guidelines." +msgstr "" + +#: ../../develop/style.rst:11 +msgid "" +"Maximum line length is 79 characters. 78 is a safer bet, though. This is" +" **NON-NEGOTIABLE**. Your code will not be accepted while you are " +"violating this guidline." +msgstr "" + +#: ../../develop/style.rst:15 +msgid "" +"Identation is 4 spaces per level. No tabs. This also is **NON-" +"NEGOTIABLE**. Your code, again, will *never* be accepted while you have " +"literal tabs in it." +msgstr "" + +#: ../../develop/style.rst:19 +msgid "" +"Single quotes are used for all string literals that aren't docstrings. " +"They're just easier to type." +msgstr "" + +#: ../../develop/style.rst:22 +msgid "Triple double quotes (``\"\"\"``) are always used for docstrings." +msgstr "" + +#: ../../develop/style.rst:24 +msgid "Raw strings (``r''`` or ``r\"\"``) should be used for regular expressions." +msgstr "" + +#: ../../develop/style.rst:26 +msgid "" +"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)." +msgstr "" + +#: ../../develop/style.rst:30 +msgid "" +"Functions calls should look like ``foo(bar(baz(x), y))``. They should " +"not look like ``foo (bar (baz (x), y))``, or like ``foo(bar(baz(x), y) " +")`` or like anything else. I hate extraneous spaces." +msgstr "" + +#: ../../develop/style.rst:34 +msgid "" +"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." +msgstr "" + +#: ../../develop/style.rst:40 +msgid "" +"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)." +msgstr "" + +#: ../../develop/style.rst:43 +msgid "" +"Unless absolutely required by some external force, imports should be " +"ordered by the string length of the module imported. I just think it " +"looks prettier." +msgstr "" + +#: ../../develop/style.rst:47 +msgid "" +"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." +msgstr "" + +#: ../../develop/style.rst:52 +msgid "" +"Database filenames should generally begin with the name of the plugin and" +" the extension should be 'db'. plugins.DBHandler does this already." +msgstr "" + +#: ../../develop/style.rst:55 +msgid "" +"Whenever creating a file descriptor or socket, keep a reference around " +"and be sure to close it. There should be no code like this::" +msgstr "" + +#: ../../develop/style.rst:60 +msgid "Instead, do this::" +msgstr "" + +#: ../../develop/style.rst:68 +msgid "This is to be sure the bot doesn't leak file descriptors." +msgstr "" + +#: ../../develop/style.rst:70 +msgid "" +"All plugin files should include a docstring decsribing what the plugin " +"does. This docstring will be returned when the user is configuring the " +"plugin. All plugin classes should also include a docstring describing how" +" to do things with the plugin; this docstring will be returned when the " +"user requests help on a plugin name." +msgstr "" + +#: ../../develop/style.rst:76 +msgid "" +"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." +msgstr "" + +#: ../../develop/style.rst:82 +msgid "" +"Whenever joining more than two strings, use string interpolation, not " +"addition::" +msgstr "" + +#: ../../develop/style.rst:89 +msgid "" +"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. People who " +"use string concatenation in a for loop will be swiftly kicked in the " +"head." +msgstr "" + +#: ../../develop/style.rst:93 +#, python-format +msgid "" +"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. If you got the ``%d`` wrong, you'll get an exception that says," +" \"foo instance can't be converted to an integer.\" But if you use " +"``%s``, you'll get to see your nice little foo instance, if it doesn't " +"convert to a string cleanly, and if it does convert cleanly, you'll get " +"to see what you expect to see. Basically, ``%d`` just sucks." +msgstr "" + +#: ../../develop/style.rst:102 +#, python-format +msgid "" +"As a corrolary to the above, note that sometimes ``%f`` is used, but on " +"when floats need to be formatted, e.g., ``%.2f``." +msgstr "" + +#: ../../develop/style.rst:105 +msgid "" +"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 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." +msgstr "" + +#: ../../develop/style.rst:111 +msgid "" +"While on the topic of logs, note that we do not use % (i.e., str.__mod__)" +" with logged strings; we simple pass the format parameters as additional " +"arguments. The reason is simple: the logging module supports it, and " +"it's cleaner (fewer tokens/glyphs) to read." +msgstr "" + +#: ../../develop/style.rst:116 +msgid "" +"While still on the topic of logs, it's also important to pick the " +"appropriate log level for given information." +msgstr "" + +#: ../../develop/style.rst:119 +msgid "" +"DEBUG: Appropriate to tell a programmer *how* we're doing something " +"(i.e., debugging printfs, basically). If you're trying to figure out why" +" your code doesn't work, DEBUG is the new printf -- use that, and leave " +"the statements in your code." +msgstr "" + +#: ../../develop/style.rst:124 +msgid "" +"INFO: Appropriate to tell a user *what* we're doing, when what we're " +"doing isn't important for the user to pay attention to. A user who likes" +" to keep up with things should enjoy watching our logging at the INFO " +"level; it shouldn't be too low-level, but it should give enough " +"information that it keeps them relatively interested at peak times." +msgstr "" + +#: ../../develop/style.rst:130 +msgid "" +"WARNING: Appropriate to tell a user when we're doing something that they" +" really ought to pay attention to. Users should see WARNING and think, " +"\"Hmm, should I tell the Supybot developers about this?\" Later, they " +"should decide not to, but it should give the user a moment to pause and " +"think about what's actually happening with their bot." +msgstr "" + +#: ../../develop/style.rst:136 +msgid "" +"ERROR: Appropriate to tell a user when something has gone wrong. " +"Uncaught exceptions are ERRORs. Conditions that we absolutely want to " +"hear about should be errors. Things that should *scare* the user should " +"be errors." +msgstr "" + +#: ../../develop/style.rst:141 +msgid "" +"CRITICAL: Not really appropriate. I can think of no absolutely critical " +"issue yet encountered in Supybot; the only possible thing I can imagine " +"is to notify the user that the partition on which Supybot is running has " +"filled up. That would be a CRITICAL condition, but it would also be hard" +" to log :)" +msgstr "" + +#: ../../develop/style.rst:148 +msgid "" +"All plugins should have test cases written for them. Even if it doesn't " +"actually test anything but just exists, it's good to have the test there " +"so there's a place to add more tests later (and so we can be sure that " +"all plugins are adequately documented; PluginTestCase checks that every " +"command has documentation)" +msgstr "" + +#: ../../develop/style.rst:154 +msgid "" +"All uses of eval() that expect to get integrated in Supybot must be " +"approved by jemfinch, no exceptions. Chances are, it won't be accepted." +" Have you looked at utils.safeEval?" +msgstr "" + +#: ../../develop/style.rst:158 +msgid "" +"SQL table names should be all-lowercase and include underscores to " +"separate words. This is because SQL itself is case-insensitive. This " +"doesn't change, however the fact that variable/member names should be " +"camel case." +msgstr "" + +#: ../../develop/style.rst:162 +msgid "SQL statements in code should put SQL words in ALL CAPS::" +msgstr "" + +#: ../../develop/style.rst:166 +msgid "This makes SQL significantly easier to read." +msgstr "" + +#: ../../develop/style.rst:168 +msgid "Common variable names" +msgstr "" + +#: ../../develop/style.rst:170 +msgid "L => an arbitrary list." +msgstr "" + +#: ../../develop/style.rst:172 +msgid "t => an arbitrary tuple." +msgstr "" + +#: ../../develop/style.rst:174 +msgid "x => an arbitrary float." +msgstr "" + +#: ../../develop/style.rst:176 +msgid "s => an arbitrary string." +msgstr "" + +#: ../../develop/style.rst:178 +msgid "f => an arbitrary function." +msgstr "" + +#: ../../develop/style.rst:180 +msgid "p => an arbitrary predicate." +msgstr "" + +#: ../../develop/style.rst:182 +msgid "i,n => an arbitrary integer." +msgstr "" + +#: ../../develop/style.rst:184 +msgid "cb => an arbitrary callback." +msgstr "" + +#: ../../develop/style.rst:186 +msgid "db => a database handle." +msgstr "" + +#: ../../develop/style.rst:188 +msgid "fd => a file-like object." +msgstr "" + +#: ../../develop/style.rst:190 +msgid "msg => an ircmsgs.IrcMsg object." +msgstr "" + +#: ../../develop/style.rst:192 +msgid "irc => an irclib.Irc object (or proxy)" +msgstr "" + +#: ../../develop/style.rst:194 +msgid "nick => a string that is an IRC nick." +msgstr "" + +#: ../../develop/style.rst:196 +msgid "channel => a string that is an IRC channel." +msgstr "" + +#: ../../develop/style.rst:198 +msgid "hostmask => a string that is a user's IRC prefix." +msgstr "" + +#: ../../develop/style.rst:200 +msgid "" +"When the semantic functionality (that is, the \"meaning\" of a variable " +"is obvious from context), one of these names should be used. This just " +"makes it easier for people reading our code to know what a variable " +"represents without scouring the surrounding code." +msgstr "" + +#: ../../develop/style.rst:205 +msgid "" +"Multiple variable assignments should always be surrounded with " +"parentheses -- i.e., if you're using the partition function, then your " +"assignment statement should look like::" +msgstr "" + +#: ../../develop/style.rst:211 +msgid "" +"The parentheses make it obvious that you're doing a multiple assignment, " +"and that's important because I hate reading code and wondering where a " +"variable came from." +msgstr "" + +#: ../../develop/using_utils.rst:3 +msgid "Using Supybot's utils module" +msgstr "" + +#: ../../develop/using_utils.rst:4 +msgid "" +"Supybot provides a wealth of utilities for plugin writers in the " +"supybot.utils module, this tutorial describes these utilities and shows " +"you how to use them." +msgstr "" + +#: ../../develop/using_utils.rst:8 +msgid "str.py" +msgstr "" + +#: ../../develop/using_utils.rst:10 +msgid "The Format Function" +msgstr "" + +#: ../../develop/using_utils.rst:12 +#, python-format +msgid "" +"The supybot.utils.str module provides a bunch of utility functions for " +"handling string values. This section contains a quick rundown of all of " +"the functions available, along with descriptions of the arguments they " +"take. First and foremost is the format function, which provides a lot of " +"capability in just one function that uses string-formatting style to " +"accomplish a lot. So much so that it gets its own section in this " +"tutorial. All other functions will be in other sections. format takes " +"several arguments - first, the format string (using the format characters" +" described below), and then after that, each individual item to be " +"formatted. Do not attempt to use the % operator to do the formatting " +"because that will fall back on the normal string formatting operator. The" +" format function uses the following string formatting characters." +msgstr "" + +#: ../../develop/using_utils.rst:24 +msgid "% - literal ``%``" +msgstr "" + +#: ../../develop/using_utils.rst:25 +msgid "i - integer" +msgstr "" + +#: ../../develop/using_utils.rst:26 +msgid "s - string" +msgstr "" + +#: ../../develop/using_utils.rst:27 +msgid "f - float" +msgstr "" + +#: ../../develop/using_utils.rst:28 +msgid "r - repr" +msgstr "" + +#: ../../develop/using_utils.rst:29 +msgid "b - form of the verb ``to be`` (takes an int)" +msgstr "" + +#: ../../develop/using_utils.rst:30 +msgid "h - form of the verb ``to have`` (takes an int)" +msgstr "" + +#: ../../develop/using_utils.rst:31 +msgid "L - commaAndify (takes a list of strings or a tuple of ([strings], and))" +msgstr "" + +#: ../../develop/using_utils.rst:32 +msgid "p - pluralize (takes a string)" +msgstr "" + +#: ../../develop/using_utils.rst:33 +msgid "q - quoted (takes a string)" +msgstr "" + +#: ../../develop/using_utils.rst:34 +msgid "" +"n - n items (takes a 2-tuple of (n, item) or a 3-tuple of (n, between, " +"item))" +msgstr "" + +#: ../../develop/using_utils.rst:35 +msgid "S - a human-readable size (takes an int)" +msgstr "" + +#: ../../develop/using_utils.rst:36 +msgid "t - time, formatted (takes an int)" +msgstr "" + +#: ../../develop/using_utils.rst:37 +msgid "T - time delta, formatted (takes an int)" +msgstr "" + +#: ../../develop/using_utils.rst:38 +msgid "u - url, wrapped in braces" +msgstr "" + +#: ../../develop/using_utils.rst:39 +msgid "" +"v - void, takes one or many arguments, but doesn't display it (useful for" +" translation)" +msgstr "" + +#: ../../develop/using_utils.rst:43 +msgid "" +"Until stock Supybot and Gribble merge them, %S, %T, and %v are only " +"available in Limnoria." +msgstr "" + +#: ../../develop/using_utils.rst:47 +msgid "Here are a few examples to help elaborate on the above descriptions::" +msgstr "" + +#: ../../develop/using_utils.rst:72 +msgid "" +"As you can see, you can combine all sorts of combinations of formatting " +"strings into one. In fact, that was the major motivation behind format. " +"We have specific functions that you can use individually for each of " +"those formatting types, but it became much easier just to use special " +"formatting chars and the format function than concatenating a bunch of " +"strings that were the result of other utils.str functions." +msgstr "" + +#: ../../develop/using_utils.rst:80 +msgid "The Other Functions" +msgstr "" + +#: ../../develop/using_utils.rst:82 +msgid "" +"These are the functions that can't be handled by format. They are sorted " +"in what I perceive to be the general order of usefulness (and I'm leaving" +" the ones covered by format for the next section)." +msgstr "" + +#: ../../develop/using_utils.rst:86 +msgid "" +"ellipsisify(s, n) - Returns a shortened version of a string. Produces up " +"to the first n chars at the nearest word boundary." +msgstr "" + +#: ../../develop/using_utils.rst:89 +msgid "s: the string to be shortened" +msgstr "" + +#: ../../develop/using_utils.rst:90 +msgid "n: the number of characters to shorten it to" +msgstr "" + +#: ../../develop/using_utils.rst:92 +msgid "" +"perlReToPythonRe(s) - Converts a Perl-style regexp (e.g., \"/abcd/i\" or " +"\"m/abcd/i\") to an actual Python regexp (an re object)" +msgstr "" + +#: ../../develop/using_utils.rst:95 ../../develop/using_utils.rst:100 +msgid "s: the regexp string" +msgstr "" + +#: ../../develop/using_utils.rst:97 +msgid "" +"perlReToReplacer(s) - converts a perl-style replacement regexp (eg, " +"\"s/foo/bar/g\") to a Python function that performs such a replacement" +msgstr "" + +#: ../../develop/using_utils.rst:102 +msgid "" +"dqrepr(s) - Returns a repr() of s guaranteed to be in double quotes. " +"(Double Quote Repr)" +msgstr "" + +#: ../../develop/using_utils.rst:105 +msgid "s: the string to be double-quote repr()'ed" +msgstr "" + +#: ../../develop/using_utils.rst:107 +msgid "" +"toBool(s) - Determines whether or not a string means True or False and " +"returns the appropriate boolean value. True is any of \"true\", \"on\", " +"\"enable\", \"enabled\", or \"1\". False is any of \"false\", \"off\", " +"\"disable\", \"disabled\", or \"0\"." +msgstr "" + +#: ../../develop/using_utils.rst:112 +msgid "s: the string to determine the boolean value for" +msgstr "" + +#: ../../develop/using_utils.rst:114 +msgid "" +"rsplit(s, sep=None, maxsplit=-1) - functionally the same as str.split in " +"the Python standard library except splitting from the right instead of " +"the left. Python 2.4 has str.rsplit (which this function defers to for " +"those versions >= 2.4), but Python 2.3 did not." +msgstr "" + +#: ../../develop/using_utils.rst:119 +msgid "s: the string to be split" +msgstr "" + +#: ../../develop/using_utils.rst:120 +msgid "sep: the separator to split on, defaults to whitespace" +msgstr "" + +#: ../../develop/using_utils.rst:121 +msgid "" +"maxsplit: the maximum number of splits to perform, -1 splits all possible" +" splits." +msgstr "" + +#: ../../develop/using_utils.rst:124 +msgid "" +"normalizeWhitespace(s) - reduces all multi-spaces in a string to a single" +" space" +msgstr "" + +#: ../../develop/using_utils.rst:127 +msgid "s: the string to normalize" +msgstr "" + +#: ../../develop/using_utils.rst:129 +msgid "depluralize(s) - the opposite of pluralize" +msgstr "" + +#: ../../develop/using_utils.rst:131 +msgid "s: the string to depluralize" +msgstr "" + +#: ../../develop/using_utils.rst:133 +msgid "" +"unCommaThe(s) - Takes a string of the form \"foo, the\" and turns it into" +" \"the foo\"" +msgstr "" + +#: ../../develop/using_utils.rst:136 +msgid "s: string, the" +msgstr "" + +#: ../../develop/using_utils.rst:138 +msgid "" +"distance(s, t) - computes the levenshtein distance (or \"edit distance\")" +" between two strings" +msgstr "" + +#: ../../develop/using_utils.rst:141 +msgid "s: the first string" +msgstr "" + +#: ../../develop/using_utils.rst:142 +msgid "t: the second string" +msgstr "" + +#: ../../develop/using_utils.rst:144 +msgid "soundex(s, length=4) - computes the soundex for a given string" +msgstr "" + +#: ../../develop/using_utils.rst:146 +msgid "s: the string to compute the soundex for" +msgstr "" + +#: ../../develop/using_utils.rst:147 +msgid "length: the length of the soundex to generate" +msgstr "" + +#: ../../develop/using_utils.rst:149 +msgid "" +"matchCase(s1, s2) - Matches the case of the first string in the second " +"string." +msgstr "" + +#: ../../develop/using_utils.rst:152 +msgid "s1: the first string" +msgstr "" + +#: ../../develop/using_utils.rst:153 +msgid "s2: the string which will be made to match the case of the first" +msgstr "" + +#: ../../develop/using_utils.rst:156 +msgid "The Commands Format Already Covers" +msgstr "" + +#: ../../develop/using_utils.rst:158 +msgid "" +"These commands aren't necessary because you can achieve them more easily " +"by using the format command, but they exist if you decide you want to use" +" them anyway though it is greatly discouraged for general use." +msgstr "" + +#: ../../develop/using_utils.rst:162 +msgid "" +"commaAndify(seq, comma=\",\", And=\"and\") - transforms a list of items " +"into a comma separated list with an \"and\" preceding the last element. " +"For example, [\"foo\", \"bar\", \"baz\"] becomes \"foo, bar, and baz\". " +"Is smart enough to convert two-element lists to just \"item1 and item2\" " +"as well." +msgstr "" + +#: ../../develop/using_utils.rst:167 +msgid "" +"seq: the sequence of items (don't have to be strings, but need to be " +"'str()'-able)" +msgstr "" + +#: ../../develop/using_utils.rst:169 +msgid "comma: the character to use to separate the list" +msgstr "" + +#: ../../develop/using_utils.rst:170 +msgid "And: the word to use before the last element" +msgstr "" + +#: ../../develop/using_utils.rst:172 +msgid "" +"pluralize(s) - Returns the plural of a string. Put any exceptions to the " +"general English rules of pluralization in the plurals dictionary in " +"supybot.utils.str." +msgstr "" + +#: ../../develop/using_utils.rst:176 +msgid "s: the string to pluralize" +msgstr "" + +#: ../../develop/using_utils.rst:178 +msgid "" +"nItems(n, item, between=None) - returns a string that describes a given " +"number of an item (with any string between the actual number and the item" +" itself), handles pluralization with the pluralize function above. Note " +"that the arguments here are in a different order since between is " +"optional." +msgstr "" + +#: ../../develop/using_utils.rst:183 +msgid "n: the number of items" +msgstr "" + +#: ../../develop/using_utils.rst:184 +msgid "item: the type of item" +msgstr "" + +#: ../../develop/using_utils.rst:185 +msgid "" +"between: the optional string that goes between the number and the type of" +" item" +msgstr "" + +#: ../../develop/using_utils.rst:188 +msgid "quoted(s) - Returns the string surrounded by double-quotes." +msgstr "" + +#: ../../develop/using_utils.rst:190 +msgid "s: the string to quote" +msgstr "" + +#: ../../develop/using_utils.rst:192 +msgid "" +"be(i) - Returns the proper form of the verb \"to be\" based on the number" +" provided (be(1) is \"is\", be(anything else) is \"are\")" +msgstr "" + +#: ../../develop/using_utils.rst:195 +msgid "i: the number of things that \"be\"" +msgstr "" + +#: ../../develop/using_utils.rst:197 +msgid "" +"has(i) - Returns the proper form of the verb \"to have\" based on the " +"number provided (has(1) is \"has\", has(anything else) is \"have\")" +msgstr "" + +#: ../../develop/using_utils.rst:200 +msgid "i: the number of things that \"has\"" +msgstr "" + +#: ../../develop/using_utils.rst:203 +msgid "structures.py" +msgstr "" + +#: ../../develop/using_utils.rst:205 ../../develop/using_utils.rst:341 +msgid "Intro" +msgstr "" + +#: ../../develop/using_utils.rst:207 +msgid "" +"This module provides a number of useful data structures that aren't found" +" in the standard Python library. For the most part they were created as " +"needed for the bot and plugins themselves, but they were created in such " +"a way as to be of general use for anyone who needs a data structure that " +"performs a like duty. As usual in this document, I'll try and order these" +" in order of usefulness, starting with the most useful." +msgstr "" + +#: ../../develop/using_utils.rst:215 +msgid "The queue classes" +msgstr "" + +#: ../../develop/using_utils.rst:217 +msgid "" +"The structures module provides two general-purpose queue classes for you " +"to use. The \"queue\" class is a robust full-featured queue that scales " +"up to larger sized queues. The \"smallqueue\" class is for queues that " +"will contain fewer (less than 1000 or so) items. Both offer the same " +"common interface, which consists of:" +msgstr "" + +#: ../../develop/using_utils.rst:223 +msgid "" +"a constructor which will optionally accept a sequence to start the queue " +"off with" +msgstr "" + +#: ../../develop/using_utils.rst:225 +msgid "enqueue(item) - adds an item to the back of the queue" +msgstr "" + +#: ../../develop/using_utils.rst:226 +msgid "dequeue() - removes (and returns) the item from the front of the queue" +msgstr "" + +#: ../../develop/using_utils.rst:227 +msgid "peek() - returns the item from the front of the queue without removing it" +msgstr "" + +#: ../../develop/using_utils.rst:228 +msgid "reset() - empties the queue entirely" +msgstr "" + +#: ../../develop/using_utils.rst:230 +msgid "" +"In addition to these general-use queue classes, there are two other more " +"specialized queue classes as well. The first is the \"TimeoutQueue\" " +"which holds a queue of items until they reach a certain age and then they" +" are removed from the queue. It features the following:" +msgstr "" + +#: ../../develop/using_utils.rst:235 +msgid "" +"TimeoutQueue(timeout, queue=None) - you must specify the timeout (in " +"seconds) in the constructor. Note that you can also optionally pass it a " +"queue which uses any implementation you wish to use whether it be one of " +"the above (queue or smallqueue) or if it's some custom queue you create " +"that implements the same interface. If you don't pass it a queue instance" +" to use, it will build its own using smallqueue." +msgstr "" + +#: ../../develop/using_utils.rst:242 +msgid "reset(), enqueue(item), dequeue() - all same as above queue classes" +msgstr "" + +#: ../../develop/using_utils.rst:243 +msgid "setTimeout(secs) - allows you to change the timeout value" +msgstr "" + +#: ../../develop/using_utils.rst:245 +msgid "" +"And for the final queue class, there's the \"MaxLengthQueue\" class. As " +"you may have guessed, it's a queue that is capped at a certain specified " +"length. It features the following:" +msgstr "" + +#: ../../develop/using_utils.rst:249 +msgid "" +"MaxLengthQueue(length, seq=()) - the constructor naturally requires that " +"you set the max length and it allows you to optionally pass in a sequence" +" to be used as the starting queue. The underlying implementation is " +"actually the queue from before." +msgstr "" + +#: ../../develop/using_utils.rst:254 +msgid "" +"enqueue(item) - adds an item onto the back of the queue and if it would " +"push it over the max length, it dequeues the item on the front (it does " +"not return this item to you)" +msgstr "" + +#: ../../develop/using_utils.rst:257 +msgid "all the standard methods from the queue class are inherited for this class" +msgstr "" + +#: ../../develop/using_utils.rst:260 +msgid "The Other Structures" +msgstr "" + +#: ../../develop/using_utils.rst:262 +msgid "" +"The most useful of the other structures is actually very similar to the " +"\"MaxLengthQueue\". It's the \"RingBuffer\", which is essentially a " +"MaxLengthQueue which fills up to its maximum size and then circularly " +"replaces the old contents as new entries are added instead of dequeuing." +" It features the following:" +msgstr "" + +#: ../../develop/using_utils.rst:268 +msgid "" +"RingBuffer(size, seq=()) - as with the MaxLengthQueue you specify the " +"size of the RingBuffer and optionally give it a sequence." +msgstr "" + +#: ../../develop/using_utils.rst:271 +msgid "" +"append(item) - adds item to the end of the buffer, pushing out an item " +"from the front if necessary" +msgstr "" + +#: ../../develop/using_utils.rst:273 +msgid "reset() - empties out the buffer entirely" +msgstr "" + +#: ../../develop/using_utils.rst:274 +msgid "resize(i) - shrinks/expands the RingBuffer to the size provided" +msgstr "" + +#: ../../develop/using_utils.rst:275 +msgid "" +"extend(seq) - append the items from the provided sequence onto the end of" +" the RingBuffer" +msgstr "" + +#: ../../develop/using_utils.rst:278 +msgid "" +"The next data structure is the TwoWayDictionary, which as the name " +"implies is a dictionary in which key-value pairs have mappings going both" +" directions. It features the following:" +msgstr "" + +#: ../../develop/using_utils.rst:282 +msgid "" +"TwoWayDictionary(seq=(), \\**kwargs) - Takes an optional sequence of " +"(key, value) pairs as well as any key=value pairs specified in the " +"constructor as initial values for the two-way dict." +msgstr "" + +#: ../../develop/using_utils.rst:286 +msgid "" +"other than that, no extra features that a normal Python dict doesn't " +"already offer with the exception that any (key, val) pair added to the " +"dict is also added as (val, key) as well, so the mapping goes both ways. " +"Elements are still accessed the same way you always do with Python " +"'dict's." +msgstr "" + +#: ../../develop/using_utils.rst:292 +msgid "" +"There is also a MultiSet class available, but it's very unlikely that it " +"will serve your purpose, so I won't go into it here. The curious coder " +"can go check the source and see what it's all about if they wish (it's " +"only used once in our code, in the Relay plugin)." +msgstr "" + +#: ../../develop/using_utils.rst:298 +msgid "web.py" +msgstr "" + +#: ../../develop/using_utils.rst:299 +msgid "" +"The web portion of Supybot's utils module is mainly used for retrieving " +"data from websites but it also has some utility functions pertaining to " +"HTML and email text as well. The functions in web are listed below, once " +"again in order of usefulness." +msgstr "" + +#: ../../develop/using_utils.rst:304 +msgid "" +"getUrl(url, size=None, headers=None) - gets the data at the URL provided " +"and returns it as one large string" +msgstr "" + +#: ../../develop/using_utils.rst:307 ../../develop/using_utils.rst:315 +msgid "" +"url: the location of the data to be retrieved or a urllib2.Request object" +" to be used in the retrieval" +msgstr "" + +#: ../../develop/using_utils.rst:309 +msgid "" +"size: the maximum number of bytes to retrieve, defaults to None, meaning " +"that it is to try to retrieve all data" +msgstr "" + +#: ../../develop/using_utils.rst:311 ../../develop/using_utils.rst:317 +msgid "headers: a dictionary mapping header types to header data" +msgstr "" + +#: ../../develop/using_utils.rst:313 +msgid "getUrlFd(url, headers=None) - returns a file-like object for a url" +msgstr "" + +#: ../../develop/using_utils.rst:319 +msgid "" +"htmlToText(s, tagReplace=\" \") - strips out all tags in a string of " +"HTML, replacing them with the specified character" +msgstr "" + +#: ../../develop/using_utils.rst:322 +msgid "s: the HTML text to strip the tags out of" +msgstr "" + +#: ../../develop/using_utils.rst:323 +msgid "tagReplace: the string to replace tags with" +msgstr "" + +#: ../../develop/using_utils.rst:325 +msgid "" +"strError(e) - pretty-printer for web exceptions, returns a descriptive " +"string given a web-related exception" +msgstr "" + +#: ../../develop/using_utils.rst:328 +msgid "e: the exception to pretty-print" +msgstr "" + +#: ../../develop/using_utils.rst:330 +msgid "" +"mungeEmail(s) - a naive e-mail obfuscation function, replaces \"@\" with " +"\"AT\" and \".\" with \"DOT\"" +msgstr "" + +#: ../../develop/using_utils.rst:333 +msgid "s: the e-mail address to obfuscate" +msgstr "" + +#: ../../develop/using_utils.rst:335 +msgid "getDomain(url) - returns the domain of a URL - url: the URL in question" +msgstr "" + +#: ../../develop/using_utils.rst:339 +msgid "The Best of the Rest" +msgstr "" + +#: ../../develop/using_utils.rst:343 +msgid "" +"Rather than document each of the remaining portions of the supybot.utils " +"module, I've elected to just pick out the choice bits from specific parts" +" and document those instead. Here they are, broken out by module name." +msgstr "" + +#: ../../develop/using_utils.rst:348 +msgid "supybot.utils.file - file utilities" +msgstr "" + +#: ../../develop/using_utils.rst:350 +msgid "" +"touch(filename) - updates the access time of a file by opening it for " +"writing and immediately closing it" +msgstr "" + +#: ../../develop/using_utils.rst:353 +msgid "" +"mktemp(suffix=\"\") - creates a decent random string, suitable for a " +"temporary filename with the given suffix, if provided" +msgstr "" + +#: ../../develop/using_utils.rst:356 +msgid "" +"the AtomicFile class - used for files that need to be atomically written," +" i.e., if there's a failure the original file remains unmodified. For " +"more info consult file.py in src/utils" +msgstr "" + +#: ../../develop/using_utils.rst:361 +msgid "supybot.utils.gen - general utilities" +msgstr "" + +#: ../../develop/using_utils.rst:363 +msgid "" +"timeElapsed(elapsed, [lots of optional args]) - given the number of " +"seconds elapsed, returns a string with the English description of the " +"amount of time passed, consult gen.py in src/utils for the exact argument" +" list and documentation if you feel you could use this function." +msgstr "" + +#: ../../develop/using_utils.rst:368 +msgid "" +"exnToString(e) - improved exception-to-string function. Provides nicer " +"output than a simple str(e)." +msgstr "" + +#: ../../develop/using_utils.rst:371 +msgid "" +"InsensitivePreservingDict class - a dict class that is case-insensitive " +"when accessing keys" +msgstr "" + +#: ../../develop/using_utils.rst:375 +msgid "supybot.utils.iter - iterable utilities" +msgstr "" + +#: ../../develop/using_utils.rst:377 +msgid "len(iterable) - returns the length of a given iterable" +msgstr "" + +#: ../../develop/using_utils.rst:379 +msgid "" +"groupby(key, iterable) - equivalent to the itertools.groupby function " +"available as of Python 2.4. Provided for backwards compatibility." +msgstr "" + +#: ../../develop/using_utils.rst:382 +msgid "" +"any(p, iterable) - Returns true if any element in the iterable satisfies " +"the predicate p" +msgstr "" + +#: ../../develop/using_utils.rst:385 +msgid "" +"all(p, iterable) - Returns true if all elements in the iterable satisfy " +"the predicate p" +msgstr "" + +#: ../../develop/using_utils.rst:388 +msgid "choice(iterable) - Returns a random element from the iterable" +msgstr "" + +#: ../../develop/using_utils.rst:392 +msgid "supybot.dynamicScope / dynamic - accessing variables in the stack" +msgstr "" + +#: ../../develop/using_utils.rst:394 +msgid "" +"This feature is not in `supybot.utils` but still deserves to be " +"documented as a utility." +msgstr "" + +#: ../../develop/using_utils.rst:397 +msgid "" +"Althrough you should avoid using this feature as long as you can, it is " +"sometimes necessary to access variables the Supybot API does not provide " +"you." +msgstr "" + +#: ../../develop/using_utils.rst:400 +msgid "" +"For instance, the `Aka` plugin provides per-channel aliases by overriding" +" :ref:`getCommandMethod `. However, the channel where " +"the command is called is not passed to this functions, so when writing " +"`Aka` I could either add this parameter (and thus break all plugins all " +"plugins already overriding this method) or use this hack. I choosed this " +"hack." +msgstr "" + +#: ../../develop/using_utils.rst:406 +msgid "" +"How does it work? This is quite simple: ``dynamic.channel`` is a shortcut" +" for ``supybot.dynamicScope.DynamicScope.__getattr__('channel')``, which " +"browse the call stack backwards, looking for a variable named " +"``channel``, and then returns is as far as it finds it (and returns " +"``None`` if there is no such variale)." +msgstr "" + +#: ../../develop/using_utils.rst:412 +msgid "" +"Note that you don't have to import ``dynamicScope``, the ``dynamic`` " +"object is automatically set as a global variable when Supybot starts." +msgstr "" + +#: ../../develop/using_wrap.rst:3 +msgid "Using commands.wrap to parse your command's arguments" +msgstr "" + +#: ../../develop/using_wrap.rst +msgid "Contents" +msgstr "" + +#: ../../develop/using_wrap.rst:9 +msgid "" +"To plugin developers for older (pre-0.80) versions of Supybot, one of the" +" more annoying aspects of writing commands was handling the arguments " +"that were passed in. In fact, many commands often had to duplicate " +"parsing and verification code, resulting in lots of duplicated code for " +"not a whole lot of action. So, instead of forcing plugin writers to come " +"up with their own ways of cleaning it up, we wrote up the wrap function " +"to handle all of it." +msgstr "" + +#: ../../develop/using_wrap.rst:16 +msgid "" +"It allows a much simpler and more flexible way of checking things than " +"before and it doesn't require that you know the bot internals to do " +"things like check and see if a user exists, or check if a command name " +"exists and whatnot." +msgstr "" + +#: ../../develop/using_wrap.rst:20 +msgid "" +"If you are a plugin author this document is absolutely required reading, " +"as it will massively ease the task of writing commands." +msgstr "" + +#: ../../develop/using_wrap.rst:24 +msgid "Using Wrap" +msgstr "" + +#: ../../develop/using_wrap.rst:25 +msgid "" +"First off, to get the wrap function, it is recommended (strongly) that " +"you use the following import line::" +msgstr "" + +#: ../../develop/using_wrap.rst:30 +msgid "" +"This will allow you to access the wrap command (and it allows you to do " +"it without the commands prefix). Note that this line is added to the " +"imports of plugin templates generated by the supybot-plugin-create " +"script." +msgstr "" + +#: ../../develop/using_wrap.rst:34 +msgid "" +"Let's write a quickie command that uses wrap to get a feel for how it " +"makes our lives better. Let's write a command that repeats a string of " +"text a given number of times. So you could say \"repeat 3 foo\" and it " +"would say \"foofoofoo\". Not a very useful command, but it will serve our" +" purpose just fine. Here's how it would be done without wrap::" +msgstr "" + +#: ../../develop/using_wrap.rst:52 +msgid "" +"Note that all of the argument validation and parsing takes up 5 of the 6 " +"lines (and you should have seen it before we had privmsg.getArgs!). Now, " +"here's what our command will look like with wrap applied::" +msgstr "" + +#: ../../develop/using_wrap.rst:64 +msgid "" +"Pretty short, eh? With wrap all of the argument parsing and validation is" +" handled for us and we get the arguments we want, formatted how we want " +"them, and converted into whatever types we want them to be - all in one " +"simple function call that is used to wrap the function! So now the code " +"inside each command really deals with how to execute the command and not " +"how to deal with the input." +msgstr "" + +#: ../../develop/using_wrap.rst:71 +msgid "" +"So, now that you see the benefits of wrap, let's figure out what stuff we" +" have to do to use it." +msgstr "" + +#: ../../develop/using_wrap.rst:75 +msgid "Syntax Changes" +msgstr "" + +#: ../../develop/using_wrap.rst:76 +msgid "" +"There are two syntax changes to the old style that are implemented. " +"First, the definition of the command function must be changed. The basic " +"syntax for the new definition is::" +msgstr "" + +#: ../../develop/using_wrap.rst:82 +msgid "" +"Where arg1 and arg2 (up through as many as you want) are the variables " +"that will store the parsed arguments. \"Now where do these parsed " +"arguments come from?\" you ask. Well, that's where the second syntax " +"change comes in. The second syntax change is the actual use of the wrap " +"function itself to decorate our command names. The basic decoration " +"syntax is::" +msgstr "" + +#: ../../develop/using_wrap.rst:92 +msgid "" +"This should go on the line immediately following the body of the " +"command's definition, so it can easily be located (and it obviously must " +"go after the command's definition so that commandname is defined)." +msgstr "" + +#: ../../develop/using_wrap.rst:96 +msgid "" +"Each of the converters in the above listing should be one of the " +"converters in commands.py (I will describe each of them in detail later.)" +" The converters are applied in order to the arguments given to the " +"command, generally taking arguments off of the front of the argument list" +" as they go. Note that each of the arguments is actually a string " +"containing the NAME of the converter to use and not a reference to the " +"actual converter itself. This way we can have converters with names like " +"int and not have to worry about polluting the builtin namespace by " +"overriding the builtin int." +msgstr "" + +#: ../../develop/using_wrap.rst:105 +msgid "" +"As you will find out when you look through the list of converters below, " +"some of the converters actually take arguments. The syntax for supplying " +"them (since we aren't actually calling the converters, but simply " +"specifying them), is to wrap the converter name and args list into a " +"tuple. For example::" +msgstr "" + +#: ../../develop/using_wrap.rst:113 +msgid "" +"For the most part you won't need to use an argument with the converters " +"you use either because the defaults are satisfactory or because it " +"doesn't even take any." +msgstr "" + +#: ../../develop/using_wrap.rst:118 +msgid "Customizing Wrap" +msgstr "" + +#: ../../develop/using_wrap.rst:119 +msgid "" +"Converters alone are a pretty powerful tool, but for even more advanced " +"(yet simpler!) argument handling you may want to use contexts. Contexts " +"describe how the converters are applied to the arguments, while the " +"converters themselves do the actual parsing and validation." +msgstr "" + +#: ../../develop/using_wrap.rst:124 +msgid "" +"For example, one of the contexts is \"optional\". By using this context, " +"you're saying that a given argument is not required, and if the supplied " +"converter doesn't find anything it likes, we should use some default. Yet" +" another example is the \"reverse\" context. This context tells the " +"supplied converter to look at the last argument and work backwards " +"instead of the normal first-to-last way of looking at arguments." +msgstr "" + +#: ../../develop/using_wrap.rst:131 +msgid "" +"So, that should give you a feel for the role that contexts play. They are" +" not by any means necessary to use wrap. All of the stuff we've done to " +"this point will work as-is. However, contexts let you do some very " +"powerful things in very easy ways, and are a good thing to know how to " +"use." +msgstr "" + +#: ../../develop/using_wrap.rst:136 +msgid "" +"Now, how do you use them? Well, they are in the global namespace of " +"src/commands.py, so your previous import line will import them all; you " +"can call them just as you call wrap. In fact, the way you use them is you" +" simply call the context function you want to use, with the converter " +"(and its arguments) as arguments. It's quite simple. Here's an example::" +msgstr "" + +#: ../../develop/using_wrap.rst:144 +msgid "" +"In this example, our command is looking for an optional integer argument " +"first. Then, after that, any number of arguments which can be anything " +"(as long as they are something, of course)." +msgstr "" + +#: ../../develop/using_wrap.rst:148 +msgid "" +"Do note, however, that the type of the arguments that are returned can be" +" changed if you apply a context to it. So, optional(\"int\") may very " +"well return None as well as something that passes the \"int\" converter, " +"because after all it's an optional argument and if it is None, that " +"signifies that nothing was there. Also, for another example, " +"many(\"something\") doesn't return the same thing that just \"something\"" +" would return, but rather a list of \"something\"s." +msgstr "" + +#: ../../develop/using_wrap.rst:156 +msgid "Converter List" +msgstr "" + +#: ../../develop/using_wrap.rst:157 +msgid "" +"Below is a list of all the available converters to use with wrap. If the " +"converter accepts any arguments, they are listed after it and if they are" +" optional, the default value is shown." +msgstr "" + +#: ../../develop/using_wrap.rst:162 +msgid "Numbers and time" +msgstr "" + +#: ../../develop/using_wrap.rst:164 +msgid "expiry" +msgstr "" + +#: ../../develop/using_wrap.rst:166 +msgid "" +"Takes a number of seconds and adds it to the current time to create an " +"expiration timestamp." +msgstr "" + +#: ../../develop/using_wrap.rst:169 +msgid "id, kind=\"integer\"" +msgstr "" + +#: ../../develop/using_wrap.rst:171 +msgid "" +"Returns something that looks like an integer ID number. Takes an optional" +" \"kind\" argument for you to state what kind of ID you are looking for, " +"though this doesn't affect the integrity-checking. Basically requires " +"that the argument be an integer, does no other integrity-checking, and " +"provides a nice error message with the kind in it." +msgstr "" + +#: ../../develop/using_wrap.rst:177 +msgid "index" +msgstr "" + +#: ../../develop/using_wrap.rst:179 +msgid "" +"Basically (\"int\", \"index\"), but with a twist. This will take a " +"1-based index and turn it into a 0-based index (which is more useful in " +"code). It doesn't transform 0, and it maintains negative indices as is " +"(note that it does allow them!)." +msgstr "" + +#: ../../develop/using_wrap.rst:184 +msgid "int, type=\"integer\", p=None" +msgstr "" + +#: ../../develop/using_wrap.rst:186 +msgid "" +"Gets an integer. The \"type\" text can be used to customize the error " +"message received when the argument is not an integer. \"p\" is an " +"optional predicate to test the integer with. If p(i) fails (where i is " +"the integer arg parsed out of the argument string), the arg will not be " +"accepted." +msgstr "" + +#: ../../develop/using_wrap.rst:191 +msgid "now" +msgstr "" + +#: ../../develop/using_wrap.rst:193 +msgid "" +"Simply returns the current timestamp as an arg, does not reference or " +"modify the argument list." +msgstr "" + +#: ../../develop/using_wrap.rst:196 +msgid "long, type=\"long\"" +msgstr "" + +#: ../../develop/using_wrap.rst:198 +msgid "" +"Basically the same as int minus the predicate, except that it converts " +"the argument to a long integer regardless of the size of the int." +msgstr "" + +#: ../../develop/using_wrap.rst:201 +msgid "float, type=\"floating point number\"" +msgstr "" + +#: ../../develop/using_wrap.rst:203 +msgid "" +"Basically the same as int minus the predicate, except that it converts " +"the argument to a float." +msgstr "" + +#: ../../develop/using_wrap.rst:206 +msgid "nonInt, type=\"non-integer value\"" +msgstr "" + +#: ../../develop/using_wrap.rst:208 +msgid "" +"Accepts everything but integers, and returns them unchanged. The \"type\"" +" value, as always, can be used to customize the error message that is " +"displayed upon failure." +msgstr "" + +#: ../../develop/using_wrap.rst:212 +msgid "positiveInt" +msgstr "" + +#: ../../develop/using_wrap.rst:214 +msgid "Accepts only positive integers." +msgstr "" + +#: ../../develop/using_wrap.rst:216 +msgid "nonNegativeInt" +msgstr "" + +#: ../../develop/using_wrap.rst:218 +msgid "Accepts only non-negative integers." +msgstr "" + +#: ../../develop/using_wrap.rst:221 +msgid "Channel" +msgstr "" + +#: ../../develop/using_wrap.rst:223 +msgid "channelDb" +msgstr "" + +#: ../../develop/using_wrap.rst:225 +msgid "" +"Sets the channel appropriately in order to get to the databases for that " +"channel (handles whether or not a given channel uses channel-specific " +"databases and whatnot)." +msgstr "" + +#: ../../develop/using_wrap.rst:229 +msgid "channel" +msgstr "" + +#: ../../develop/using_wrap.rst:231 +msgid "" +"Gets a channel to use the command in. If the channel isn't supplied, uses" +" the channel the message was sent in. If using a different channel, does " +"sanity-checking to make sure the channel exists on the current IRC " +"network." +msgstr "" + +#: ../../develop/using_wrap.rst:235 +msgid "inChannel" +msgstr "" + +#: ../../develop/using_wrap.rst:237 +msgid "" +"Requires that the command be called from within any channel that the bot " +"is currently in or with one of those channels used as an argument to the " +"command." +msgstr "" + +#: ../../develop/using_wrap.rst:241 +msgid "onlyInChannel" +msgstr "" + +#: ../../develop/using_wrap.rst:243 +msgid "" +"Requires that the command be called from within any channel that the bot " +"is currently in." +msgstr "" + +#: ../../develop/using_wrap.rst:246 +msgid "callerInGivenChannel" +msgstr "" + +#: ../../develop/using_wrap.rst:248 +msgid "" +"Takes the given argument as a channel and makes sure that the caller is " +"in that channel." +msgstr "" + +#: ../../develop/using_wrap.rst:251 +msgid "public" +msgstr "" + +#: ../../develop/using_wrap.rst:253 +msgid "" +"Requires that the command be sent in a channel instead of a private " +"message." +msgstr "" + +#: ../../develop/using_wrap.rst:256 +msgid "private" +msgstr "" + +#: ../../develop/using_wrap.rst:258 +msgid "" +"Requires that the command be sent in a private message instead of a " +"channel." +msgstr "" + +#: ../../develop/using_wrap.rst:261 +msgid "validChannel" +msgstr "" + +#: ../../develop/using_wrap.rst:263 +msgid "Gets a channel argument once it makes sure it's a valid channel." +msgstr "" + +#: ../../develop/using_wrap.rst:266 +msgid "Words" +msgstr "" + +#: ../../develop/using_wrap.rst:268 +msgid "color" +msgstr "" + +#: ../../develop/using_wrap.rst:270 +msgid "" +"Accepts arguments that describe a text color code (e.g., \"black\", " +"\"light blue\") and returns the mIRC color code for that color. (Note " +"that many other IRC clients support the mIRC color code scheme, not just " +"mIRC)" +msgstr "" + +#: ../../develop/using_wrap.rst:274 +msgid "letter" +msgstr "" + +#: ../../develop/using_wrap.rst:276 +msgid "" +"Looks for a single letter. (Technically, it looks for any one-element " +"sequence)." +msgstr "" + +#: ../../develop/using_wrap.rst:279 +msgid "literal, literals, errmsg=None" +msgstr "" + +#: ../../develop/using_wrap.rst:281 +msgid "" +"Takes a required sequence or string (literals) and any argument that " +"uniquely matches the starting substring of one of the literals is " +"transformed into the full literal. For example, with ``(\"literal\", " +"(\"bar\", \"baz\", \"qux\"))``, you'd get \"bar\" for \"bar\", \"baz\" " +"for \"baz\", and \"qux\" for any of \"q\", \"qu\", or \"qux\". \"b\" and " +"\"ba\" would raise errors because they don't uniquely identify one of the" +" literals in the list. You can override errmsg to provide a specific " +"(full) error message, otherwise the default argument error message is " +"displayed." +msgstr "" + +#: ../../develop/using_wrap.rst:290 +msgid "lowered" +msgstr "" + +#: ../../develop/using_wrap.rst:292 +msgid "" +"Returns the argument lowered (NOTE: it is lowered according to IRC " +"conventions, which does strange mapping with some punctuation " +"characters)." +msgstr "" + +#: ../../develop/using_wrap.rst:295 +msgid "to" +msgstr "" + +#: ../../develop/using_wrap.rst:297 +msgid "" +"Returns the string \"to\" if the arg is any form of \"to\" (case-" +"insensitive)." +msgstr "" + +#: ../../develop/using_wrap.rst:300 +msgid "Network" +msgstr "" + +#: ../../develop/using_wrap.rst:302 +msgid "ip" +msgstr "" + +#: ../../develop/using_wrap.rst:304 +msgid "" +"Checks and makes sure the argument looks like a valid IP and then returns" +" it." +msgstr "" + +#: ../../develop/using_wrap.rst:307 +msgid "url" +msgstr "" + +#: ../../develop/using_wrap.rst:309 +msgid "Checks for a valid URL." +msgstr "" + +#: ../../develop/using_wrap.rst:311 +msgid "httpUrl" +msgstr "" + +#: ../../develop/using_wrap.rst:313 +msgid "Checks for a valid HTTP URL." +msgstr "" + +#: ../../develop/using_wrap.rst:316 +msgid "Users, nicks, and permissions" +msgstr "" + +#: ../../develop/using_wrap.rst:318 +msgid "haveOp, action=\"do that\"" +msgstr "" + +#: ../../develop/using_wrap.rst:320 +msgid "" +"Simply requires that the bot have ops in the channel that the command is " +"called in. The action parameter completes the error message: \"I need to " +"be opped to ...\"." +msgstr "" + +#: ../../develop/using_wrap.rst:324 +msgid "nick" +msgstr "" + +#: ../../develop/using_wrap.rst:326 +msgid "Checks that the arg is a valid nick on the current IRC server." +msgstr "" + +#: ../../develop/using_wrap.rst:328 +msgid "seenNick" +msgstr "" + +#: ../../develop/using_wrap.rst:330 +msgid "" +"Checks that the arg is a nick that the bot has seen (NOTE: this is " +"limited by the size of the history buffer that the bot has)." +msgstr "" + +#: ../../develop/using_wrap.rst:333 +msgid "nickInChannel" +msgstr "" + +#: ../../develop/using_wrap.rst:335 +msgid "" +"Requires that the argument be a nick that is in the current channel, and " +"returns that nick." +msgstr "" + +#: ../../develop/using_wrap.rst:338 +msgid "capability" +msgstr "" + +#: ../../develop/using_wrap.rst:340 +msgid "Used to retrieve an argument that describes a capability." +msgstr "" + +#: ../../develop/using_wrap.rst:342 +msgid "hostmask" +msgstr "" + +#: ../../develop/using_wrap.rst:344 +msgid "Returns the hostmask of any provided nick or hostmask argument." +msgstr "" + +#: ../../develop/using_wrap.rst:346 +msgid "banmask" +msgstr "" + +#: ../../develop/using_wrap.rst:348 +msgid "Returns a generic banmask of the provided nick or hostmask argument." +msgstr "" + +#: ../../develop/using_wrap.rst:350 +msgid "user" +msgstr "" + +#: ../../develop/using_wrap.rst:352 +msgid "Requires that the caller be a registered user." +msgstr "" + +#: ../../develop/using_wrap.rst:354 +msgid "otherUser" +msgstr "" + +#: ../../develop/using_wrap.rst:356 +msgid "Returns the user specified by the username or hostmask in the argument." +msgstr "" + +#: ../../develop/using_wrap.rst:358 +msgid "owner" +msgstr "" + +#: ../../develop/using_wrap.rst:360 +msgid "Requires that the command caller has the \"owner\" capability." +msgstr "" + +#: ../../develop/using_wrap.rst:362 +msgid "admin" +msgstr "" + +#: ../../develop/using_wrap.rst:364 +msgid "Requires that the command caller has the \"admin\" capability." +msgstr "" + +#: ../../develop/using_wrap.rst:366 +msgid "checkCapability, capability" +msgstr "" + +#: ../../develop/using_wrap.rst:368 +msgid "Checks to make sure that the caller has the specified capability." +msgstr "" + +#: ../../develop/using_wrap.rst:372 +msgid "checkChannelCapability, capability" +msgstr "" + +#: ../../develop/using_wrap.rst:371 +msgid "" +"Checks to make sure that the caller has the specified capability on the " +"channel the command is called in." +msgstr "" + +#: ../../develop/using_wrap.rst:375 +msgid "Matching" +msgstr "" + +#: ../../develop/using_wrap.rst:377 +msgid "anything" +msgstr "" + +#: ../../develop/using_wrap.rst:379 +msgid "Returns anything as is." +msgstr "" + +#: ../../develop/using_wrap.rst:381 +msgid "something, errorMsg=None, p=None" +msgstr "" + +#: ../../develop/using_wrap.rst:383 +msgid "" +"Takes anything but the empty string. errorMsg can be used to customize " +"the error message. p is any predicate function that can be used to test " +"the validity of the input." +msgstr "" + +#: ../../develop/using_wrap.rst:387 +msgid "somethingWithoutSpaces" +msgstr "" + +#: ../../develop/using_wrap.rst:389 +msgid "" +"Same as something, only with the exception of disallowing spaces of " +"course." +msgstr "" + +#: ../../develop/using_wrap.rst:391 +msgid "matches, regexp, errmsg" +msgstr "" + +#: ../../develop/using_wrap.rst:393 +msgid "" +"Searches the args with the given regexp and returns the matches. If no " +"match is found, errmsg is given." +msgstr "" + +#: ../../develop/using_wrap.rst:396 +msgid "regexpMatcher" +msgstr "" + +#: ../../develop/using_wrap.rst:398 +msgid "Gets a matching regexp argument (m// or //)." +msgstr "" + +#: ../../develop/using_wrap.rst:400 +msgid "glob" +msgstr "" + +#: ../../develop/using_wrap.rst:402 +msgid "" +"Gets a glob string. Basically, if there are no wildcards (``*``, ``?``) " +"in the argument, returns ``*string*``, making a glob string that matches " +"anything containing the given argument." +msgstr "" + +#: ../../develop/using_wrap.rst:406 +msgid "regexpReplacer" +msgstr "" + +#: ../../develop/using_wrap.rst:408 +msgid "Gets a replacing regexp argument (s//)." +msgstr "" + +#: ../../develop/using_wrap.rst:411 ../../develop/using_wrap.rst:489 +msgid "Other" +msgstr "" + +#: ../../develop/using_wrap.rst:413 +msgid "networkIrc, errorIfNoMatch=False" +msgstr "" + +#: ../../develop/using_wrap.rst:415 +msgid "" +"Returns the IRC object of the specified IRC network. If one isn't " +"specified, the IRC object of the IRC network the command was called on is" +" returned." +msgstr "" + +#: ../../develop/using_wrap.rst:419 +msgid "plugin, require=True" +msgstr "" + +#: ../../develop/using_wrap.rst:421 +msgid "" +"Returns the plugin specified by the arg or None. If require is True, an " +"error is raised if the plugin cannot be retrieved." +msgstr "" + +#: ../../develop/using_wrap.rst:424 +msgid "boolean" +msgstr "" + +#: ../../develop/using_wrap.rst:426 +msgid "" +"Converts the text string to a boolean value. Acceptable true values are: " +"\"1\", \"true\", \"on\", \"enable\", or \"enabled\" (case-insensitive). " +"Acceptable false values are: \"0\", false\", \"off\", \"disable\", or " +"\"disabled\" (case-insensitive)." +msgstr "" + +#: ../../develop/using_wrap.rst:431 +msgid "filename" +msgstr "" + +#: ../../develop/using_wrap.rst:433 +msgid "Used to get a filename argument." +msgstr "" + +#: ../../develop/using_wrap.rst:435 +msgid "commandName" +msgstr "" + +#: ../../develop/using_wrap.rst:437 +msgid "" +"Returns the canonical command name version of the given string (ie, the " +"string is lowercased and dashes and underscores are removed)." +msgstr "" + +#: ../../develop/using_wrap.rst:440 +msgid "text" +msgstr "" + +#: ../../develop/using_wrap.rst:442 +msgid "" +"Takes the rest of the arguments as one big string. Note that this differs" +" from the \"anything\" context in that it clobbers the arg string when " +"it's done. Using any converters after this is most likely incorrect." +msgstr "" + +#: ../../develop/using_wrap.rst:447 +msgid "Contexts List" +msgstr "" + +#: ../../develop/using_wrap.rst:448 +msgid "What contexts are available for me to use?" +msgstr "" + +#: ../../develop/using_wrap.rst:450 +msgid "" +"The list of available contexts is below. Unless specified otherwise, it " +"can be assumed that the type returned by the context itself matches the " +"type of the converter it is applied to." +msgstr "" + +#: ../../develop/using_wrap.rst:455 +msgid "Options" +msgstr "" + +#: ../../develop/using_wrap.rst:460 +msgid "optional" +msgstr "" + +#: ../../develop/using_wrap.rst:458 +msgid "" +"Look for an argument that satisfies the supplied converter, but if it's " +"not the type I'm expecting or there are no arguments for us to check, " +"then use the default value. Will return the converted argument as is or " +"None." +msgstr "" + +#: ../../develop/using_wrap.rst:465 +msgid "additional" +msgstr "" + +#: ../../develop/using_wrap.rst:463 +msgid "" +"Look for an argument that satisfies the supplied converter, making sure " +"that it's the right type. If there aren't any arguments to check, then " +"use the default value. Will return the converted argument as is or None." +msgstr "" + +#: ../../develop/using_wrap.rst:469 +msgid "first" +msgstr "" + +#: ../../develop/using_wrap.rst:468 +msgid "" +"Tries each of the supplied converters in order and returns the result of " +"the first successfully applied converter." +msgstr "" + +#: ../../develop/using_wrap.rst:472 +msgid "Multiplicity" +msgstr "" + +#: ../../develop/using_wrap.rst:476 +msgid "any" +msgstr "" + +#: ../../develop/using_wrap.rst:475 +msgid "" +"Looks for any number of arguments matching the supplied converter. Will " +"return a sequence of converted arguments or None." +msgstr "" + +#: ../../develop/using_wrap.rst:481 +msgid "many" +msgstr "" + +#: ../../develop/using_wrap.rst:479 +msgid "" +"Looks for multiple arguments matching the supplied converter. Expects at " +"least one to work, otherwise it will fail. Will return the sequence of " +"converted arguments." +msgstr "" + +#: ../../develop/using_wrap.rst:486 +msgid "commalist" +msgstr "" + +#: ../../develop/using_wrap.rst:484 +msgid "" +"Looks for a comma separated list of arguments that match the supplied " +"converter. Returns a list of the successfully converted arguments. If any" +" of the arguments fail, this whole context fails." +msgstr "" + +#: ../../develop/using_wrap.rst:493 +msgid "rest" +msgstr "" + +#: ../../develop/using_wrap.rst:492 +msgid "" +"Treat the rest of the arguments as one big string, and then convert. If " +"the conversion is unsuccessful, restores the arguments." +msgstr "" + +#: ../../develop/using_wrap.rst:500 +msgid "getopts" +msgstr "" + +#: ../../develop/using_wrap.rst:496 +msgid "" +"Handles --option style arguments. Each option should be a key in a " +"dictionary that maps to the name of the converter that is to be used on " +"that argument. To make the option take no argument, use \"\" as the " +"converter name in the dictionary. For no conversion, use None as the " +"converter name in the dictionary." +msgstr "" + +#: ../../develop/using_wrap.rst:505 +msgid "reverse" +msgstr "" + +#: ../../develop/using_wrap.rst:503 +msgid "" +"Reverse the argument list, apply the converters, and then reverse the " +"argument list back." +msgstr "" + +#: ../../develop/using_wrap.rst:508 +msgid "Final Word" +msgstr "" + +#: ../../develop/using_wrap.rst:510 +msgid "" +"Now that you know how to use wrap, and you have a list of converters and " +"contexts you can use, your task of writing clean, simple, and safe plugin" +" code should become much easier. Enjoy!" +msgstr "" + diff --git a/locale/fr/LC_MESSAGES/index.po b/locale/fr/LC_MESSAGES/index.po new file mode 100644 index 0000000..d99b04f --- /dev/null +++ b/locale/fr/LC_MESSAGES/index.po @@ -0,0 +1,43 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2003-2015, the Limnoria/Gribble/Supybot contributors +# This file is distributed under the same license as the Limnoria package. +# FIRST AUTHOR , 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: Limnoria 0.83\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-02-24 17:46+0100\n" +"PO-Revision-Date: 2016-02-24 17:49+0100\n" +"Last-Translator: Valentin Lorentz \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.2.0\n" +"Language: fr\n" +"X-Generator: Poedit 1.6.10\n" + +#: ../../index.rst:7 +msgid "Welcome to Limnoria's documentation!" +msgstr "Bienvenue sur la documentation de Limnoria !" + +#: ../../index.rst:9 +msgid "Contents:" +msgstr "Sommaire :" + +#: ../../index.rst:19 +msgid "Indices and tables" +msgstr "Indexes et tableaux" + +#: ../../index.rst:21 +msgid ":ref:`genindex`" +msgstr ":ref:`genindex`" + +#: ../../index.rst:22 +msgid ":ref:`modindex`" +msgstr ":ref:`modindex`" + +#: ../../index.rst:23 +msgid ":ref:`search`" +msgstr ":ref:`search`" diff --git a/locale/fr/LC_MESSAGES/use.po b/locale/fr/LC_MESSAGES/use.po new file mode 100644 index 0000000..01dc71b --- /dev/null +++ b/locale/fr/LC_MESSAGES/use.po @@ -0,0 +1,2460 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2003-2015, the Limnoria/Gribble/Supybot contributors +# This file is distributed under the same license as the Limnoria package. +# FIRST AUTHOR , 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: Limnoria 0.83\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-02-24 21:01+0100\n" +"PO-Revision-Date: 2016-02-24 21:25+0100\n" +"Last-Translator: Valentin Lorentz \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.2.0\n" +"Language: fr\n" +"X-Generator: Poedit 1.6.10\n" + +#: ../../use/capabilities.rst:5 +msgid "Capabilities" +msgstr "Capacités" + +#: ../../use/capabilities.rst:8 ../../use/configuration.rst:6 +#: ../../use/getting_started.rst:8 +msgid "Introduction" +msgstr "Introduction" + +#: ../../use/capabilities.rst:10 +msgid "" +"Ok, some explanation of the capabilities system is probably in order. With " +"most IRC bots (including the ones I've written myself prior to this one) " +"\"what a user can do\" is set in one of two ways. On the *really* simple " +"bots, each user has a numeric \"level\" and commands check to see if a user " +"has a \"high enough level\" to perform some operation. On bots that are " +"slightly more complicated, users have a list of \"flags\" whose meanings are " +"hardcoded, and the bot checks to see if a user possesses the necessary flag " +"before performing some operation. Both methods, IMO, are rather arbitrary, " +"and force the user and the programmer to be unduly confined to less " +"expressive constructs." +msgstr "" +"Ok, il est temps d’expliquer le fonctionnement du système de capacités. " +"Pour la plupart des bots IRC (y compris certains que j’ai moi-même écrits " +"avant celui), « ce qu’un-e utilisateur-trice peut faire » peut être défini " +"de deux façons différentes. Pour les bots *très* simples, chacun-e a un " +"« niveau » et les commandes vérifies si le niveau d’un-e utilisateur-trice " +"est assez élevé pour effectuer telle ou telle opération. Pour les bots " +"légèrement plus évolués, les utilisateurs-trices ont une liste de " +"« flags » (drapeaux, étiquettes) dont la signifie est intégrée au bot, qui " +"vérifie que la personne qui veut effectuer une opération les a. Les deux " +"méthodes sont, à mon avis, assez arbitraires, et forcent les utilisateurs-" +"trices et développeurs-euses à être inutilement forcé-es à utiliser des " +"constructions peu expressives.\t" + +#: ../../use/capabilities.rst:20 +msgid "" +"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." +msgstr "" +"Ce bot est différent. Chaque utilisateur-trice a un ensemble de " +"« capacités », qui est consulté à chaque fois qu’iel envoie une commande au " +"bot. Les commandes, plutôt que de vérifier qu’iel a un niveau de 100, ou " +"vérifier qu’iel a le flag « o », sont capables de vérifier qu’iel a la " +"capacité « owner ». Pour le moment, une telle différence ne semble pas " +"révolutionnaire, mais on peut déjà constater que cette méthode est plus " +"explicite, et plus facile pour les personnes qui s’en servent et développent " +"pour comprendre ce qu’il se passe vraiment." + +#: ../../use/capabilities.rst:29 ../../use/capabilities.rst:127 +msgid "User Capabilities" +msgstr "Capacité utilisateur-trice" + +#: ../../use/capabilities.rst:30 +msgid "What the heck can these capabilities DO?" +msgstr "Que permettent donc les capacités de faire ?" + +#: ../../use/capabilities.rst:32 +msgid "" +"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 scenes 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." +msgstr "" +"Si c’était tout, eh bien, le système de capacités serait *cool*, mais peu de " +"gens diraient *génial*. Mais il **est** génial ! Plusieurs choses arrivent " +"derrière le décors pour que ça soit génial, et ce sont des choses qui " +"n’arrivent pas avec les bots qui utilisent des niveaux numériques ou des " +"flags d’un seul caractère. Premièrement, quand quelqu’un envoie une " +"commande au bot, le dispatcher de commande vérifie qu’iel n’a pas " +"l’« anticapacité » pour cete commande. Une anticapacité est une capacité " +"qui, plutôt que de dire ce que quelqu’un peut faire, dit ce que cette " +"personne ne peut *pas* faire. Elle est formée simplement en ajoutant un " +"tirer (« - ») au début du nom de la capacité : « rot13 » est une capacité, " +"« -rot13 » est une anticapacité.\t\t" + +#: ../../use/capabilities.rst:43 +msgid "" +"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' (anti)capabilities before even considering responding to the user. So " +"commands can be turned on or off on a *per user* basis, offering fine-" +"grained control not often (if at all!) seen in other bots. This can be " +"further refined by limiting the (anti)capability to a command in a specific " +"plugin or even an entire plugin. For example, the rot13 command is in the " +"Filter plugin. If a user should be able to use another rot13 command, but " +"not the one in the Format plugin, they would simply need to be given '-" +"Format.rot13' anticapability. Similarly, if a user were to be banned from " +"using the Filter plugin altogether, they would simply need to be given the '-" +"Filter' anticapability." +msgstr "" +"Bref, quand quelqu’un envoie une commande au bot, par exemple « calc » ou " +"« help », le bot vérifie d’apport qu’iel n’a pas les anticapacités « -calc » " +"ou « -help » avant même de songer à lui réponse. Donc les commandes peuvent " +"être activées ou désactivées pour chaque personne, permettant un contrôle " +"fin, qui n’est pas souvent (voire jamais) possible avec d’autres bots. Cela " +"peut être raffiné encore plus en limitant les (anti)capacités à une commande " +"d’un plugin en particulier, ou à tout un plugin. Par exemple, la commande " +"rot13 est dans le plugin Filter. Si quelqu’un devrait pouvoir utilisr la " +"commande rot13 d’un autre plugin, mais pas celle du plugin Format, iel " +"aurait seulement besoin de recevoir l’anticapacité « -Format.rot13 ». " +"Similairement, si quelqu’un doit se faire bannir du plugin Filter, il suffit " +"de lui donner l’anticapacité « -Filter »." + +#: ../../use/capabilities.rst:56 +msgid "Channel Capabilities" +msgstr "" + +#: ../../use/capabilities.rst:57 +msgid "What if #linux wants completely different capabilities from #windows?" +msgstr "" + +#: ../../use/capabilities.rst:59 +msgid "" +"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!" +msgstr "" + +#: ../../use/capabilities.rst:69 +msgid "" +"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 errors right then and there, telling " +"the user that he lacks the 'bar' capability. 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, it tells " +"the user that they lack the 'bar' capability. If neither of these " +"anticapabilities are present, then the bot just responds to the user like " +"normal." +msgstr "" + +#: ../../use/capabilities.rst:80 +msgid "Default Capabilities" +msgstr "" + +#: ../../use/capabilities.rst:81 +msgid "So what capabilities am I dealing with already?" +msgstr "" + +#: ../../use/capabilities.rst:83 +msgid "" +"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. It's so " +"important, in fact, that the bot will not allow you to add it with a " +"command--you'll have you edit the users file directly to give it to someone." +msgstr "" + +#: ../../use/capabilities.rst:90 +msgid "" +"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, cause the bot to ignore a given user, make the bot join or part " +"channels, etc. They generally cannot do administration related to channels, " +"which is reserved for people with the next capability." +msgstr "" + +#: ../../use/capabilities.rst:96 +msgid "" +"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 them the '#supybot,op' capability. " +"This is in addition to their '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." +msgstr "" + +#: ../../use/capabilities.rst:109 +msgid "" +"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 'icalc' in the 'Math' " +"plugin, which can 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 the 're' command in the " +"'Utilities' plugin, which (due to the regular expression implementation in " +"Python (and any other language that uses NFA regular expressions, like Perl " +"or Ruby or Lua or ...) which can allow a regular expression to take " +"exponential time to process). Consider what would happen if someone gave " +"the bot the command 're [format join \"\" s/./ [dict go] /] [dict go]' It " +"would basically replace every character in the output of 'dict go' (14,896 " +"characters!) with the entire output of 'dict go', resulting in 221MB of " +"memory allocated! And that's not even the worst example!" +msgstr "" + +#: ../../use/capabilities.rst:124 +msgid "Managing capabilities" +msgstr "" + +#: ../../use/capabilities.rst:129 +msgid "" +"User capabilities are controlled with the ``admin capability `` " +"and ``channel capability ``. Their difference is that the first " +"one is only restricted to those who have the admin capability." +msgstr "" + +#: ../../use/capabilities.rst:133 +msgid "To make user1 admin, I would run::" +msgstr "" + +#: ../../use/capabilities.rst:137 +msgid "" +"If the bot joins on a channel where there should be ops who should't have " +"power over any other channel, I would run::" +msgstr "" + +#: ../../use/capabilities.rst:142 +msgid "" +"Note that admins cannot give anyone capability which they don't have by " +"themselves first, so user1 couldn't use ``channel capability add`` unless " +"they were made #channel,op first. The command::" +msgstr "" + +#: ../../use/capabilities.rst:148 +msgid "" +"has the same effect as ``channel capability add``, but it requires user to " +"have the admin capability in addition to #channel,op." +msgstr "" + +#: ../../use/capabilities.rst:151 +msgid "" +"If there is abusive user who shouldn't have op capability but still does for " +"one reason or another, I could run either::" +msgstr "" + +#: ../../use/capabilities.rst:156 +msgid "or::" +msgstr "" + +#: ../../use/capabilities.rst:160 +msgid "" +"Anticapabilities are checked before normal capabilities so the first command " +"would work even if user3 still had the op capability. Removing capability " +"which isn't given to user or channel adds anti-capability automatically." +msgstr "" + +#: ../../use/capabilities.rst:165 +msgid "User capabilities can be viewed with ``user capabilities`` command." +msgstr "" + +#: ../../use/capabilities.rst:168 +msgid "Channel" +msgstr "" + +#: ../../use/capabilities.rst:170 +msgid "" +"Channel capabilities affect everyone on the current channel including " +"unidentified users. They are controlled with the ``channel capability `` commands." +msgstr "" + +#: ../../use/capabilities.rst:173 +msgid "" +"If I wanted to make everyone on the channel able to voice themselves or get " +"automatically voiced by the AutoMode plugin, I would start by unsetting the " +"default anticapability and setting the capability.::" +msgstr "" + +#: ../../use/capabilities.rst:180 +msgid "" +"Now anyone on the channel can voice themselves or if AutoMode plugin is " +"configured to voice voiced people, the will automatically get voiced on join." +msgstr "" + +#: ../../use/capabilities.rst:184 +msgid "" +"If there was unwanted plugin or plugin which output was causing spam, Games " +"for example, I could add anticapability for it and prevent the whole plugin " +"from being used.::" +msgstr "" + +#: ../../use/capabilities.rst:190 +msgid "Note that I didn't specify any separate command after Games." +msgstr "" + +#: ../../use/capabilities.rst:193 +msgid "Default" +msgstr "" + +#: ../../use/capabilities.rst:195 +msgid "" +"Default capabilities affect everyone whether they are identified or not. " +"They are controlled by the ``owner defaultcapability `` command " +"and they arecommonly used for preventing users from adding/removing akas, " +"using Unix Progstats which disabling is asked about in supybot-wizard or " +"registering to the bot using anticapabilities.::" +msgstr "" + +#: ../../use/capabilities.rst:206 +msgid "To undo this I would simply do the opposite.::" +msgstr "" + +#: ../../use/capabilities.rst:213 +msgid "" +"Defaultcapabilities can be restored with two commands from the First is only " +"in Limnoria at the time of writing::" +msgstr "" + +#: ../../use/capabilities.rst:220 ../../use/getting_started.rst:325 +msgid "Final Word" +msgstr "" + +#: ../../use/capabilities.rst:222 +msgid "" +"From a programmer's perspective, capabilties are flexible and easy to use. " +"Any command can check if a user has any capability, even ones not thought of " +"when the bot was originally written. Plugins can easily 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." +msgstr "" + +#: ../../use/capabilities.rst:228 +msgid "" +"From an user's perspective, capabilities remove a lot of the mystery and " +"esotery of bot control, in addition to giving a bot owner absolutely " +"finegrained control over what users are allowed to do with the bot. " +"Additionally, defaults can be set by the bot owner for both individual " +"channels and for the bot as a whole, letting an end-user set the policy they " +"want the bot to follow for users that haven't yet registered in their user " +"database. It's really a revolution!" +msgstr "" + +#: ../../use/configuration.rst:3 ../../use/httpserver.rst:6 +msgid "Configuration" +msgstr "" + +#: ../../use/configuration.rst:7 +msgid "" +"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." +msgstr "" + +#: ../../use/configuration.rst:12 +msgid "" +"Configuration of Supybot is handled via the `Config` plugin, which controls " +"runtime access to Supybot's registry (the configuration file generated by " +"the 'supybot-wizard' program you ran). The `Config` 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: ``config``, ``list``, and ``help``. If you don't know how to " +"get help on those commands, take a look at the GETTING_STARTED document." +msgstr "" + +#: ../../use/configuration.rst:22 +msgid "Configuration Registry" +msgstr "" + +#: ../../use/configuration.rst:23 +msgid "" +"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. But there is " +"at least one good idea in Windows' registry: hierarchical configuration." +msgstr "" + +#: ../../use/configuration.rst:28 +msgid "" +"Supybot's configuration variables are organized in a hierarchy: variables " +"having to do with the way Supybot makes replies all start with `supybot." +"reply`; variables having to do with the way a plugin works all start with " +"`supybot.plugins.Plugin` (where '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." +msgstr "" + +#: ../../use/configuration.rst:36 +msgid "" +"Some of the more important configuration values are located directly under " +"the base group, `supybot`. 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: `plugins` (where all the " +"plugin-specific configuration is held), `reply` (where variables affecting " +"the way a Supybot makes its replies resides), `replies` (where all the " +"specific standard replies are kept), and `directories` (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." +msgstr "" + +#: ../../use/configuration.rst:48 +msgid "Configuration Groups" +msgstr "" + +#: ../../use/configuration.rst:49 +msgid "" +"Using the `Config` plugin, you can list 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::" +msgstr "" + +#: ../../use/configuration.rst:58 +msgid "" +"These are all the configuration groups and values which are under the base " +"`supybot` group. Actually, their full names would each have a 'supybot.' " +"prepended to them, but it is omitted in the listing in order to shorten the " +"output. The first entries in the output are the groups (distinguished by " +"the '@' symbol in front of them), and the rest are the configuration " +"values. The '@' symbol (like the '#' symbol we'll discuss later) is simply " +"a visual cue and is not actually part of the name." +msgstr "" + +#: ../../use/configuration.rst:67 +msgid "Configuration Values" +msgstr "" + +#: ../../use/configuration.rst:68 +msgid "" +"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." +msgstr "" + +#: ../../use/configuration.rst:72 +msgid "" +"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." +"snarfThrottle` configuration variable is all about, we'd do this::" +msgstr "" + +#: ../../use/configuration.rst:86 +msgid "Pretty simple, eh?" +msgstr "" + +#: ../../use/configuration.rst:88 +msgid "" +"Now if you're curious what the current value of a configuration variable is, " +"you'll use the ``config`` command with one argument, the name of the " +"variable you want to see the value of::" +msgstr "" + +#: ../../use/configuration.rst:95 +msgid "To set this value, just stick an extra argument after the name::" +msgstr "" + +#: ../../use/configuration.rst:100 +msgid "Now check this out::" +msgstr "" + +#: ../../use/configuration.rst:105 +msgid "" +"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 which the " +"bot was running). Instead, I'll revert the change::" +msgstr "" + +#: ../../use/configuration.rst:116 +msgid "Default Values" +msgstr "" + +#: ../../use/configuration.rst:117 +msgid "" +"If you're ever curious what the default for a given configuration variable " +"is, use the ``config default`` command::" +msgstr "" + +#: ../../use/configuration.rst:123 +msgid "" +"Thus, to reset a configuration variable to its default value, you can simply " +"say::" +msgstr "" + +#: ../../use/configuration.rst:130 +msgid "Simple, eh?" +msgstr "" + +#: ../../use/configuration.rst:133 +msgid "Searching the Registry" +msgstr "" + +#: ../../use/configuration.rst:134 +msgid "" +"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::" +msgstr "" + +#: ../../use/configuration.rst:144 +msgid "" +"Sure, it showed 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 are currently 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." +msgstr "" + +#: ../../use/configuration.rst:151 +msgid "Channel-Specific Configuration" +msgstr "" + +#: ../../use/configuration.rst:152 +msgid "" +"Many configuration variables can be specific to individual channels. The " +"`Config` plugin provides an easy way to configure something for a specific " +"channel; for instance, in order to set the prefix chars for a specific " +"channel, do this in that channel::" +msgstr "" + +#: ../../use/configuration.rst:160 +msgid "" +"That'll set the prefix chars in the channel from which the message was sent " +"to '!'. Voila, channel-specific values! Also, note that when using the " +"`Config` plugin's ``list`` command, channel-specific values are preceeded by " +"a '#' character to indicate such (similar to how '@' is used to indicate a " +"group of values)." +msgstr "" + +#: ../../use/configuration.rst:168 +msgid "Editing the Configuration Values by Hand" +msgstr "" + +#: ../../use/configuration.rst:170 +msgid "" +"NOTE: **We don't recommend this and you shouldn't ever do this, you should " +"do everything with the commands in the Config plugin.**" +msgstr "" + +#: ../../use/configuration.rst:173 +msgid "" +"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." +msgstr "" + +#: ../../use/configuration.rst:178 +msgid "" +"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 " +"its configuration files and database 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' while editing the files, and no automatic " +"flushing will occur." +msgstr "" + +#: ../../use/configuration.rst:186 +msgid "" +"If you cannot access the bot on IRC and your bot is running on a POSIX " +"system, you can also send it a SIGHUP signal; it is exactly the same as " +"``config reload`` (note that the Config plugin has to be loaded to do that)." +msgstr "" + +#: ../../use/faq.rst:3 +msgid "Frequently Asked Questions" +msgstr "" + +#: ../../use/faq.rst:6 +msgid "How do I make my Supybot connect to multiple servers?" +msgstr "" + +#: ../../use/faq.rst:8 +msgid "Just use the `connect` command in the `Network` plugin." +msgstr "" + +#: ../../use/faq.rst:11 +msgid "" +"Why does my bot not recognize me or tell me that I don't have the 'owner' " +"capability?" +msgstr "" + +#: ../../use/faq.rst:13 +msgid "Because you've not given it anything to recognize you from!" +msgstr "" + +#: ../../use/faq.rst:15 +msgid "" +"You'll need to identify to the bot (``help identify`` to see how that works) " +"or add your hostmask to your user record (``help hostmask add`` to see how " +"that works) for it to know that you're you." +msgstr "" + +#: ../../use/faq.rst:19 +msgid "" +"You may wish to note that ``hostmask add`` can accept a password; rather " +"than identify, you can send the command::" +msgstr "" + +#: ../../use/faq.rst:24 +msgid "" +"and the bot will add your current hostmask to your owner user (of course, " +"you should change myOwnerUser and myOwnerUserPassword appropriately for your " +"bot)." +msgstr "" + +#: ../../use/faq.rst:28 +msgid "" +"For additional ways to identify to your bot, you may want to see :ref:" +"`getting-started`." +msgstr "" + +#: ../../use/faq.rst:32 +msgid "What is a hostmask?" +msgstr "" + +#: ../../use/faq.rst:34 +msgid "" +"Each user on IRC is uniquely identified by a string which we call a " +"`hostmask`. The IRC RFC refers to it as a prefix. Either way, it consists of " +"a nick, a user, and a host, in the form ``nick!user@host``. If your Supybot " +"complains that something you've given to it isn't a hostmask, make sure that " +"you have those three components and that they're joined in the appropriate " +"manner." +msgstr "" + +#: ../../use/faq.rst:42 +msgid "My bot can't handle nicks with brackets in them!" +msgstr "" + +#: ../../use/faq.rst:44 +msgid "" +"It always complains about something not being a valid command, or about " +"spurious or missing right brackets, etc." +msgstr "" + +#: ../../use/faq.rst:47 +msgid "" +"You should quote arguments (using double quotes, like this: ``" +"\"foo[bar]\"``) that have brackets in them that you don't wish to be " +"evaluated as nested commands. Alternatively, you can turn off nested " +"commands by setting `supybot.commands.nested` to False, or change the " +"brackets that nest commands by setting `supybot.commands.nested.brackets` to " +"some other value (like ``<>``, which can't occur in IRC nicks)." +msgstr "" + +#: ../../use/faq.rst:56 +msgid "I loaded Alias before, how do I move to Aka?" +msgstr "" + +#: ../../use/faq.rst:58 +msgid "" +"First load both of the plugins, Aka and Alias. Then run ``aka " +"importaliasdatabase`` and ``unload Alias``. Now all your aliases should be " +"imported to the Aka plugin." +msgstr "" + +#: ../../use/faq.rst:63 +msgid "I added an aka, but it doesn't work!" +msgstr "" + +#: ../../use/faq.rst:65 +msgid "" +"Take a look at ``aka show ``. If the aka the bot has listed " +"doesn't match what you're giving it, chances are you need to quote your aka " +"in order for the brackets not to be evaluated. For instance, if you're " +"adding an aka to give you a link to your homepage, you need to say::" +msgstr "" + +#: ../../use/faq.rst:73 +msgid "and not::" +msgstr "" + +#: ../../use/faq.rst:77 +msgid "" +"The first version works; the second version will always return the same url." +msgstr "" + +#: ../../use/faq.rst:81 +msgid "What does 'lobotomized' mean?" +msgstr "" + +#: ../../use/faq.rst:83 +msgid "" +"I see this word in commands and in my `channels.conf`, but I don't know what " +"it means. What does Supybot mean when it says lobotomized?" +msgstr "" + +#: ../../use/faq.rst:86 +msgid "" +"A lobotomy is an operation that removes the frontal lobe of the brain, the " +"part that does most of a person's thinking. To lobotomize a bot is to tell " +"it to stop thinking--thus, a lobotomized bot will not respond to anything " +"said by anyone other than its owner in whichever channels it is lobotomized." +msgstr "" + +#: ../../use/faq.rst:92 +msgid "" +"The term is certainly suboptimal, but remains in use because it was " +"historically used by certain other IRC bots, and we wanted to ease the " +"transition to Supybot from those bots by reusing as much terminology as " +"possible." +msgstr "" + +#: ../../use/faq.rst:98 +msgid "Is there a way to load all the plugins Supybot has?" +msgstr "" + +#: ../../use/faq.rst:100 +msgid "" +"No, there isn't. Even if there were, some plugins conflict with other " +"plugins, so it wouldn't make much sense to load them. For instance, what " +"would a bot do with `Factoids`, `MoobotFactoids`, and `Infobot` all loaded? " +"Probably just annoy people :)" +msgstr "" + +#: ../../use/faq.rst:105 +msgid "" +"You can also install user-contributed plugins using the PluginDownloader " +"plugin (``load PluginDownloader``). The ``repolist`` command can list " +"repositories and their contents, and the ``install`` command installs " +"plugins." +msgstr "" + +#: ../../use/faq.rst:111 +msgid "" +"Is there a command that can tell me what capability another command requires?" +msgstr "" + +#: ../../use/faq.rst:113 +msgid "No, there isn't, and there probably never will be." +msgstr "" + +#: ../../use/faq.rst:115 +msgid "" +"Commands have the flexibility to check any capabilities they wish to check; " +"while this flexibility is useful, it also makes it hard to guess what " +"capability a certain command requires. We could make a solution that would " +"work in a large majority of cases, but it wouldn't (and couldn't!) be " +"absolutely correct in all circumstances, and since we're anal and we hate " +"doing things halfway, we probably won't ever add this partial solution." +msgstr "" + +#: ../../use/faq.rst:124 +msgid "Why doesn't `Karma` seem to work for me?" +msgstr "" + +#: ../../use/faq.rst:126 +msgid "" +"`Karma`, 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 `Karma` acknowledge karma " +"updates, change the `supybot.plugins.Karma.response` configuration variable " +"to \"True\"." +msgstr "" + +#: ../../use/faq.rst:133 +msgid "Why won't Supybot respond to private messages?" +msgstr "" + +#: ../../use/faq.rst:135 +msgid "" +"The most likely cause is that your bot has a mode blocking messages from " +"unregistered users. Around Sept. 2005, for example, Freenode added a user " +"mode where registered users could set ``+R``, which `blocks`_ private " +"messages from unregistered users. So, the reason you aren't seeing a " +"response from your Supybot is likely:" +msgstr "" + +#: ../../use/faq.rst:141 +msgid "" +"Your Supybot is not registered with NickServ, you are registered, and you " +"have set the +R user mode for yourself." +msgstr "" + +#: ../../use/faq.rst:144 +msgid "" +"or: you have registered your Supybot with NickServ, you aren't registered, " +"and your Supybot has the +R user mode set." +msgstr "" + +#: ../../use/faq.rst:148 +msgid "Can users with the admin capability change the configuration?" +msgstr "" + +#: ../../use/faq.rst:150 +msgid "" +"Currently, no. 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." +msgstr "" + +#: ../../use/faq.rst:156 +msgid "How can I make my Supybot log my IRC channel?" +msgstr "" + +#: ../../use/faq.rst:158 +msgid "" +"To log all the channels your Supybot is in, simply load the `ChannelLogger` " +"plugin, which is included in the main distribution." +msgstr "" + +#: ../../use/faq.rst:162 +msgid "How do I get channel modes when writing a plugin?" +msgstr "" + +#: ../../use/faq.rst:164 +msgid "" +"I want to know who's an op in a certain channel, or who's voiced, or what " +"the modes on the channel are. How do I do that?" +msgstr "" + +#: ../../use/faq.rst:167 +msgid "" +"Everything you need is kept in a `ChannelState` object in an `IrcState` " +"object in the `Irc` object your plugin is given. To see the ops in a given " +"channel, for instance, you would do this::" +msgstr "" + +#: ../../use/faq.rst:173 +msgid "" +"To see a dictionary mapping mode chars to values (if any), you would do " +"this::" +msgstr "" + +#: ../../use/faq.rst:178 +msgid "From there, things should be self-evident." +msgstr "" + +#: ../../use/faq.rst:181 +msgid "Can Supybot connect through a proxy server?" +msgstr "" + +#: ../../use/faq.rst:183 +msgid "" +"Limnoria can connect to specific network using socks proxy, simply set the " +"configuration variable `supybot.networks..socksproxy`. For " +"specifying proxy which is used for HTTP requests, set the configuration " +"variable `supybot.protocols.http.proxy`." +msgstr "" + +#: ../../use/faq.rst:188 +msgid "" +"Supybot also works with transparent proxy server helpers like tsocks_ that " +"are designed to proxy-enable all network applications, and Supybot does work " +"with these." +msgstr "" + +#: ../../use/faq.rst:193 +msgid "Why can't Supybot find the plugin I want to load?" +msgstr "" + +#: ../../use/faq.rst:195 +msgid "" +"Why does my bot say that 'No plugin \"foo\" exists.' when I try to load the " +"foo plugin?" +msgstr "" + +#: ../../use/faq.rst:198 +msgid "" +"First, make sure you are typing the plugin name correctly. ``@load foo`` " +"may not be the same as ``@load Foo`` depending on your Supybot version " +"[#plugindir]_. If that is not the problem," +msgstr "" + +#: ../../use/faq.rst:202 +msgid "" +"Yes, it used to be the same, but then we moved to using directories for " +"plugins instead of a single file. Apparently, that makes a difference to " +"Python." +msgstr "" + +#: ../../use/faq.rst:207 +msgid "I've found a bug, what do I do?" +msgstr "" + +#: ../../use/faq.rst:209 +msgid "Submit your bug at our `issue tracker`_." +msgstr "" + +#: ../../use/faq.rst:212 +msgid "Is Python installed?" +msgstr "" + +#: ../../use/faq.rst:214 +msgid "" +"I run Windows, and I'm not sure if Python is installed on my computer. How " +"can I find out for sure?" +msgstr "" + +#: ../../use/faq.rst:217 +msgid "" +"Python isn't commonly installed by default on Windows computers. If you " +"don't see it in your start menu somewhere, it's probably not installed." +msgstr "" + +#: ../../use/faq.rst:221 +msgid "" +"The easiest way to find out if Python is installed is simply to `download " +"it`_ and try to install it. If the installer complains, you probably " +"already have it installed. If it doesn't, well, now you have Python " +"installed." +msgstr "" + +#: ../../use/faq.rst:227 +msgid "" +"Can I make Supybot silent, but still working on channel (as titlesnarfer or " +"something)?" +msgstr "" + +#: ../../use/faq.rst:229 +msgid "" +"With lobotomy, the bot stops doing everything on the channel. If you want it " +"to not reply to commands, but still work as titlesnarfer or similar, you can " +"configure it to not respond to anything." +msgstr "" + +#: ../../use/faq.rst:233 +msgid "Globally::" +msgstr "" + +#: ../../use/faq.rst:241 +msgid "Or just for one channel::" +msgstr "" + +#: ../../use/faq.rst:250 +msgid "How to make a connection secure?" +msgstr "" + +#: ../../use/faq.rst:252 +msgid "First, you should make the bot use SSL for each network::" +msgstr "" + +#: ../../use/faq.rst:256 +msgid "" +"Then, you must update the server port for the network the bot connects to " +"(this is usually 6697, but some networks use a different one)::" +msgstr "" + +#: ../../use/faq.rst:261 +msgid "" +"In the previous command, you must of course replace `irc.network.com` with " +"the hostname of a server of the network. You could either check out the " +"network's website, or get the current one, with this command::" +msgstr "" + +#: ../../use/faq.rst:268 +msgid "How to make Limnoria use Python 3 instead of Python 2?" +msgstr "" + +#: ../../use/faq.rst:270 +msgid "First, uninstall Limnoria::" +msgstr "" + +#: ../../use/faq.rst:274 +msgid "Or, if you did not install Limnoria as root::" +msgstr "" + +#: ../../use/faq.rst:278 +msgid "" +"Then, follow the :ref:`install guide `. In short, just run " +"this::" +msgstr "" + +#: ../../use/getting_started.rst:5 +msgid "Getting Started with Supybot" +msgstr "" + +#: ../../use/getting_started.rst:10 +msgid "" +"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 :)" +msgstr "" + +#: ../../use/getting_started.rst:14 +msgid "" +"You should have already read through our install document (if you had to " +"manually install) before reading any further. Now we'll give you a " +"whirlwind tour as to how you can get Supybot setup and use Supybot " +"effectively." +msgstr "" + +#: ../../use/getting_started.rst:19 +msgid "Initial Setup" +msgstr "" + +#: ../../use/getting_started.rst:21 +msgid "" +"Now that you have Supybot installed, you'll want to get it running. The " +"first thing you'll want to do is run supybot-wizard. Before running supybot-" +"wizard, you should be in the directory in which you want your bot-related " +"files to reside. The wizard will walk you through setting up a base config " +"file for your Supybot. Once you've completed the wizard, you will have a " +"config file called botname.conf. In order to get the bot running, run " +"``supybot botname.conf``." +msgstr "" + +#: ../../use/getting_started.rst:30 +msgid "Listing Commands" +msgstr "" + +#: ../../use/getting_started.rst:32 +msgid "" +"Ok, so let's assume your bot connected to the server and joined the channels " +"you told it to join. For now we'll assume you named your bot 'supybot' (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 (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::" +msgstr "" + +#: ../../use/getting_started.rst:41 +msgid "" +"Replacing 'supybot' with the actual name you picked for your bot, of course. " +"Your bot should reply with a list of the plugins it currently has loaded. " +"At least `Admin`, `Channel`, `Config`, `Misc`, `Owner`, and `User` should be " +"there; if you used supybot-wizard to create your configuration file you may " +"have many more plugins loaded. The list command can also be used to list " +"the commands in a given plugin::" +msgstr "" + +#: ../../use/getting_started.rst:50 +msgid "" +"will list all the commands in the `Misc` plugin. If you want to see the " +"help for any command, just use the help command::" +msgstr "" + +#: ../../use/getting_started.rst:57 +msgid "" +"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::" +msgstr "" + +#: ../../use/getting_started.rst:65 +msgid "" +"Anytime your bot tells you that a given command is defined in several " +"plugins, you'll want to use this syntax (\"plugin command\") to disambiguate " +"which plugin's command you wish to call. For instance, if you wanted to " +"call the Config plugin's list command, then you'd need to say::" +msgstr "" + +#: ../../use/getting_started.rst:72 +msgid "Rather than just 'list'." +msgstr "" + +#: ../../use/getting_started.rst:75 +msgid "Making Supybot Recognize You" +msgstr "" + +#: ../../use/getting_started.rst:77 +msgid "" +"For making the bot to identify to services, please see :ref:`identifying to " +"services. `" +msgstr "" + +#: ../../use/getting_started.rst:79 +msgid "" +"If you ran the wizard, then it is almost certainly the case that you already " +"added an owner user for yourself. If not, however, you can add one via the " +"handy-dandy 'supybot-adduser' script. You'll want to run it while the bot " +"is not running (otherwise it could overwrite supybot-adduser'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 'owner' capability, restart the bot and " +"you'll be ready to load some plugins!" +msgstr "" + +#: ../../use/getting_started.rst:88 +msgid "" +"Now, in order for the bot to recognize you as your owner user, you'll have " +"to identify with the bot." +msgstr "" + +#: ../../use/getting_started.rst:91 +msgid "" +"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::" +msgstr "" + +#: ../../use/getting_started.rst:97 +msgid "" +"And follow the instructions; the command you send will probably look like " +"this, with 'myowneruser' and 'myuserpassword' replaced::" +msgstr "" + +#: ../../use/getting_started.rst:102 +msgid "" +"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 Owner and " +"Admin plugins, which you may want to take a look at (using the list and help " +"commands, of course). One command in particular that you might want to use " +"(it's from the User plugin) is the 'hostmask add' command: it lets you add a " +"hostmask to your user record so the bot recognizes you by your hostmask " +"instead of requiring you always to identify with it before it recognizes " +"you. Use the 'help' command to see how this command works. Here's how I " +"often use it::" +msgstr "" + +#: ../../use/getting_started.rst:114 +msgid "" +"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 Misc 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 mypassword if I'm not already identified with the bot." +msgstr "" + +#: ../../use/getting_started.rst:122 +msgid "" +"It might often be better to specify the hostmask by yourself instead of " +"nesting the hostmask command as the hostmask command gives your exact " +"hostmask of that moment meaning ``nick!ident@host`` which means that you " +"will get unidentified if you change your nickname." +msgstr "" + +#: ../../use/getting_started.rst:127 +msgid "" +"I (Mikaela) often specify hostmasks in two other forms depending on the " +"situation which I go through in next subtopics." +msgstr "" + +#: ../../use/getting_started.rst:131 +msgid "Wildcard nick" +msgstr "" + +#: ../../use/getting_started.rst:133 +msgid "" +"In case my username and host stay the same or there aren't bots on same " +"server which could get identified as me to other bots, I use::" +msgstr "" + +#: ../../use/getting_started.rst:138 +msgid "" +"I only recommend this if there is ident server configured and the IRC " +"network checks for it." +msgstr "" + +#: ../../use/getting_started.rst:142 +msgid "Host only" +msgstr "" + +#: ../../use/getting_started.rst:144 +msgid "" +"In case I am the only one who has the same host (cloaks/vhosts on many " +"networks which have account in them, (for example freenode) or server where " +"no one else has access and no bots share it either), I use::" +msgstr "" + +#: ../../use/getting_started.rst:150 +msgid "" +"Mycloak at freenode is usually in format ``unaffiliated/accountname``. You " +"can usually request hostmasks using HostServ, ``/msg HostServ help``, or " +"asking on help channel of your IRC network, in case of freenode that is " +"#freenode. OFTC is exception to this and uses ``/msg NickServ set cloak " +"on``, but whatever your network users, you can ask it on their help channel." +msgstr "" + +#: ../../use/getting_started.rst:158 +msgid "Limnoria" +msgstr "" + +#: ../../use/getting_started.rst:160 +msgid "Limnoria has two additional methods to identify. GPG and NickAuth." +msgstr "" + +#: ../../use/getting_started.rst:163 +msgid "GPG" +msgstr "" + +#: ../../use/getting_started.rst:165 +msgid "" +"First you must associate your GPG key with your Limnoria account. The gpg " +"add command takes two arguments, key id and key server." +msgstr "" + +#: ../../use/getting_started.rst:168 +msgid "" +"My key is 0x0C207F07B2F32B67 and it's on keyserver pool.sks-keyservers.net " +"so and now I add it to my bot::" +msgstr "" + +#: ../../use/getting_started.rst:174 +msgid "Now I can get token to sign so I can identify::" +msgstr "" + +#: ../../use/getting_started.rst:179 +msgid "Then I follow the instructions and sign my token in terminal::" +msgstr "" + +#: ../../use/getting_started.rst:183 +msgid "" +"Note that I sent the output to curl with flags to directly send the " +"clearsigned content to sprunge.us pastebin. Curl should be installed on most " +"of distributions and comes with msysgit. If you remove the curl part, you " +"get the output to terminal and can pastebin it to any pastebin of your " +"choice. Sprunge.us has only plain text and is easy so I used it in this " +"example." +msgstr "" + +#: ../../use/getting_started.rst:190 +msgid "And last I give the bot link to the plain text signature::" +msgstr "" + +#: ../../use/getting_started.rst:196 +msgid "NickAuth" +msgstr "" + +#: ../../use/getting_started.rst:198 +msgid "" +"This requires you to load the NickAuth plugin (see next section of this page " +"for loading plugins)." +msgstr "" + +#: ../../use/getting_started.rst:201 +msgid "" +"NickAuth allows you to identify to the bot using your NickServ account. " +"First I add my NickServ account name which I can see with \"/whois Mikaela " +"Mikaela\" (because my current nick is Mikaela). It gives me something like::" +msgstr "" + +#: ../../use/getting_started.rst:206 +msgid "" +"Now I tell the bot add my NickServ account Mikaela to my bot user on " +"freenode. The syntax is [] ::" +msgstr "" + +#: ../../use/getting_started.rst:212 +msgid "" +"Next time when I identify to NickServ I will get identified automatically if " +"the bot sees that I was identified when I joined. This requires server to " +"support extended-join and WHOX. Most of modern networks support them, but if " +"your bot is using some bouncer, it might not support them." +msgstr "" + +#: ../../use/getting_started.rst:217 +msgid "" +"Automatic identification doesn't work always even when it's supported, but " +"when it fails, I can always use the NickAuth Auth command to identify to the " +"bot::" +msgstr "" + +#: ../../use/getting_started.rst:227 +msgid "Loading Plugins" +msgstr "" + +#: ../../use/getting_started.rst:229 +msgid "" +"Let's take a look at loading other plugins. If you didn't use supybot-" +"wizard, though, you might do well to try it before playing around with " +"loading plugins yourself: each plugin has its own configure function that " +"the wizard uses to setup the appropriate registry entries if the plugin " +"requires any." +msgstr "" + +#: ../../use/getting_started.rst:234 +msgid "" +"If you do want to play around with loading plugins, you're going to need to " +"have the owner capability." +msgstr "" + +#: ../../use/getting_started.rst:237 +msgid "" +"Remember earlier when I told you to try ``help load``? That's the very " +"command you'll be using. Basically, if you want to load, say, the Games " +"plugin, then ``load Games``. Simple, right? If you need a list of the " +"plugins you can load, you'll have to list the directory the plugins are in " +"(using whatever command is appropriate for your operating system, either " +"'ls' or 'dir')." +msgstr "" + +#: ../../use/getting_started.rst:244 +msgid "Understanding the help syntax" +msgstr "" + +#: ../../use/getting_started.rst:246 +msgid "" +"The syntax of a command describes how to run a command. The syntax is given " +"by the help command. Some examples:" +msgstr "" + +#: ../../use/getting_started.rst:263 +msgid "help [] []" +msgstr "" + +#: ../../use/getting_started.rst:251 +msgid "This is the help of :ref:`command-plugin-help`." +msgstr "" + +#: ../../use/getting_started.rst:253 +msgid "" +"The chevrons mean you have to replace and by a plugin " +"name and a command name." +msgstr "" + +#: ../../use/getting_started.rst:256 +msgid "The brackets mean the argument they wrap is **optional**." +msgstr "" + +#: ../../use/getting_started.rst:258 +msgid "So, the fellowing commands are correct::" +msgstr "" + +#: ../../use/getting_started.rst:268 +msgid "ping takes no arguments" +msgstr "" + +#: ../../use/getting_started.rst:266 +msgid "This is the help for :ref:`command-misc-ping`." +msgstr "" + +#: ../../use/getting_started.rst:268 +msgid "I think it is clear enough." +msgstr "" + +#: ../../use/getting_started.rst:278 +msgid "join []" +msgstr "" + +#: ../../use/getting_started.rst:271 +msgid "This is the help for :ref:`command-admin-join`." +msgstr "" + +#: ../../use/getting_started.rst:273 +msgid "It requires a channel name, and the channel key is optional." +msgstr "" + +#: ../../use/getting_started.rst:275 +msgid "This two commands are ok::" +msgstr "" + +#: ../../use/getting_started.rst:286 +msgid "utilities last [ ...]" +msgstr "" + +#: ../../use/getting_started.rst:281 +msgid "" +"This is the help for :ref:`command-utilities-last`. By the way, there is " +"another ``last`` command in the `Misc` plugin, which doesn't do the same " +"thing, that's why you need to give the plugin name." +msgstr "" + +#: ../../use/getting_started.rst:285 +msgid "" +"You have to give at least one argument, but you can give as many as you wish." +msgstr "" + +#: ../../use/getting_started.rst:289 +msgid "Getting More From Your Supybot" +msgstr "" + +#: ../../use/getting_started.rst:291 +msgid "" +"Another command you might find yourself needing somewhat often is the 'more' " +"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 default " +"value of `supybot.replies.genericNoCapability` -- it's so long that it'll " +"stretch across two messages::" +msgstr "" + +#: ../../use/getting_started.rst:317 +msgid "" +"So basically, the bot keeps, for each person it sees, a list of \"chunks\" " +"which are \"released\" one at a time by the `more` command. In fact, you " +"can even get the more chunks for another user: if you want to see another " +"chunk in the last command jemfinch gave, for instance, you would just say " +"`more jemfinch` after which, his \"chunks\" now belong to you. So, you " +"would just need to say `more` to continue seeing chunks from jemfinch's " +"initial command." +msgstr "" + +#: ../../use/getting_started.rst:327 +msgid "" +"You should now have a solid foundation for using Supybot. You can use the " +"`list` command to see what plugins your bot has loaded and what commands are " +"in those plugins; you can use the 'help' command to see how to use a " +"specific command, and you can use the 'more' command to continue a long " +"response from the bot. With these three commands, you should have a strong " +"basis with which to discover the rest of the features of Supybot!" +msgstr "" + +#: ../../use/getting_started.rst:334 +msgid "" +"Do be sure to read our other documentation and make use of the resources we " +"provide for assistance; this website and, of course, #supybot on irc." +"freenode.net if you run into any trouble!" +msgstr "" + +#: ../../use/httpserver.rst:3 +msgid "Using the HTTP server" +msgstr "" + +#: ../../use/httpserver.rst:8 +msgid "The HTTP server comes with a couple of additional variables:" +msgstr "" + +#: ../../use/httpserver.rst:10 +msgid "" +":ref:`supybot.servers.http.favicon`: Path to the file which is shown to " +"browsers as favicon." +msgstr "" + +#: ../../use/httpserver.rst:12 +msgid "" +":ref:`supybot.servers.http.hosts4`: The IPv4 addresses where the bot will " +"bind. In most of the cases, you will use 0.0.0.0 (everything) or 127.0.0.1 " +"(restricted to local connections). Defaults to 0.0.0.0" +msgstr "" + +#: ../../use/httpserver.rst:15 +msgid "" +":ref:`supybot.servers.http.hosts6`: The IPv6 addresses where the bot will " +"bind. Defaults to empty." +msgstr "" + +#: ../../use/httpserver.rst:17 +msgid "" +":ref:`supybot.servers.http.keepAlive`: Determines whether the HTTP server " +"will run even if has nothing to serve. Defaults to False, because the daemon " +"might require changing the port, if it is already taken." +msgstr "" + +#: ../../use/httpserver.rst:20 +msgid "" +":ref:`supybot.servers.http.port`: The port the bot will bind. May not work " +"if the number is below 1024. Defaults to 8080 (alternative HTTP port)." +msgstr "" + +#: ../../use/httpserver.rst:25 +msgid "Using the server" +msgstr "" + +#: ../../use/httpserver.rst:27 +msgid "" +"At the root of the server, you will find a list of the plugins that have a " +"Web interface, and a link to them. Each plugin has one or more " +"subdirectories of its own." +msgstr "" + +#: ../../use/httpserver.rst:31 +msgid "" +"You may also want to run Apache httpd or Nginx in front of Supybot's HTTP " +"server, if you want to use subdomains or load balancing." +msgstr "" + +#: ../../use/httpserver.rst:34 +msgid "" +"Here is an example of Apache httpd configuration (I didn't test it with the " +"rewrite, please notify me whether it works or not):" +msgstr "" + +#: ../../use/httpserver.rst:48 +msgid "" +"Here is an example of the Nginx configuration. Create a new site ``/etc/" +"nginx/sites-enabled/bot``:" +msgstr "" + +#: ../../use/httpserver.rst:67 +msgid "" +"Note that any HTTP server which can provide a reverse proxy service can be " +"configured to act as an intermediary or front end for the Limnoria HTTP " +"server. Configuring these alternatives is left as an exercise to the system " +"administrator (who ought to be familiar enough with it already)." +msgstr "" + +#: ../../use/httpserver.rst:75 +msgid "Templates" +msgstr "" + +#: ../../use/httpserver.rst:77 +msgid "" +"Among the plugins which use the HTTP server, some use the standard templates " +"system which allows you to edit page templates in a standard way (for other " +"plugins, check their documentation)." +msgstr "" + +#: ../../use/httpserver.rst:81 +msgid "" +"Templates are located in the `data/web/` folder. There is a folder per " +"plugin (and a `generic` folder, which holds generic pages), and all file " +"names end with `.example`, which is the default template provided by the " +"plugin. To customize it, rename it to remove `.example` (for instance: ``mv " +"fooplugin/foopage.html.example fooplugin/foopage.html``) and edit it (either " +"do it intuitively or check the plugin documentation to see how it handles " +"its templates)." +msgstr "" + +#: ../../use/identifying_to_services.rst:5 +msgid "Identifying the bot to services" +msgstr "" + +#: ../../use/identifying_to_services.rst:7 +msgid "" +"The different methods listed here are in the order how they are usually " +"recommended by network operators." +msgstr "" + +#: ../../use/identifying_to_services.rst:10 +msgid "" +"Please also note that SASL and CertFP are only fully supported on Limnoria. " +"Gribble has imported partial SASL support (only PLAIN)." +msgstr "" + +#: ../../use/identifying_to_services.rst:14 +msgid "Registering to services" +msgstr "" + +#: ../../use/identifying_to_services.rst:16 +msgid "" +"You can safely jump over this section if your bot is already registered to " +"services." +msgstr "" + +#: ../../use/identifying_to_services.rst:19 +msgid "" +"First start by checking what is the syntax for registering with ``/msg " +"nickserv help register``. It returns you something like this (Atheme 7.2.4)::" +msgstr "" + +#: ../../use/identifying_to_services.rst:25 +msgid "Assuming that that is the syntax, we can register the bot with::" +msgstr "" + +#: ../../use/identifying_to_services.rst:29 +msgid "" +"Note that the email address must be correct. Next check that ``/msg nickserv " +"info bot`` doesn't say something about being unverified. If it does, go to " +"the email address and run::" +msgstr "" + +#: ../../use/identifying_to_services.rst:35 +msgid "" +"Now your bot should be successfully registered and you can move to setting " +"up automatic identifying below. If you need to identify to services now, ``/" +"msg nickserv help identify`` and following the syntax (I am still assuming " +"that you are on Atheme 7.2.4) ``owner ircquote nickserv identify username " +"password``." +msgstr "" + +#: ../../use/identifying_to_services.rst:42 +msgid "SASL PLAIN" +msgstr "" + +#: ../../use/identifying_to_services.rst:44 +msgid "" +"*To use SASL EXTERNAL, you must only configure CertFP and it's attempted " +"automatically.* SASL PLAIN is identifying using username and password, SASL " +"EXTERNAL is identifying by using CertFP which is explained later on this " +"document. It doesn't need username or password to be configured." +msgstr "" + +#: ../../use/identifying_to_services.rst:49 +msgid "" +"Note that SASL isn't supported on all networks. As the only way to check if " +"SASL is supported is either ``/quote CAP LS`` (which usually gets eaten by " +"bouncers) or connecting to the network and seeing if it works, we recommend " +"always configuring SASL and whoising the bot to see if it worked. If it " +"didn't work, you might want to ask the network operators about their SASL " +"support and request them to start supporting it." +msgstr "" + +#: ../../use/identifying_to_services.rst:56 +msgid "" +"SASL is widely agreed as the best method to identify to services as it " +"identifies you before anyone (other than IRC operators) can see that you are " +"connected. To enable SASL, simply::" +msgstr "" + +#: ../../use/identifying_to_services.rst:63 +msgid "" +"where you of course replace AccountName and P455w0rd with your actual " +"NickServ account name and password. Remember to replace ```` with " +"the real network name like ``freenode``." +msgstr "" + +#: ../../use/identifying_to_services.rst:68 +msgid "CertFP" +msgstr "" + +#: ../../use/identifying_to_services.rst:70 +msgid "" +"You can test if CertFP is supported by services simply by doing ``/msg " +"NickServ cert``. If you get an error about \"Insufficient parameters for CERT" +"\", CertFP is supported, and if you get an error about unknown command, it's " +"not supported." +msgstr "" + +#: ../../use/identifying_to_services.rst:75 +msgid "" +"CertFP identifies you to services using a client (SSL) certificate and " +"naturally requires an SSL connection. It doesn't identify you as soon as " +"SASL, but unlike SASL, it identifies you even when services return from a " +"netsplit, unlike any other mechanism." +msgstr "" + +#: ../../use/identifying_to_services.rst:80 +msgid "" +"First you must generate a certificate, and the easiest method is probably " +"using OpenSSL which you should have even on Windows if you installed with " +"pip::" +msgstr "" + +#: ../../use/identifying_to_services.rst:85 +msgid "" +"Now you should have a ``.pem`` file in the directory where you ran the " +"command, presumably your home directory and you only tell your bot where to " +"find it and tell NickServ that it belongs to you. Note that you should " +"replace ```` with the account name of your bot." +msgstr "" + +#: ../../use/identifying_to_services.rst:90 +msgid "You have two choices, using the same certificate on all networks::" +msgstr "" + +#: ../../use/identifying_to_services.rst:94 +msgid "or only on one or more network where it's manually configured::" +msgstr "" + +#: ../../use/identifying_to_services.rst:98 +msgid "" +"And lastly, you must tell the services what is your certificate fingerprint, " +"which you can find out with::" +msgstr "" + +#: ../../use/identifying_to_services.rst:103 +msgid "" +"This results in something like ``05dd01fedc1b821b796d0d785160f03e32f53fa8`` " +"which you tell your bot to tell services::" +msgstr "" + +#: ../../use/identifying_to_services.rst:109 +msgid "Or if your bot identifies as you, you can do that by yourself with::" +msgstr "" + +#: ../../use/identifying_to_services.rst:114 +msgid "" +"Remember to replace ``05dd01fedc1b821b796d0d785160f03e32f53fa8`` with your " +"own fingerprint! Next time your bot connects, it should get identified " +"automatically." +msgstr "" + +#: ../../use/identifying_to_services.rst:119 +msgid "SASL ECDSA-NIST256P-CHALLENGE" +msgstr "" + +#: ../../use/identifying_to_services.rst:121 +msgid "First you must ECDSA key for the bot to use::" +msgstr "" + +#: ../../use/identifying_to_services.rst:125 +msgid "and get the public key using::" +msgstr "" + +#: ../../use/identifying_to_services.rst:129 +msgid "" +"After getting the public key, you must tell your bot to use it and tell " +"services about it (just like with CertFP/SASL EXTERNAL)::" +msgstr "" + +#: ../../use/identifying_to_services.rst:136 +msgid "" +"and after reconnecting, the bot should successfully identify using SASL " +"ECDSA-NIST256P-CHALLENGE." +msgstr "" + +#: ../../use/identifying_to_services.rst:139 +msgid "" +"*NOTE:* You can use ``ecdsa pubkey`` to get the public key, but you cannot " +"generate the key pair using it as pyecdsa doesn't support ecdsatool " +"generated keys." +msgstr "" + +#: ../../use/identifying_to_services.rst:144 +msgid "Server password" +msgstr "" + +#: ../../use/identifying_to_services.rst:146 +msgid "" +"Many networks support identifying using ``username:password`` as server " +"password. If this is the case with your network (anything that uses a " +"charybdis-like IRCd), this should work for you. Note that this identifies " +"you after SASL so, your real host might be seen. To do this, simply::" +msgstr "" + +#: ../../use/identifying_to_services.rst:153 +msgid "" +"Replace ```` with the name of network, for example ``freenode`` and " +"username:password with your real username and password." +msgstr "" + +#: ../../use/identifying_to_services.rst:157 +msgid "ZNC" +msgstr "" + +#: ../../use/identifying_to_services.rst:159 +msgid "If you wish to connect your bot to ZNC, the recommended way is::" +msgstr "" + +#: ../../use/identifying_to_services.rst:164 +msgid "" +"The identifier is free text to describe which client your Limnoria is. It " +"came with ZNC 1.6.0 and is completely optional. ```` again has been " +"there since ZNC 1.0 which is very old and has multiple security issues that " +"have been fixed since then. You should always run the latest release." +msgstr "" + +#: ../../use/identifying_to_services.rst:170 +msgid "Services plugin" +msgstr "" + +#: ../../use/identifying_to_services.rst:172 +msgid "" +"The Services plugin comes with Supybot and should be an easy way to identify " +"your bot, but SASL and ``username:password`` as server password are " +"recommended over it. Start by loading Services with::" +msgstr "" + +#: ../../use/identifying_to_services.rst:178 +msgid "and then tell it what NickServ and ChanServ are called::" +msgstr "" + +#: ../../use/identifying_to_services.rst:183 +msgid "" +"Remember to replace NickServ/ChanServ with their real names if they have a " +"different name on any network. Note that they must have the same name on all " +"networks, and you must have the same password on all networks." +msgstr "" + +#: ../../use/identifying_to_services.rst:187 +msgid "Now you can set your password::" +msgstr "" + +#: ../../use/identifying_to_services.rst:191 +msgid "" +"makes the bot attempt identifying as Bot using password P455w0rd. Replace " +"them with your real nickname and password. Note that if you have multiple " +"nicknames, you must run ``services password`` for them all." +msgstr "" + +#: ../../use/identifying_to_services.rst:195 +msgid "" +"If your bot happens to get a nickname that isn't configured, it won't know " +"how to identify. You might be able to avoid this issue by loading " +"NickCapture, (``load NickCapture``) which attempts to regain the primary " +"nick, when it's possible, and when it regains the primary nick, the " +"identification should work." +msgstr "" + +#: ../../use/index.rst:5 +msgid "The Supybot user guide" +msgstr "" + +#: ../../use/install.rst:7 +msgid "Installing Limnoria" +msgstr "" + +#: ../../use/install.rst:9 +msgid "" +"This is the \"easy to follow\" guide to installing Limnoria. The " +"installation documentation provided with the supybot distribution is really " +"quite good already, but since people keep coming to IRC, asking a repeating " +"pattern of questions, we thought it would be a good idea to expand it a bit " +"to make it a little more of a \"foolproof guide\"." +msgstr "" + +#: ../../use/install.rst:17 +msgid "Limnoria is a modified version of Supybot." +msgstr "" + +#: ../../use/install.rst:20 +msgid "Dependencies" +msgstr "" + +#: ../../use/install.rst:22 +msgid "" +"The only mandatory dependency is `Python`_ 2.6 or greater. However, it is " +"highly recommended you use Python 3.4 or greater." +msgstr "" + +#: ../../use/install.rst:25 +msgid "" +"You may also install chardet and feedparser, which are used by Limnoria if " +"they are available." +msgstr "" + +#: ../../use/install.rst:28 +msgid "" +"The remaining of this guide will assume you have Python 3. If you don't, " +"replace `python3` by `python` in the given commands" +msgstr "" + +#: ../../use/install.rst:34 +msgid "Installation: UNIX/Linux/BSD" +msgstr "" + +#: ../../use/install.rst:37 ../../use/install.rst:157 +msgid "Install Python" +msgstr "" + +#: ../../use/install.rst:39 +msgid "" +"Python will usually come by installed by default in your distribution. If " +"not, grab the appropriate packages from the distribution's repository." +msgstr "" + +#: ../../use/install.rst:42 +msgid "" +"If you're installing Python using your distribution's packages, you may need " +"a ''python-dev'' or ''python-devel'' package installed, too. To see if this " +"is the case, open up a terminal, start python, and run:" +msgstr "" + +#: ../../use/install.rst:50 +msgid "" +"If it works, you're good to go. Otherwise, install the `python3-dev` or " +"`python3-devel` package and try again." +msgstr "" + +#: ../../use/install.rst:53 +msgid "" +"You may also install \"manually\" by downloading the source archive from " +"http://python.org, and compiling it. That is outside the scope of this " +"guide, however." +msgstr "" + +#: ../../use/install.rst:58 +msgid "Install Limnoria" +msgstr "" + +#: ../../use/install.rst:60 +msgid "" +"In the next section of this guide we will use `pip`_, which is a generic way " +"of installing Python software." +msgstr "" + +#: ../../use/install.rst:63 +msgid "" +"There are some :ref:`alternative install methods ` at " +"the bottom of this guide, if you don't want to use `pip`." +msgstr "" + +#: ../../use/install.rst:69 +msgid "Global installation (with root access)" +msgstr "" + +#: ../../use/install.rst:71 +msgid "If you do not have root access, skip this section." +msgstr "" + +#: ../../use/install.rst:73 +msgid "" +"If you are logged in as root, you can remove ``sudo`` from the install " +"commands." +msgstr "" + +#: ../../use/install.rst:76 +msgid "" +"*In case you want to use the testing branch which might be more up-to date " +"BUT LESS TESTED, replace ``master`` with ``testing`` in the commands.*" +msgstr "" + +#: ../../use/install.rst:79 +msgid "" +"First we install Limnoria's optional dependencies (you can skip this step, " +"but some features won't be available)::" +msgstr "" + +#: ../../use/install.rst:84 +msgid "And then Limnoria itself::" +msgstr "" + +#: ../../use/install.rst:88 +msgid "" +"If you have an error saying `No module named pip`, install `pip` using your " +"package manager (the package is usually named `python3-pip`)." +msgstr "" + +#: ../../use/install.rst:92 +msgid "Local installation (without root access)" +msgstr "" + +#: ../../use/install.rst:94 +msgid "If you have followed the previous section, skip this one." +msgstr "" + +#: ../../use/install.rst:96 +msgid "" +"Simply add ``--user`` to the end of both commands. First we install " +"requirements (you can skip it, but some features won't be available) and " +"then Limnoria itself.::" +msgstr "" + +#: ../../use/install.rst:103 +msgid "You might need to add $HOME/.local/bin to your PATH.::" +msgstr "" + +#: ../../use/install.rst:108 +msgid "" +"If you have an error saying `No module named pip`, install `pip` using this " +"guide: https://pip.pypa.io/en/stable/installing/" +msgstr "" + +#: ../../use/install.rst:112 +msgid "Configure Supybot" +msgstr "" + +#: ../../use/install.rst:114 +msgid "" +"We are now ready to configure Supybot. Supybot creates quite a few auxiliary " +"files/directories to store its runtime data. It is thus recommended to " +"create an empty directory from which you'll be running supybot, to keep all " +"the data in a nice dedicated location. For example, you may create a " +"'runbot' directory inside your home directory." +msgstr "" + +#: ../../use/install.rst:120 +msgid "" +"Now you can cd to your 'runbot' directory, and from within it run ``supybot-" +"wizard``, which will walk you through a series of questions to generate the " +"bot config file." +msgstr "" + +#: ../../use/install.rst:124 +msgid "" +"One thing to make sure to do in the wizard, to make your life easier down " +"the line, is to select **y** for the *Would you like to add an owner user " +"for your bot?* question, and actually create the owner user. Remember that " +"password, so that you can later ''identify'' with the bot on IRC and " +"administer it." +msgstr "" + +#: ../../use/install.rst:129 +msgid "" +"Once you generate the config file, which will be named ``yourbotnick.conf`` " +"(where \"yourbotnick\" is the nick you have chosen for your bot in the " +"wizard), it will be placed in your 'runbot' directory. (As long as you leave " +"the default answer to the ''Where would you like to create these " +"directories?'' question.)" +msgstr "" + +#: ../../use/install.rst:134 +msgid "Now to start the bot, run, still from within the 'runbot' directory::" +msgstr "" + +#: ../../use/install.rst:138 ../../use/install.rst:234 +msgid "And watch the magic!" +msgstr "" + +#: ../../use/install.rst:140 +msgid "" +"For a tutorial on using and managing the bot from here on, see the " +"`Supybook`_." +msgstr "" + +#: ../../use/install.rst:145 +msgid "Installation: OS X" +msgstr "" + +#: ../../use/install.rst:147 +msgid "" +"The steps are essentially the same as those of the previous section, except " +"there are no repositories. Grab the latest python installer for OS X from " +"http://python.org, and follow the rest of the steps." +msgstr "" + +#: ../../use/install.rst:152 +msgid "Installation: Windows" +msgstr "" + +#: ../../use/install.rst:159 +msgid "" +"Download the latest **Python 3** installer from https://www.python.org, " +"3.5.1, as of 2016-01-26) and run it to install Python." +msgstr "" + +#: ../../use/install.rst:162 +msgid "" +"Installing Python is mostly clicking next, but in the next screen remember " +"the destination directory where you installed Python. These instructions " +"refer to it as ``C:\\Python35\\`` which is the current name on 2016-01-26." +msgstr "" + +#: ../../use/install.rst:166 +msgid "" +"Then you are asked to customize your installation. Click the drive on left " +"side of \"Python\" text and select \"Entire feature will be installed on " +"local hard drive\"." +msgstr "" + +#: ../../use/install.rst:170 +msgid "Now Python installs itself which may take several minutes." +msgstr "" + +#: ../../use/install.rst:172 +msgid "" +"Python should be now installed and you can check that the \"python\" command " +"points to correct python. Open ``cmd.exe`` (press the Windows button on your " +"keyboard and type \"cmd.exe\") and run ``where python`` and the toppernmost " +"entry should be ``C:\\Python35\\python.exe``." +msgstr "" + +#: ../../use/install.rst:178 +msgid "Install git" +msgstr "" + +#: ../../use/install.rst:180 +msgid "" +"In order to install the latest Limnoria from the git repository, you need " +"git in your %PATH%. You can get it from http://git-scm.com/." +msgstr "" + +#: ../../use/install.rst:183 +msgid "" +"In the \"Adjusting your PATH environment\", select the last option, \"Use " +"Git and optional Unix tools from the Windows Command Prompt\" or you will " +"have issues in the next step." +msgstr "" + +#: ../../use/install.rst:188 +msgid "Install Supybot" +msgstr "" + +#: ../../use/install.rst:190 +msgid "" +"Now we are ready to install Limnoria and it's requirements. Open ``cmd.exe`` " +"as **Administrator** (right click it in the previous place) and run::" +msgstr "" + +#: ../../use/install.rst:197 +msgid "" +"We are now ready to configure Supybot. Supybot creates quite a few auxiliary " +"files/directories to store its runtime data. It is thus recommended to " +"create an empty directory from which you'll be running supybot, to keep all " +"the data in a nice dedicated location. For example, you may create a ``C:" +"\\Users\\\\runbot`` for this purpose." +msgstr "" + +#: ../../use/install.rst:204 +msgid "" +"Now you open cmd.exe as **normal user**, and create and cd into your runbot " +"directory::" +msgstr "" + +#: ../../use/install.rst:210 +msgid "and from within it run ``supybot-wizard``::" +msgstr "" + +#: ../../use/install.rst:214 +msgid "" +"which will walk you through a series of questions to generate the bot config " +"file." +msgstr "" + +#: ../../use/install.rst:217 +msgid "" +"One thing to make sure to do in the wizard, to make your life easier down " +"the line, is to select *y* for the *Would you like to add an owner user for " +"your bot?* question, and actually create the owner user. Remember that " +"password, so that you can later ''identify'' with the bot on IRC and " +"administer it." +msgstr "" + +#: ../../use/install.rst:223 +msgid "" +"Once you generate the config file, which will be named ``yourbotnick.conf`` " +"(where ``yourbotnick`` is the nick you have chosen for your bot in the " +"wizard), it will be placed in your ``runbot`` directory. (As long as you " +"leave the default answer to the *Where would you like to create these " +"directories?* question.)" +msgstr "" + +#: ../../use/install.rst:229 +msgid "" +"Now to start the bot, run, still from within the ``C:\\users\\" +"\\runbot`` directory::" +msgstr "" + +#: ../../use/install.rst:236 +msgid "" +"This guide has been mainly written by nanotube (Daniel Folkinshteyn), and is " +"licensed under the Creative Commons Attribution ShareAlike 3.0 Unported " +"license and/or the GNU Free Documentation License v 1.3 or later." +msgstr "" + +#: ../../use/install.rst:247 +msgid "Alternative install methods" +msgstr "" + +#: ../../use/install.rst:249 +msgid "" +"If you know what you are doing and you don't want to use pip, you can use " +"one of these methods:" +msgstr "" + +#: ../../use/install.rst:252 +msgid "Download a .deb or .rpm package at `ProgVal's build repo`_." +msgstr "" + +#: ../../use/install.rst:253 +msgid "" +"Use `git`_ to clone the `Limnoria repository`_ and follow the instructions " +"in `Limnoria's README.md`_." +msgstr "" + +#: ../../use/install.rst:255 +msgid "" +"Click the \"Download ZIP\" button at the `Limnoria repository`_. Then, " +"extract the zipball to some temporary directory, and ``cd`` into the " +"`Limnoria-master` directory which contains the extracted code." +msgstr "" + +#: ../../use/security.rst:3 +msgid "Security in Limnoria" +msgstr "" + +#: ../../use/security.rst:5 +msgid "" +"Some security features are disabled by default. We know this is arguable, " +"but enabling them would make it quite hard to start using the bot. This " +"guide is for people who want to enable these features to make their bot as " +"secure as possible." +msgstr "" + +#: ../../use/security.rst:13 +msgid "" +"Limnoria (or Gribble or Supybot) have never been audited by a security " +"professional. We do the best we can to make it secure, but we cannot " +"guarantee it is completely safe." +msgstr "" + +#: ../../use/security.rst:19 +msgid "Trust in network operators" +msgstr "" + +#: ../../use/security.rst:21 +msgid "" +"As you may know, it is possible to do anything from IRC, including loading " +"the Unix plugin and using the `@call` command. The only safeguard is " +"checking the user calling the commands is authenticated as the owner of the " +"bot; and network operators are able to spoof hostmasks and collect your " +"password, thus allowing them to execute commands as the owner." +msgstr "" + +#: ../../use/security.rst:28 +msgid "" +"Although network operators of most well-known IRC networks are not known to " +"do that, you should be aware of that risk." +msgstr "" + +#: ../../use/security.rst:35 +msgid "Network connections / SSL" +msgstr "" + +#: ../../use/security.rst:38 +msgid "Background on SSL certification validation" +msgstr "" + +#: ../../use/security.rst:40 +msgid "" +"It is often believed using SSL magically makes impossible any attack on your " +"connection (from the bot to the server). It is true that it prevents passive " +"eavesdropping, but other attack methods are still possible." +msgstr "" + +#: ../../use/security.rst:45 +msgid "" +"The main one involves man-in-the-middle, ie. someone acting as a proxy " +"between you (your bot, in that case) and the IRC network. If certificates " +"are not validated, the attacker can allow you to connect to itself using " +"their own SSL certificate, and you would never know about it." +msgstr "" + +#: ../../use/security.rst:50 +msgid "" +"This is why it is important to check the SSL certificate of the server you " +"connect to: an attacker cannot spoof a certificate, or the trust of a " +"Certificate Authority in a network's certificates." +msgstr "" + +#: ../../use/security.rst:54 +msgid "" +"Of course, this assumes there is no bug in your SSL library, the network's, " +"and the protocols involved." +msgstr "" + +#: ../../use/security.rst:58 +msgid "Certificate validation in Limnoria" +msgstr "" + +#: ../../use/security.rst:60 +msgid "" +"Until version 2016.02.24, Limnoria did not support certificate validation. " +"Starting from this version, it is possible, but disabled by default, in " +"order to not break existing bot when updating." +msgstr "" + +#: ../../use/security.rst:64 +msgid "Certificate validation can be enabled using this command::" +msgstr "" + +#: ../../use/security.rst:68 +msgid "" +"Available validation mechanisms are Certification Authorities and " +"fingerprint checking." +msgstr "" + +#: ../../use/security.rst:72 +msgid "Certificate Authorities" +msgstr "" + +#: ../../use/security.rst:74 +msgid "" +"By default, Limnoria only checks certificates using CA certificates " +"installed on your system. However, some networks use a CA that is not " +"trusted by your system, such as CACert." +msgstr "" + +#: ../../use/security.rst:78 +msgid "Limnoria allows you to add a CA certificate for a network::" +msgstr "" + +#: ../../use/security.rst:82 +msgid "" +"Note that you are responsible for making sure this is the right certificate " +"for the CA, and trust this CA to sign correctly certificates valid for the " +"network's hostname(s)." +msgstr "" + +#: ../../use/security.rst:88 +msgid "Fingerprint checking" +msgstr "" + +#: ../../use/security.rst:90 +msgid "" +"Alternatively, for networks that do not use a CA, you can give Limnoria the " +"list of fingerprints of certificates used by the network::" +msgstr "" + +#: ../../use/security.rst:95 +msgid "" +"Adding fingerprints will disable CA verifications (useful if you do not want " +"to trust CAs)." +msgstr "" + +#: ../../use/security.rst:98 +msgid "" +"Note that you are responsible for giving the correct list of fingerprints." +msgstr "" + +#: ../../use/security.rst:103 +msgid "Supported python versions" +msgstr "" + +#: ../../use/security.rst:105 +msgid "Fingerprint checking is available in all Python versions." +msgstr "" + +#: ../../use/security.rst:107 +msgid "" +"CA validation is available in Python 2, starting on 2.7.9; and Python 3, " +"starting on 3.4." +msgstr "" + +#: ../../use/supybot-botchk.rst:5 +msgid "Restarting the bot automatically" +msgstr "" + +#: ../../use/supybot-botchk.rst:7 +msgid "" +"This page documents the different ways to automatically restart your bot in " +"case of crash or system reboot or anything that can make the bot quit." +msgstr "" + +#: ../../use/supybot-botchk.rst:10 +msgid "Note that you only need to use one." +msgstr "" + +#: ../../use/supybot-botchk.rst:13 +msgid "supybot-botchk" +msgstr "" + +#: ../../use/supybot-botchk.rst:15 +msgid "" +"supybot-botchk is a script that comes with Supybot which restarts the bot if " +"it quits or system reboots or anything that causes the bot to quit. It's " +"placed to crontab so cron will run it with scheduled intervals." +msgstr "" + +#: ../../use/supybot-botchk.rst:20 +msgid "How to use it?" +msgstr "" + +#: ../../use/supybot-botchk.rst:23 +msgid "Configuring the bot" +msgstr "" + +#: ../../use/supybot-botchk.rst:25 +msgid "" +"Start by telling your bot to write a pidfile somewhere where it can write " +"and restart the bot. For example::" +msgstr "" + +#: ../../use/supybot-botchk.rst:30 +msgid "" +"where is replaced with the system username and is replaced " +"with the name of the bot." +msgstr "" + +#: ../../use/supybot-botchk.rst:34 +msgid "crontab" +msgstr "" + +#: ../../use/supybot-botchk.rst:36 +msgid "" +"After the pidfile is configured, you can modify crontab. First you should " +"copy the output of::" +msgstr "" + +#: ../../use/supybot-botchk.rst:41 +msgid "" +"and open crontab with ``EDITOR=nano crontab -e`` and paste the output of " +"previous command to the first lines which don't have comments. This should " +"be on top. You will probably also want to configure locale and timezone " +"which happens by adding the following lines::" +msgstr "" + +#: ../../use/supybot-botchk.rst:58 +msgid "NOTE: Lines starting with # are comments and don't need to be written." +msgstr "" + +#: ../../use/supybot-botchk.rst:60 +msgid "" +"Now you finally add the bot. If you have multiple bots, simply add separate " +"lines for them all::" +msgstr "" + +#: ../../use/supybot-botchk.rst:65 +msgid "" +"If you needed to use diferent environment for other bot, you could specify " +"that on the same line. For example, my other bot uses en_US.utf8 as locale " +"and UTC as timezone::" +msgstr "" + +#: ../../use/supybot-botchk.rst:71 +msgid "" +"Note that environment doesn't need to be specified on supybot-botchk line " +"unless it differs from globally specified environment which we added as the " +"first thing to crontab." +msgstr "" + +#: ../../use/supybot-botchk.rst:75 +msgid "" +"Now you can save the crontab by pressing ``CTRL + O`` answering ``y`` and " +"then quitting nano with ``CTRL + X``." +msgstr "" + +#: ../../use/supybot-botchk.rst:78 +msgid "" +"If you are wondering what ``*/5 * * * *`` means, it simply means \"run this " +"every five minutes every day\". The 5 can be replaced with any other number " +"and there are also ``@hourly`` etc. which can be used on it's place, but you " +"most likely won't want to wait hour or more if your bot crashes." +msgstr "" + +#: ../../use/supybot-botchk.rst:84 +msgid "systemd service" +msgstr "" + +#: ../../use/supybot-botchk.rst:86 +msgid "" +"You need root access as no one has got this to work as user service yet. You " +"must also use systemd as your init." +msgstr "" + +#: ../../use/supybot-botchk.rst:89 +msgid "" +"Create a new file ``/etc/systemd/system/.service`` with the " +"following content replacing things were suitable::" +msgstr "" + +#: ../../use/supybot-botchk.rst:107 +msgid "" +"Now you should run ``systemctl daemon-reload`` to make systemd aware of " +"changed files and ``systemctl enable .service`` to make the bot " +"start on boot etc. and ``systemctl start .service`` to start the " +"bot." +msgstr "" + +#: ../../use/supybot-botchk.rst:112 +#, python-format +msgid "" +"Remember to check the ``Ènvironment`` line. You can get your PATH with " +"``printf 'PATH=%s\\n' \"$PATH\"``." +msgstr "" + +#: ../../use/supybot-botchk.rst:116 +msgid "Some commands" +msgstr "" + +#: ../../use/supybot-botchk.rst:118 +msgid "autostart on boot: ``systemctl enable .service``" +msgstr "" + +#: ../../use/supybot-botchk.rst:119 +msgid "disable autostart on boot: ``systemctl disable .service``" +msgstr "" + +#: ../../use/supybot-botchk.rst:120 +msgid "start the bot: ``systemctl start .service``" +msgstr "" + +#: ../../use/supybot-botchk.rst:121 +msgid "stop the bot: ``systemctl stop .service``" +msgstr "" + +#: ../../use/supybot-botchk.rst:122 +msgid "reload config files: ``systemctl reload .service``" +msgstr ""