diff --git a/scripts/supybot b/scripts/supybot new file mode 100755 index 000000000..b08a90920 --- /dev/null +++ b/scripts/supybot @@ -0,0 +1,175 @@ +#!/usr/bin/env python + +### +# Copyright (c) 2003, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +""" +This is the main program to run Supybot. +""" + +__revision__ = "$Id$" + +import re +import os +import sys + +if sys.version_info < (2, 3, 0): + sys.stderr.write('This program requires Python >= 2.3.0\n') + sys.exit(-1) + +if os.name == 'posix': + if os.getuid() == 0 or os.geteuid() == 0: + sys.stderr.write('Dude, don\'t even try to run this as root.\n') + sys.exit(-1) + +import time +import optparse + +started = time.time() + +import supybot +import registry + +def main(): + import conf + import world + import drivers + import schedule + schedule.addPeriodicEvent(world.upkeep, 300) + world.startedAt = started + try: + try: + while world.ircs: + drivers.run() + log.info('No more Irc objects, exiting.') + except KeyboardInterrupt: + log.info('Exiting due to Ctrl-C.') + raise SystemExit, 'Goodbye!' + except: + log.exception('Exception raised out of drivers.run:') + finally: + registry.close(conf.supybot, args[0]) + +if __name__ == '__main__': + ### + # Options: + # -p (profiling) + # -O (optimizing) + # -n, --nick (nick) + # -s, --server (server) + # --startup (commands to run onStart) + # --connect (commands to run afterConnect) + # --config (configuration values) + parser = optparse.OptionParser(usage='Usage: %prog [options] configFile', + version='supybot 0.76.1') + parser.add_option('-P', '--profile', action='store_true', dest='profile', + help='enables profiling') + parser.add_option('-O', action='count', dest='optimize', + help='-O optimizes asserts out of the code; ' \ + '-OO optimizes asserts and uses psyco.') + parser.add_option('-n', '--nick', action='store', + dest='nick', default='', + help='nick the bot should use') + parser.add_option('-s', '--server', action='store', + dest='server', default='', + help='server to connect to') + parser.add_option('-u', '--user', action='store', + dest='user', default='', + help='full username the bot should use') + parser.add_option('-i', '--ident', action='store', + dest='ident', default='', + help='ident the bot should use') + parser.add_option('-p', '--password', action='store', + dest='password', default='', + help='server password the bot should use') + + (options, args) = parser.parse_args() + + if not args or len(args) > 1: + parser.error() + + try: + registry.open(args[0]) + except registry.InvalidRegistryFile, e: + sys.stderr.write(str(e)) + sys.stderr.write('\n') + sys.exit(-1) + + import log + import conf + + nick = options.nick or conf.supybot.nick.get() + user = options.user or conf.supybot.user.get() + ident = options.ident or conf.supybot.ident.get() + password = options.password or conf.supybot.password.get() + + server = options.server or conf.supybot.server.get() + if ':' in server: + serverAndPort = server.split(':', 1) + serverAndPort[1] = int(serverAndPort[1]) + server = tuple(serverAndPort) + else: + server = (server, 6667) + + if options.optimize: + __builtins__.__debug__ = False + if options.optimize > 1: + try: + import psyco + psyco.full() + except ImportError: + log.warning('Psyco isn\'t installed, cannot -OO.') + + if not os.path.exists(conf.supybot.directories.log.get()): + os.mkdir(conf.supybot.directories.log.get()) + if not os.path.exists(conf.supybot.directories.conf.get()): + os.mkdir(conf.supybot.directories.conf.get()) + if not os.path.exists(conf.supybot.directories.data.get()): + os.mkdir(conf.supybot.directories.data.get()) + + import irclib + import ircmsgs + import drivers + import callbacks + import Owner + + irc = irclib.Irc(nick, user, ident, password) + callback = Owner.Class() + irc.addCallback(callback) + driver = drivers.newDriver(server, irc) + + if options.profile: + import profile + profile.run('main()', '%s-%i.prof' % (nick, time.time())) + else: + main() + + + +# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: diff --git a/src/Config.py b/src/Config.py new file mode 100644 index 000000000..e35198995 --- /dev/null +++ b/src/Config.py @@ -0,0 +1,149 @@ +#!/usr/bin/python + +### +# Copyright (c) 2002, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +""" +Handles configuration of the bot while it's running. +""" + +import plugins + +import conf +import utils +import registry +import privmsgs +import callbacks + +### +# Now, to setup the registry. +### +import registry + +class InvalidRegistryName(callbacks.Error): + pass + +def getWrapper(name): + parts = name.split() + if not parts or parts[0] != 'supybot': + raise InvalidRegistryName, name + group = conf.supybot + parts.pop(0) + while parts: + try: + group = getattr(group, parts.pop(0)) + except registry.NonExistentRegistryEntry: + raise InvalidRegistryName, name + return group + + +class Config(callbacks.Privmsg): + def callCommand(self, method, irc, msg, *L): + try: + callbacks.Privmsg.callCommand(method, irc, msg, *L) + except InvalidRegistryName, e: + irc.error('%r is not a valid configuration variable.' % e) + except registry.InvalidRegistryValue, e: + irc.error(str(e)) + + def list(self, irc, msg, args): + """ + + Returns the configuration variables available under the given + configuration . + """ + name = privmsgs.getArgs(args) + group = getWrapper(name) + if hasattr(group, 'getValues'): + L = zip(*group.getValues())[0] + irc.reply(utils.commaAndify(L)) + else: + irc.error('%r is not a valid configuration group.' % name) + + def get(self, irc, msg, args): + """ + + Shows the current value of the configuration variable . + """ + name = privmsgs.getArgs(args) + wrapper = getWrapper(name) + irc.reply(str(wrapper)) + + def set(self, irc, msg, args): + """ + + Sets the current value of the configuration variable to . + """ + (name, value) = privmsgs.getArgs(args, required=2) + wrapper = getWrapper(name) + wrapper.set(value) + irc.replySuccess() + + def help(self, irc, msg, args): + """ + + Returns the description of the configuration variable . + """ + name = privmsgs.getArgs(args) + wrapper = getWrapper(name) + irc.reply(msg, wrapper.help) + + def reset(self, irc, msg, args): + """ + + Resets the configuration variable to its original value. + """ + name = privmsgs.getArgs(args) + wrapper = getWrapper(name) + wrapper.reset() + irc.replySuccess() + + def default(self, irc, msg, args): + """ + + Returns the default value of the configuration variable . + """ + name = privmsgs.getArgs(args) + wrapper = getWrapper(name) + irc.reply(wrapper.default) + + def flush(self, irc, msg, args): + """ + + Flushes the current registry to the file given. + """ + filename = privmsgs.getArgs(args) + registry.close(conf.supybot, filename) + irc.replySuccess() + flush = privmsgs.checkCapability(flush, 'owner') + + +Class = Config + +# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: