Initial Release
This commit is contained in:
commit
d66203e1ea
|
@ -0,0 +1 @@
|
|||
Insert a description of your plugin here, with any notes, etc. about using it.
|
|
@ -0,0 +1,61 @@
|
|||
###
|
||||
# Copyright (c) 2005, Daniel DiPaolo
|
||||
# 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.
|
||||
###
|
||||
|
||||
"""
|
||||
Allows folks to talk through the bot anonymously.
|
||||
"""
|
||||
|
||||
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__ = "%%VERSION%%"
|
||||
|
||||
# XXX Replace this with an appropriate author or supybot.Author instance.
|
||||
__author__ = supybot.authors.strike
|
||||
|
||||
# This is a dictionary mapping supybot.Author instances to lists of
|
||||
# contributions.
|
||||
__contributors__ = {}
|
||||
|
||||
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 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,63 @@
|
|||
###
|
||||
# Copyright (c) 2005, Daniel DiPaolo
|
||||
# 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('Anonymous', True)
|
||||
|
||||
|
||||
Anonymous = conf.registerPlugin('Anonymous')
|
||||
# This is where your configuration variables (if any) should go. For example:
|
||||
# conf.registerGlobalValue(Anonymous, 'someConfigVariableName',
|
||||
# registry.Boolean(False, """Help for someConfigVariableName."""))
|
||||
conf.registerChannelValue(conf.supybot.plugins.Anonymous,
|
||||
'requirePresenceInChannel', registry.Boolean(True, """Determines whether
|
||||
the bot should require people trying to use this plugin to be in the
|
||||
channel they wish to anonymously send to."""))
|
||||
conf.registerGlobalValue(conf.supybot.plugins.Anonymous, 'requireRegistration',
|
||||
registry.Boolean(True, """Determines whether the bot should require people
|
||||
trying to use this plugin to be registered."""))
|
||||
conf.registerGlobalValue(conf.supybot.plugins.Anonymous, 'requireCapability',
|
||||
registry.String('', """Determines what capability (if any) the bot should
|
||||
require people trying to use this plugin to have."""))
|
||||
conf.registerGlobalValue(conf.supybot.plugins.Anonymous, 'allowPrivateTarget',
|
||||
registry.Boolean(False, """Determines whether the bot will require targets
|
||||
of the "say" command to be public (i.e., channels). If this is True, the
|
||||
bot will allow people to use the "say" command to send private messages to
|
||||
other users."""))
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,96 @@
|
|||
###
|
||||
# Copyright (c) 2005, Daniel DiPaolo
|
||||
# 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.ircdb as ircdb
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import supybot.callbacks as callbacks
|
||||
|
||||
class Anonymous(callbacks.Plugin):
|
||||
"""This plugin allows users to act through the bot anonymously. The 'do'
|
||||
command has the bot perform an anonymous action in a given channel, and
|
||||
the 'say' command allows other people to speak through the bot. Since
|
||||
this can be fairly well abused, you might want to set
|
||||
supybot.plugins.Anonymous.requireCapability so only users with that
|
||||
capability can use this plugin. For extra security, you can require that
|
||||
the user be *in* the channel they are trying to address anonymously with
|
||||
supybot.plugins.Anonymous.requirePresenceInChannel, or you can require
|
||||
that the user be registered by setting
|
||||
supybot.plugins.Anonymous.requireRegistration.
|
||||
"""
|
||||
def _preCheck(self, irc, msg, channel):
|
||||
if self.registryValue('requireRegistration'):
|
||||
try:
|
||||
_ = ircdb.users.getUser(msg.prefix)
|
||||
except KeyError:
|
||||
irc.errorNotRegistered(Raise=True)
|
||||
capability = self.registryValue('requireCapability')
|
||||
if capability:
|
||||
if not ircdb.checkCapability(msg.prefix, capability):
|
||||
irc.errorNoCapability(capability, Raise=True)
|
||||
if self.registryValue('requirePresenceInChannel', channel) and \
|
||||
msg.nick not in irc.state.channels[channel].users:
|
||||
irc.error(format('You must be in %s to %q in there.',
|
||||
channel, 'say'), Raise=True)
|
||||
c = ircdb.channels.getChannel(channel)
|
||||
if c.lobotomized:
|
||||
irc.error(format('I\'m lobotomized in %s.', channel), Raise=True)
|
||||
if not c._checkCapability(self.name()):
|
||||
irc.error('That channel has set its capabilities so as to '
|
||||
'disallow the use of this plugin.', Raise=True)
|
||||
|
||||
def say(self, irc, msg, args, channel, text):
|
||||
"""<channel> <text>
|
||||
|
||||
Sends <text> to <channel>.
|
||||
"""
|
||||
self._preCheck(irc, msg, channel)
|
||||
self.log.info('Saying %q in %s due to %s.',
|
||||
text, channel, msg.prefix)
|
||||
irc.queueMsg(ircmsgs.privmsg(channel, text))
|
||||
irc.noReply()
|
||||
say = wrap(say, ['inChannel', 'text'])
|
||||
|
||||
def do(self, irc, msg, args, channel, text):
|
||||
"""<channel> <action>
|
||||
|
||||
Performs <action> in <channel>.
|
||||
"""
|
||||
self._preCheck(irc, msg, channel)
|
||||
self.log.info('Performing %q in %s due to %s.',
|
||||
text, channel, msg.prefix)
|
||||
irc.queueMsg(ircmsgs.action(channel, text))
|
||||
irc.noReply()
|
||||
do = wrap(do, ['inChannel', 'text'])
|
||||
|
||||
Class = Anonymous
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,56 @@
|
|||
###
|
||||
# Copyright (c) 2005, Daniel DiPaolo
|
||||
# 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 AnonymousTestCase(ChannelPluginTestCase):
|
||||
plugins = ('Anonymous',)
|
||||
def testSay(self):
|
||||
m = self.assertError('anonymous say %s I love you!' % self.channel)
|
||||
try:
|
||||
orig = conf.supybot.plugins.Anonymous.requireRegistration()
|
||||
conf.supybot.plugins.Anonymous.requireRegistration.setValue(False)
|
||||
m = self.assertNotError('anonymous say %s foo!'%self.channel)
|
||||
self.failUnless(m.args[1] == 'foo!')
|
||||
finally:
|
||||
conf.supybot.plugins.Anonymous.requireRegistration.setValue(orig)
|
||||
|
||||
def testAction(self):
|
||||
m = self.assertError('anonymous do %s loves you!' % self.channel)
|
||||
try:
|
||||
orig = conf.supybot.plugins.Anonymous.requireRegistration()
|
||||
conf.supybot.plugins.Anonymous.requireRegistration.setValue(False)
|
||||
m = self.assertNotError('anonymous do %s loves you!'%self.channel)
|
||||
self.assertEqual(m.args, ircmsgs.action(self.channel,
|
||||
'loves you!').args)
|
||||
finally:
|
||||
conf.supybot.plugins.Anonymous.requireRegistration.setValue(orig)
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
|
@ -0,0 +1 @@
|
|||
Insert a description of your plugin here, with any notes, etc. about using it.
|
|
@ -0,0 +1,43 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
"""
|
||||
Add a description of the plugin (to be presented to the user inside the wizard)
|
||||
here. This should describe *what* the plugin does.
|
||||
"""
|
||||
|
||||
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.authors.unknown
|
||||
|
||||
# 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/Raumstatus/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.Flipdot
|
||||
configure = config.configure
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
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('Flipdot', True)
|
||||
|
||||
|
||||
Flipdot = conf.registerPlugin('Flipdot')
|
||||
# This is where your configuration variables (if any) should go. For example:
|
||||
conf.registerGlobalValue(Flipdot, 'host',
|
||||
registry.String("2001:67c:275c:a9::c", """Host of Flipdot"""))
|
||||
conf.registerGlobalValue(Flipdot, 'port',
|
||||
registry.Integer(2323, """Port number of Flipdot"""))
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,75 @@
|
|||
###
|
||||
# Copyright (c) 2011, henne
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
from threading import Event, Thread
|
||||
import subprocess
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.plugins as plugins
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.callbacks as callbacks
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import socket, time
|
||||
import Image, ImageFont, ImageDraw, sys
|
||||
import fileinput
|
||||
|
||||
class Flipdot(callbacks.Plugin):
|
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
def list2byte(l):
|
||||
byte = 0
|
||||
i = 0
|
||||
for i in range(8):
|
||||
byte += 2**(7-i) if l[i] else 0
|
||||
return byte
|
||||
|
||||
def array2packet(a):
|
||||
return str(bytearray([list2byte(a[i*8:i*8+8]) for i in range(len(a)/8)]))
|
||||
|
||||
def str2array(s):
|
||||
IMG_SIZE = (80,16)
|
||||
FONT_SIZE = 11
|
||||
FONT_OFFSET= (1, 3)
|
||||
|
||||
C_BLACK = (0, 0, 0)
|
||||
C_WHITE = (255, 255, 255)
|
||||
|
||||
image = Image.new("RGBA", IMG_SIZE, C_BLACK)
|
||||
draw = ImageDraw.Draw(image)
|
||||
draw.fontmode = "1" # No AA
|
||||
#font = ImageFont.load_default()
|
||||
font = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeSans.ttf", FONT_SIZE)
|
||||
|
||||
draw.text(FONT_OFFSET, s, font=font, fill=C_WHITE)
|
||||
|
||||
imgmap = []
|
||||
for pixel in image.getdata():
|
||||
r, g, b, a = pixel
|
||||
if r == 255:
|
||||
imgmap.append(1)
|
||||
else:
|
||||
imgmap.append(0)
|
||||
return imgmap
|
||||
|
||||
def __init__(self, irc):
|
||||
self.__parent = super(Flipdot, self)
|
||||
self.__parent.__init__(irc)
|
||||
# def __del__(self, irc):
|
||||
# ampel.connection.close()
|
||||
def start(self, irc, msg, args):
|
||||
irc.reply("Lampel kann nun gesteuert werden (noch nicht.....)")
|
||||
# ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
# ampel.connection.write("io get port 2\n")
|
||||
# buf = ampel.connection.read_until("\n", 1)
|
||||
# self.state = buf[-2]
|
||||
# irc.reply(self.state)
|
||||
start = wrap(start)
|
||||
def hilfe(self, irc, msg, args):
|
||||
irc.reply("hilfe: Hilft dir...")
|
||||
hilfe = wrap(hilfe)
|
||||
def send(self, irc, msg, args):
|
||||
sock.sendto(array2packet(str2array(msg.strip())), (self.registryValue('host'), self.registryValue('port')))
|
||||
send = wrap(send)
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,41 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
"""
|
||||
Add a description of the plugin (to be presented to the user inside the wizard)
|
||||
here. This should describe *what* the plugin does.
|
||||
"""
|
||||
|
||||
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.authors.unknown
|
||||
|
||||
# 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/Raumstatus/download'
|
||||
|
||||
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.Gem
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,35 @@
|
|||
###
|
||||
# Copyright (c) 2011, henne
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
from threading import Event, Thread
|
||||
import subprocess
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.plugins as plugins
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.callbacks as callbacks
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import random
|
||||
class Gem(callbacks.Plugin):
|
||||
gemActive = False
|
||||
def __init__(self, irc):
|
||||
self.__parent = super(Gem, self)
|
||||
self.__parent.__init__(irc)
|
||||
def gem(self, irc, msg, args):
|
||||
if self.gemActive:
|
||||
irc.reply("Gem Deactivated")
|
||||
else:
|
||||
c = random.randint(1,100)
|
||||
if c>99:
|
||||
irc.reply("Perfect Gem Activated")
|
||||
elif c>90:
|
||||
irc.reply("Mooooooooooooo!")
|
||||
else:
|
||||
irc.reply("Gem Activated")
|
||||
self.gemActive = not self.gemActive
|
||||
gem = wrap(gem)
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Insert a description of your plugin here, with any notes, etc. about using it.
|
|
@ -0,0 +1,43 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
"""
|
||||
Add a description of the plugin (to be presented to the user inside the wizard)
|
||||
here. This should describe *what* the plugin does.
|
||||
"""
|
||||
|
||||
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.authors.unknown
|
||||
|
||||
# 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/Raumstatus/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.Lampel
|
||||
configure = config.configure
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
import telnetlib
|
||||
connection = telnetlib.Telnet()
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
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('Lampel', True)
|
||||
|
||||
|
||||
Lampel = conf.registerPlugin('Lampel')
|
||||
# This is where your configuration variables (if any) should go. For example:
|
||||
conf.registerGlobalValue(Lampel, 'host',
|
||||
registry.String("lampel.raum.ctdo.de", """Host of Lampel"""))
|
||||
conf.registerGlobalValue(Lampel, 'port',
|
||||
registry.Integer(2701, """Port number of Lampel"""))
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,171 @@
|
|||
###
|
||||
# Copyright (c) 2011, henne
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
from threading import Event, Thread
|
||||
import subprocess
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.plugins as plugins
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.callbacks as callbacks
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import ampel
|
||||
import random
|
||||
import time
|
||||
class Lampel(callbacks.Plugin):
|
||||
# state = 00
|
||||
threaded = True
|
||||
discoan = False
|
||||
def __init__(self, irc):
|
||||
self.__parent = super(Lampel, self)
|
||||
self.__parent.__init__(irc)
|
||||
# def __del__(self, irc):
|
||||
# ampel.connection.close()
|
||||
def start(self, irc, msg, args):
|
||||
irc.reply("Lampel kann nun gesteuert werden (noch nicht.....)")
|
||||
# ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
# ampel.connection.write("io get port 2\n")
|
||||
# buf = ampel.connection.read_until("\n", 1)
|
||||
# self.state = buf[-2]
|
||||
# irc.reply(self.state)
|
||||
start = wrap(start)
|
||||
def rot(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 04\n")
|
||||
ampel.connection.close()
|
||||
rot = wrap(rot)
|
||||
red = wrap(rot)
|
||||
def gelb(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 02\n")
|
||||
ampel.connection.close()
|
||||
gelb = wrap(gelb)
|
||||
yellow = wrap(gelb)
|
||||
def gruen(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 01\n")
|
||||
ampel.connection.close()
|
||||
gruen = wrap(gruen)
|
||||
green = wrap(gruen)
|
||||
def rotgelbgruen(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 07\n")
|
||||
ampel.connection.close()
|
||||
rotgelbgruen = wrap(rotgelbgruen)
|
||||
allcolors = wrap(rotgelbgruen)
|
||||
allefarben = wrap(rotgelbgruen)
|
||||
alle = wrap(rotgelbgruen)
|
||||
def rotgelb(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 06\n")
|
||||
ampel.connection.close()
|
||||
rotgelb = wrap(rotgelb)
|
||||
gelbrot = wrap(rotgelb)
|
||||
redyellow = wrap(rotgelb)
|
||||
yellowred = wrap(rotgelb)
|
||||
def rotgruen(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 05\n")
|
||||
ampel.connection.close()
|
||||
rotgruen = wrap(rotgruen)
|
||||
redgreen = wrap(rotgruen)
|
||||
gruenrot = wrap(rotgruen)
|
||||
greenred = wrap(rotgruen)
|
||||
def gelbgruen(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 03\n")
|
||||
ampel.connection.close()
|
||||
gelbgruen = wrap(gelbgruen)
|
||||
yellowgreen = wrap(gelbgruen)
|
||||
gruengelb = wrap(gelbgruen)
|
||||
greenyellow = wrap(gelbgruen)
|
||||
def aus(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 00\n")
|
||||
ampel.connection.close()
|
||||
aus = wrap(aus)
|
||||
off = wrap(aus)
|
||||
def hilfe(self, irc, msg, args):
|
||||
irc.reply("Help for the Lampelcontrol")
|
||||
irc.reply("rot: Nur rot an (oder red)")
|
||||
irc.reply("gelb: Nur gelb an (oder yellow)")
|
||||
irc.reply("gruen: Nur gruen an (oder gruen)")
|
||||
irc.reply("rotgelb: Rot und Gelb an (oder gelbrot, redyellow, yellowred)")
|
||||
irc.reply("rotgruen: Rot und Gruen an (oder gruenrot, greenred, redgreen)")
|
||||
irc.reply("gelbgruen: Gelb und Gruen an (oder gruengelb, greenyellow, yellowgreen)")
|
||||
irc.reply("rotgelbgruen: alle an (oder alle, allefarben, allcolors)")
|
||||
irc.reply("aus: alle aus (oder off)")
|
||||
irc.reply("hilfe: Hilft dir...")
|
||||
|
||||
hilfe = wrap(hilfe)
|
||||
def ampelaus(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
for i in range(1, 5):
|
||||
ampel.connection.write("io set port 2 00\n")
|
||||
time.sleep(1)
|
||||
ampel.connection.write("io set port 2 02\n")
|
||||
time.sleep(1)
|
||||
ampel.connection.close()
|
||||
def moo(self, irc, msg, args):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 00\n")
|
||||
time.sleep(1)
|
||||
ampel.connection.write("io set port 2 01\n")
|
||||
time.sleep(1)
|
||||
ampel.connection.write("io set port 2 02\n")
|
||||
time.sleep(1)
|
||||
ampel.connection.write("io set port 2 04\n")
|
||||
time.sleep(1)
|
||||
ampel.connection.write("io set port 2 00\n")
|
||||
ampel.connection.close()
|
||||
moo = wrap(moo)
|
||||
def disco(self, irc, msg, args):
|
||||
if not self.discoan:
|
||||
irc.reply("And the Party begins")
|
||||
self.discoTimer = meinTimer(2, self.discof, 0, [irc])
|
||||
self.discoTimer.daemon = True
|
||||
self.discoan = True
|
||||
self.discoTimer.start()
|
||||
else:
|
||||
irc.reply("The Party is over")
|
||||
self.discoTimer.cancel()
|
||||
self.discoan = False
|
||||
disco = wrap(disco)
|
||||
def discof(self, irc):
|
||||
ampel.connection.open(self.registryValue('host'), self.registryValue('port'))
|
||||
ampel.connection.write("io set port 2 0" + str(random.randint(0, 7)) + "\n")
|
||||
# ampel.connection.write("io set port 2 01\n")
|
||||
ampel.connection.close()
|
||||
# def getState(self, irc, msg, args):
|
||||
# ampel.connection.write("io get port 2\n")
|
||||
# buf = ampel.connection.read_until("\n", 1)
|
||||
# self.state = buf[-2]
|
||||
# irc.reply(buf)
|
||||
# getstate = wrap(getState)
|
||||
|
||||
|
||||
class meinTimer(Thread):
|
||||
def __init__(self, interval, function, iterations=0, args=[], kwargs={}):
|
||||
Thread.__init__(self)
|
||||
self.interval = interval
|
||||
self.function = function
|
||||
self.iterations = iterations
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.finished = Event()
|
||||
|
||||
def run(self):
|
||||
count = 0
|
||||
while not self.finished.isSet() and (self.iterations <= 0 or count < self.iterations):
|
||||
self.finished.wait(self.interval)
|
||||
if not self.finished.isSet():
|
||||
self.function(*self.args, **self.kwargs)
|
||||
count += 1
|
||||
|
||||
def cancel(self):
|
||||
self.finished.set()
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Insert a description of your plugin here, with any notes, etc. about using it.
|
|
@ -0,0 +1,43 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
"""
|
||||
Add a description of the plugin (to be presented to the user inside the wizard)
|
||||
here. This should describe *what* the plugin does.
|
||||
"""
|
||||
|
||||
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.authors.unknown
|
||||
|
||||
# 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/Raumstatus/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:
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
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('Raumstatus', True)
|
||||
|
||||
|
||||
Raumstatus = conf.registerPlugin('Raumstatus')
|
||||
# This is where your configuration variables (if any) should go. For example:
|
||||
conf.registerGlobalValue(Raumstatus, 'target',
|
||||
registry.String("switch2.raum.chaostreff-dortmund.de", """IP Address to ping."""))
|
||||
conf.registerGlobalValue(Raumstatus, 'interval',
|
||||
registry.Integer(30, """Checking interval."""))
|
||||
conf.registerGlobalValue(Raumstatus, 'channel',
|
||||
registry.String("#ccc.do", """Channel to set topic."""))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
# Stub so local is a module, used for third-party modules
|
|
@ -0,0 +1,100 @@
|
|||
###
|
||||
# Copyright (c) 2011, xleave
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
from threading import Event, Thread
|
||||
import subprocess
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.plugins as plugins
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.callbacks as callbacks
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import re
|
||||
|
||||
raum_in_str = re.compile(".*(raum:|r:).*", re.I).match
|
||||
raumstatus_is_open = re.compile("(raum: |r: )(auf|offen|open)", re.I).match
|
||||
raumstatus_is_closed = re.compile("(raum: |r: )(zu|geschlossen|closed)", re.I).match
|
||||
raumstatus_replace = re.compile("((raum: |r: ))[^ ]*", re.I).sub
|
||||
|
||||
class Raumstatus(callbacks.Plugin):
|
||||
threaded = True
|
||||
foo = "2"
|
||||
def __init__(self, irc):
|
||||
self.__parent = super(Raumstatus, self)
|
||||
self.__parent.__init__(irc)
|
||||
self.meinTimer = RepeatTimer(2, self.Bla, 0, [irc])
|
||||
self.meinTimer.daemon = True
|
||||
def start(self, irc, msg, args):
|
||||
irc.reply("starting timer")
|
||||
self.meinTimer.start()
|
||||
irc.reply("MUST DESTROY UNIVERSE!!!")
|
||||
start = wrap(start)
|
||||
|
||||
def stop(self, irc, msg, args):
|
||||
irc.reply("stopping timer")
|
||||
self.meinTimer.cancel()
|
||||
irc.reply("FUCKED")
|
||||
stop = wrap(stop)
|
||||
|
||||
def Bla(self, irc):
|
||||
c = currentTopic = irc.state.getTopic(self.registryValue('channel'))
|
||||
# import pdb;pdb.set_trace()
|
||||
# c = currentTopic = irc.state.channels["#ccc.do"].topic
|
||||
|
||||
# raise Exception("%s %s %s %s"%("fuck you", type(c), dir(c), c))
|
||||
# print "blabla %s " % self.registryValue('target')
|
||||
ret = subprocess.call("ping -c6 -i .2 %s" % self.registryValue('target'),
|
||||
shell=True,
|
||||
stdout=open('/dev/null','w'),
|
||||
stderr=subprocess.STDOUT)
|
||||
x = raum_in_str(c)
|
||||
if ret == 0:
|
||||
if not x:
|
||||
currentTopic = "Raum: auf | %s"%currentTopic
|
||||
else:
|
||||
if not raumstatus_is_open(currentTopic):
|
||||
currentTopic = raumstatus_replace('\\1auf', currentTopic)
|
||||
|
||||
else:
|
||||
if not x:
|
||||
currentTopic = "Raum: zu | %s"%currentTopic
|
||||
else:
|
||||
if not raumstatus_is_closed(currentTopic):
|
||||
currentTopic = raumstatus_replace('\\1zu', currentTopic)
|
||||
|
||||
if c != currentTopic:
|
||||
irc.queueMsg(ircmsgs.topic(self.registryValue('channel'), currentTopic[:159]))
|
||||
# irc.sendMsg(ircmsgs.privmsg("#ccc.do", "reset topic"))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class RepeatTimer(Thread):
|
||||
def __init__(self, interval, function, iterations=0, args=[], kwargs={}):
|
||||
Thread.__init__(self)
|
||||
self.interval = interval
|
||||
self.function = function
|
||||
self.iterations = iterations
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.finished = Event()
|
||||
|
||||
def run(self):
|
||||
count = 0
|
||||
while not self.finished.isSet() and (self.iterations <= 0 or count < self.iterations):
|
||||
self.finished.wait(self.interval)
|
||||
if not self.finished.isSet():
|
||||
self.function(*self.args, **self.kwargs)
|
||||
count += 1
|
||||
|
||||
def cancel(self):
|
||||
self.finished.set()
|
||||
|
||||
Class = Raumstatus
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
|||
###
|
||||
# Copyright (c) 2011, Fuck You
|
||||
# All rights reserved.
|
||||
#
|
||||
#
|
||||
###
|
||||
|
||||
from supybot.test import *
|
||||
|
||||
class RaumstatusTestCase(PluginTestCase):
|
||||
plugins = ('Raumstatus',)
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
|
@ -0,0 +1,58 @@
|
|||
###
|
||||
# Copyright (c) 2005, 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.
|
||||
###
|
||||
|
||||
"""
|
||||
Includes various web-related commands.
|
||||
"""
|
||||
|
||||
import supybot
|
||||
import supybot.world as world
|
||||
|
||||
__version__ = "%%VERSION%%"
|
||||
|
||||
__author__ = supybot.authors.jemfinch
|
||||
|
||||
# This is a dictionary mapping supybot.Author instances to lists of
|
||||
# contributions.
|
||||
__contributors__ = {}
|
||||
|
||||
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 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,61 @@
|
|||
###
|
||||
# Copyright (c) 2005, 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.
|
||||
###
|
||||
|
||||
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
|
||||
Web = conf.registerPlugin('Web', True)
|
||||
if yn("""This plugin also offers a snarfer that will try to fetch the
|
||||
title of URLs that it sees in the channel. Would like you this
|
||||
snarfer to be enabled?""", default=False):
|
||||
Web.titleSnarfer.setValue(True)
|
||||
|
||||
|
||||
Web = conf.registerPlugin('Web')
|
||||
conf.registerChannelValue(Web, 'titleSnarfer',
|
||||
registry.Boolean(False, """Determines whether the bot will output the HTML
|
||||
title of URLs it sees in the channel."""))
|
||||
conf.registerChannelValue(Web, 'nonSnarfingRegexp',
|
||||
registry.Regexp(None, """Determines what URLs are to be snarfed and stored
|
||||
in the database in the channel; URLs matching the regexp given will not be
|
||||
snarfed. Give the empty string if you have no URLs that you'd like to
|
||||
exclude from being snarfed."""))
|
||||
|
||||
conf.registerGroup(Web, 'fetch')
|
||||
conf.registerGlobalValue(Web.fetch, 'maximum',
|
||||
registry.NonNegativeInteger(0, """Determines the maximum number of
|
||||
bytes the bot will download via the 'fetch' command in this plugin."""))
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,244 @@
|
|||
###
|
||||
# Copyright (c) 2005, 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.
|
||||
###
|
||||
|
||||
import re
|
||||
import HTMLParser
|
||||
import htmlentitydefs
|
||||
|
||||
import supybot.conf as conf
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.plugins as plugins
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.callbacks as callbacks
|
||||
|
||||
class Title(HTMLParser.HTMLParser):
|
||||
entitydefs = htmlentitydefs.entitydefs.copy()
|
||||
entitydefs['nbsp'] = ' '
|
||||
entitydefs['apos'] = '\''
|
||||
def __init__(self):
|
||||
self.inTitle = False
|
||||
self.title = ''
|
||||
HTMLParser.HTMLParser.__init__(self)
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag == 'title':
|
||||
self.inTitle = True
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
if tag == 'title':
|
||||
self.inTitle = False
|
||||
|
||||
def handle_data(self, data):
|
||||
if self.inTitle:
|
||||
self.title += data
|
||||
|
||||
def handle_entityref(self, name):
|
||||
if self.inTitle:
|
||||
if name in self.entitydefs:
|
||||
self.title += self.entitydefs[name]
|
||||
|
||||
class Web(callbacks.PluginRegexp):
|
||||
"""Add the help for "@help Web" here."""
|
||||
threaded = True
|
||||
regexps = ['titleSnarfer']
|
||||
def callCommand(self, command, irc, msg, *args, **kwargs):
|
||||
try:
|
||||
super(Web, self).callCommand(command, irc, msg, *args, **kwargs)
|
||||
except utils.web.Error, e:
|
||||
irc.reply(str(e))
|
||||
|
||||
def titleSnarfer(self, irc, msg, match):
|
||||
r"https?://[^\])>\s]+"
|
||||
channel = msg.args[0]
|
||||
if not irc.isChannel(channel):
|
||||
return
|
||||
if callbacks.addressed(irc.nick, msg):
|
||||
return
|
||||
if self.registryValue('titleSnarfer', channel):
|
||||
url = match.group(0)
|
||||
r = self.registryValue('nonSnarfingRegexp', channel)
|
||||
if r and r.search(url):
|
||||
self.log.debug('Not titleSnarfing %q.', url)
|
||||
return
|
||||
try:
|
||||
size = conf.supybot.protocols.http.peekSize()
|
||||
text = utils.web.getUrl(url, size=size)
|
||||
except utils.web.Error, e:
|
||||
self.log.info('Couldn\'t snarf title of %u: %s.', url, e)
|
||||
return
|
||||
parser = Title()
|
||||
try:
|
||||
parser.feed(text)
|
||||
except HTMLParser.HTMLParseError:
|
||||
self.log.debug('Encountered a problem parsing %u. Title may '
|
||||
'already be set, though', url)
|
||||
if parser.title:
|
||||
domain = utils.web.getDomain(url)
|
||||
title = utils.web.htmlToText(parser.title.strip())
|
||||
s = format('Title: %s (at %s)', title, domain)
|
||||
irc.reply(s, prefixNick=False)
|
||||
titleSnarfer = urlSnarfer(titleSnarfer)
|
||||
|
||||
def headers(self, irc, msg, args, url):
|
||||
"""<url>
|
||||
|
||||
Returns the HTTP headers of <url>. Only HTTP urls are valid, of
|
||||
course.
|
||||
"""
|
||||
fd = utils.web.getUrlFd(url)
|
||||
try:
|
||||
s = ', '.join([format('%s: %s', k, v)
|
||||
for (k, v) in fd.headers.items()])
|
||||
irc.reply(s)
|
||||
finally:
|
||||
fd.close()
|
||||
headers = wrap(headers, ['httpUrl'])
|
||||
|
||||
_doctypeRe = re.compile(r'(<!DOCTYPE[^>]+>)', re.M)
|
||||
def doctype(self, irc, msg, args, url):
|
||||
"""<url>
|
||||
|
||||
Returns the DOCTYPE string of <url>. Only HTTP urls are valid, of
|
||||
course.
|
||||
"""
|
||||
size = conf.supybot.protocols.http.peekSize()
|
||||
s = utils.web.getUrl(url, size=size)
|
||||
m = self._doctypeRe.search(s)
|
||||
if m:
|
||||
s = utils.str.normalizeWhitespace(m.group(0))
|
||||
irc.reply(s)
|
||||
else:
|
||||
irc.reply('That URL has no specified doctype.')
|
||||
doctype = wrap(doctype, ['httpUrl'])
|
||||
|
||||
def size(self, irc, msg, args, url):
|
||||
"""<url>
|
||||
|
||||
Returns the Content-Length header of <url>. Only HTTP urls are valid,
|
||||
of course.
|
||||
"""
|
||||
fd = utils.web.getUrlFd(url)
|
||||
try:
|
||||
try:
|
||||
size = fd.headers['Content-Length']
|
||||
irc.reply(format('%u is %i bytes long.', url, size))
|
||||
except KeyError:
|
||||
size = conf.supybot.protocols.http.peekSize()
|
||||
s = fd.read(size)
|
||||
if len(s) != size:
|
||||
irc.reply(format('%u is %i bytes long.', url, len(s)))
|
||||
else:
|
||||
irc.reply(format('The server didn\'t tell me how long %u '
|
||||
'is but it\'s longer than %i bytes.',
|
||||
url, size))
|
||||
finally:
|
||||
fd.close()
|
||||
size = wrap(size, ['httpUrl'])
|
||||
|
||||
def title(self, irc, msg, args, url):
|
||||
"""<url>
|
||||
|
||||
Returns the HTML <title>...</title> of a URL.
|
||||
"""
|
||||
size = conf.supybot.protocols.http.peekSize()
|
||||
text = utils.web.getUrl(url, size=size)
|
||||
parser = Title()
|
||||
try:
|
||||
parser.feed(text)
|
||||
except HTMLParser.HTMLParseError:
|
||||
self.log.debug('Encountered a problem parsing %u. Title may '
|
||||
'already be set, though', url)
|
||||
if parser.title:
|
||||
irc.reply(utils.web.htmlToText(parser.title.strip()))
|
||||
elif len(text) < size:
|
||||
irc.reply('That URL appears to have no HTML title.')
|
||||
else:
|
||||
irc.reply(format('That URL appears to have no HTML title '
|
||||
'within the first %i bytes.', size))
|
||||
title = wrap(title, ['httpUrl'])
|
||||
|
||||
_netcraftre = re.compile(r'td align="left">\s+<a[^>]+>(.*?)<a href',
|
||||
re.S | re.I)
|
||||
def netcraft(self, irc, msg, args, hostname):
|
||||
"""<hostname|ip>
|
||||
|
||||
Returns Netcraft.com's determination of what operating system and
|
||||
webserver is running on the host given.
|
||||
"""
|
||||
url = 'http://uptime.netcraft.com/up/graph/?host=' + hostname
|
||||
html = utils.web.getUrl(url)
|
||||
m = self._netcraftre.search(html)
|
||||
if m:
|
||||
html = m.group(1)
|
||||
s = utils.web.htmlToText(html, tagReplace='').strip()
|
||||
s = s.rstrip('-').strip()
|
||||
irc.reply(s) # Snip off "the site"
|
||||
elif 'We could not get any results' in html:
|
||||
irc.reply('No results found for %s.' % hostname)
|
||||
else:
|
||||
irc.error('The format of page the was odd.')
|
||||
netcraft = wrap(netcraft, ['text'])
|
||||
|
||||
def urlquote(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns the URL quoted form of the text.
|
||||
"""
|
||||
irc.reply(utils.web.urlquote(text))
|
||||
urlquote = wrap(urlquote, ['text'])
|
||||
|
||||
def urlunquote(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns the text un-URL quoted.
|
||||
"""
|
||||
s = utils.web.urlunquote(text)
|
||||
irc.reply(s)
|
||||
urlunquote = wrap(urlunquote, ['text'])
|
||||
|
||||
def fetch(self, irc, msg, args, url):
|
||||
"""<url>
|
||||
|
||||
Returns the contents of <url>, or as much as is configured in
|
||||
supybot.plugins.Web.fetch.maximum. If that configuration variable is
|
||||
set to 0, this command will be effectively disabled.
|
||||
"""
|
||||
max = self.registryValue('fetch.maximum')
|
||||
if not max:
|
||||
irc.error('This command is disabled '
|
||||
'(supybot.plugins.Web.fetch.maximum is set to 0).',
|
||||
Raise=True)
|
||||
fd = utils.web.getUrlFd(url)
|
||||
irc.reply(fd.read(max))
|
||||
fetch = wrap(fetch, ['url'])
|
||||
|
||||
Class = Web
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Binary file not shown.
|
@ -0,0 +1,130 @@
|
|||
###
|
||||
# Copyright (c) 2005, 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.
|
||||
###
|
||||
|
||||
from supybot.test import *
|
||||
|
||||
class WebTestCase(ChannelPluginTestCase):
|
||||
plugins = ('Web',)
|
||||
timeout = 10
|
||||
if network:
|
||||
def testHeaders(self):
|
||||
self.assertError('headers ftp://ftp.cdrom.com/pub/linux')
|
||||
self.assertNotError('headers http://www.slashdot.org/')
|
||||
|
||||
def testDoctype(self):
|
||||
self.assertError('doctype ftp://ftp.cdrom.com/pub/linux')
|
||||
self.assertNotError('doctype http://www.slashdot.org/')
|
||||
m = self.getMsg('doctype http://moobot.sf.net/')
|
||||
self.failUnless(m.args[1].endswith('>'))
|
||||
|
||||
def testSize(self):
|
||||
self.assertError('size ftp://ftp.cdrom.com/pub/linux')
|
||||
self.assertNotError('size http://supybot.sf.net/')
|
||||
self.assertNotError('size http://www.slashdot.org/')
|
||||
|
||||
def testTitle(self):
|
||||
self.assertResponse('title http://www.slashdot.org/',
|
||||
'Slashdot - News for nerds, stuff that matters')
|
||||
# Amazon add a bunch of scripting stuff to the top of their page,
|
||||
# so we need to allow for a larger peekSize
|
||||
# Actually, screw Amazon. Even bumping this up to 10k doesn't give us enough
|
||||
# info.
|
||||
# try:
|
||||
# orig = conf.supybot.protocols.http.peekSize()
|
||||
# conf.supybot.protocols.http.peekSize.setValue(8192)
|
||||
# self.assertNotRegexp('title '
|
||||
# 'http://www.amazon.com/exec/obidos/tg/detail/-/'
|
||||
# '1884822312/qid=1063140754/sr=8-1/ref=sr_8_1/'
|
||||
# '002-9802970-2308826?v=glance&s=books&n=507846',
|
||||
# 'no HTML title')
|
||||
# finally:
|
||||
# conf.supybot.protocols.http.peekSize.setValue(orig)
|
||||
# Checks the non-greediness of the regexp
|
||||
self.assertResponse('title '
|
||||
'http://www.space.com/scienceastronomy/'
|
||||
'jupiter_dark_spot_031023.html',
|
||||
'SPACE.com -- Mystery Spot on Jupiter Baffles '
|
||||
'Astronomers')
|
||||
# Checks for @title not-working correctly
|
||||
self.assertResponse('title '
|
||||
'http://www.catb.org/~esr/jargon/html/F/foo.html',
|
||||
'foo')
|
||||
# Checks for only grabbing the real title tags instead of title
|
||||
# tags inside, for example, script tags. Bug #1190350
|
||||
self.assertNotRegexp('title '
|
||||
'http://www.irinnews.org/report.asp?ReportID=45910&'
|
||||
'SelectRegion=West_Africa&SelectCountry=CHAD',
|
||||
r'document\.write\(')
|
||||
# Checks that title parser grabs the full title instead of just
|
||||
# part of it.
|
||||
self.assertRegexp('title http://www.n-e-r-d.com/', 'N.*E.*R.*D')
|
||||
# Checks that the parser doesn't hang on invalid tags
|
||||
print
|
||||
print "If we have not fixed a bug with the parser, the following",
|
||||
print "test will hang the test-suite."
|
||||
self.assertNotError(
|
||||
'title http://www.youtube.com/watch?v=x4BtiqPN4u8')
|
||||
|
||||
def testNetcraft(self):
|
||||
self.assertNotError('netcraft slashdot.org')
|
||||
|
||||
def testTitleSnarfer(self):
|
||||
try:
|
||||
conf.supybot.plugins.Web.titleSnarfer.setValue(True)
|
||||
self.assertSnarfResponse('http://microsoft.com/',
|
||||
'Title: Microsoft Corporation'
|
||||
' (at microsoft.com)')
|
||||
finally:
|
||||
conf.supybot.plugins.Web.titleSnarfer.setValue(False)
|
||||
|
||||
def testNonSnarfing(self):
|
||||
snarf = conf.supybot.plugins.Web.nonSnarfingRegexp()
|
||||
title = conf.supybot.plugins.Web.titleSnarfer()
|
||||
try:
|
||||
conf.supybot.plugins.Web.nonSnarfingRegexp.set('m/sf/')
|
||||
try:
|
||||
conf.supybot.plugins.Web.titleSnarfer.setValue(True)
|
||||
self.assertSnarfNoResponse('http://sf.net/', 2)
|
||||
self.assertSnarfRegexp('http://www.sourceforge.net/',
|
||||
r'Sourceforge\.net')
|
||||
finally:
|
||||
conf.supybot.plugins.Web.titleSnarfer.setValue(title)
|
||||
finally:
|
||||
conf.supybot.plugins.Web.nonSnarfingRegexp.setValue(snarf)
|
||||
|
||||
def testNonSnarfingRegexpConfigurable(self):
|
||||
self.assertSnarfNoResponse('http://foo.bar.baz/', 2)
|
||||
try:
|
||||
conf.supybot.plugins.Web.nonSnarfingRegexp.set('m/biff/')
|
||||
self.assertSnarfNoResponse('http://biff.bar.baz/', 2)
|
||||
finally:
|
||||
conf.supybot.plugins.Web.nonSnarfingRegexp.set('')
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue