diff --git a/docs/Configuration.md b/docs/Configuration.md new file mode 100644 index 0000000..72b1e0d --- /dev/null +++ b/docs/Configuration.md @@ -0,0 +1,115 @@ +# Configuration # + + +Skybot uses a JSON configuration file to hold settings: `/config` + +On first run this file is created with default settings: + +```json +{ + "connections": + { + "local irc": + { + "server": "localhost", + "nick": "skybot", + "channels": ["#test"] + } + } +} +``` + + +## Options ## + +Connections is an associative array of connection_name : connection_settings +key/value pairs. + +`connection_settings:` + +Required: + +* nick: the name of the bot. +* server: the hostname of the irc server. +* channels: channels to join. A list of strings. Can be [] + +Optional: + +* port: defaults to 6667. The port to connect to. +* user: defaults to "skybot". (user@netmask) +* realname: defaults to "Python bot - http://github.com/rmmh/skybot" + (Shown in whois) +* server_password: the server password. Omit if not needed. +* nickserv_password: defaults to "" (no login is performed) +* nickserv_name: defaults to "nickserv" (standard on most networks) +* nickserv_command: defaults to "IDENTIFY %s" (interpolated with password) +* ssl: defaults to false. Set to true to connect to the server using SSL +* ignore_cert: defaults to true. Set to false to validate the certificate + that the remote host uses for the SSL connection. + + +## Examples ## + +A single skybot instance can have multiple connections and multiple channels: + +```json +{ + "connections": + { + "public bot": + { + "server": "irc.example.org", + "nick": "publicbot", + "channels": ["#main"] + }, + "private bot": + { + "server": "irc.example.org", + "nick": "privatebot", + "channels": ["#secret", "#admin"] + } + } +} +``` + +The user and realname can be set. + +* user: defaults to "skybot" +* realname: defaults to "Python bot - http://github.com/rmmh/skybot" + +```json +{ + "connections": + { + "poker irc": + { + "server": "irc.poker.example.com", + "nick": "pokerbot", + "channels": ["#poker"], + "user": "pokerbot", + "realname": "Pokerbot - a fork of Skybot", + } + } +} +``` + +Automatic identification is possible. + +* nickserv_password: defaults to "" (no login is performed) +* nickserv_name: defaults to "nickserv" (standard on most networks) +* nickserv_command: defaults to "IDENTIFY %s" (interpolated with password) + +```json +{ + "connections": + { + "poker irc": + { + "server": "irc.poker.example.com", + "nick": "pokerbot", + "nickserv_password": "aceofspades", + "channels": ["#poker"] + } + } +} +``` diff --git a/docs/Home.md b/docs/Home.md new file mode 100644 index 0000000..58ce895 --- /dev/null +++ b/docs/Home.md @@ -0,0 +1,34 @@ +# Skybot documentation # + + +Skybot is a python IRC bot. + +## Introduction ## + +### Goals ### + +* simplicity +* little boilerplate +* minimal magic +* power +* multithreading +* automatic reloading +* extensibility + +### Features ### + +* multithreaded dispatch and the ability to connect to multiple networks at + a time +* easy plugin development with automatic reloading and a simple hooking API + +### Requirements ### + +Skybot runs on Python 2.6 and 2.7. Many of the plugins require +[lxml](http://lxml.de/). + + +## Table of contents ## + +* [[Installation]] +* [[Configuration]] +* [[Plugin development]] \ No newline at end of file diff --git a/docs/Installation.md b/docs/Installation.md new file mode 100644 index 0000000..adc3527 --- /dev/null +++ b/docs/Installation.md @@ -0,0 +1,26 @@ +# Installation # + + +## Requirements ## + +* Python 2.6 or 2.7 +* Many of the plugins require [lxml](http://lxml.de/) + + +## Download ## + +You can easily retrieve Skybot's files using git. Browse to the directory in +which you wish to place the bot and run the following command: + + git clone git://github.com/rmmh/skybot.git + + +## First run ## + +Browse to Skybot's directory and run the following command: + + python bot.py + +On first run, Skybot will create a default configuration file in its +directory. You can then stop the bot and follow the [[Configuration]] page's +instructions. \ No newline at end of file diff --git a/docs/Plugin-development.md b/docs/Plugin-development.md new file mode 100644 index 0000000..f9b1c5b --- /dev/null +++ b/docs/Plugin-development.md @@ -0,0 +1,148 @@ +# Plugin development # + + +> This documentation page needs to be improved. Contributions are welcomed. + +##Overview ## + +Skybot continually scans the `plugins/` directory for new or changed .py +files. When it finds one, it runs it and examines each function to see whether +it is a plugin hook. + +All plugins need to `from util import hook` in order to be callable. + + +## A simple example ## + +plugins/echo.py: + +```python +from util import hook + +@hook.command +def echo(inp): + return inp + inp +``` + +usage: + + .echo hots + Scaevolus: hotshots + + +This plugin example defines a command that replies with twice its input. It +can be invoked by saying phrases in a channel the bot is in, notably ".echo", +"skybot: echo", and "skybot, echo" (assuming the bot's nick is "skybot"). + + +## Plugin hooks ## + +There are four types of plugin hooks: commands, regexes, events, and sieves. +The hook type is assigned to plugin functions using decorators found +in `util/hook.py`. + + +There is also a secondary hook decorator: `@hook.singlethread` + +It indicates that the function should run in its own thread. Note that, in +that case, you can't use the existing database connection object. + +### Shared arguments ### + +> This section has to be verified. + +These arguments are shared by functions of all hook types: + +* nick -- string, the nickname of whoever sent the message. +* channel -- string, the channel the message was sent on. Equal to nick if + it's a private message. +* msg -- string, the line that was sent. +* raw -- string, the raw full line that was sent. +* re -- the result of doing `re.match(hook, msg)`. +* bot -- the running bot object. +* db -- the database connection object. +* input -- the triggering line of text + +### Commands hook ### + +`@hook.command` +`@hook.command(command_name)` + +Commands run when the beginning of a normal chat line matches one of +`.command`, `botnick: command`, or `botnick, command`, where `command` is the +command name, and `botnick` is the bot's nick on the server. + +Commands respond to abbreviated forms: a command named "`dictionary`" will be +invoked on both "`.dictionary`" and "`.dict`". If an abbreviated command is +ambiguous, the bot will return with a list of possibilities: given commands +"`dictionary`" and "`dice`", attempting to run command "`.di`" will make the +bot say "`did you mean dictionary or dice?`". + +When `@hook.command` is used without arguments, the command name is set to the +function name. When given an argument, it is used as the command name. This +allows one function to respond to multiple commands: + +```python +from util import hook + +@hook.command('hi') +@hook.command +def hello(inp): + return "Hey there!" +``` + +Users can invoke this function with either "`.hello`" or "`.hi`". + +### Regexes hook ### + +> This section needs to be improved. + +`@hook.regex(pattern)` + +Each line of chat is matched against the provided regex pattern. If it is +successful, the hook function will be called with the matched object. + +```python +from util import hook + +@hook.regex("lame bot") +def hurtfulcomment(match): + return "I have FEELINGS!" +``` + +### Events hook ### + +> This section needs to be improved. + +`@hook.event(irc_command)` + +Event hooks are called whenever a specific IRC command is issued. For example, +if you provide "*" as parameter, it will trigger on every line. If you provide +"PRIVMSG", it will only trigger on actual lines of chat (not nick-changes). + +The first argument in these cases will be a two-element list of the form +["#channel", "text"]. + +### Sieves hook ### + +> This section needs to be improved. + +`@hook.sieve` + +Sieves can prevent commands, regexes, and events from running. + +For instance, commands could be tagged as admin-only, and then a sieve would +verify that the user invoking the command has the necessary privileges. + +The function must take 5 arguments: (bot, input, func, type, args). +To cancel a call, return None. + +## Available objects ## + +> This section needs to be written. + +### The bot object ### + +### The db object ### + +### The input object ### diff --git a/docs/bots b/docs/bots deleted file mode 100644 index c78274d..0000000 --- a/docs/bots +++ /dev/null @@ -1,26 +0,0 @@ -Other bots we should "borrow" ideas from: - -supybot http://supybot.com/ - - horribly bloated plugin structure, each plugin has its own directory and 4 files (unit testing for plugins what) - -phenny http://inamidst.com/phenny/ - - inspiration for skybot, too much magic and not easy enough to change - -pyfibot http://code.google.com/p/pyfibot/ - - interesting, but lots of magic - -rbot http://linuxbrit.co.uk/rbot/ - - Ruby - - lots of plugins - -pyirc http://www.k-pdt.net/pyirc/ - - very simple, not multithreaded - - poor use of regexes, skybot has much better parsing, but it implements many more irc control codes - - can convert irc colors to vt100 escape codes -- should implement this - - autoreconnect - -pybot - - can handle multiple servers, but not multithreaded - - ugly modules - - too many external dependencies - - attempt at NLP diff --git a/docs/interface b/docs/interface deleted file mode 100644 index 92ce1ee..0000000 --- a/docs/interface +++ /dev/null @@ -1,19 +0,0 @@ -GOALS: -simplicity -as little boilerplate and magic as possible -multithreaded dispatch - -plugins are located in plugins/ - -input: -nick -- string, the nickname of whoever sent the message -channel -- string, the channel the message was sent on. Equal to nick if it's a private message. -msg -- string, the line that was sent -raw -- string, the raw full line that was sent -re -- the result of doing re.match(hook, msg) - -attributes and methods of bot: -say(msg): obvious -reply(msg): say(input.nick + ": " + msg) -msg(target, msg): sends msg to target -(other irc commands, like mode, topic, etc) diff --git a/docs/plugins b/docs/plugins deleted file mode 100644 index 430d1b0..0000000 --- a/docs/plugins +++ /dev/null @@ -1,27 +0,0 @@ -All plugins need to 'from util import hook' if they want to be callable. - -There are three ways to set when a plugin is called using -decorators. @hook.command causes it to be callable using normal command -syntax; an argument will register it under that name (so if my function is -called foo and I use @hook.command, .foo will work; if I use -@hook.command("bar"), .bar will work but not .foo). The first argument, inp, -will be the text that occurs after the command. (e.g., "bar" in ".foo bar"). - -@hook.regex takes an argument corresponding to the regex string (not the -compiled regex), followed by optional flags. It will attempt to match the regex -on all inputs; if so, the hooked function will be called with the match object. - -@hook.event requires a parameter; if it's '*", it will trigger on every line. If -it's 'PRIVMSG', it'll trigger on only actual lines of chat (not -nick-changes). The first argument in these cases will be a two-element list of -the form ["#channel", "text"]; I don't know what it's like for NICK or other -'commands'. - -@hook.singlethread indicates that the command should run in its own thread; this -means that you can't use the existing database connection object! - -In addition to the standard argument, plugins can take other arguments; db is -the database object; input corresponds to the triggering line of text, and bot -is the bot itself. - -TODO: describe what can be done with db, input, and bot. \ No newline at end of file