mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-30 06:49:24 +01:00
others/timeparse.py
This commit is contained in:
parent
6548085878
commit
0a2802f56e
3
TODO
3
TODO
@ -1,6 +1,9 @@
|
||||
Roughly in order of precedence (the closer to the front of the file,
|
||||
the more likely it'll be done before next release):
|
||||
|
||||
* We should have a channel-global value in ircdb.IrcChannel for
|
||||
ignoring unregistered users.
|
||||
|
||||
* It'd be nice to be able to use a backslash to continue lines in the
|
||||
registry, so we could linewrap long strings or lists.
|
||||
|
||||
|
231
others/timeparse.py
Normal file
231
others/timeparse.py
Normal file
@ -0,0 +1,231 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2004, Mike Taylor
|
||||
# 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.
|
||||
#
|
||||
|
||||
__author__ = "Mike Taylor <bear@code-bear.com>"
|
||||
__copyright__ = "Copyright (c) 2004 Mike Taylor"
|
||||
__license__ = "BSD"
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import os, string, re, time
|
||||
|
||||
RE_SPECIAL = r'(?P<special>^[in|last|next]+)\s+'
|
||||
RE_UNITS = r'\s+(?P<units>[hour|minute|second|day|week|month|year]+)'
|
||||
RE_QUNITS = r'(?P<qunits>[0-9]+[hmsdwmy])'
|
||||
RE_MODIFIER = r'(?P<modifier>[from|before|after|ago|prior]+)\s+'
|
||||
|
||||
CRE_SPECIAL = re.compile(RE_SPECIAL, re.IGNORECASE)
|
||||
CRE_UNITS = re.compile(RE_UNITS, re.IGNORECASE)
|
||||
CRE_QUNITS = re.compile(RE_QUNITS, re.IGNORECASE)
|
||||
CRE_MODIFIER = re.compile(RE_MODIFIER, re.IGNORECASE)
|
||||
|
||||
# Used to adjust the returned date before/after the source
|
||||
|
||||
_Modifiers = {'from': 1,
|
||||
'before': -1,
|
||||
'after': 1,
|
||||
'ago': 1,
|
||||
'prior': -1}
|
||||
|
||||
_Minute = 60
|
||||
_Hour = 60 * _Minute
|
||||
_Day = 24 * _Hour
|
||||
_Week = 7 * _Day
|
||||
_Month = 30 * _Day
|
||||
_Year = 365 * _Day
|
||||
|
||||
# This looks hokey - but it is a nice simple way to get
|
||||
# the proper unit value and it has the advantage that
|
||||
# later I can morph it into something localized.
|
||||
# Any trailing s will be removed before lookup.
|
||||
|
||||
_Units = {'second': 1,
|
||||
'sec': 1,
|
||||
's': 1,
|
||||
'minute': _Minute,
|
||||
'min': _Minute,
|
||||
'm': _Minute,
|
||||
'hour': _Hour,
|
||||
'hr': _Hour,
|
||||
'h': _Hour,
|
||||
'day': _Day,
|
||||
'dy': _Day,
|
||||
'd': _Day,
|
||||
'week': _Week,
|
||||
'wk': _Week,
|
||||
'w': _Week,
|
||||
'month': _Month,
|
||||
'mth': _Month,
|
||||
'm': _Month,
|
||||
'year': _Year,
|
||||
'yr': _Year,
|
||||
'y': _Year}
|
||||
|
||||
def _buildTime(sourceTime, quantity, modifier, units):
|
||||
"""Take quantity, modifier and units strings and convert them
|
||||
into values, calcuate the time and return the adjusted
|
||||
sourceTime
|
||||
"""
|
||||
# print '[%s][%s][%s]' % (quantity, modifier, units)
|
||||
|
||||
q = int(quantity)
|
||||
|
||||
if _Modifiers.has_key(modifier):
|
||||
q = q * _Modifiers[modifier]
|
||||
|
||||
if units[-1] == 's':
|
||||
units = units[:-1]
|
||||
|
||||
if _Units.has_key(units):
|
||||
u = _Units[units]
|
||||
else:
|
||||
u = 1
|
||||
|
||||
# print 'sourceTime [%d]' % sourceTime
|
||||
# print 'quantity [%d]' % q
|
||||
# print 'units [%d]' % u
|
||||
|
||||
return sourceTime + (q * u)
|
||||
|
||||
|
||||
def parse(timeString, sourceTime=None):
|
||||
"""Parse timeString and return the number of seconds from sourceTime
|
||||
that the timeString expression represents.
|
||||
|
||||
This version of parse understands only the more basic of expressions
|
||||
in this form:
|
||||
|
||||
<quantity> <units> <modifier> <target>
|
||||
|
||||
Example:
|
||||
|
||||
5 minutes from now
|
||||
last week
|
||||
2 hours before noon
|
||||
|
||||
Valid units - hour, minute, second, month, week, day and year
|
||||
(including their plural forms)
|
||||
Valid modifiers - from, before, after, ago, prior
|
||||
"""
|
||||
|
||||
if sourceTime == None:
|
||||
sourceTime = int(time.time())
|
||||
else:
|
||||
sourceTime = int(sourceTime)
|
||||
|
||||
quantity = ''
|
||||
units = ''
|
||||
modifier = ''
|
||||
target = ''
|
||||
|
||||
s = string.strip(string.lower(timeString))
|
||||
|
||||
m = CRE_SPECIAL.search(s)
|
||||
|
||||
if m <> None:
|
||||
target = 'now'
|
||||
|
||||
if m.group('special') == 'last':
|
||||
modifier = 'before'
|
||||
else:
|
||||
modifier = 'from'
|
||||
|
||||
s = s[m.end('special'):]
|
||||
|
||||
m = CRE_UNITS.search(s)
|
||||
|
||||
if m <> None:
|
||||
units = m.group('units')
|
||||
quantity = s[:m.start('units')]
|
||||
s = s[m.end('units'):]
|
||||
|
||||
else:
|
||||
m = CRE_MODIFIER.search(s)
|
||||
|
||||
if m <> None:
|
||||
modifier = m.group('modifier')
|
||||
target = s[m.end('modifier'):]
|
||||
s = s[:m.start('modifier'):]
|
||||
|
||||
m = CRE_UNITS.search(s)
|
||||
|
||||
if m <> None:
|
||||
units = m.group('units')
|
||||
quantity = s[:m.start('units')]
|
||||
target = s[m.end('units'):]
|
||||
|
||||
return _buildTime(sourceTime, quantity, modifier, units)
|
||||
|
||||
def _test(text, value):
|
||||
print text
|
||||
|
||||
v = parse(text)
|
||||
|
||||
print '\t%s\t%d\t%d' % ((v == value), value, v)
|
||||
|
||||
#
|
||||
# TODO
|
||||
#
|
||||
# - make month unit adjustment aware of the actual number of days in each
|
||||
# month between source and target
|
||||
# - handle edge case where quantity and unit are merged: 5s for 5 sec
|
||||
# - handle compound/nested quantites and modifiers
|
||||
# - bring unit test over from prototype into this file
|
||||
# - convert 'five' to 5 and also 'twenty five' to 25
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = int(time.time())
|
||||
tests = { '5 minutes from now': start + 5 * _Minute,
|
||||
'5 min from now': start + 5 * _Minute,
|
||||
'in 5 minutes': start + 5 * _Minute,
|
||||
'5 days from today': start + 5 * _Day,
|
||||
'5 days before today': start - 5 * _Day,
|
||||
'5 minutes': start + 5 * _Minute,
|
||||
'5 min': start + 5 * _Minute,
|
||||
'30 seconds from now': start + 30,
|
||||
'30 sec from now': start + 30,
|
||||
'30 seconds': start + 30,
|
||||
'30 sec': start + 30,
|
||||
'1 week': start + _Week,
|
||||
'1 wk': start + _Week,
|
||||
'1 week': start + _Week,
|
||||
'5 days': start + 5 * _Day,
|
||||
'1 year': start + _Year,
|
||||
'2 years': start + 2 * _Year}
|
||||
|
||||
for test in tests.keys():
|
||||
_test(test, tests[test])
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -45,9 +45,12 @@ import time
|
||||
sys.path.append(os.pardir)
|
||||
|
||||
import supybot.conf as conf
|
||||
import supybot.utils as utils
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.privmsgs as privmsgs
|
||||
import supybot.registry as registry
|
||||
import supybot.schedule as schedule
|
||||
import supybot.callbacks as callbacks
|
||||
|
||||
conf.registerPlugin('Ctcp')
|
||||
@ -63,8 +66,13 @@ conf.registerGlobalValue(conf.supybot.abuse.flood.ctcp, 'maximum',
|
||||
conf.registerGlobalValue(conf.supybot.abuse.flood.ctcp, 'punishment',
|
||||
registry.PositiveInteger(300, """Determines how many seconds the bot will
|
||||
ignore CTCP messages from users who flood it with CTCP messages."""))
|
||||
conf.registerGlobalValue(conf.supybot.plugins.Ctcp, 'versionWait',
|
||||
registry.PositiveInteger(10, """Determines how many seconds the bot will
|
||||
wait after getting a version command (not a CTCP VERSION, but an actual
|
||||
call of the command in this plugin named "version") before replying with
|
||||
the results it has collected."""))
|
||||
|
||||
class Ctcp(callbacks.PrivmsgRegexp):
|
||||
class Ctcp(callbacks.PrivmsgCommandAndRegexp):
|
||||
public = False
|
||||
def __init__(self):
|
||||
self.__parent = super(Ctcp, self)
|
||||
@ -96,35 +104,77 @@ class Ctcp(callbacks.PrivmsgRegexp):
|
||||
s = '\x01%s\x01' % s
|
||||
irc.reply(s, notice=True, private=True, to=msg.nick)
|
||||
|
||||
def ping(self, irc, msg, match):
|
||||
regexps = ('ctcpPing', 'ctcpVersion', 'ctcpUserinfo',
|
||||
'ctcpTime', 'ctcpFinger', 'ctcpSource')
|
||||
def ctcpPing(self, irc, msg, match):
|
||||
"\x01PING (.*)\x01"
|
||||
self.log.info('Received CTCP PING from %s', msg.prefix)
|
||||
self._reply(irc, msg, 'PING %s' % match.group(1))
|
||||
|
||||
def version(self, irc, msg, match):
|
||||
def ctcpVersion(self, irc, msg, match):
|
||||
"\x01VERSION\x01"
|
||||
self.log.info('Received CTCP VERSION from %s', msg.prefix)
|
||||
self._reply(irc, msg, 'VERSION Supybot %s' % conf.version)
|
||||
|
||||
def userinfo(self, irc, msg, match):
|
||||
def ctcpUserinfo(self, irc, msg, match):
|
||||
"\x01USERINFO\x01"
|
||||
self.log.info('Received CTCP USERINFO from %s', msg.prefix)
|
||||
self._reply(irc, msg, 'USERINFO')
|
||||
|
||||
def time(self, irc, msg, match):
|
||||
def ctcpTime(self, irc, msg, match):
|
||||
"\x01TIME\x01"
|
||||
self.log.info('Received CTCP TIME from %s' % msg.prefix)
|
||||
self._reply(irc, msg, time.ctime())
|
||||
|
||||
def finger(self, irc, msg, match):
|
||||
def ctcpFinger(self, irc, msg, match):
|
||||
"\x01FINGER\x01"
|
||||
self.log.info('Received CTCP FINGER from %s' % msg.prefix)
|
||||
self._reply(irc, msg, 'Supybot, the best Python IRC bot in existence!')
|
||||
|
||||
def source(self, irc, msg, match):
|
||||
def ctcpSource(self, irc, msg, match):
|
||||
"\x01SOURCE\x01"
|
||||
self.log.info('Received CTCP SOURCE from %s' % msg.prefix)
|
||||
self._reply(irc, msg, 'http://www.sourceforge.net/projects/supybot/')
|
||||
|
||||
def doNotice(self, irc, msg):
|
||||
if ircmsgs.isCtcp(msg):
|
||||
try:
|
||||
(version, payload) = msg.args[1][1:-1].split(None, 1)
|
||||
except ValueError:
|
||||
return
|
||||
if version == 'VERSION':
|
||||
self.versions.setdefault(payload, []).append(msg.nick)
|
||||
|
||||
def version(self, irc, msg, args):
|
||||
"""[<channel>] [--nicks]
|
||||
|
||||
Sends a CTCP VERSION to <channel>, returning the various
|
||||
version strings returned. It waits for 10 seconds before returning
|
||||
the versions received at that point. If --nicks is given, nicks are
|
||||
associated with the version strings; otherwise, only the version
|
||||
strings are given.
|
||||
"""
|
||||
self.versions = ircutils.IrcDict()
|
||||
nicks = False
|
||||
while '--nicks' in args:
|
||||
nicks = True
|
||||
args.remove('--nicks')
|
||||
channel = privmsgs.getChannel(msg, args)
|
||||
irc.queueMsg(ircmsgs.privmsg(channel, '\x01VERSION\x01'))
|
||||
def doReply():
|
||||
if self.versions:
|
||||
L = []
|
||||
for (reply, nicks) in self.versions.iteritems():
|
||||
if nicks:
|
||||
L.append('%s responded with %r' %
|
||||
(utils.commaAndify(nicks), reply))
|
||||
else:
|
||||
L.append(reply)
|
||||
irc.reply(utils.commaAndify(L))
|
||||
else:
|
||||
irc.reply('I received no version responses.')
|
||||
wait = self.registryValue('versionWait')
|
||||
schedule.addEvent(doReply, time.time()+wait)
|
||||
|
||||
Class = Ctcp
|
||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
||||
|
@ -275,8 +275,7 @@ class Debian(callbacks.Privmsg,
|
||||
r = utils.perlReToPythonRe(arg)
|
||||
predicates.append(r.search)
|
||||
except ValueError:
|
||||
irc.error('%r is not a valid regexp.' % arg)
|
||||
return
|
||||
irc.errorInvalid('regular expression', arg, Raise=True)
|
||||
elif option == '--arch':
|
||||
arg = '_%s.' % arg
|
||||
archPredicate = lambda s, arg=arg: (arg in s)
|
||||
|
@ -194,8 +194,7 @@ class Dunno(callbacks.Privmsg):
|
||||
try:
|
||||
id = int(id)
|
||||
except ValueError:
|
||||
irc.error('Invalid id: %r' % id)
|
||||
return
|
||||
irc.error('id', id, Raise=True)
|
||||
dunno = self.db.get(channel, id)
|
||||
if by != dunno.by:
|
||||
cap = ircdb.makeChannelCapability(channel, 'op')
|
||||
@ -238,8 +237,7 @@ class Dunno(callbacks.Privmsg):
|
||||
try:
|
||||
id = int(id)
|
||||
except ValueError:
|
||||
irc.error('%r is not a valid dunno id.' % id)
|
||||
return
|
||||
irc.errorInvalid('dunno id', id, Raise=True)
|
||||
try:
|
||||
dunno = self.db.get(channel, id)
|
||||
name = ircdb.users.getUser(dunno.by).name
|
||||
@ -268,18 +266,15 @@ class Dunno(callbacks.Privmsg):
|
||||
try:
|
||||
id = int(id)
|
||||
except ValueError:
|
||||
irc.error('%r is not a valid dunno id.' % id)
|
||||
return
|
||||
irc.errorInvalid('dunno id', id, Raise=True)
|
||||
try:
|
||||
_ = self.db.get(channel, id)
|
||||
except KeyError:
|
||||
irc.error('There is no dunno #%s.' % id)
|
||||
return
|
||||
try:
|
||||
replacer = utils.perlReToReplacer(regexp)
|
||||
except:
|
||||
irc.error('%r is not a valid regular expression.' % regexp)
|
||||
return
|
||||
irc.errorInvalid('regular expression', regexp, Raise=True)
|
||||
self.db.change(channel, id, replacer)
|
||||
irc.replySuccess()
|
||||
|
||||
|
@ -171,8 +171,7 @@ class Factoids(plugins.ChannelDBHandler, callbacks.Privmsg):
|
||||
try:
|
||||
irc.reply(factoids[number-1])
|
||||
except IndexError:
|
||||
irc.error('That\'s not a valid number for that key.')
|
||||
return
|
||||
irc.errorInvalid('number for that key', number, Raise=True)
|
||||
else:
|
||||
intro = self.registryValue('factoidPrefix', channel)
|
||||
prefix = '%r %s' % (key, intro)
|
||||
@ -214,8 +213,7 @@ class Factoids(plugins.ChannelDBHandler, callbacks.Privmsg):
|
||||
try:
|
||||
number = int(number)
|
||||
except ValueError:
|
||||
irc.error('%s is not a valid number.' % number)
|
||||
return
|
||||
irc.errorInvalid('number', number, Raise=True)
|
||||
else:
|
||||
number = 0
|
||||
factoids = self._lookupFactoid(channel, key)
|
||||
@ -293,8 +291,7 @@ class Factoids(plugins.ChannelDBHandler, callbacks.Privmsg):
|
||||
try:
|
||||
(_, id) = results[number]
|
||||
except IndexError:
|
||||
irc.error('Invalid factoid number.')
|
||||
return
|
||||
irc.errorInvalid('factoid number', number, Raise=True)
|
||||
cursor.execute("DELETE FROM factoids WHERE id=%s", id)
|
||||
db.commit()
|
||||
irc.replySuccess()
|
||||
@ -370,15 +367,13 @@ class Factoids(plugins.ChannelDBHandler, callbacks.Privmsg):
|
||||
try:
|
||||
replacer = utils.perlReToReplacer(regexp)
|
||||
except ValueError, e:
|
||||
irc.error('Invalid regexp: %s' % e)
|
||||
return
|
||||
irc.errorInvalid('regular expression', regexp, str(e), Raise=True)
|
||||
try:
|
||||
number = int(number)
|
||||
if number <= 0:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
irc.error('Invalid key id.')
|
||||
return
|
||||
irc.errorInvalid('id', number, Raise=True)
|
||||
db = self.getDb(channel)
|
||||
cursor = db.cursor()
|
||||
cursor.execute("""SELECT factoids.id, factoids.fact
|
||||
|
@ -101,14 +101,12 @@ class Format(callbacks.Privmsg):
|
||||
try:
|
||||
fg = ircutils.mircColors[fg]
|
||||
except KeyError:
|
||||
irc.error('%r is not a valid foreground color.' % fg)
|
||||
return
|
||||
irc.errorInvalid('foreground color', fg, Raise=True)
|
||||
if bg is not None:
|
||||
try:
|
||||
bg = ircutils.mircColors[bg]
|
||||
except KeyError:
|
||||
irc.error('%r is not a valid background color.' % bg)
|
||||
return
|
||||
irc.errorInvalid('background color', bg, Raise=True)
|
||||
irc.reply(ircutils.mircColor(text, fg=fg, bg=bg))
|
||||
|
||||
def join(self, irc, msg, args):
|
||||
@ -172,7 +170,7 @@ class Format(callbacks.Privmsg):
|
||||
try:
|
||||
size = int(size)
|
||||
except ValueError:
|
||||
irc.error('%r is not a valid integer.' % size)
|
||||
irc.errorInvalid('integer', size, Raise=True)
|
||||
irc.reply(text[:size])
|
||||
|
||||
def field(self, irc, msg, args):
|
||||
@ -187,11 +185,11 @@ class Format(callbacks.Privmsg):
|
||||
if index > 0:
|
||||
index -= 1
|
||||
except ValueError:
|
||||
irc.error('%r is not a valid integer.' % number)
|
||||
irc.errorInvalid('integer', number, Raise=True)
|
||||
try:
|
||||
irc.reply(text.split()[index])
|
||||
except IndexError:
|
||||
irc.error('That\'s not a valid field.')
|
||||
irc.errorInvalid('field')
|
||||
|
||||
def format(self, irc, msg, args):
|
||||
"""<format string> [<arg> ...]
|
||||
|
@ -252,8 +252,7 @@ class Herald(callbacks.Privmsg):
|
||||
try:
|
||||
changer = utils.perlReToReplacer(regexp)
|
||||
except ValueError, e:
|
||||
irc.error('That\'s not a valid regexp: %s.' % e)
|
||||
return
|
||||
irc.errorInvalid('regular expression', regexp, str(e), Raise=True)
|
||||
s = self.db[channel, id]
|
||||
newS = changer(s)
|
||||
self.db[channel, id] = newS
|
||||
|
@ -133,8 +133,7 @@ class Lookup(callbacks.Privmsg):
|
||||
name = privmsgs.getArgs(args)
|
||||
name = callbacks.canonicalName(name)
|
||||
if name not in self.lookupDomains:
|
||||
irc.error('That\'s not a valid lookup to remove.')
|
||||
return
|
||||
irc.errorInvalid('lookup', name, Raise=True)
|
||||
db = self.dbHandler.getDb()
|
||||
cursor = db.cursor()
|
||||
try:
|
||||
@ -249,9 +248,7 @@ class Lookup(callbacks.Privmsg):
|
||||
try:
|
||||
r = utils.perlReToPythonRe(arg)
|
||||
except ValueError, e:
|
||||
irc.error('%r is not a valid regular expression' %
|
||||
arg)
|
||||
return
|
||||
irc.errorInvalid('regular expression', arg, Raise=True)
|
||||
def p(s, r=r):
|
||||
return int(bool(r.search(s)))
|
||||
db.create_function(predicateName, 1, p)
|
||||
|
@ -194,7 +194,7 @@ class Observer(callbacks.Privmsg):
|
||||
"""
|
||||
name = privmsgs.getArgs(args)
|
||||
if name not in self.registryValue('observers'):
|
||||
irc.error('That\'s not a valid observer.', Raise=True)
|
||||
irc.errorInvalid('observer', name, Raise=True)
|
||||
g = self.registryValue('observers.%s' % name, value=False)
|
||||
regexp = g()
|
||||
command = g.command()
|
||||
@ -222,8 +222,9 @@ class Observer(callbacks.Privmsg):
|
||||
probability = 1.0
|
||||
(name, regexp, command) = privmsgs.getArgs(args, required=3)
|
||||
if not registry.isValidRegistryName(name):
|
||||
irc.error('That\'s not a valid observer name. Please be sure '
|
||||
'there are no spaces in the name.', Raise=True)
|
||||
irc.errorInvalid('observer name', name,
|
||||
'Please be sure there are no spaces in the name.',
|
||||
Raise=True)
|
||||
registerObserver(name, regexp, command, probability)
|
||||
irc.replySuccess()
|
||||
|
||||
|
@ -323,8 +323,7 @@ class Quotes(callbacks.Privmsg):
|
||||
try:
|
||||
id = int(id)
|
||||
except ValueError:
|
||||
irc.error('Invalid id: %r' % id)
|
||||
return
|
||||
irc.errorInvalid('id', id, Raise=True)
|
||||
try:
|
||||
quote = self.db.get(channel, id)
|
||||
irc.reply(str(quote))
|
||||
@ -342,7 +341,7 @@ class Quotes(callbacks.Privmsg):
|
||||
try:
|
||||
id = int(id)
|
||||
except ValueError:
|
||||
irc.error('That\'s not a valid id: %r' % id)
|
||||
irc.errorInvalid('id', id, Raise=True)
|
||||
try:
|
||||
self.db.remove(channel, id)
|
||||
irc.replySuccess()
|
||||
|
@ -112,9 +112,7 @@ class Todo(callbacks.Privmsg):
|
||||
try:
|
||||
userid = ircdb.users.getUserId(arg)
|
||||
except KeyError:
|
||||
irc.error(
|
||||
'%r is not a valid task id or username' % arg)
|
||||
return
|
||||
irc.errorInvalid('task or username', arg, Raise=True)
|
||||
db = self.dbHandler.getDb()
|
||||
cursor = db.cursor()
|
||||
if not userid and not taskid:
|
||||
@ -151,8 +149,7 @@ class Todo(callbacks.Privmsg):
|
||||
cursor.execute("""SELECT userid,priority,added_at,task,active
|
||||
FROM todo WHERE id = %s""", taskid)
|
||||
if cursor.rowcount == 0:
|
||||
irc.error('%r is not a valid task id' % taskid)
|
||||
return
|
||||
irc.errorInvalid('task id', taskid, Raise=True)
|
||||
(userid, pri, added_at, task, active) = cursor.fetchone()
|
||||
# Construct and return the reply
|
||||
user = ircdb.users.getUser(userid)
|
||||
@ -191,8 +188,7 @@ class Todo(callbacks.Privmsg):
|
||||
try:
|
||||
priority = int(arg)
|
||||
except ValueError, e:
|
||||
irc.error('%r is an invalid priority' % arg)
|
||||
return
|
||||
irc.errorInvalid('priority', arg, Raise=True)
|
||||
text = privmsgs.getArgs(rest)
|
||||
db = self.dbHandler.getDb()
|
||||
cursor = db.cursor()
|
||||
@ -272,9 +268,7 @@ class Todo(callbacks.Privmsg):
|
||||
try:
|
||||
r = utils.perlReToPythonRe(arg)
|
||||
except ValueError, e:
|
||||
irc.error('%r is not a valid regular expression' %
|
||||
arg)
|
||||
return
|
||||
irc.errorInvalid('regular expression', arg, Raise=True)
|
||||
def p(s, r=r):
|
||||
return int(bool(r.search(s)))
|
||||
db.create_function(predicateName, 1, p)
|
||||
@ -337,19 +331,17 @@ class Todo(callbacks.Privmsg):
|
||||
try:
|
||||
replacer = utils.perlReToReplacer(regexp)
|
||||
except ValueError:
|
||||
irc.error('%r is not a valid regexp' % regexp)
|
||||
return
|
||||
irc.errorInvalid('regular expression', regexp, Raise=True)
|
||||
db = self.dbHandler.getDb()
|
||||
cursor = db.cursor()
|
||||
cursor.execute("""SELECT task FROM todo
|
||||
WHERE userid = %s AND id = %s
|
||||
AND active = 1""", userid, taskid)
|
||||
if cursor.rowcount == 0:
|
||||
irc.error('%r is not a valid task id' % taskid)
|
||||
return
|
||||
irc.errorInvalid('task id', taskid, Raise=True)
|
||||
newtext = replacer(cursor.fetchone()[0])
|
||||
cursor.execute("""UPDATE todo SET task = %s
|
||||
WHERE id = %s""", newtext, taskid)
|
||||
cursor.execute("""UPDATE todo SET task = %s WHERE id = %s""",
|
||||
newtext, taskid)
|
||||
db.commit()
|
||||
irc.replySuccess()
|
||||
|
||||
|
@ -166,7 +166,7 @@ class Topic(callbacks.Privmsg):
|
||||
n += len(topics)
|
||||
return n
|
||||
except (ValueError, IndexError):
|
||||
irc.error('That\'s not a valid topic number.', Raise=True)
|
||||
irc.errorInvalid('topic number', n, Raise=True)
|
||||
|
||||
def topic(self, irc, msg, args, channel):
|
||||
"""[<channel>]
|
||||
@ -308,14 +308,12 @@ class Topic(callbacks.Privmsg):
|
||||
(number, regexp) = privmsgs.getArgs(args, required=2)
|
||||
topics = self._splitTopic(irc.state.getTopic(channel), channel)
|
||||
if not topics:
|
||||
irc.error('There are no topics to change.')
|
||||
return
|
||||
irc.error('There are no topics to change.', Raise=True)
|
||||
number = self._topicNumber(irc, number, topics=topics)
|
||||
try:
|
||||
replacer = utils.perlReToReplacer(regexp)
|
||||
except ValueError, e:
|
||||
irc.error('The regexp wasn\'t valid: %s' % e)
|
||||
return
|
||||
irc.errorInvalid('regexp', regexp, Raise=True)
|
||||
topics[number] = replacer(topics[number])
|
||||
self._sendTopics(irc, channel, topics)
|
||||
change = privmsgs.channel(change)
|
||||
|
@ -303,10 +303,10 @@ class Words(callbacks.Privmsg):
|
||||
else:
|
||||
# User input an invalid character
|
||||
if len(letter) == 1:
|
||||
irc.error('That is not a valid letter.')
|
||||
irc.errorInvalid('letter', letter, Raise=True)
|
||||
# User input an invalid word (len(try) != len(hidden))
|
||||
else:
|
||||
irc.error('That is not a valid word guess.')
|
||||
irc.errorInvalid('word guess', letter, Raise=True)
|
||||
# Verify if the user won or lost
|
||||
if game.guessed and game.tries > 0:
|
||||
self._hangmanReply(irc, channel,
|
||||
|
Loading…
Reference in New Issue
Block a user