mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-01-10 20:22:36 +01:00
Added the Filter plugin in the new plugin format.
This commit is contained in:
parent
f85431435a
commit
d9689f818b
1
plugins/Filter/README.txt
Normal file
1
plugins/Filter/README.txt
Normal file
@ -0,0 +1 @@
|
||||
Insert a description of your plugin here, with any notes, etc. about using it.
|
55
plugins/Filter/__init__.py
Normal file
55
plugins/Filter/__init__.py
Normal file
@ -0,0 +1,55 @@
|
||||
###
|
||||
# Copyright (c) 2004, 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.
|
||||
###
|
||||
|
||||
"""
|
||||
Provides numerous filters, and a command (outfilter) to set them as filters on
|
||||
the output of the bot.
|
||||
"""
|
||||
|
||||
import supybot
|
||||
import supybot.world as world
|
||||
|
||||
__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.
|
||||
|
||||
if world.testing:
|
||||
import test
|
||||
|
||||
Class = plugin.Class
|
||||
configure = config.configure
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
57
plugins/Filter/config.py
Normal file
57
plugins/Filter/config.py
Normal file
@ -0,0 +1,57 @@
|
||||
###
|
||||
# Copyright (c) 2004, 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
|
||||
|
||||
Filter = conf.registerPlugin('Filter')
|
||||
conf.registerGroup(Filter, 'spellit')
|
||||
conf.registerGlobalValue(Filter.spellit,
|
||||
'replaceLetters', registry.Boolean(True, """Determines whether or not to
|
||||
replace letters in the output of spellit."""))
|
||||
conf.registerGlobalValue(Filter.spellit,
|
||||
'replacePunctuation', registry.Boolean(True, """Determines whether or not
|
||||
to replace punctuation in the output of spellit."""))
|
||||
conf.registerGlobalValue(Filter.spellit,
|
||||
'replaceNumbers', registry.Boolean(True, """Determines whether or not to
|
||||
replace numbers in the output of spellit."""))
|
||||
conf.registerGroup(Filter, 'shrink')
|
||||
conf.registerChannelValue(Filter.shrink, 'minimum',
|
||||
registry.PositiveInteger(4, """Determines the minimum number of a letters
|
||||
in a word before it will be shrunken by the shrink command/filter."""))
|
||||
|
||||
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('Filter', True)
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78
|
620
plugins/Filter/plugin.py
Normal file
620
plugins/Filter/plugin.py
Normal file
@ -0,0 +1,620 @@
|
||||
###
|
||||
# Copyright (c) 2002-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.plugins as plugins
|
||||
|
||||
import re
|
||||
import string
|
||||
import random
|
||||
import itertools
|
||||
from cStringIO import StringIO
|
||||
|
||||
import supybot.conf as conf
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.registry as registry
|
||||
import supybot.callbacks as callbacks
|
||||
|
||||
class MyFilterProxy(object):
|
||||
def reply(self, s):
|
||||
self.s = s
|
||||
|
||||
class Filter(callbacks.Privmsg):
|
||||
"""This plugin offers several commands which transform text in some way.
|
||||
It also provides the capability of using such commands to 'filter' the
|
||||
output of the bot -- for instance, you could make everything the bot says
|
||||
be in leetspeak, or Morse code, or any number of other kinds of filters.
|
||||
Not very useful, but definitely quite fun :)"""
|
||||
def __init__(self):
|
||||
self.outFilters = ircutils.IrcDict()
|
||||
callbacks.Privmsg.__init__(self)
|
||||
|
||||
def outFilter(self, irc, msg):
|
||||
if msg.command == 'PRIVMSG':
|
||||
if msg.args[0] in self.outFilters:
|
||||
if ircmsgs.isAction(msg):
|
||||
s = ircmsgs.unAction(msg)
|
||||
else:
|
||||
s = msg.args[1]
|
||||
methods = self.outFilters[msg.args[0]]
|
||||
for filtercommand in methods:
|
||||
myIrc = MyFilterProxy()
|
||||
filtercommand(myIrc, msg, [s])
|
||||
s = myIrc.s
|
||||
if ircmsgs.isAction(msg):
|
||||
msg = ircmsgs.action(msg.args[0], s, msg=msg)
|
||||
else:
|
||||
msg = ircmsgs.IrcMsg(msg=msg, args=(msg.args[0], s))
|
||||
return msg
|
||||
|
||||
_filterCommands = ['jeffk', 'leet', 'rot13', 'hexlify', 'binary', 'lithp',
|
||||
'scramble', 'morse', 'reverse', 'colorize', 'squish',
|
||||
'supa1337', 'colorstrip', 'aol', 'rainbow', 'spellit',
|
||||
'hebrew', 'undup', 'gnu', 'shrink']
|
||||
def outfilter(self, irc, msg, args, channel, command):
|
||||
"""[<channel>] [<command>]
|
||||
|
||||
Sets the outFilter of this plugin to be <command>. If no command is
|
||||
given, unsets the outFilter. <channel> is only necessary if the
|
||||
message isn't sent in the channel itself.
|
||||
"""
|
||||
if command:
|
||||
if not self.isDisabled(command) and \
|
||||
command in self._filterCommands:
|
||||
method = getattr(self, command)
|
||||
self.outFilters.setdefault(channel, []).append(method)
|
||||
irc.replySuccess()
|
||||
else:
|
||||
irc.error('That\'s not a valid filter command.')
|
||||
else:
|
||||
self.outFilters[channel] = []
|
||||
irc.replySuccess()
|
||||
outfilter = wrap(outfilter,
|
||||
[('checkChannelCapability', 'op'),
|
||||
additional('commandName')])
|
||||
|
||||
def hebrew(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Removes all the vowels from <text>. (If you're curious why this is
|
||||
named 'hebrew' it's because I (jemfinch) thought of it in Hebrew class,
|
||||
and printed Hebrew often elides the vowels.)
|
||||
"""
|
||||
text = filter(lambda c: c not in 'aeiou', text)
|
||||
irc.reply(text)
|
||||
hebrew = wrap(hebrew, ['text'])
|
||||
|
||||
def squish(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Removes all the spaces from <text>.
|
||||
"""
|
||||
text = ''.join(text.split())
|
||||
irc.reply(text)
|
||||
squish = wrap(squish, ['text'])
|
||||
|
||||
def undup(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text>, with all consecutive duplicated letters removed.
|
||||
"""
|
||||
L = [text[0]]
|
||||
for c in text:
|
||||
if c != L[-1]:
|
||||
L.append(c)
|
||||
irc.reply(''.join(L))
|
||||
undup = wrap(undup, ['text'])
|
||||
|
||||
def binary(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns the binary representation of <text>.
|
||||
"""
|
||||
L = []
|
||||
for c in text:
|
||||
LL = []
|
||||
i = ord(c)
|
||||
counter = 8
|
||||
while i:
|
||||
counter -= 1
|
||||
if i & 1:
|
||||
LL.append('1')
|
||||
else:
|
||||
LL.append('0')
|
||||
i >>= 1
|
||||
while counter:
|
||||
LL.append('0')
|
||||
counter -= 1
|
||||
LL.reverse()
|
||||
L.extend(LL)
|
||||
irc.reply(''.join(L))
|
||||
binary = wrap(binary, ['text'])
|
||||
|
||||
def hexlify(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns a hexstring from the given string; a hexstring is a string
|
||||
composed of the hexadecimal value of each character in the string
|
||||
"""
|
||||
irc.reply(text.encode('hex_codec'))
|
||||
hexlify = wrap(hexlify, ['text'])
|
||||
|
||||
def unhexlify(self, irc, msg, args, text):
|
||||
"""<hexstring>
|
||||
|
||||
Returns the string corresponding to <hexstring>. Obviously,
|
||||
<hexstring> must be a string of hexadecimal digits.
|
||||
"""
|
||||
try:
|
||||
irc.reply(text.decode('hex_codec'))
|
||||
except TypeError:
|
||||
irc.error('Invalid input.')
|
||||
unhexlify = wrap(unhexlify, ['text'])
|
||||
|
||||
def rot13(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Rotates <text> 13 characters to the right in the alphabet. Rot13 is
|
||||
commonly used for text that simply needs to be hidden from inadvertent
|
||||
reading by roaming eyes, since it's easily reversible.
|
||||
"""
|
||||
irc.reply(text.encode('rot13'))
|
||||
rot13 = wrap(rot13, ['text'])
|
||||
|
||||
def lithp(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns the lisping version of <text>
|
||||
"""
|
||||
text = text.replace('sh', 'th')
|
||||
text = text.replace('SH', 'TH')
|
||||
text = text.replace('Sh', 'Th')
|
||||
text = text.replace('ss', 'th')
|
||||
text = text.replace('SS', 'TH')
|
||||
text = text.replace('s', 'th')
|
||||
text = text.replace('z', 'th')
|
||||
text = text.replace('S', 'Th')
|
||||
text = text.replace('Z', 'Th')
|
||||
text = text.replace('x', 'kth')
|
||||
text = text.replace('X', 'KTH')
|
||||
text = text.replace('cce', 'kth')
|
||||
text = text.replace('CCE', 'KTH')
|
||||
text = text.replace('tion', 'thion')
|
||||
text = text.replace('TION', 'THION')
|
||||
irc.reply(text)
|
||||
lithp = wrap(lithp, ['text'])
|
||||
|
||||
_leettrans = string.maketrans('oOaAeElBTiIts', '004433187!1+5')
|
||||
_leetres = [(re.compile(r'\b(?:(?:[yY][o0O][oO0uU])|u)\b'), 'j00'),
|
||||
(re.compile(r'fear'), 'ph33r'),
|
||||
(re.compile(r'[aA][tT][eE]'), '8'),
|
||||
(re.compile(r'[aA][tT]'), '@'),
|
||||
(re.compile(r'[sS]\b'), 'z'),
|
||||
(re.compile(r'x'), '><'),]
|
||||
def leet(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns the l33tspeak version of <text>
|
||||
"""
|
||||
for (r, sub) in self._leetres:
|
||||
text = re.sub(r, sub, text)
|
||||
text = text.translate(self._leettrans)
|
||||
irc.reply(text)
|
||||
leet = wrap(leet, ['text'])
|
||||
|
||||
_supaleetreplacers = [('xX', '><'), ('kK', '|<'), ('rR', '|2'),
|
||||
('hH', '|-|'), ('L', '|_'), ('uU', '|_|'),
|
||||
('O', '()'), ('nN', '|\\|'), ('mM', '/\\/\\'),
|
||||
('G', '6'), ('Ss', '$'), ('i', ';'), ('aA', '/-\\'),
|
||||
('eE', '3'), ('t', '+'), ('T', '7'), ('l', '1'),
|
||||
('D', '|)'), ('B', '|3'), ('I', ']['), ('Vv', '\\/'),
|
||||
('wW', '\\/\\/'), ('d', 'c|'), ('b', '|>'),
|
||||
('c', '<'), ('h', '|n'),]
|
||||
def supa1337(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Replies with an especially k-rad translation of <text>.
|
||||
"""
|
||||
for (r, sub) in self._leetres:
|
||||
text = re.sub(r, sub, text)
|
||||
for (letters, replacement) in self._supaleetreplacers:
|
||||
for letter in letters:
|
||||
text = text.replace(letter, replacement)
|
||||
irc.reply(text)
|
||||
supa1337 = wrap(supa1337, ['text'])
|
||||
|
||||
_scrambleRe = re.compile(r'(?:\b|(?![a-zA-Z]))([a-zA-Z])([a-zA-Z]*)'
|
||||
r'([a-zA-Z])(?:\b|(?![a-zA-Z]))')
|
||||
def scramble(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Replies with a string where each word is scrambled; i.e., each internal
|
||||
letter (that is, all letters but the first and last) are shuffled.
|
||||
"""
|
||||
def _subber(m):
|
||||
L = list(m.group(2))
|
||||
random.shuffle(L)
|
||||
return '%s%s%s' % (m.group(1), ''.join(L), m.group(3))
|
||||
s = self._scrambleRe.sub(_subber, text)
|
||||
irc.reply(s)
|
||||
scramble = wrap(scramble, ['text'])
|
||||
|
||||
_code = {
|
||||
"A" : ".-",
|
||||
"B" : "-...",
|
||||
"C" : "-.-.",
|
||||
"D" : "-..",
|
||||
"E" : ".",
|
||||
"F" : "..-.",
|
||||
"G" : "--.",
|
||||
"H" : "....",
|
||||
"I" : "..",
|
||||
"J" : ".---",
|
||||
"K" : "-.-",
|
||||
"L" : ".-..",
|
||||
"M" : "--",
|
||||
"N" : "-.",
|
||||
"O" : "---",
|
||||
"P" : ".--.",
|
||||
"Q" : "--.-",
|
||||
"R" : ".-.",
|
||||
"S" : "...",
|
||||
"T" : "-",
|
||||
"U" : "..-",
|
||||
"V" : "...-",
|
||||
"W" : ".--",
|
||||
"X" : "-..-",
|
||||
"Y" : "-.--",
|
||||
"Z" : "--..",
|
||||
"0" : "-----",
|
||||
"1" : ".----",
|
||||
"2" : "..---",
|
||||
"3" : "...--",
|
||||
"4" : "....-",
|
||||
"5" : ".....",
|
||||
"6" : "-....",
|
||||
"7" : "--...",
|
||||
"8" : "---..",
|
||||
"9" : "----.",
|
||||
"." : ".-.-.-",
|
||||
"," : "--..--",
|
||||
":" : "---...",
|
||||
"?" : "..--..",
|
||||
"'" : ".----.",
|
||||
"-" : "-....-",
|
||||
"/" : "-..-.",
|
||||
'"' : ".-..-.",
|
||||
"@" : ".--.-.",
|
||||
"=" : "-...-"
|
||||
}
|
||||
_revcode = dict([(y, x) for (x, y) in _code.items()])
|
||||
_unmorsere = re.compile('([.-]+)')
|
||||
def unmorse(self, irc, msg, args, text):
|
||||
"""<Morse code text>
|
||||
|
||||
Does the reverse of the morse command.
|
||||
"""
|
||||
text = text.replace('_', '-')
|
||||
def morseToLetter(m):
|
||||
s = m.group(1)
|
||||
return self._revcode.get(s, s)
|
||||
text = self._unmorsere.sub(morseToLetter, text)
|
||||
text = text.replace(' ', '\x00')
|
||||
text = text.replace(' ', '')
|
||||
text = text.replace('\x00', ' ')
|
||||
irc.reply(text)
|
||||
unmorse = wrap(unmorse, ['text'])
|
||||
|
||||
def morse(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Gives the Morse code equivalent of a given string.
|
||||
"""
|
||||
L = []
|
||||
for c in text.upper():
|
||||
if c in self._code:
|
||||
L.append(self._code[c])
|
||||
else:
|
||||
L.append(c)
|
||||
irc.reply(' '.join(L))
|
||||
morse = wrap(morse, ['text'])
|
||||
|
||||
def reverse(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Reverses <text>.
|
||||
"""
|
||||
irc.reply(text[::-1])
|
||||
reverse = wrap(reverse, ['text'])
|
||||
|
||||
def _color(self, c, fg=None):
|
||||
if c == ' ':
|
||||
return c
|
||||
if fg is None:
|
||||
fg = str(random.randint(2, 15)).zfill(2)
|
||||
return '\x03%s%s' % (fg, c)
|
||||
|
||||
def colorize(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text> with each character randomly colorized.
|
||||
"""
|
||||
L = [self._color(c) for c in text]
|
||||
irc.reply('%s%s' % (''.join(L), '\x03'))
|
||||
colorize = wrap(colorize, ['text'])
|
||||
|
||||
def rainbow(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text> colorized like a rainbow.
|
||||
"""
|
||||
colors = itertools.cycle([4, 7, 8, 3, 2, 12, 6])
|
||||
L = [self._color(c, fg=colors.next()) for c in text]
|
||||
irc.reply(''.join(L) + '\x03')
|
||||
rainbow = wrap(rainbow, ['text'])
|
||||
|
||||
def stripcolor(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text> stripped of all color codes.
|
||||
"""
|
||||
irc.reply(ircutils.stripColor(text))
|
||||
stripcolor = wrap(stripcolor, ['text'])
|
||||
|
||||
def aol(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text> as if an AOLuser had said it.
|
||||
"""
|
||||
text = text.replace(' you ', ' u ')
|
||||
text = text.replace(' are ', ' r ')
|
||||
text = text.replace(' love ', ' <3 ')
|
||||
text = text.replace(' luv ', ' <3 ')
|
||||
text = text.replace(' too ', ' 2 ')
|
||||
text = text.replace(' to ', ' 2 ')
|
||||
text = text.replace(' two ', ' 2 ')
|
||||
text = text.replace('fore', '4')
|
||||
text = text.replace(' for ', ' 4 ')
|
||||
text = text.replace('be', 'b')
|
||||
text = text.replace('four', ' 4 ')
|
||||
text = text.replace(' their ', ' there ')
|
||||
text = text.replace(', ', ' ')
|
||||
text = text.replace(',', ' ')
|
||||
text = text.replace("'", '')
|
||||
text = text.replace('one', '1')
|
||||
smiley = random.choice(['<3', ':)', ':-)', ':D', ':-D'])
|
||||
text += smiley*3
|
||||
irc.reply(text)
|
||||
aol = wrap(aol, ['text'])
|
||||
|
||||
def jeffk(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text> as if JeffK had said it himself.
|
||||
"""
|
||||
def randomlyPick(L):
|
||||
return random.choice(L)
|
||||
def quoteOrNothing(m):
|
||||
return randomlyPick(['"', '']).join(m.groups())
|
||||
def randomlyReplace(s, probability=0.5):
|
||||
def f(m):
|
||||
if random.random() < probability:
|
||||
return m.expand(s)
|
||||
else:
|
||||
return m.group(0)
|
||||
return f
|
||||
def randomExclaims(m):
|
||||
if random.random() < 0.85:
|
||||
return ('!' * random.randrange(1, 5)) + m.group(1)
|
||||
else:
|
||||
return '.' + m.group(1)
|
||||
def randomlyShuffle(m):
|
||||
L = list(m.groups())
|
||||
random.shuffle(L)
|
||||
return ''.join(L)
|
||||
def lessRandomlyShuffle(m):
|
||||
L = list(m.groups())
|
||||
if random.random() < .4:
|
||||
random.shuffle(L)
|
||||
return ''.join(L)
|
||||
def randomlyLaugh(text, probability=.3):
|
||||
if random.random() < probability:
|
||||
if random.random() < .5:
|
||||
insult = random.choice([' fagot1', ' fagorts', ' jerks',
|
||||
'fagot' ' jerk', ' dumbshoes',
|
||||
' dumbshoe'])
|
||||
else:
|
||||
insult = ''
|
||||
laugh1 = random.choice(['ha', 'hah', 'lol', 'l0l', 'ahh'])
|
||||
laugh2 = random.choice(['ha', 'hah', 'lol', 'l0l', 'ahh'])
|
||||
laugh1 = laugh1 * random.randrange(1, 5)
|
||||
laugh2 = laugh2 * random.randrange(1, 5)
|
||||
exclaim = random.choice(['!', '~', '!~', '~!!~~',
|
||||
'!!~', '~~~!'])
|
||||
exclaim += random.choice(['!', '~', '!~', '~!!~~',
|
||||
'!!~', '~~~!'])
|
||||
if random.random() < 0.5:
|
||||
exclaim += random.choice(['!', '~', '!~', '~!!~~',
|
||||
|
||||
'!!~', '~~~!'])
|
||||
laugh = ''.join([' ', laugh1, laugh2, insult, exclaim])
|
||||
text += laugh
|
||||
return text
|
||||
if random.random() < .03:
|
||||
irc.reply(randomlyLaugh('NO YUO', probability=1))
|
||||
return
|
||||
alwaysInsertions = {
|
||||
r'er\b': 'ar',
|
||||
r'\bthe\b': 'teh',
|
||||
r'\byou\b': 'yuo',
|
||||
r'\bis\b': 'si',
|
||||
r'\blike\b': 'liek',
|
||||
r'[^e]ing\b': 'eing',
|
||||
}
|
||||
for (r, s) in alwaysInsertions.iteritems():
|
||||
text = re.sub(r, s, text)
|
||||
randomInsertions = {
|
||||
r'i': 'ui',
|
||||
r'le\b': 'al',
|
||||
r'i': 'io',
|
||||
r'l': 'll',
|
||||
r'to': 'too',
|
||||
r'that': 'taht',
|
||||
r'[^s]c([ei])': r'sci\1',
|
||||
r'ed\b': r'e',
|
||||
r'\band\b': 'adn',
|
||||
r'\bhere\b': 'hear',
|
||||
r'\bthey\'re': 'their',
|
||||
r'\bthere\b': 'they\'re',
|
||||
r'\btheir\b': 'there',
|
||||
r'[^e]y': 'ey',
|
||||
}
|
||||
for (r, s) in randomInsertions.iteritems():
|
||||
text = re.sub(r, randomlyReplace(s), text)
|
||||
text = re.sub(r'(\w)\'(\w)', quoteOrNothing, text)
|
||||
text = re.sub(r'\.(\s+|$)', randomExclaims, text)
|
||||
text = re.sub(r'([aeiou])([aeiou])', randomlyShuffle, text)
|
||||
text = re.sub(r'([bcdfghkjlmnpqrstvwxyz])([bcdfghkjlmnpqrstvwxyz])',
|
||||
lessRandomlyShuffle, text)
|
||||
text = randomlyLaugh(text)
|
||||
if random.random() < .4:
|
||||
text = text.upper()
|
||||
irc.reply(text)
|
||||
jeffk = wrap(jeffk, ['text'])
|
||||
|
||||
# Keeping these separate so people can just replace the alphabets for
|
||||
# whatever their language of choice
|
||||
_spellLetters = {
|
||||
'a': 'ay', 'b': 'bee', 'c': 'see', 'd': 'dee', 'e': 'ee', 'f': 'eff',
|
||||
'g': 'gee', 'h': 'aych', 'i': 'eye', 'j': 'jay', 'k': 'kay', 'l':
|
||||
'ell', 'm': 'em', 'n': 'en', 'o': 'oh', 'p': 'pee', 'q': 'cue', 'r':
|
||||
'arr', 's': 'ess', 't': 'tee', 'u': 'you', 'v': 'vee', 'w':
|
||||
'double-you', 'x': 'ecks', 'y': 'why', 'z': 'zee'
|
||||
}
|
||||
for (k, v) in _spellLetters.items():
|
||||
_spellLetters[k.upper()] = v
|
||||
_spellPunctuation = {
|
||||
'!': 'exclamation point',
|
||||
'"': 'quote',
|
||||
'#': 'pound',
|
||||
'$': 'dollar sign',
|
||||
'%': 'percent',
|
||||
'&': 'ampersand',
|
||||
'\'': 'single quote',
|
||||
'(': 'left paren',
|
||||
')': 'right paren',
|
||||
'*': 'asterisk',
|
||||
'+': 'plus',
|
||||
',': 'comma',
|
||||
'-': 'minus',
|
||||
'.': 'period',
|
||||
'/': 'slash',
|
||||
':': 'colon',
|
||||
';': 'semicolon',
|
||||
'<': 'less than',
|
||||
'=': 'equals',
|
||||
'>': 'greater than',
|
||||
'?': 'question mark',
|
||||
'@': 'at',
|
||||
'[': 'left bracket',
|
||||
'\\': 'backslash',
|
||||
']': 'right bracket',
|
||||
'^': 'caret',
|
||||
'_': 'underscore',
|
||||
'`': 'backtick',
|
||||
'{': 'left brace',
|
||||
'|': 'pipe',
|
||||
'}': 'right brace',
|
||||
'~': 'tilde'
|
||||
}
|
||||
_spellNumbers = {
|
||||
'0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
|
||||
'5': 'five', '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine'
|
||||
}
|
||||
def spellit(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text>, phonetically spelled out.
|
||||
"""
|
||||
d = {}
|
||||
if self.registryValue('spellit.replaceLetters'):
|
||||
d.update(self._spellLetters)
|
||||
if self.registryValue('spellit.replaceNumbers'):
|
||||
d.update(self._spellNumbers)
|
||||
if self.registryValue('spellit.replacePunctuation'):
|
||||
d.update(self._spellPunctuation)
|
||||
# A bug in unicode on OSX prevents me from testing this.
|
||||
## dd = {}
|
||||
## for (c, v) in d.iteritems():
|
||||
## dd[ord(c)] = unicode(v + ' ')
|
||||
## irc.reply(unicode(text).translate(dd))
|
||||
out = StringIO()
|
||||
write = out.write
|
||||
for c in text:
|
||||
try:
|
||||
c = d[c]
|
||||
write(' ')
|
||||
except KeyError:
|
||||
pass
|
||||
write(c)
|
||||
irc.reply(out.getvalue())
|
||||
spellit = wrap(spellit, ['text'])
|
||||
|
||||
def gnu(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text> as GNU/RMS would say it.
|
||||
"""
|
||||
irc.reply(' '.join(['GNU/' + s for s in text.split()]))
|
||||
gnu = wrap(gnu, ['text'])
|
||||
|
||||
def shrink(self, irc, msg, args, text):
|
||||
"""<text>
|
||||
|
||||
Returns <text> with each word longer than
|
||||
supybot.plugins.Filter.shrink.minimum being shrunken (i.e., like
|
||||
"internationalization" becomes "i18n").
|
||||
"""
|
||||
L = []
|
||||
minimum = self.registryValue('shrink.minimum', msg.args[0])
|
||||
r = re.compile(r'[A-Za-z]{%s,}' % minimum)
|
||||
def shrink(m):
|
||||
s = m.group(0)
|
||||
return ''.join((s[0], str(len(s)-2), s[-1]))
|
||||
text = r.sub(shrink, text)
|
||||
irc.reply(text)
|
||||
shrink = wrap(shrink, ['text'])
|
||||
|
||||
|
||||
Class = Filter
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
169
plugins/Filter/test.py
Normal file
169
plugins/Filter/test.py
Normal file
@ -0,0 +1,169 @@
|
||||
###
|
||||
# Copyright (c) 2002-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 *
|
||||
|
||||
import re
|
||||
|
||||
import supybot.utils as utils
|
||||
import supybot.callbacks as callbacks
|
||||
|
||||
class FilterTest(ChannelPluginTestCase):
|
||||
plugins = ('Filter', 'Utilities')
|
||||
def testNoErrors(self):
|
||||
self.assertNotError('leet foobar')
|
||||
self.assertNotError('supa1337 foobar')
|
||||
self.assertNotError('lithp meghan sweeney')
|
||||
self.assertNotError('aol I\'m too legit to quit.')
|
||||
|
||||
def testDisabledCommandsCannotFilter(self):
|
||||
self.assertNotError('outfilter rot13')
|
||||
self.assertResponse('echo foo', 'sbb')
|
||||
self.assertNotError('outfilter')
|
||||
try:
|
||||
self.assertNotError('disable rot13')
|
||||
self.assertError('outfilter rot13')
|
||||
self.assertNotError('enable rot13')
|
||||
self.assertNotError('outfilter rot13')
|
||||
finally:
|
||||
try:
|
||||
callbacks.Privmsg._disabled.remove('rot13')
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def testHebrew(self):
|
||||
self.assertResponse('hebrew The quick brown fox '
|
||||
'jumps over the lazy dog.',
|
||||
'Th qck brwn fx jmps vr th lzy dg.')
|
||||
def testJeffk(self):
|
||||
for i in range(100):
|
||||
self.assertNotError('jeffk the quick brown fox is ghetto')
|
||||
|
||||
def testSquish(self):
|
||||
self.assertResponse('squish foo bar baz', 'foobarbaz')
|
||||
self.assertResponse('squish "foo bar baz"', 'foobarbaz')
|
||||
|
||||
def testUndup(self):
|
||||
self.assertResponse('undup foo bar baz quux', 'fo bar baz qux')
|
||||
self.assertResponse('undup aaaaaaaaaa', 'a')
|
||||
|
||||
def testLithp(self):
|
||||
self.assertResponse('lithp jamessan', 'jamethan')
|
||||
self.assertResponse('lithp Shame', 'Thame')
|
||||
|
||||
def testMorse(self):
|
||||
self.assertResponse('unmorse [morse jemfinch]', 'JEMFINCH')
|
||||
|
||||
def testReverse(self):
|
||||
for s in map(str, range(1000, 1010)):
|
||||
self.assertResponse('reverse %s' % s, s[::-1])
|
||||
|
||||
def testBinary(self):
|
||||
self.assertResponse('binary A', '01000001')
|
||||
|
||||
def testRot13(self):
|
||||
for s in map(str, range(1000, 1010)):
|
||||
self.assertResponse('rot13 [rot13 %s]' % s, s)
|
||||
|
||||
def testRot13HandlesNonAsciiStuff(self):
|
||||
self.assertNotError('rot13 \xe4')
|
||||
|
||||
def testHexlifyUnhexlify(self):
|
||||
for s in map(str, range(1000, 1010)):
|
||||
self.assertResponse('unhexlify [hexlify %s]' % s, s)
|
||||
|
||||
def testScramble(self):
|
||||
s = 'the recalcitrant jamessan tests his scramble function'
|
||||
self.assertNotRegexp('scramble %s' % s, s)
|
||||
s = 'the recalc1trant jam3ssan tests his scramble fun><tion'
|
||||
self.assertNotRegexp('scramble %s' % s, s)
|
||||
|
||||
def testColorize(self):
|
||||
self.assertNotRegexp('colorize foobar', r'\s+')
|
||||
self.assertRegexp('colorize foobar', r'\x03')
|
||||
# Make sure we're closing colorize with an 'end color' marker
|
||||
self.assertRegexp('colorize foobar', r'\x03$')
|
||||
|
||||
_strings = ('Supybot pwns!', '123456', 'A string with \x02bold\x15')
|
||||
def testColorstrip(self):
|
||||
for s in self._strings:
|
||||
self.assertResponse('stripcolor [colorize %s]' % s, s)
|
||||
|
||||
def testSpellit(self):
|
||||
self.assertRegexp('spellit abc123!.%', 'ay bee see one two three '
|
||||
'exclamation point period percent')
|
||||
self.assertNotError('config plugins.Filter.spellit.replaceLetters off')
|
||||
self.assertRegexp('spellit asasdfasdf12345@#$!%^',
|
||||
'asasdfasdf one two three four five at pound '
|
||||
'dollar sign exclamation point percent caret')
|
||||
self.assertNotError('config plugins.Filter.spellit.replaceNumbers off')
|
||||
self.assertRegexp('spellit asasdfasdf12345@#$!%^',
|
||||
'asasdfasdf12345 at pound dollar sign exclamation '
|
||||
'point percent caret')
|
||||
self.assertNotError('config '
|
||||
'plugins.Filter.spellit.replacePunctuation off')
|
||||
self.assertResponse('spellit asasdfasdf12345@#$!%^',
|
||||
'asasdfasdf12345@#$!%^')
|
||||
|
||||
def testOutfilter(self):
|
||||
s = self.nick.encode('rot13')
|
||||
self.assertNotError('outfilter rot13')
|
||||
self.assertResponse('rot13 foobar', '%s: foobar' % s)
|
||||
self.assertNotError('outfilter rot13')
|
||||
self.assertResponse('rot13 foobar', 'sbbone')
|
||||
self.assertNotError('outfilter')
|
||||
self.assertResponse('rot13 foobar', 'sbbone')
|
||||
self.assertNotError('outfilter ROT13')
|
||||
self.assertResponse('rot13 foobar', '%s: foobar' % s)
|
||||
self.assertNotError('outfilter')
|
||||
self.assertResponse('rot13 foobar', 'sbbone')
|
||||
|
||||
def testOutfilterAction(self):
|
||||
s = self.nick.encode('rot13')
|
||||
self.assertNotError('outfilter rot13')
|
||||
self.assertResponse('rot13 foobar', '%s: foobar' % s)
|
||||
m = self.getMsg('action foobar')
|
||||
self.failUnless(ircmsgs.isAction(m))
|
||||
s = ircmsgs.unAction(m)
|
||||
self.assertEqual(s, 'sbbone')
|
||||
|
||||
def testGnu(self):
|
||||
self.assertResponse('gnu foo bar baz', 'GNU/foo GNU/bar GNU/baz')
|
||||
self.assertNotError('outfilter gnu')
|
||||
self.assertResponse('echo foo bar baz', 'GNU/foo GNU/bar GNU/baz')
|
||||
self.assertNotError('outfilter')
|
||||
|
||||
def testShrink(self):
|
||||
self.assertResponse('shrink I love you', 'I l2e you')
|
||||
self.assertResponse('shrink internationalization', 'i18n')
|
||||
self.assertResponse('shrink "I love you"', 'I l2e you')
|
||||
self.assertResponse('shrink internationalization, localization',
|
||||
'i18n, l10n')
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
Loading…
Reference in New Issue
Block a user