Make sure all files have encoding set to utf-8 unless they already have an encoding Added COPYING with contense of GPL-2 Added plugin name prefix to all log output. This should take the form of self.log.severity("Plugin: message"), when not logging from plugin.py use: "Plugin/file_without_dot_py: message" Bantracker: Made the confgure() function do something, it also creates an initial database if it doesn't exist Encyclopedia: Made the configure() function do something, it also creates an initial database if it doesn't exist PackageInfo: Improve the configure() function, it also now creates some initial .list files and prompts to run update_apt and update_apt_file This goes some way to getting an "ubottu" package together, all we need to do is patch supybot-wizard to download the plugins from bzr and put them somewhere supybot will see them, then the wizard will do all the initial setup
274 lines
10 KiB
Python
274 lines
10 KiB
Python
# -*- Encoding: utf-8 -*-
|
|
###
|
|
# Copyright (c) 2006-2007 Dennis Kaarsemaker
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of version 2 of the GNU General Public License as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
###
|
|
|
|
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 random, re, time, commands, urllib2
|
|
import supybot.ircmsgs as ircmsgs
|
|
import supybot.conf as conf
|
|
import threading
|
|
import os
|
|
|
|
mess = {
|
|
't': ('Mr. T facts', 'http://4q.cc/?pid=fact&person=mrt', r'<div id="factbox">\s*(?P<fact>.*?)\s*</div>', False),
|
|
'chuck': ('Chuck Norris facts', 'http://4q.cc/?pid=fact&person=chuck', r'<div id="factbox">\s*(?P<fact>.*?)\s*</div>', False),
|
|
'vin': ('Vin Diesel facts', 'http://4q.cc/?pid=fact&person=vin', r'<div id="factbox">\s*(?P<fact>.*?)\s*</div>', False),
|
|
'bauer': ('Jack Bauer facts', 'http://www.notrly.com/jackbauer/', r'<p class="fact">(?P<fact>.*?)</p>', False),
|
|
'bruce': ('Bruce Schneier facts', 'http://geekz.co.uk/schneierfacts/', r'p class="fact">(?P<fact>.*?)</p', False),
|
|
'esr': ('Eric S. Raymond facts', 'http://geekz.co.uk/esrfacts/', r'p class="fact">(?P<fact>.*?)</p', False),
|
|
'mcgyver': ('McGyver facts', 'http://www.macgyver.co.za/', r'wishtable">\s*(?P<fact>.*?)<div', False),
|
|
'macgyver': ('McGyver facts', 'http://www.macgyver.co.za/', r'wishtable">\s*(?P<fact>.*?)<div', False),
|
|
'hamster': ('Hamster quotes', 'http://hamsterrepublic.com/dyn/bobsez', r'<font.*?<b>(?P<fact>.*?)</font>', False),
|
|
#'yourmom': ('', 'http://pfa.php1h.com', r'<p>(?P<fact>.*?)</p>', True),
|
|
'bush': ('Bush quotes', 'http://www.dubyaspeak.com/random.phtml', r'(?P<fact><font.*</font>)', True),
|
|
#southpark': ('', 'http://www.southparkquotes.com/random.php?num=1', r'<p>(?P<fact>.*)</p>', True),
|
|
'mjg': ('Matthew Garrett facts', 'http://www.angryfacts.com', r'</p><h1>(?P<fact>.*?)</h1>', False),
|
|
'mjg59': ('Matthew Garrett facts', 'http://www.angryfacts.com', r'</p><h1>(?P<fact>.*?)</h1>', False),
|
|
'vmjg': ('Virtual Matthew Garrett', 'http://www.rjek.com/vmjg59.cgi', r'<body>(?P<fact>.*?)<p>', True),
|
|
'vmjg59': ('Virtual Matthew Garrett', 'http://www.rjek.com/vmjg59.cgi', r'<body>(?P<fact>.*?)<p>', True),
|
|
'shakespeare': ('Shakespeare quotes', 'http://www.pangloss.com/seidel/Shaker/', r'<font.*?>(?P<fact>.*?)</font>', False),
|
|
'lugradio': ('Lugradio facts', 'http://planet.lugradio.org/facts/', r'<h2>\s*(?P<fact>.*?)</h2>', False),
|
|
'bofh': ('BOFH excuses', '%s/bofh.txt' % os.path.split(os.path.abspath(__file__))[0], 'BOFH Excuse #%d: ', False),
|
|
'42': ('HHGTTG quotes', '%s/42.txt' % os.path.split(os.path.abspath(__file__))[0], '', False),
|
|
'magic8ball': ('The magic 8ball', '%s/ball.txt' % os.path.split(os.path.abspath(__file__))[0], '', False),
|
|
'ferengi': ('Ferengi rules of acquisition', '%s/ferengi.txt' % os.path.split(os.path.abspath(__file__))[0], 'Ferengi rule of acquisition ', False),
|
|
}
|
|
data = {}
|
|
for m in mess.keys():
|
|
if mess[m][1].startswith('http'):
|
|
mess[m] = (mess[m][0], mess[m][1],re.compile(mess[m][2], re.I|re.DOTALL), mess[m][3])
|
|
else:
|
|
fd = open(mess[m][1])
|
|
data[mess[m][1]] = [x.strip() for x in fd.readlines()]
|
|
fd.close()
|
|
|
|
badwords = ['sex','masturbate','fuck','rape','dick','pussy','prostitute','hooker',
|
|
'orgasm','sperm','cunt','penis','shit','piss','urin','bitch','semen','cock',
|
|
'retard', 'cancer', 'hiv', 'aids']
|
|
tagre = re.compile(r'<.*?>')
|
|
def filter(txt,off):
|
|
_txt = txt.lower()
|
|
if not off:
|
|
for b in badwords:
|
|
if b in _txt:
|
|
return None
|
|
txt = txt.replace('<br />','').replace('\n','').replace('\r','')
|
|
txt = txt.replace('<i>','/').replace('</i>','/').replace('<b>','*').replace('</b>','*')
|
|
txt = txt.replace('"','"').replace('<','<').replace('>','>')
|
|
txt = tagre.sub('',txt)
|
|
return txt
|
|
|
|
times = {}
|
|
|
|
def ok(func):
|
|
def newfunc(*args, **kwargs):
|
|
global time
|
|
plugin = args[0]
|
|
channel = args[2].args[0]
|
|
if not channel.startswith('#'):
|
|
delay = 5
|
|
else:
|
|
if not plugin.registryValue('enabled', channel):
|
|
return
|
|
delay = plugin.registryValue('delay', channel)
|
|
if channel not in times.keys():
|
|
times[channel] = time.time()
|
|
elif times[channel] < time.time() - delay:
|
|
times[channel] = time.time()
|
|
else:
|
|
return
|
|
i=0
|
|
func(*args, **kwargs)
|
|
newfunc.__doc__ = func.__doc__
|
|
return newfunc
|
|
|
|
class Mess(callbacks.PluginRegexp):
|
|
"""Random Mess plugin"""
|
|
threaded = True
|
|
regexps = ['hugme']
|
|
hugs = ["hugs %s","gives %s a big hug","gives %s a sloppy wet kiss",
|
|
"huggles %s","squeezes %s","humps %s"]
|
|
|
|
|
|
def isCommandMethod(self, name):
|
|
if not callbacks.PluginRegexp.isCommandMethod(self, name):
|
|
if name in mess:
|
|
return True
|
|
else:
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def listCommands(self):
|
|
commands = callbacks.PluginRegexp.listCommands(self)
|
|
commands.remove('messcb')
|
|
commands.extend(mess.keys())
|
|
commands.sort()
|
|
return commands
|
|
|
|
def getCommandMethod(self, command):
|
|
try:
|
|
return callbacks.PluginRegexp.getCommandMethod(self, command)
|
|
except AttributeError:
|
|
return self.messcb
|
|
|
|
def getCommandHelp(self, command):
|
|
try:
|
|
return callbacks.PluginRegexp.getCommandMethod(self, command)
|
|
except AttributeError:
|
|
return mess[command[0]][0]
|
|
|
|
def _callCommand(self, command, irc, msg, *args, **kwargs):
|
|
method = self.getCommandMethod(command)
|
|
if command[0] in mess:
|
|
msg.tag('messcmd', command[0])
|
|
try:
|
|
method(irc, msg, *args, **kwargs)
|
|
except Exception, e:
|
|
self.log.exception('Mess: Uncaught exception in %s.', command)
|
|
if conf.supybot.reply.error.detailed():
|
|
irc.error(utils.exnToString(e))
|
|
else:
|
|
irc.replyError()
|
|
|
|
@ok
|
|
def messcb(self, irc, msg, args, text):
|
|
"""General mess"""
|
|
t = threading.Thread(target=self.messthread, args=(irc, msg, args, text))
|
|
t.start()
|
|
|
|
def messthread(self, irc, msg, args, text):
|
|
global data
|
|
cmd = msg.tagged('messcmd')
|
|
try:
|
|
(doc, loc, tx, off) = mess[cmd]
|
|
except:
|
|
cmd = cmd[1:]
|
|
(doc, loc, tx, off) = mess[cmd]
|
|
if off and not self.registryValue('offensive', msg.args[0]):
|
|
return
|
|
if loc.startswith('http'):
|
|
i = 0
|
|
while i < 5:
|
|
inp = utils.web.getUrl(loc)
|
|
fact = tx.search(inp).group('fact')
|
|
fact = filter(fact,off)
|
|
if fact:
|
|
irc.reply(fact)
|
|
return
|
|
i += 1
|
|
else:
|
|
i = random.randint(0,len(data[loc])-1)
|
|
if '%d' in tx:
|
|
tx = tx % i
|
|
irc.reply(tx + data[loc][i])
|
|
messcb = wrap(messcb, [additional('text')])
|
|
|
|
# WARNING: depends on an alteration in supybot/callbacks.py - don't do
|
|
# str(s) if s is unicode!
|
|
@ok
|
|
def dice(self, irc, msg, args, count):
|
|
"""[<count>]
|
|
Roll the dice, if count is given then roll that many times.
|
|
"""
|
|
if not count: count = 1
|
|
elif count > 5: count = 5
|
|
elif count < 1: count = 1
|
|
t = u' '.join([x.__call__([u"\u2680",u"\u2681",u"\u2682",u"\u2683",u"\u2684",u"\u2685"]) for x in [random.choice]*count])
|
|
irc.reply(t)
|
|
dice = wrap(dice, [additional('int')])
|
|
|
|
@ok
|
|
def hugme(self, irc, msg, match):
|
|
r""".*hug.*ubotu"""
|
|
irc.queueMsg(ircmsgs.action(msg.args[0], self.hugs[random.randint(0,len(self.hugs)-1)] % msg.nick))
|
|
|
|
@ok
|
|
def fortune(self, irc, msg, args):
|
|
""" Display a fortune cookie """
|
|
f = commands.getoutput('/usr/games/fortune -s')
|
|
f.replace('\t',' ')
|
|
f = f.split('\n')
|
|
for l in f:
|
|
if l:
|
|
irc.reply(l)
|
|
fortune = wrap(fortune)
|
|
|
|
@ok
|
|
def ofortune(self, irc, msg, args):
|
|
""" Display a possibly offensive fortune cookie """
|
|
if not self.registryValue('offensive', msg.args[0]):
|
|
return
|
|
f = commands.getoutput('/usr/games/fortune -so')
|
|
f.replace('\t',' ')
|
|
f = f.split('\n')
|
|
for l in f:
|
|
if l:
|
|
irc.reply(l)
|
|
ofortune = wrap(ofortune)
|
|
|
|
@ok
|
|
def futurama(self, irc, msg, args):
|
|
""" Display a futurama quote """
|
|
u = urllib2.urlopen('http://slashdot.org')
|
|
h = [x for x in u.headers.headers if x.startswith('X') and not x.startswith('X-Powered-By')][0]
|
|
irc.reply(h[2:-2].replace(' ',' "',1) + '"')
|
|
futurama = wrap(futurama)
|
|
|
|
@ok
|
|
def pony(self, irc, msg, args, text):
|
|
"""[<user>]
|
|
Can you or <user> have a pony?
|
|
"""
|
|
if not text:
|
|
text = 'you'
|
|
irc.reply("No %s can't have a pony, %s!" % (text, msg.nick))
|
|
pony = wrap(pony, [additional('text')])
|
|
|
|
def callPrecedence(self, irc):
|
|
before = []
|
|
for cb in irc.callbacks:
|
|
if cb.name() == 'IRCLogin':
|
|
before.append(cb)
|
|
return (before, [])
|
|
|
|
def inFilter(self, irc, msg):
|
|
if not msg.command == 'PRIVMSG':
|
|
return msg
|
|
if not conf.supybot.defaultIgnore():
|
|
return msg
|
|
s = callbacks.addressed(irc.nick, msg)
|
|
if not s:
|
|
return msg
|
|
if checkIgnored(msg.prefix):
|
|
return msg
|
|
try:
|
|
if ircdb.users.getUser(msg.prefix):
|
|
return msg
|
|
except:
|
|
pass
|
|
cmd, args = (s.split(None, 1) + [None])[:2]
|
|
if cmd and cmd[0] in str(conf.supybot.reply.whenAddressedBy.chars.get(msg.args[0])):
|
|
cmd = cmd[1:]
|
|
if cmd in self.listCommands():
|
|
tokens = callbacks.tokenize(s, channel=msg.args[0])
|
|
self.Proxy(irc, msg, tokens)
|
|
return msg
|
|
# self._callCommand([cmd], irc, msg, [])
|
|
Class = Mess
|