diff --git a/plugins/MegaHAL/README.txt b/plugins/MegaHAL/README.txt
deleted file mode 100644
index d60b47a97..000000000
--- a/plugins/MegaHAL/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-Insert a description of your plugin here, with any notes, etc. about using it.
diff --git a/plugins/MegaHAL/__init__.py b/plugins/MegaHAL/__init__.py
deleted file mode 100644
index 6802d6d2c..000000000
--- a/plugins/MegaHAL/__init__.py
+++ /dev/null
@@ -1,67 +0,0 @@
-###
-# Copyright (c) 2010, Valentin Lorentz
-# 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 plugins provides a MegaHAL integration for Supybot.
-MegaHAL must be installed ('apt-get install megahal' on Debian)
-"""
-
-import supybot
-import supybot.world as world
-
-# Use this for the version of this plugin. You may wish to put a CVS keyword
-# in here if you're keeping the plugin in CVS or some similar system.
-__version__ = ""
-
-# XXX Replace this with an appropriate author or supybot.Author instance.
-__author__ = supybot.Author('Valentin Lorentz', 'ProgVal',
- 'progval@gmail.com')
-
-# This is a dictionary mapping supybot.Author instances to lists of
-# contributions.
-__contributors__ = {}
-
-# This is a url where the most recent plugin package can be downloaded.
-__url__ = '' # 'http://supybot.com/Members/yourname/MegaHAL/download'
-
-import config
-import plugin
-reload(plugin) # In case we're being reloaded.
-# Add more reloads here if you add third-party modules and want them to be
-# reloaded when this plugin is reloaded. Don't forget to import them as well!
-
-if world.testing:
- import test
-
-Class = plugin.Class
-configure = config.configure
-
-
-# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
diff --git a/plugins/MegaHAL/config.py b/plugins/MegaHAL/config.py
deleted file mode 100644
index 19f4e84c9..000000000
--- a/plugins/MegaHAL/config.py
+++ /dev/null
@@ -1,72 +0,0 @@
-###
-# Copyright (c) 2010, Valentin Lorentz
-# 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.
-
-###
-
-import supybot.conf as conf
-import supybot.registry as registry
-try:
- from supybot.i18n import PluginInternationalization
- from supybot.i18n import internationalizeDocstring
- _ = PluginInternationalization('MegaHAL')
-except:
- _ = lambda x:x
- internationalizeDocstring = lambda x:x
-
-def configure(advanced):
- # This will be called by supybot to configure this module. advanced is
- # a bool that specifies whether the user identified himself as an advanced
- # user or not. You should effect your configuration by manipulating the
- # registry as appropriate.
- from supybot.questions import expect, anything, something, yn
- conf.registerPlugin('MegaHAL', True)
-
-
-MegaHAL = conf.registerPlugin('MegaHAL')
-# This is where your configuration variables (if any) should go. For example:
-# conf.registerGlobalValue(MegaHAL, 'someConfigVariableName',
-# registry.Boolean(False, """Help for someConfigVariableName."""))
-
-conf.registerGroup(MegaHAL, 'learn')
-conf.registerGlobalValue(MegaHAL.learn, 'commands',
- registry.Boolean(False, _("""Determines whether the bot answers to messages
- beginning by a non-alphanumeric char.""")))
-conf.registerGroup(MegaHAL, 'answer')
-conf.registerChannelValue(MegaHAL.answer, 'commands',
- registry.Boolean(False, _("""Determines whether messages beginning by a
- non-alphanumeric char are learned.""")))
-conf.registerChannelValue(MegaHAL.answer, 'probability',
- registry.Integer(10, _("""Determines the percent of messages the bot will
- answer (zero is recommended if you have a tiny database).""")))
-conf.registerChannelValue(MegaHAL.answer, 'probabilityWhenAddressed',
- registry.Integer(100, _("""Determines the percent of messages adressed to
- the bot the bot will answer.""")))
-
-
-
-# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
diff --git a/plugins/MegaHAL/plugin.py b/plugins/MegaHAL/plugin.py
deleted file mode 100644
index 1889947fe..000000000
--- a/plugins/MegaHAL/plugin.py
+++ /dev/null
@@ -1,155 +0,0 @@
-###
-# Copyright (c) 2010, Valentin Lorentz
-# 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.
-
-###
-
-import re
-import os
-import sys
-import random
-import supybot.conf as conf
-import supybot.utils as utils
-from cStringIO import StringIO
-from supybot.commands import *
-import supybot.plugins as plugins
-import supybot.ircutils as ircutils
-import supybot.callbacks as callbacks
-
-try:
- import mh_python as megahal
-except ImportError:
- raise callbacks.Error, 'You need to have MegaHAL installed to use this ' \
- 'plugin. Download it at ' \
- '' \
- 'or with '
-
-try:
- from supybot.i18n import PluginInternationalization
- from supybot.i18n import internationalizeDocstring
- _ = PluginInternationalization('MegaHAL')
-except:
- # This are useless function that's allow to run the plugin on a bot
- # without the i18n plugin
- _ = lambda x:x
- internationalizeDocstring = lambda x:x
-
-class MegaHAL(callbacks.Plugin):
- """This plugins provides a MegaHAL integration for Supybot.
- MegaHAL must be installed ('apt-get install megahal' on Debian)"""
- callAfter = ['MoobotFactoids', 'Factoids', 'Infobot']
- callBefore = ['Dunno']
-
- def __init__(self, irc):
- # Call Supybot's scripts
- self.__parent = super(MegaHAL, self)
- self.__parent.__init__(irc)
-
- # Save state
- saved = (sys.stdout, os.getcwd())
-
- # Create proxy for MegaHAL
- os.chdir(conf.supybot.directories.data())
- sys.stdout = StringIO()
-
- # Initialize MegaHAL
- megahal.initbrain()
-
- # Restore state
- sys.stdout, cwd = saved
- os.chdir(cwd)
-
- random.seed()
-
- _dontKnow = [
- 'I don\'t know enough to answer you yet!',
- 'I am utterly speechless!',
- 'I forgot what I was going to say!'
- ]
- _translations = {
- 'I don\'t know enough to answer you yet!':
- _('I don\'t know enough to answer you yet!'),
- 'I am utterly speechless!':
- _('I am utterly speechless!'),
- 'I forgot what I was going to say!':
- _('I forgot what I was going to say!'),
- }
-
- def _response(self, msg, prb, reply):
- if random.randint(0, 100) < prb:
- response = megahal.doreply(msg)
- if self._translations.has_key(response):
- response = self._translations[response]
- reply(response, prefixNick=False)
- else:
- megahal.learn(msg)
-
- def doPrivmsg(self, irc, msg):
- if not msg.args[0].startswith('#'): # It is a private message
- return
- message = msg.args[1]
-
- if message.startswith(irc.nick) or re.match('\W.*', message):
- # Managed by invalidCommand
- return
-
- probability = self.registryValue('answer.probability', msg.args[0])
- self._response(message, probability, irc.reply)
-
- def invalidCommand(self, irc, msg, tokens):
- if not msg.args[0].startswith('#'): # It is a private message
- # Actually, we would like to answer, but :
- # 1) It may be a mistyped identify command (or whatever)
- # 2) MegaHAL can't reply without learning
- return
- message = msg.args[1]
- usedToStartWithNick = False
- if message.startswith(message):
- parsed = re.match('(.+ |\W)?(?P\w.*)', message)
- message = parsed.group('message')
- usedToStartWithNick = True
- if self.registryValue('answer.commands') or usedToStartWithNick:
- print msg.args[0]
- self._response(message,
- self.registryValue('answer.probabilityWhenAddressed',
- msg.args[0]),
- irc.reply)
- elif self.registryValue('learn.commands'):
- megahal.learn(message)
-
- @internationalizeDocstring
- def cleanup(self, irc, msg, args):
- """takes no argument
-
- Saves MegaHAL brain to disk."""
- megahal.cleanup()
- irc.replySuccess()
-
-Class = MegaHAL
-
-
-# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
diff --git a/plugins/MegaHAL/test.py b/plugins/MegaHAL/test.py
deleted file mode 100644
index 6d4b075fd..000000000
--- a/plugins/MegaHAL/test.py
+++ /dev/null
@@ -1,43 +0,0 @@
-###
-# Copyright (c) 2010, Valentin Lorentz
-# 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.
-
-###
-
-from supybot.test import *
-
-class MegaHALTestCase(PluginTestCase):
- plugins = ('MegaHAL',)
-
- def testCleanup(self):
- self.assertNotError('cleanup')
-
- def testAnswer(self):
- self.assertNotRegexp('foo', '.*not a valid.*')
-
-
-# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
diff --git a/plugins/SupySandbox/README.txt b/plugins/SupySandbox/README.txt
deleted file mode 100644
index d60b47a97..000000000
--- a/plugins/SupySandbox/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-Insert a description of your plugin here, with any notes, etc. about using it.
diff --git a/plugins/SupySandbox/__init__.py b/plugins/SupySandbox/__init__.py
deleted file mode 100644
index 5e5a07162..000000000
--- a/plugins/SupySandbox/__init__.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf8 -*-
-###
-# Copyright (c) 2010, Valentin Lorentz
-# 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.
-
-###
-
-"""
-Ce plugin est un portage du robot IRC Fschfsch, servant à fournir un accès
-à la pysandbox sur IRC.
-"""
-
-import supybot
-import supybot.world as world
-
-# Use this for the version of this plugin. You may wish to put a CVS keyword
-# in here if you're keeping the plugin in CVS or some similar system.
-__version__ = "0.1"
-
-# XXX Replace this with an appropriate author or supybot.Author instance.
-__author__ = supybot.Author('Valentin Lorentz', 'ProgVal',
- 'progval@gmail.com')
-
-# This is a dictionary mapping supybot.Author instances to lists of
-# contributions.
-__contributors__ = {}
-
-# This is a url where the most recent plugin package can be downloaded.
-__url__ = 'http://supybot-fr.tk/SupySandbox'
-
-import config
-import plugin
-reload(plugin) # In case we're being reloaded.
-# Add more reloads here if you add third-party modules and want them to be
-# reloaded when this plugin is reloaded. Don't forget to import them as well!
-
-if world.testing:
- import test
-
-Class = plugin.Class
-configure = config.configure
-
-
-# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
diff --git a/plugins/SupySandbox/config.py b/plugins/SupySandbox/config.py
deleted file mode 100644
index 748065cad..000000000
--- a/plugins/SupySandbox/config.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- coding: utf8 -*-
-###
-# Copyright (c) 2010, Valentin Lorentz
-# 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.
-
-###
-
-import supybot.conf as conf
-import supybot.registry as registry
-
-def configure(advanced):
- # This will be called by supybot to configure this module. advanced is
- # a bool that specifies whether the user identified himself as an advanced
- # user or not. You should effect your configuration by manipulating the
- # registry as appropriate.
- from supybot.questions import expect, anything, something, yn
- conf.registerPlugin('SupySandbox', True)
-
-
-PySandbox = conf.registerPlugin('SupySandbox')
-# This is where your configuration variables (if any) should go. For example:
-# conf.registerGlobalValue(PySandbox, 'someConfigVariableName',
-# registry.Boolean(False, """Help for someConfigVariableName."""))
-
-
-# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
diff --git a/plugins/SupySandbox/local/__init__.py b/plugins/SupySandbox/local/__init__.py
deleted file mode 100644
index e86e97b86..000000000
--- a/plugins/SupySandbox/local/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# Stub so local is a module, used for third-party modules
diff --git a/plugins/SupySandbox/local/fschfsch.py b/plugins/SupySandbox/local/fschfsch.py
deleted file mode 100644
index 20872fae6..000000000
--- a/plugins/SupySandbox/local/fschfsch.py
+++ /dev/null
@@ -1,279 +0,0 @@
-#!/usr/bin/env python
-# this file is under the WTFPLv2 [http://sam.zoy.org/wtfpl]
-# v1: 2010/05/23
-# Author: Tila
-
-# You need a configuration file: ~/.fschfsch.py. Config example:
-# ---
-# host = 'irc.freenode.net'
-# port = 7000
-# ssl = True
-# nickname = 'botnickname'
-# password = 'secret'
-# channels = ['##fschfsch', '#channel2', '#channel3']
-# texts = {'help': 'I am fschfsch, a robot snake that evals python code',
-# 'sandbox': "I am powered by setrlimit and pysandbox [http://github.com/haypo/pysandbox], I don't fear you"}
-# ---
-
-'''
-fschfsch is a Python-evaluating bot. fschfsch is pronounced "fssshh! fssshh!".
-'''
-
-IN_MAXLEN = 300 # bytes
-OUT_MAXLEN = 300 # bytes
-TIMEOUT = 3 # seconds
-
-EVAL_MAXTIMESECONDS = TIMEOUT
-EVAL_MAXMEMORYBYTES = 10 * 1024 * 1024 # 10 MiB
-
-
-try:
- import sandbox as S
-except ImportError:
- print 'You need pysandbox in order to run fschfsch [http://github.com/haypo/pysandbox].'
- raise
-try:
- import twisted
-except ImportError:
- print 'You need twisted in order to run fschfsch.'
- raise
-from twisted.internet.protocol import ReconnectingClientFactory
-from twisted.internet import ssl, reactor
-from twisted.words.im.ircsupport import IRCProto
-from twisted.words.protocols.irc import IRCClient
-# other imports
-import re
-import sys
-import os
-import resource as R
-import select
-import signal
-import time
-import threading
-import random
-
-def createSandboxConfig():
- cfg = S.SandboxConfig(
- 'stdout',
- 'stderr',
- 'regex',
- 'unicodedata', # flow wants u'\{ATOM SYMBOL}' :-)
- 'future',
- 'code',
- 'time',
- 'datetime',
- 'math',
- 'itertools',
- 'random',
- 'encodings',
- )
- cfg.allowModule('sys',
- 'version', 'hexversion', 'version_info')
- return cfg
-
-def _evalPython(line, locals):
- locals = dict(locals)
- try:
- if "\n" in line:
- raise SyntaxError()
- code = compile(line, "", "single")
- except SyntaxError:
- code = compile(line, "", "exec")
- exec code in locals
-
-def evalPython(line, locals=None):
- sandbox = S.Sandbox(config=createSandboxConfig())
-
- if locals is not None:
- locals = dict(locals)
- else:
- locals = dict()
- try:
- sandbox.call(_evalPython, line, locals)
- except BaseException, e:
- print 'Error: [%s] %s' % (e.__class__.__name__, str(e))
- except:
- print 'Error: '
- sys.stdout.flush()
-
-def childProcess(line, w, locals):
- # reseed after a fork to avoid generating the same sequence for each child
- random.seed()
-
- sys.stdout = sys.stderr = os.fdopen(w, 'w')
-
- R.setrlimit(R.RLIMIT_CPU, (EVAL_MAXTIMESECONDS, EVAL_MAXTIMESECONDS))
- R.setrlimit(R.RLIMIT_AS, (EVAL_MAXMEMORYBYTES, EVAL_MAXMEMORYBYTES))
- R.setrlimit(R.RLIMIT_NPROC, (0, 0)) # 0 forks
-
- evalPython(line, locals)
-
-def handleChild(childpid, r):
- txt = ''
- if any(select.select([r], [], [], TIMEOUT)):
- txt = os.read(r, OUT_MAXLEN + 1)
- os.close(r)
- if OUT_MAXLEN < len(txt):
- txt = txt[:OUT_MAXLEN] + '...'
-
- n = 0
- while n < 6:
- pid, status = os.waitpid(childpid, os.WNOHANG)
- if pid:
- break
- time.sleep(.5)
- n += 1
- if not pid:
- os.kill(childpid, signal.SIGKILL)
- return 'Timeout'
- elif os.WIFEXITED(status):
- txts = txt.rstrip().split('\n')
- if len(txts) > 1:
- txt = txts[0].rstrip() + ' [+ %d line(s)]' % (len(txts) - 1)
- else:
- txt = txts[0].rstrip()
- return 'Output: ' + txt
- elif os.WIFSIGNALED(status):
- return 'Killed'
-
-
-
-class EvalJob(threading.Thread):
- def __init__(self, line, irc, channel):
- super(EvalJob, self).__init__()
- self.line = line
- self.irc = irc
- self.channel = channel
-
- def run(self):
- output = self.handle_line(self.line)
- reactor.callFromThread(self.irc.say, self.channel, output)
- self.irc.executionLock.release()
-
- def handle_line(self, line):
- if IN_MAXLEN < len(line):
- return '(command is too long: %s bytes, the maximum is %s)' % (len(line), IN_MAXLEN)
-
- print("Process %s" % repr(line))
- r, w = os.pipe()
- childpid = os.fork()
- if not childpid:
- os.close(r)
- childProcess(line, w, self.irc.factory.morevars)
- os._exit(0)
- else:
- os.close(w)
- result = handleChild(childpid, r)
- print("=> %s" % repr(result))
- return result
-
-
-
-class EvalBot(IRCClient):
- versionName = 'fschfsch'
- versionNum = '0.1'
-
- #~ def __init__(self, *a, **k):
- def connectionMade(self):
- self.nickname = self.factory.nick
- self.password = self.factory.password
- self.talkre = re.compile('^%s[>:,] (.*)$' % self.nickname)
-
- self.executionLock = threading.Semaphore()
- self.pingSelfId = None
-
- IRCClient.connectionMade(self)
-
- def signedOn(self):
- self.pingSelfId = reactor.callLater(180, self.pingSelf)
- for chan in self.factory.channels:
- self.join(chan)
-
- def pingSelf(self):
- # used to avoid some timeouts where fschfsch does not reconnect
- self.ping(self.nickname)
- self.pingSelfId = reactor.callLater(180, self.pingSelf)
-
- def privmsg(self, user, channel, message):
- if self.pingSelfId is not None:
- self.pingSelfId.reset(180)
- if user.startswith('haypo') and message.startswith('exit'):
- os._exit(0)
- if not channel:
- return
- if not message.startswith(self.nickname):
- return
- if not self.talkre.match(message):
- return
- if not self.executionLock.acquire(blocking=False):
- return
-
- pyline = self.talkre.match(message).group(1)
- pyline = pyline.replace(' $$ ', '\n')
-
- self.handleThread = EvalJob(pyline, self, channel)
- self.handleThread.start()
-
-
-class MyFactory(ReconnectingClientFactory):
- def __init__(self, **kw):
- for k in kw:
- if k in ('nick', 'password', 'channels', 'morevars'):
- setattr(self, k, kw[k])
- protocol = EvalBot
-
-def check_output(expr, expected, locals=None):
- from cStringIO import StringIO
- original_stdout = sys.stdout
- try:
- output = StringIO()
- sys.stdout = output
- evalPython(expr, locals)
- stdout = output.getvalue()
- assert stdout == expected, "%r != %r" % (stdout, expected)
- finally:
- sys.stdout = original_stdout
-
-def runTests():
- # single
- check_output('1+1', '2\n')
- check_output('1; 2', '1\n2\n')
- check_output(
- # written in a single line
- "prime=lambda n,i=2:"
- "False if n%i==0 else prime(n,i+1) if i*i", "single")
- except SyntaxError:
- code = compile(line, "", "exec")
- exec code in locals
-
-def evalPython(line, locals=None):
- sandbox = S.Sandbox(config=createSandboxConfig())
-
- if locals is not None:
- locals = dict(locals)
- else:
- locals = dict()
- try:
- sandbox.call(_evalPython, line, locals)
- except BaseException, e:
- print 'Error: [%s] %s' % (e.__class__.__name__, str(e))
- except:
- print 'Error: '
- sys.stdout.flush()
-
-def check_output(expr, expected, locals=None):
- from cStringIO import StringIO
- original_stdout = sys.stdout
- try:
- output = StringIO()
- sys.stdout = output
- evalPython(expr, locals)
- stdout = output.getvalue()
- assert stdout == expected, "%r != %r" % (stdout, expected)
- finally:
- sys.stdout = original_stdout
-
-def runTests():
- # single
- check_output('1+1', '2\n')
- check_output('1; 2', '1\n2\n')
- check_output(
- # written in a single line
- "prime=lambda n,i=2:"
- "False if n%i==0 else prime(n,i+1) if i*i.*)')
- def sandbox(self, irc, msg, args):
- """
-
- Runs Python code safely thanks to pysandbox"""
- code = self._parser.match(msg.args[1]).group('code')
- irc.reply(handle_line(code.replace(' $$ ', '\n')))
-
- def runtests(self, irc, msg, args):
- irc.reply(runTests())
-
-
-Class = SupySandbox
-
-
-# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
diff --git a/plugins/SupySandbox/test.py b/plugins/SupySandbox/test.py
deleted file mode 100644
index abf415165..000000000
--- a/plugins/SupySandbox/test.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- coding: utf8 -*-
-###
-# Copyright (c) 2010, Valentin Lorentz
-# 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.
-
-###
-
-from supybot.test import *
-
-class SupySandboxTestCase(PluginTestCase):
- plugins = ('SupySandbox',)
-
- def testFschfschTestcase(self):
- self.assertResponse('runtests', 'True')
-
- def testCodeIsSuccessfullyRunned(self):
- self.assertResponse('sandbox 1+1', "2")
- self.assertResponse('sandbox print 1+1', "2")
- self.assertResponse('sandbox print \'toto\'', "toto")
-
- def testMultine(self):
- self.assertResponse('sandbox print 1; print 2', "'1\\n2'")
- self.assertResponse('sandbox print 1 $$ print 2', "'1\\n2'")
- self.assertResponse('sandbox toto=True $$ while toto: $$ print "foo"'
- ' $$ toto=False', "foo")
-
- def testProtections(self):
- #self.assertResponse('sandbox while True: print 1', "Timeout")
- pass
-
-
-# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: