2003-09-24 07:56:34 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
import supybot
|
|
|
|
|
2003-10-05 15:02:56 +02:00
|
|
|
import fix
|
2003-09-24 09:49:02 +02:00
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
import os
|
2003-10-15 22:34:25 +02:00
|
|
|
import re
|
2003-09-25 09:14:47 +02:00
|
|
|
import sys
|
2003-10-11 18:22:07 +02:00
|
|
|
import sets
|
2003-09-24 07:56:34 +02:00
|
|
|
import pydoc
|
2003-09-25 09:14:47 +02:00
|
|
|
import pprint
|
2003-09-24 07:56:34 +02:00
|
|
|
import socket
|
2003-11-26 19:21:12 +01:00
|
|
|
import logging
|
2003-10-02 07:26:10 +02:00
|
|
|
import optparse
|
2003-10-24 15:35:35 +02:00
|
|
|
from itertools import imap
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2003-09-25 09:14:47 +02:00
|
|
|
import ansi
|
2003-09-24 07:56:34 +02:00
|
|
|
import utils
|
2004-01-19 21:34:02 +01:00
|
|
|
import ircutils
|
2004-01-20 01:21:15 +01:00
|
|
|
import registry
|
2003-09-25 09:14:47 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
import questions
|
|
|
|
from questions import output, yn, anything, something, expect, getpass
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-20 01:21:15 +01:00
|
|
|
def getPlugins(pluginDirs):
|
2003-09-24 07:56:34 +02:00
|
|
|
filenames = []
|
2004-01-20 01:21:15 +01:00
|
|
|
for pluginDir in pluginDirs:
|
2004-01-20 17:17:56 +01:00
|
|
|
try:
|
|
|
|
filenames.extend(os.listdir(pluginDir))
|
|
|
|
except OSError:
|
|
|
|
continue
|
2003-10-11 12:29:11 +02:00
|
|
|
plugins = sets.Set([])
|
2003-09-24 07:56:34 +02:00
|
|
|
for filename in filenames:
|
|
|
|
if filename.endswith('.py') and filename[0].isupper():
|
2003-10-11 12:29:11 +02:00
|
|
|
plugins.add(os.path.splitext(filename)[0])
|
2003-10-21 08:40:37 +02:00
|
|
|
plugins.discard('Owner')
|
2003-10-11 12:29:11 +02:00
|
|
|
plugins = list(plugins)
|
2003-09-24 07:56:34 +02:00
|
|
|
plugins.sort()
|
|
|
|
return plugins
|
|
|
|
|
|
|
|
def loadPlugin(name):
|
2004-01-20 01:21:15 +01:00
|
|
|
import Owner
|
2003-09-24 07:56:34 +02:00
|
|
|
try:
|
2003-10-21 08:40:37 +02:00
|
|
|
module = Owner.loadPluginModule(name)
|
2003-09-24 07:56:34 +02:00
|
|
|
if hasattr(module, 'Class'):
|
|
|
|
return module
|
|
|
|
else:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""That plugin loaded fine, but didn't seem to be a real
|
2003-09-24 07:56:34 +02:00
|
|
|
Supybot plugin; there was no Class variable to tell us what class
|
|
|
|
to load when we load the plugin. We'll skip over it for now, but
|
|
|
|
you can always add it later.""")
|
|
|
|
return None
|
|
|
|
except Exception, e:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""We encountered a bit of trouble trying to load plugin %r.
|
2003-10-30 04:19:18 +01:00
|
|
|
Python told us %r. We'll skip over it for now, you can always add it
|
2003-11-26 19:21:12 +01:00
|
|
|
later.""" % (name, utils.exnToString(e)))
|
2003-09-24 07:56:34 +02:00
|
|
|
return None
|
|
|
|
|
|
|
|
def describePlugin(module, showUsage):
|
|
|
|
if module.__doc__:
|
2004-01-19 18:44:50 +01:00
|
|
|
output(module.__doc__, unformatted=False)
|
2003-09-24 07:56:34 +02:00
|
|
|
elif hasattr(module.Class, '__doc__'):
|
2004-01-19 18:44:50 +01:00
|
|
|
output(module.Class.__doc__, unformatted=False)
|
2003-09-24 07:56:34 +02:00
|
|
|
else:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Unfortunately, this plugin doesn't seem to have any
|
2003-09-24 07:56:34 +02:00
|
|
|
documentation. Sorry about that.""")
|
|
|
|
if showUsage:
|
|
|
|
if hasattr(module, 'example'):
|
|
|
|
if yn('This plugin has a usage example. '
|
2004-01-19 18:44:50 +01:00
|
|
|
'Would you like to see it?', default=False):
|
2003-09-24 07:56:34 +02:00
|
|
|
pydoc.pager(module.example)
|
|
|
|
else:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""This plugin has no usage example.""")
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-20 01:21:15 +01:00
|
|
|
def clearLoadedPlugins(plugins, pluginRegistry):
|
|
|
|
for plugin in plugins:
|
|
|
|
try:
|
2004-02-06 05:39:47 +01:00
|
|
|
pluginKey = pluginRegistry.get(plugin)
|
2004-01-20 01:21:15 +01:00
|
|
|
if pluginKey():
|
|
|
|
plugins.remove(plugin)
|
2004-02-06 05:39:47 +01:00
|
|
|
except registry.NonExistentRegistryEntry:
|
2004-01-20 01:21:15 +01:00
|
|
|
continue
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2003-10-15 22:34:25 +02:00
|
|
|
_windowsVarRe = re.compile(r'%(\w+)%')
|
2003-09-24 07:56:34 +02:00
|
|
|
def getDirectoryName(default):
|
|
|
|
done = False
|
|
|
|
while not done:
|
2004-01-19 18:44:50 +01:00
|
|
|
dir = something('What directory do you want to use?',
|
|
|
|
default=os.path.join(os.curdir, default))
|
2003-09-30 12:19:20 +02:00
|
|
|
dir = os.path.expanduser(dir)
|
2003-10-15 22:34:25 +02:00
|
|
|
dir = _windowsVarRe.sub(r'$\1', dir)
|
|
|
|
dir = os.path.expandvars(dir)
|
2003-09-25 09:14:47 +02:00
|
|
|
dir = os.path.abspath(dir)
|
2003-09-24 07:56:34 +02:00
|
|
|
try:
|
2003-09-25 09:14:47 +02:00
|
|
|
os.makedirs(dir)
|
2003-09-24 07:56:34 +02:00
|
|
|
done = True
|
|
|
|
except OSError, e:
|
|
|
|
if e.args[0] != 17: # File exists.
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Sorry, I couldn't make that directory for some
|
2003-09-24 07:56:34 +02:00
|
|
|
reason. The Operating System told me %s. You're going to
|
|
|
|
have to pick someplace else.""" % e)
|
|
|
|
else:
|
|
|
|
done = True
|
2003-10-15 22:34:25 +02:00
|
|
|
return os.path.expandvars(os.path.expanduser(dir))
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-20 12:53:34 +01:00
|
|
|
def getRegistryValue(setting, prompt='', showHelp=True, showType=True):
|
|
|
|
if not prompt:
|
|
|
|
prompt = 'What would you like to set this option to?'
|
|
|
|
if showHelp:
|
|
|
|
help = ''
|
|
|
|
if showType:
|
|
|
|
help = '%s: ' % type(setting).__name__
|
|
|
|
help = '%s%s' % (help, setting.help)
|
|
|
|
output(textwrap.fill(help), unformatted=False)
|
|
|
|
ret = None
|
|
|
|
while not ret:
|
|
|
|
try:
|
|
|
|
setting.set(expect(prompt, [], default=str(setting)))
|
|
|
|
ret = setting()
|
|
|
|
except registry.InvalidRegistryValue, reason:
|
|
|
|
output(str(reason))
|
|
|
|
return ret
|
|
|
|
|
2003-10-02 07:11:40 +02:00
|
|
|
def main():
|
2004-01-20 01:21:15 +01:00
|
|
|
from conf import version
|
|
|
|
parser = optparse.OptionParser(usage='Usage: %prog [options] [configFile]',
|
|
|
|
version='Supybot %s' % version)
|
2003-10-02 07:26:10 +02:00
|
|
|
(options, args) = parser.parse_args()
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-20 01:21:15 +01:00
|
|
|
filename = ''
|
|
|
|
if len(args) > 1:
|
2004-01-29 19:08:38 +01:00
|
|
|
parser.error('the wizard takes one argument at most.')
|
2004-01-20 01:21:15 +01:00
|
|
|
elif len(args) == 1:
|
|
|
|
filename = args[0]
|
|
|
|
try:
|
|
|
|
registry.open(filename)
|
|
|
|
except OSError, msg:
|
|
|
|
raise SystemExit, 'Unable to open file %s: %s' % (filename, msg)
|
|
|
|
output("""It seems you already have a configuration file. We'll run
|
|
|
|
you through the options so you can change them if you want.""")
|
|
|
|
else:
|
|
|
|
output("""This is a wizard to help you start running supybot. What it
|
|
|
|
will do is create a single Python file whose effect will be that of
|
|
|
|
starting an IRC bot with the options you select here. So hold on tight
|
|
|
|
and be ready to be interrogated :)""")
|
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""First of all, we can bold the questions you're asked so you can
|
2003-09-25 09:14:47 +02:00
|
|
|
easily distinguish the mostly useless blather (like this) from the
|
|
|
|
questions that you actually have to answer.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Would you like to try this bolding?', default=True):
|
2004-01-20 17:17:56 +01:00
|
|
|
questions.useBold = True
|
2004-01-19 18:44:50 +01:00
|
|
|
if not yn('Do you see this in bold?'):
|
|
|
|
output("""Sorry, it looks like your terminal isn't ANSI compliant.
|
2003-09-25 09:14:47 +02:00
|
|
|
Try again some other day, on some other terminal :)""")
|
2004-01-20 17:17:56 +01:00
|
|
|
questions.useBold = False
|
2003-09-25 09:14:47 +02:00
|
|
|
else:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Great!""")
|
2003-09-25 09:14:47 +02:00
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
###
|
|
|
|
# Preliminary questions.
|
|
|
|
###
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""We've got some preliminary things to get out of the way before
|
2003-09-24 07:56:34 +02:00
|
|
|
we can really start asking you questions that directly relate to what your
|
|
|
|
bot is going to be like.""")
|
|
|
|
|
|
|
|
# Advanced?
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""We want to know if you consider yourself an advanced Supybot
|
2003-09-24 07:56:34 +02:00
|
|
|
user because some questions are just utterly boring and useless for new
|
|
|
|
users. Others might not make sense unless you've used Supybot for some
|
|
|
|
time.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
advanced = yn('Are you an advanced Supybot user?', default=False)
|
2004-01-20 01:21:15 +01:00
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
### Directories.
|
2004-01-20 01:21:15 +01:00
|
|
|
# We set these variables in cache because otherwise conf and log will
|
|
|
|
# create directories for the default values, which might not be what the
|
|
|
|
# user wants.
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Now we've got to ask you some questions about where some of
|
2003-09-24 07:56:34 +02:00
|
|
|
your directories are (or, perhaps, will be :)). If you're running this
|
|
|
|
wizard from the directory you'll actually be starting your bot from and
|
|
|
|
don't mind creating some directories in the current directory, then just
|
|
|
|
don't give answers to these questions and we'll create the directories we
|
|
|
|
need right here in this directory.""")
|
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.directories.log
|
|
|
|
output("""Your bot will need to put his logs somewhere. Do you have any
|
2003-09-24 07:56:34 +02:00
|
|
|
specific place you'd like them? If not, just press enter and we'll make
|
|
|
|
a directory named "logs" right here.""")
|
2004-01-20 01:21:15 +01:00
|
|
|
try:
|
2004-01-20 17:17:56 +01:00
|
|
|
logDir = registry._cache['supybot.directories.log']
|
|
|
|
logDir = utils.safeEval(logDir)
|
|
|
|
logDir = getDirectoryName(logDir)
|
2004-01-20 01:21:15 +01:00
|
|
|
except KeyError:
|
2004-01-20 17:17:56 +01:00
|
|
|
logDir = getDirectoryName('logs')
|
|
|
|
registry._cache['supybot.directories.log'] = logDir
|
2004-01-20 01:21:15 +01:00
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.directories.data
|
|
|
|
output("""Your bot will need to put various data somewhere. Things like
|
2003-09-24 07:56:34 +02:00
|
|
|
databases, downloaded files, etc. Do you have any specific place you'd
|
|
|
|
like the bot to put these things? If not, just press enter and we'll make
|
|
|
|
a directory named "data" right here.""")
|
2004-01-20 01:21:15 +01:00
|
|
|
try:
|
2004-01-20 17:17:56 +01:00
|
|
|
dataDir = registry._cache['supybot.directories.data']
|
|
|
|
dataDir = utils.safeEval(dataDir)
|
|
|
|
dataDir = getDirectoryName(dataDir)
|
2004-01-20 01:21:15 +01:00
|
|
|
except KeyError:
|
2004-01-20 17:17:56 +01:00
|
|
|
dataDir = getDirectoryName('data')
|
|
|
|
registry._cache['supybot.directories.data'] = dataDir
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.directories.conf
|
|
|
|
output("""Your bot must know where to find his configuration files. It'll
|
2003-09-24 07:56:34 +02:00
|
|
|
probably only make one or two, but it's gotta have some place to put them.
|
|
|
|
Where should that place be? If you don't care, just press enter and we'll
|
|
|
|
make a directory right here named "conf" where it'll store his stuff. """)
|
2004-01-20 01:21:15 +01:00
|
|
|
try:
|
2004-01-20 17:17:56 +01:00
|
|
|
confDir = registry._cache['supybot.directories.conf']
|
|
|
|
confDir = utils.safeEval(confDir)
|
|
|
|
confDir = getDirectoryName(confDir)
|
|
|
|
except KeyError:
|
|
|
|
confDir = getDirectoryName('conf')
|
|
|
|
registry._cache['supybot.directories.conf'] = confDir
|
|
|
|
|
|
|
|
# Store the minimum log priority if set, because we set it to a temporary
|
|
|
|
# value during the wizard
|
|
|
|
try:
|
2004-01-31 23:24:43 +01:00
|
|
|
priority = registry._cache['supybot.log.level']
|
2004-01-20 01:21:15 +01:00
|
|
|
except KeyError:
|
2004-01-20 17:17:56 +01:00
|
|
|
priority = 'INFO'
|
2004-01-31 23:24:43 +01:00
|
|
|
registry._cache['supybot.log.level'] = 'CRITICAL'
|
2004-01-20 17:17:56 +01:00
|
|
|
|
|
|
|
# Now that we're all set, import conf and log
|
|
|
|
import conf
|
|
|
|
import log
|
2003-09-24 07:56:34 +02:00
|
|
|
|
|
|
|
# pluginDirs
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Your bot will also need to know where to find his plugins at.
|
2003-09-24 07:56:34 +02:00
|
|
|
Of course, he already knows where the plugins that he came with are, but
|
|
|
|
your own personal plugins that you write for will probably be somewhere
|
2004-01-20 01:21:15 +01:00
|
|
|
else.""")
|
2004-01-20 17:17:56 +01:00
|
|
|
pluginDirs = conf.supybot.directories.plugins()
|
|
|
|
output("""Currently, the bot knows about the following directories:""")
|
|
|
|
output(utils.commaAndify(pluginDirs))
|
2004-01-19 18:44:50 +01:00
|
|
|
while yn('Would you like to add another plugin directory?',
|
|
|
|
default=False):
|
2003-09-24 07:56:34 +02:00
|
|
|
pluginDir = getDirectoryName('plugins')
|
2004-01-19 18:44:50 +01:00
|
|
|
if pluginDir not in pluginDirs:
|
|
|
|
pluginDirs.append(pluginDir)
|
2004-01-20 17:17:56 +01:00
|
|
|
conf.supybot.directories.plugins.setValue(pluginDirs)
|
2004-01-20 01:21:15 +01:00
|
|
|
|
|
|
|
output("Good! We're done with the directory stuff.")
|
2003-09-24 07:56:34 +02:00
|
|
|
|
|
|
|
###
|
|
|
|
# Bot stuff
|
|
|
|
###
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Now we're going to ask you things that actually relate to the
|
2003-09-24 07:56:34 +02:00
|
|
|
bot you'll be running.""")
|
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.server
|
2004-01-20 17:17:56 +01:00
|
|
|
# Force the user into specifying a server if he didn't have one already
|
|
|
|
try:
|
|
|
|
defaultServer = registry._cache['supybot.server']
|
|
|
|
defaultServer = utils.safeEval(defaultServer)
|
|
|
|
defaultServer = defaultServer.split(':')[0]
|
|
|
|
except KeyError:
|
|
|
|
defaultServer = None
|
2004-01-19 18:44:50 +01:00
|
|
|
server = None
|
2003-09-24 07:56:34 +02:00
|
|
|
while not server:
|
2004-01-20 17:17:56 +01:00
|
|
|
serverString = something('What server would you like to connect to?',
|
|
|
|
default=defaultServer)
|
2003-09-24 07:56:34 +02:00
|
|
|
try:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Looking up %s...""" % serverString)
|
2003-09-24 07:56:34 +02:00
|
|
|
ip = socket.gethostbyname(serverString)
|
|
|
|
except:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Sorry, I couldn't find that server. Perhaps you
|
2003-09-24 07:56:34 +02:00
|
|
|
misspelled it?""")
|
|
|
|
continue
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Found %s (%s).""" % (serverString, ip))
|
|
|
|
output("""IRC Servers almost always accept connections on port
|
2003-09-24 07:56:34 +02:00
|
|
|
6667. They can, however, accept connections anywhere their admin
|
|
|
|
feels like he wants to accept connections from.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Does this server require connection on a non-standard port?',
|
|
|
|
default=False):
|
2003-09-24 07:56:34 +02:00
|
|
|
port = 0
|
|
|
|
while not port:
|
|
|
|
port = something('What port is that?')
|
|
|
|
try:
|
|
|
|
i = int(port)
|
|
|
|
if not (0 < i < 65536):
|
|
|
|
raise ValueError
|
|
|
|
except ValueError:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""That's not a valid port.""")
|
2003-09-24 07:56:34 +02:00
|
|
|
port = 0
|
|
|
|
else:
|
|
|
|
port = 6667
|
2003-09-24 09:47:00 +02:00
|
|
|
server = ':'.join(map(str, [serverString, port]))
|
2004-01-20 01:21:15 +01:00
|
|
|
conf.supybot.server.set(server)
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.nick
|
2004-01-20 17:17:56 +01:00
|
|
|
# Force the user into specifying a nick if he didn't have one already
|
|
|
|
try:
|
|
|
|
defaultNick = registry._cache['supybot.nick']
|
|
|
|
defaultNick = utils.safeEval(defaultNick)
|
|
|
|
except KeyError:
|
|
|
|
defaultNick = None
|
|
|
|
while True:
|
|
|
|
nick = something('What nick would you like your bot to use?',
|
|
|
|
default=defaultNick)
|
|
|
|
try:
|
|
|
|
conf.supybot.nick.set(nick)
|
|
|
|
break
|
|
|
|
except registry.InvalidRegistryValue:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""That's not a valid nick. Go ahead and pick another.""")
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.user
|
2004-02-06 05:39:47 +01:00
|
|
|
if advanced:
|
|
|
|
output("""If you've ever done a /whois on a person, you know that IRC
|
|
|
|
provides a way for users to show the world their full name. What would
|
|
|
|
you like your bot's full name to be? If you don't care, just press
|
|
|
|
enter and it'll be the same as your bot's nick.""")
|
|
|
|
user = ''
|
|
|
|
try:
|
|
|
|
defaultUser = registry._cache['supybot.user']
|
|
|
|
defaultUser = utils.safeEval(defaultUser)
|
|
|
|
except KeyError:
|
|
|
|
defaultUser = nick
|
|
|
|
user = something('What would you like your bot\'s full name to be?',
|
|
|
|
default=defaultUser)
|
|
|
|
conf.supybot.user.set(user)
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.ident (if advanced)
|
2004-01-20 17:17:56 +01:00
|
|
|
try:
|
|
|
|
defaultIdent = registry._cache['supybot.ident']
|
|
|
|
defaultIdent = utils.safeEval(defaultIdent)
|
|
|
|
except KeyError:
|
|
|
|
defaultIdent = nick
|
2003-09-24 07:56:34 +02:00
|
|
|
if advanced:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""IRC servers also allow you to set your ident, which they
|
|
|
|
might need if they can't find your identd server. What would you
|
|
|
|
like your ident to be? If you don't care, press enter and we'll
|
|
|
|
use the same string as your bot's nick.""")
|
2004-01-20 17:17:56 +01:00
|
|
|
while True:
|
|
|
|
ident = something('What would you like your bot\'s ident to be?',
|
|
|
|
default=defaultIdent)
|
|
|
|
try:
|
|
|
|
conf.supybot.ident.set(ident)
|
|
|
|
break
|
|
|
|
except registry.InvalidRegistryValue:
|
|
|
|
output("""That was not a valid ident.
|
|
|
|
Go ahead and pick another.""")
|
2003-09-24 07:56:34 +02:00
|
|
|
else:
|
2004-01-20 17:17:56 +01:00
|
|
|
conf.supybot.ident.set(defaultIdent)
|
2004-01-19 18:44:50 +01:00
|
|
|
|
|
|
|
# conf.supybot.password
|
|
|
|
output("""Some servers require a password to connect to them. Most
|
|
|
|
public servers don't. If you try to connect to a server and for some
|
|
|
|
reason it just won't work, it might be that you need to set a
|
|
|
|
password.""")
|
|
|
|
if yn('Do you want to set such a password?', default=False):
|
2004-01-20 17:17:56 +01:00
|
|
|
conf.supybot.password.set(getpass())
|
2004-01-19 18:44:50 +01:00
|
|
|
|
|
|
|
# conf.supybot.channels
|
|
|
|
output("""Of course, having an IRC bot isn't the most useful thing in the
|
2003-09-24 07:56:34 +02:00
|
|
|
world unless you can make that bot join some channels.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Do you want your bot to join some channels when he connects?',
|
|
|
|
default=True):
|
2004-01-31 23:24:43 +01:00
|
|
|
defaultChannels = ' '.join(conf.supybot.channels())
|
|
|
|
while True:
|
|
|
|
channels = something('What channels? Separate channels with '
|
|
|
|
'spaces.', default=defaultChannels)
|
|
|
|
try:
|
|
|
|
conf.supybot.channels.set(channels)
|
|
|
|
break
|
|
|
|
except registry.InvalidRegistryValue:
|
|
|
|
# FIXME: say which ones weren't channels.
|
|
|
|
output("""Not all of those are valid IRC channels. Be sure to
|
2004-02-06 05:39:47 +01:00
|
|
|
prefix the channel with # (or +, or !, or &, but no one uses
|
|
|
|
those channels, really).""")
|
2003-09-24 07:56:34 +02:00
|
|
|
|
|
|
|
###
|
|
|
|
# Plugins
|
|
|
|
###
|
2004-01-20 01:21:15 +01:00
|
|
|
def configurePlugin(module, advanced):
|
|
|
|
if hasattr(module, 'configure'):
|
2004-02-06 05:39:47 +01:00
|
|
|
output("""Beginning configuration for %s...""" %
|
|
|
|
module.Class.__name__)
|
2004-01-20 01:21:15 +01:00
|
|
|
module.configure(advanced)
|
|
|
|
print # Blank line :)
|
|
|
|
output("""Done!""")
|
|
|
|
else:
|
2004-02-06 05:39:47 +01:00
|
|
|
conf.registerPlugin(module.__name__, currentValue=True)
|
2004-01-20 01:21:15 +01:00
|
|
|
|
|
|
|
plugins = getPlugins(pluginDirs)
|
2004-01-19 18:44:50 +01:00
|
|
|
for s in ('Admin', 'User', 'Channel', 'Misc', 'Config'):
|
2004-02-06 05:39:47 +01:00
|
|
|
configurePlugin(loadPlugin(s), advanced)
|
2004-01-20 01:21:15 +01:00
|
|
|
clearLoadedPlugins(plugins, conf.supybot.plugins)
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-20 17:17:56 +01:00
|
|
|
output("""Now we're going to run you through plugin configuration. There's
|
|
|
|
a variety of plugins in supybot by default, but you can create and
|
|
|
|
add your own, ofcourse. We'll allow you to take a look at the known
|
|
|
|
plugins' descriptions and configure them
|
|
|
|
if you like what you see.""")
|
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
# bulk
|
2003-09-24 18:02:31 +02:00
|
|
|
addedBulk = False
|
2004-01-19 18:44:50 +01:00
|
|
|
if advanced and yn('Would you like to add plugins en masse first?'):
|
2003-09-24 18:02:31 +02:00
|
|
|
addedBulk = True
|
2004-01-20 17:17:56 +01:00
|
|
|
output("""The available plugins are: %s.""" % \
|
|
|
|
utils.commaAndify(plugins))
|
|
|
|
output("""What plugins would you like to add? If you've changed your
|
|
|
|
mind and would rather not add plugins in bulk like this, just press
|
|
|
|
enter and we'll move on to the individual plugin configuration.""")
|
2003-09-24 07:56:34 +02:00
|
|
|
massPlugins = anything('Separate plugin names by spaces:')
|
2004-01-01 21:04:35 +01:00
|
|
|
for name in re.split(r',?\s+', massPlugins):
|
2003-09-24 07:56:34 +02:00
|
|
|
module = loadPlugin(name)
|
|
|
|
if module is not None:
|
2004-01-19 18:44:50 +01:00
|
|
|
configurePlugin(module, advanced)
|
2004-01-20 01:21:15 +01:00
|
|
|
clearLoadedPlugins(plugins, conf.supybot.plugins)
|
2003-09-24 07:56:34 +02:00
|
|
|
|
|
|
|
# individual
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Would you like to look at plugins individually?'):
|
|
|
|
output("""Next comes your oppurtunity to learn more about the plugins
|
2003-09-24 18:02:31 +02:00
|
|
|
that are available and select some (or all!) of them to run in your
|
|
|
|
bot. Before you have to make a decision, of course, you'll be able to
|
|
|
|
see a short description of the plugin and, if you choose, an example
|
|
|
|
session with the plugin. Let's begin.""")
|
2003-11-06 21:49:37 +01:00
|
|
|
# until we get example strings again, this will default to false
|
2004-01-19 18:44:50 +01:00
|
|
|
#showUsage =yn('Would you like the option of seeing usage examples?')
|
2003-11-06 21:49:37 +01:00
|
|
|
showUsage = False
|
2003-09-24 07:56:34 +02:00
|
|
|
name = expect('What plugin would you like to look at?', plugins)
|
2003-09-24 18:02:31 +02:00
|
|
|
while name:
|
|
|
|
module = loadPlugin(name)
|
|
|
|
if module is not None:
|
|
|
|
describePlugin(module, showUsage)
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Would you like to load this plugin?', default=True):
|
|
|
|
configurePlugin(module, advanced)
|
2004-01-20 01:21:15 +01:00
|
|
|
clearLoadedPlugins(plugins, conf.supybot.plugins)
|
2004-01-19 18:44:50 +01:00
|
|
|
if not yn('Would you like add another plugin?'):
|
2003-09-24 18:02:31 +02:00
|
|
|
break
|
|
|
|
name = expect('What plugin would you like to look at?', plugins)
|
2003-09-24 07:56:34 +02:00
|
|
|
|
|
|
|
###
|
|
|
|
# Sundry
|
|
|
|
###
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Although supybot offers a supybot-adduser.py script, with which
|
2003-09-24 07:56:34 +02:00
|
|
|
you can add users to your bot's user database, it's *very* important that
|
|
|
|
you have an owner user for you bot.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Would you like to add an owner user for your bot?', default=True):
|
2003-09-24 07:56:34 +02:00
|
|
|
import ircdb
|
|
|
|
name = something('What should the owner\'s username be?')
|
2003-09-29 07:51:28 +02:00
|
|
|
try:
|
|
|
|
id = ircdb.users.getUserId(name)
|
|
|
|
u = ircdb.users.getUser(id)
|
|
|
|
if u.checkCapability('owner'):
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""That user already exists, and has owner capabilities
|
2003-09-29 07:51:28 +02:00
|
|
|
already. Perhaps you added it before? """)
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Do you want to remove its owner capability?',
|
|
|
|
default=False):
|
2003-09-29 07:51:28 +02:00
|
|
|
u.removeCapability('owner')
|
2003-11-14 18:46:39 +01:00
|
|
|
ircdb.users.setUser(id, u)
|
2003-09-29 07:51:28 +02:00
|
|
|
else:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""That user already exists, but doesn't have owner
|
2003-09-29 07:51:28 +02:00
|
|
|
capabilities.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
if yn('Do you want to add to it owner capabilities?',
|
|
|
|
default=False):
|
2003-09-29 07:51:28 +02:00
|
|
|
u.addCapability('owner')
|
2003-11-14 18:46:39 +01:00
|
|
|
ircdb.users.setUser(id, u)
|
2003-09-29 07:51:28 +02:00
|
|
|
except KeyError:
|
2003-11-17 05:13:06 +01:00
|
|
|
password = getpass('What should the owner\'s password be?')
|
2003-09-29 07:51:28 +02:00
|
|
|
(id, u) = ircdb.users.newUser()
|
|
|
|
u.name = name
|
|
|
|
u.setPassword(password)
|
|
|
|
u.addCapability('owner')
|
|
|
|
ircdb.users.setUser(id, u)
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Of course, when you're in an IRC channel you can address the bot
|
2003-09-24 07:56:34 +02:00
|
|
|
by its nick and it will respond, if you give it a valid command (it may or
|
|
|
|
may not respond, depending on what your config variable replyWhenNotCommand
|
|
|
|
is set to). But your bot can also respond to a short "prefix character,"
|
|
|
|
so instead of saying "bot: do this," you can say, "@do this" and achieve
|
|
|
|
the same effect. Of course, you don't *have* to have a prefix char, but
|
|
|
|
if the bot ends up participating significantly in your channel, it'll ease
|
|
|
|
things.""")
|
2004-01-20 01:21:15 +01:00
|
|
|
if yn('Would you like to set the prefix char(s) for your bot? ',
|
2004-01-19 18:44:50 +01:00
|
|
|
default=True):
|
|
|
|
output("""Enter any characters you want here, but be careful: they
|
2003-09-24 07:56:34 +02:00
|
|
|
should be rare enough that people don't accidentally address the bot
|
|
|
|
(simply because they'll probably be annoyed if they do address the bot
|
|
|
|
on accident). You can even have more than one. I (jemfinch) am quite
|
|
|
|
partial to @, but that's because I've been using it since my ocamlbot
|
|
|
|
days.""")
|
2003-10-19 21:23:39 +02:00
|
|
|
import callbacks
|
2004-01-19 18:44:50 +01:00
|
|
|
while True:
|
|
|
|
try:
|
2004-01-20 01:21:15 +01:00
|
|
|
conf.supybot.prefixChars.set(
|
2004-01-19 18:44:50 +01:00
|
|
|
something('What would you like your '
|
|
|
|
'bot\'s prefix character(s) to be?',
|
|
|
|
default='@'))
|
|
|
|
break
|
|
|
|
except registry.InvalidRegistryValue, reason:
|
2004-01-20 01:21:15 +01:00
|
|
|
output(str(reason))
|
2003-09-24 07:56:34 +02:00
|
|
|
else:
|
2004-01-20 01:21:15 +01:00
|
|
|
conf.supybot.prefixChars.set('')
|
2003-09-24 07:56:34 +02:00
|
|
|
|
|
|
|
# enablePipeSyntax
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Supybot allows nested commands. You've probably
|
2003-09-24 07:56:34 +02:00
|
|
|
read about them in our website or documentation, and almost certainly have
|
|
|
|
seen them in the plugin examples (if you chose to read them), By default,
|
|
|
|
they work with a syntax that looks something like Lisp with square
|
|
|
|
brackets. I.e., to call the command foo on the output of bar, you would
|
|
|
|
use "foo [bar]". Supybot is also capable of providing a pipe syntax
|
|
|
|
similar to *nix pipes. In addition to "foo [bar]", you could achieve the
|
|
|
|
same effect with "bar | foo", which some people find more natural. This
|
|
|
|
syntax is disabled by default because so many people have pipes in their
|
|
|
|
nicks, and we've found it to be somewhat frustrating to have to quote such
|
|
|
|
nicks in commands.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
conf.supybot.pipeSyntax.setValue(yn('Would you like to enable the pipe '
|
2004-01-20 01:21:15 +01:00
|
|
|
'syntax for nesting? ', default=False))
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2003-09-25 09:14:47 +02:00
|
|
|
###
|
2003-11-26 19:21:12 +01:00
|
|
|
# logging variables.
|
2003-09-25 09:14:47 +02:00
|
|
|
###
|
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.log.stdout
|
|
|
|
output("""By default, your bot will log not only to files in the logs
|
2003-11-26 19:21:12 +01:00
|
|
|
directory you gave it, but also to stdout. We find this useful for
|
2003-09-25 09:14:47 +02:00
|
|
|
debugging, and also just for the pretty output (it's colored!)""")
|
2004-01-19 18:44:50 +01:00
|
|
|
conf.supybot.log.stdout.setValue(not yn('Would you like to turn off '
|
|
|
|
'this logging to stdout?', default=False))
|
|
|
|
if conf.supybot.log.stdout():
|
2003-11-26 19:21:12 +01:00
|
|
|
# conf.something
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Some terminals may not be able to display the pretty colors
|
2003-09-25 09:14:47 +02:00
|
|
|
logged to stderr. By default, though, we turn the colors off for
|
|
|
|
Windows machines and leave it on for *nix machines.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
if os.name is not 'nt':
|
|
|
|
conf.supybot.log.stdout.colorized.setValue(
|
|
|
|
not yn('Would you like to turn this colorization off?',
|
|
|
|
default=False))
|
2003-12-09 04:14:16 +01:00
|
|
|
|
2004-01-31 23:24:43 +01:00
|
|
|
# conf.supybot.log.level
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Your bot can handle debug messages at several priorities,
|
2003-12-09 04:14:16 +01:00
|
|
|
CRITICAL, in decreasing order of priority. By
|
|
|
|
default, your bot will log all of these priorities. You can, however,
|
|
|
|
specify that he only log messages above a certain priority level. Of
|
|
|
|
course, all error messages will still be logged.""")
|
2004-01-31 23:24:43 +01:00
|
|
|
newLogLevel = something('What would you like the minimum priority to be? '
|
2004-01-19 18:44:50 +01:00
|
|
|
'Just press enter to accept the default.',
|
2004-01-20 01:21:15 +01:00
|
|
|
default=priority).lower()
|
2004-01-31 23:24:43 +01:00
|
|
|
while newLogLevel not in ['debug', 'info', 'warning', 'error', 'critical']:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""That's not a valid priority. Valid priorities include
|
|
|
|
'DEBUG', 'INFO', 'WARNING', 'ERROR', and 'CRITICAL'""")
|
2004-01-31 23:24:43 +01:00
|
|
|
newLogLevel = something('What would you like the minimum priority to '
|
2004-01-20 01:21:15 +01:00
|
|
|
'be? Just press enter to accept the default.',
|
|
|
|
default=priority).lower()
|
2003-09-25 09:14:47 +02:00
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
if advanced:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Here's some stuff you only get to choose if you're an
|
2003-09-24 07:56:34 +02:00
|
|
|
advanced user :)""")
|
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.reply.withNickPrefix
|
|
|
|
output("""By defualt, the bot will respond to all commands with a
|
2003-12-08 14:02:46 +01:00
|
|
|
Nick: <response> response. That is, the user making the command will
|
2004-01-19 18:44:50 +01:00
|
|
|
have their nick prefixed to the command.
|
|
|
|
If supybot.reply.withNickPrefix is set to False, replies from the bot
|
|
|
|
will not include this nick prefix.""")
|
|
|
|
conf.supybot.reply.withNickPrefix.setValue(
|
|
|
|
not yn('Would you like to turn off this nick prefix?',
|
|
|
|
default=False))
|
|
|
|
|
|
|
|
# conf.supybot.reply.whenAddressedByNick
|
|
|
|
output("""By default, the bot will respond when addressed by its nick.
|
2003-12-08 14:02:46 +01:00
|
|
|
That is, if the bot's nick is 'botnick', then 'botnick: foo' will call
|
|
|
|
the foo command. If replyWhenAddressedByNick is False, the bot will
|
|
|
|
not respond to such messages. Make sure you have a prefixChar set if
|
|
|
|
you set this, otherwise people will only be able to communicate with
|
|
|
|
the bot through private messages.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
conf.supybot.reply.whenAddressedByNick.setValue(
|
|
|
|
not yn('Would you like to turn off the bot\'s replies to messages '
|
|
|
|
'prefixed with its nick?', default=False))
|
2003-12-08 14:02:46 +01:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.showSimpleSyntax
|
|
|
|
output("""By default, when the bot receives a message with invalid
|
2003-10-24 13:31:09 +02:00
|
|
|
arguments, the bot returns the full help (syntax and description) of
|
|
|
|
the command. If showOnlySyntax is set to True, though, the bot will
|
|
|
|
return just the syntax of the command. Of course, the help will still
|
|
|
|
be available via the help command.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
conf.supybot.showSimpleSyntax.setValue(
|
|
|
|
yn('Would you like to show only the syntax of commands when '
|
|
|
|
'they\'re given invalid arguments?', default=False))
|
2003-10-24 13:31:09 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.reply.whenNotCommand
|
|
|
|
output("""By default, when people address your bot but don't give it
|
2003-09-24 07:56:34 +02:00
|
|
|
a valid command, it'll respond with a message saying that they didn't
|
|
|
|
give it a valid command. When your channel grows more accustomed to
|
|
|
|
the bot, they may prefer that it not do that, since any command you
|
|
|
|
give the bot (at least within the included plugins) will respond with
|
|
|
|
something, so invalid commands are still noticeable. This decreases
|
|
|
|
the channel traffic somewhat.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
conf.supybot.reply.whenNotCommand.setValue(
|
|
|
|
not yn('Would you like to turn off the bot\'s replies when he\'s '
|
|
|
|
'addressed but given a non-command?', default=False))
|
2003-09-24 07:56:34 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.reply.withPrivateNotice
|
|
|
|
output("""When a user sends a command to the bot from within a
|
2003-10-20 12:10:46 +02:00
|
|
|
channel, the bot, by default, also responds to that channel. In some
|
|
|
|
rather busy channels this might be considered spam, especially if the
|
|
|
|
command returns several lines in its result. In this case you may want
|
|
|
|
to notice the user instead.""")
|
2004-01-19 18:44:50 +01:00
|
|
|
conf.supybot.reply.withPrivateNotice.setValue(
|
|
|
|
yn('Would you like the bot to notice replies to users in private '
|
|
|
|
'when a command is executed in a channel?', default=False))
|
2003-10-20 12:10:46 +02:00
|
|
|
|
2004-01-19 18:44:50 +01:00
|
|
|
# conf.supybot.throttleTime
|
|
|
|
output("""In order to prevent flooding itself off the network,
|
2003-09-24 07:56:34 +02:00
|
|
|
your bot by default will not send more than one message per second to
|
|
|
|
the network. This is, however, configurable.""")
|
|
|
|
if yn('Would you like to change the minimum amount of time between '
|
2004-01-19 18:44:50 +01:00
|
|
|
'messages your bot sends to the network?', default=False):
|
|
|
|
while True:
|
2003-09-24 07:56:34 +02:00
|
|
|
try:
|
2004-01-20 01:21:15 +01:00
|
|
|
conf.supybot.throttleTime.set(something(
|
2004-01-19 18:44:50 +01:00
|
|
|
'How long do you want your bot to wait between '
|
|
|
|
'sending messages to the server? Floating '
|
|
|
|
'point values are accepted.'))
|
|
|
|
break
|
|
|
|
except InvalidRegistryValue:
|
|
|
|
output("""That's not a valid time. You'll need to give
|
2003-09-24 07:56:34 +02:00
|
|
|
a floating-point number.""")
|
|
|
|
|
|
|
|
###
|
|
|
|
# This is close to the end.
|
|
|
|
###
|
|
|
|
if not advanced:
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""There are a lot of options we didn't ask you about simply
|
2003-09-24 07:56:34 +02:00
|
|
|
because we'd rather you get up and running and have time left to play
|
|
|
|
around with your bot. But come back and see us! When you've played
|
|
|
|
around with your bot enough to know what you like, what you don't like,
|
|
|
|
what you'd like to change, then come back and run this script again
|
|
|
|
and tell us you're an advanced user. Some of those questions might be
|
|
|
|
boring, but they'll really help you customize your bot :)""")
|
2004-01-20 01:21:15 +01:00
|
|
|
|
2003-09-24 07:56:34 +02:00
|
|
|
###
|
2004-01-20 01:21:15 +01:00
|
|
|
# Write the registry
|
2003-09-24 07:56:34 +02:00
|
|
|
###
|
2004-01-31 23:24:43 +01:00
|
|
|
# Replace the temporary value in supybot.log.level
|
|
|
|
conf.supybot.log.level.set(newLogLevel)
|
2004-01-20 01:21:15 +01:00
|
|
|
|
|
|
|
# Save the registry
|
|
|
|
if not filename:
|
|
|
|
filename = '%s.conf' % nick
|
|
|
|
registry.close(conf.supybot, filename)
|
2004-01-19 18:44:50 +01:00
|
|
|
|
2004-01-20 17:17:56 +01:00
|
|
|
# FIXME: Prevent some INFO messages from being printed when exiting
|
2004-01-19 18:44:50 +01:00
|
|
|
|
|
|
|
# Done!
|
2004-01-20 01:21:15 +01:00
|
|
|
output("""All done! Your new bot configuration is %s. If you're running
|
|
|
|
a *nix based OS, you can probably start your bot with the command line
|
2004-01-25 09:22:50 +01:00
|
|
|
"supybot %s". If you're not running a *nix or similar machine, you'll
|
2004-01-20 01:21:15 +01:00
|
|
|
just have to start it like you start all your other Python scripts.""" % \
|
|
|
|
(filename, filename))
|
2003-10-02 07:11:40 +02:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
try:
|
|
|
|
main()
|
|
|
|
except KeyboardInterrupt:
|
2004-01-19 18:44:50 +01:00
|
|
|
# We may still be using bold text when exiting during a prompt
|
2004-01-20 17:17:56 +01:00
|
|
|
if questions.useBold:
|
2004-01-19 18:44:50 +01:00
|
|
|
import ansi
|
|
|
|
print ansi.RESET
|
2003-10-21 08:22:41 +02:00
|
|
|
print
|
|
|
|
print
|
2004-01-19 18:44:50 +01:00
|
|
|
output("""Well, it looks like you cancelled out of the wizard before
|
2003-10-19 22:32:28 +02:00
|
|
|
it was done. Unfortunately, I didn't get to write anything to file.
|
|
|
|
Please run the wizard again to completion.""")
|