mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-01-11 12:42:34 +01:00
Made Configurable persistent.
This commit is contained in:
parent
028b23d41c
commit
5149d17b6a
@ -87,12 +87,13 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
threaded = True
|
||||
regexps = ['bzSnarfer']
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('bug-snarfer', plugins.ConfigurableTypes.bool, True,
|
||||
[('bug-snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the bug snarfer will be enabled, such that any
|
||||
Bugzilla URLs seen in the channel will have their information reported
|
||||
into the channel.""")]
|
||||
)
|
||||
def __init__(self):
|
||||
plugins.Configurable.__init__(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||
self.entre = re.compile('&(\S*?);')
|
||||
# Schema: {name, [url, description]}
|
||||
@ -100,6 +101,7 @@ class Bugzilla(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
self.shorthand = utils.abbrev(self.db.keys())
|
||||
|
||||
def die(self):
|
||||
plugins.Configurable.die(self)
|
||||
self.db.close()
|
||||
del self.db
|
||||
|
||||
|
@ -59,23 +59,29 @@ frowns = (':|', ':-/', ':-\\', ':\\', ':/', ':(', ':-(', ':\'(')
|
||||
smileyre = re.compile('|'.join(map(re.escape, smileys)))
|
||||
frownre = re.compile('|'.join(map(re.escape, frowns)))
|
||||
|
||||
class ChannelDB(plugins.ChannelDBHandler, # Must be first (die).
|
||||
class ChannelDB(plugins.ChannelDBHandler,
|
||||
plugins.Configurable,
|
||||
callbacks.Privmsg):
|
||||
noIgnore = True
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('self-stats', plugins.ConfigurableTypes.bool, True,
|
||||
[('self-stats', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the bot will keep channel statistics on itself,
|
||||
possibly skewing the channel stats (especially in cases where he's
|
||||
relaying between channels on a network.""")]
|
||||
)
|
||||
def __init__(self):
|
||||
callbacks.Privmsg.__init__(self)
|
||||
plugins.Configurable.__init__(self)
|
||||
plugins.ChannelDBHandler.__init__(self)
|
||||
self.lastmsg = None
|
||||
self.laststate = None
|
||||
self.outFiltering = False
|
||||
|
||||
def die(self):
|
||||
callbacks.Privmsg.die(self)
|
||||
plugins.Configurable.die(self)
|
||||
plugins.ChannelDBHandler.die(self)
|
||||
|
||||
def makeDb(self, filename):
|
||||
if os.path.exists(filename):
|
||||
db = sqlite.connect(filename)
|
||||
|
@ -72,13 +72,18 @@ class Ebay(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
threaded = True
|
||||
regexps = ['ebaySnarfer']
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('snarfer', utils.safeEval, True,
|
||||
[('snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the bot will automatically 'snarf' Ebay auction
|
||||
URLs and print information about them.""")]
|
||||
)
|
||||
def __init__(self):
|
||||
plugins.Configurable.__init__(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||
|
||||
def die(self):
|
||||
plugins.Configurable.die(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.die(self)
|
||||
|
||||
_reopts = re.I | re.S
|
||||
_invalid = re.compile(r'(is invalid, still pending, or no longer in our '\
|
||||
'database)', _reopts)
|
||||
|
@ -61,19 +61,24 @@ def configure(onStart, afterConnect, advanced):
|
||||
_chanCap = ircdb.makeChannelCapability
|
||||
class Enforcer(callbacks.Privmsg, plugins.Configurable):
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('auto-op', plugins.ConfigurableTypes.bool, False,
|
||||
[('auto-op', plugins.ConfigurableBoolType, False,
|
||||
"""Determines whether the bot will automatically op people with
|
||||
the <channel>.op capability when they join the channel."""),
|
||||
('auto-voice', plugins.ConfigurableTypes.bool, False,
|
||||
('auto-voice', plugins.ConfigurableBoolType, False,
|
||||
"""Determines whether the bot will automatically voice people with
|
||||
the <channel>.voice capability when they join the channel."""),
|
||||
('auto-halfop', plugins.ConfigurableTypes.bool, False,
|
||||
('auto-halfop', plugins.ConfigurableBoolType, False,
|
||||
"""Determines whether the bot will automatically halfop people with
|
||||
the <channel>.halfop capability when they join the channel."""),]
|
||||
)
|
||||
started = False
|
||||
def __init__(self):
|
||||
callbacks.Privmsg.__init__(self)
|
||||
plugins.Configurable.__init__(self)
|
||||
|
||||
def die(self):
|
||||
callbacks.Privmsg.die(self)
|
||||
plugins.Configurable.die(self)
|
||||
|
||||
def start(self, irc, msg, args):
|
||||
"""[<CHANSERV> <revenge>]
|
||||
|
@ -72,11 +72,11 @@ class Gameknot(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
threaded = True
|
||||
regexps = ['gameknotSnarfer', 'gameknotStatsSnarfer']
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('game-snarfer', plugins.ConfigurableTypes.bool, True,
|
||||
[('game-snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the game URL snarfer is active; if so, the bot
|
||||
will reply to the channel with a summary of the game data when it
|
||||
sees a Gameknot game on the channel."""),
|
||||
('stats-snarfer', plugins.ConfigurableTypes.bool, True,
|
||||
('stats-snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the stats URL snarfer is active; if so, the bot
|
||||
will reply to the channel with a summary of the stats of any player
|
||||
whose stats URL is seen on the channel.""")]
|
||||
@ -87,6 +87,14 @@ class Gameknot(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
'"#FFFF00">(\d+)')
|
||||
_gkteam = re.compile(r'Team:(<.*?>)+(?P<name>.*?)</span>')
|
||||
_gkseen = re.compile(r'(seen on GK:\s+([^[]+ago)|.*?is hiding.*?)')
|
||||
def __init__(self):
|
||||
plugins.Configurable.__init__(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||
|
||||
def die(self):
|
||||
plugins.Configurable.die(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.die(self)
|
||||
|
||||
def getStats(self, name):
|
||||
gkprofile = 'http://www.gameknot.com/stats.pl?%s' % name
|
||||
try:
|
||||
|
@ -123,21 +123,26 @@ class Google(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
threaded = True
|
||||
regexps = sets.Set(['googleSnarfer', 'googleGroups'])
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('groups-snarfer', plugins.ConfigurableTypes.bool, True,
|
||||
[('groups-snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the groups snarfer is enabled. If so, URLs at
|
||||
groups.google.com will be snarfed and their group/title messaged to
|
||||
the channel."""),
|
||||
('search-snarfer', plugins.ConfigurableTypes.bool, False,
|
||||
('search-snarfer', plugins.ConfigurableBoolType, False,
|
||||
"""Determines whether the search snarfer is enabled. If so, messages
|
||||
(even unaddressed ones) beginning with the word 'google' will result
|
||||
in the first URL Google returns being sent to the channel.""")]
|
||||
)
|
||||
def __init__(self):
|
||||
super(Google, self).__init__()
|
||||
plugins.Configurable.__init__(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||
self.total = 0
|
||||
self.totalTime = 0
|
||||
self.last24hours = structures.queue()
|
||||
|
||||
def die(self):
|
||||
plugins.Configurable.die(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.die(self)
|
||||
|
||||
def formatData(self, data):
|
||||
if isinstance(data, basestring):
|
||||
return data
|
||||
|
@ -75,12 +75,20 @@ class Python(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
threaded = True
|
||||
regexps = ['aspnRecipes']
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('aspn-snarfer', plugins.ConfigurableTypes.bool, True,
|
||||
[('aspn-snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the ASPN Python recipe snarfer is enabled. If
|
||||
so, it will message the channel with the name of the recipe when it
|
||||
sees an ASPN Python recipe link on the channel.""")]
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
plugins.Configurable.__init__(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||
|
||||
def die(self):
|
||||
plugins.Configurable.die(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.die(self)
|
||||
|
||||
def pydoc(self, irc, msg, args):
|
||||
"""<python function>
|
||||
|
||||
|
@ -66,7 +66,7 @@ class QuoteGrabs(plugins.ChannelDBHandler,
|
||||
plugins.Configurable,
|
||||
callbacks.Privmsg):
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('random-grabber', plugins.ConfigurableTypes.bool, False,
|
||||
[('random-grabber', plugins.ConfigurableBoolType, False,
|
||||
"""Determines whether the bot will randomly grab possibly-suitable
|
||||
quotes for someone."""),]
|
||||
)
|
||||
|
@ -95,12 +95,13 @@ class Relay(callbacks.Privmsg, plugins.Configurable):
|
||||
noIgnore = True
|
||||
priority = sys.maxint
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('color', plugins.ConfigurableTypes.bool, True,
|
||||
[('color', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the bot will color relayed PRIVMSGs so as to
|
||||
make the messages easier to read."""),]
|
||||
)
|
||||
def __init__(self):
|
||||
callbacks.Privmsg.__init__(self)
|
||||
plugins.Configurable.__init__(self)
|
||||
self.ircs = {}
|
||||
self._color = 0
|
||||
self._whois = {}
|
||||
@ -122,6 +123,8 @@ class Relay(callbacks.Privmsg, plugins.Configurable):
|
||||
callbacks.Privmsg.__call__(self, irc, msg)
|
||||
|
||||
def die(self):
|
||||
callbacks.Privmsg.die(self)
|
||||
plugins.Configurable.die(self)
|
||||
for irc in self.abbreviations:
|
||||
if irc != self.originalIrc:
|
||||
irc.callbacks[:] = []
|
||||
|
@ -98,14 +98,21 @@ class Sourceforge(callbacks.PrivmsgCommandAndRegexp, plugins.Configurable):
|
||||
_res =(_resolution, _assigned, _submitted, _priority, _status)
|
||||
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('tracker-snarfer', plugins.ConfigurableTypes.bool, True,
|
||||
[('tracker-snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the bot will reply to SF.net Tracker URLs in
|
||||
the channel with a nice summary of the tracker item."""),
|
||||
('default-project', plugins.ConfigurableTypes.str, '',
|
||||
('default-project', plugins.ConfigurableStrType, '',
|
||||
"""Sets the default project (used by the bugs/rfes commands in the
|
||||
case that no explicit project is given).""")]
|
||||
)
|
||||
_projectURL = 'http://sourceforge.net/projects/'
|
||||
def __init__(self):
|
||||
plugins.Configurable.__init__(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.__init__(self)
|
||||
|
||||
def die(self):
|
||||
plugins.Configurable.die(self)
|
||||
callbacks.PrivmsgCommandAndRegexp.die(self)
|
||||
|
||||
def _formatResp(self, text, num=''):
|
||||
"""
|
||||
|
@ -64,18 +64,24 @@ def configure(onStart, afterConnect, advanced):
|
||||
|
||||
class URL(callbacks.Privmsg, plugins.Configurable, plugins.ChannelDBHandler):
|
||||
configurables = plugins.ConfigurableDictionary(
|
||||
[('tinyurl-snarfer', plugins.ConfigurableTypes.bool, True,
|
||||
[('tinyurl-snarfer', plugins.ConfigurableBoolType, True,
|
||||
"""Determines whether the bot will output shorter versions of URLs
|
||||
longer than the tinyurl-minimum-length config variable."""),
|
||||
('tinyurl-minimum-length', plugins.ConfigurableTypes.int, 46,
|
||||
('tinyurl-minimum-length', plugins.ConfigurableIntType, 46,
|
||||
"""The minimum length a URL must be before the tinyurl-snarfer will
|
||||
snarf it and offer a tinyurl replacement."""),]
|
||||
)
|
||||
def __init__(self):
|
||||
self.nextMsgs = {}
|
||||
callbacks.Privmsg.__init__(self)
|
||||
plugins.Configurable.__init__(self)
|
||||
plugins.ChannelDBHandler.__init__(self)
|
||||
|
||||
def die(self):
|
||||
callbacks.Privmsg.die(self)
|
||||
plugins.Configurable.die(self)
|
||||
plugins.ChannelDBHandler.die(self)
|
||||
|
||||
def makeDb(self, filename):
|
||||
if os.path.exists(filename):
|
||||
return sqlite.connect(filename)
|
||||
|
@ -41,6 +41,7 @@ import types
|
||||
import random
|
||||
import urllib2
|
||||
import threading
|
||||
import cPickle as pickle
|
||||
|
||||
import fix
|
||||
import cdb
|
||||
@ -53,11 +54,6 @@ import ircutils
|
||||
import privmsgs
|
||||
import callbacks
|
||||
|
||||
__all__ = ['ChannelDBHandler',
|
||||
'PeriodicFileDownloader',
|
||||
'ConfigurableDictionary',
|
||||
'Configurable']
|
||||
|
||||
class ChannelDBHandler(object):
|
||||
"""A class to handle database stuff for individual channels transparently.
|
||||
"""
|
||||
@ -244,41 +240,35 @@ class ConfigurableDictionary(object):
|
||||
def names(self):
|
||||
return self.originalNames
|
||||
|
||||
# XXX: Make persistent.
|
||||
|
||||
class ConfigurableTypeError(TypeError):
|
||||
pass
|
||||
|
||||
class _ConfigurableTypes(object):
|
||||
def bool(self, s):
|
||||
s = s.lower()
|
||||
if s in ('true', 'enable', 'on'):
|
||||
return True
|
||||
elif s in ('false', 'disable', 'off'):
|
||||
return False
|
||||
else:
|
||||
s = 'Value must be one of on/off/true/false/enable/disable.'
|
||||
raise ConfigurableTypeError, s
|
||||
def ConfigurableBoolType(s):
|
||||
s = s.lower()
|
||||
if s in ('true', 'enable', 'on'):
|
||||
return True
|
||||
elif s in ('false', 'disable', 'off'):
|
||||
return False
|
||||
else:
|
||||
s = 'Value must be one of on/off/true/false/enable/disable.'
|
||||
raise ConfigurableTypeError, s
|
||||
|
||||
def str(self, s):
|
||||
if s and s[0] not in '\'"' and s[-1] not in '\'"':
|
||||
s = repr(s)
|
||||
try:
|
||||
v = utils.safeEval(s)
|
||||
if type(v) is not str:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
raise ConfigurableTypeError, 'Value must be a string.'
|
||||
return v
|
||||
def ConfigurableStrType(s):
|
||||
if s and s[0] not in '\'"' and s[-1] not in '\'"':
|
||||
s = repr(s)
|
||||
try:
|
||||
v = utils.safeEval(s)
|
||||
if type(v) is not str:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
raise ConfigurableTypeError, 'Value must be a string.'
|
||||
return v
|
||||
|
||||
def int(self, s):
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
raise ConfigurableTypeError, 'Value must be an int.'
|
||||
ConfigurableTypes = _ConfigurableTypes()
|
||||
|
||||
foobar = 'baz'
|
||||
def ConfigurableIntType(s):
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
raise ConfigurableTypeError, 'Value must be an int.'
|
||||
|
||||
class Configurable(object):
|
||||
"""A mixin class to provide a "config" command that can be consistent
|
||||
@ -292,6 +282,21 @@ class Configurable(object):
|
||||
variable should take on; help is a string that'll be returned to describe
|
||||
the purpose of the config variable.
|
||||
"""
|
||||
def __init__(self):
|
||||
className = self.__class__.__name__
|
||||
self.filename = os.path.join(conf.confDir,'%s-configurable'%className)
|
||||
try:
|
||||
if os.path.exists(self.filename):
|
||||
configurables = pickle.load(file(self.filename, 'rb'))
|
||||
if configurables.names() == self.configurables.names():
|
||||
self.configurables = configurables
|
||||
except Exception, e:
|
||||
debug.msg('%s raised when trying to unpickle %s configurables' %
|
||||
(debug.exnToString(e), className))
|
||||
|
||||
def die(self):
|
||||
pickle.dump(self.configurables, file(self.filename, 'wb'), -1)
|
||||
|
||||
def config(self, irc, msg, args):
|
||||
"""[<channel>] [<name>] [<value>]
|
||||
|
||||
@ -318,7 +323,7 @@ class Configurable(object):
|
||||
return
|
||||
if not value:
|
||||
help = self.configurables.help(name)
|
||||
value = self.configurables.get(name)
|
||||
value = self.configurables.get(name, channel=channel)
|
||||
irc.reply(msg, '%s: %s (Current value: %r)' % (name, help, value))
|
||||
return
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user