mirror of
https://github.com/ncoevoet/ChanTracker.git
synced 2025-04-26 13:01:06 -05:00
Various improvements.
* Handle 'edit' and 'editandmark' strict wrt expected arguments. * Allow specifying duration using multiple units as single string. * Improve handling of items prompted for commenting. * Improve exempting commands from prompt input. * Improve consistency in coloring output. * Improve smartlog handling.
This commit is contained in:
parent
0d257df7d6
commit
4c53d28f11
129
plugin.py
129
plugin.py
@ -51,6 +51,15 @@ mcidr = re.compile(r'^(\d{1,3}\.){0,3}\d{1,3}/\d{1,2}$')
|
|||||||
m6cidr = re.compile(r'^([0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}/\d{1,3}$')
|
m6cidr = re.compile(r'^([0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}/\d{1,3}$')
|
||||||
|
|
||||||
|
|
||||||
|
def checkAddressed(irc, text, channel):
|
||||||
|
if irc.isChannel(channel):
|
||||||
|
if text[0] in str(conf.supybot.reply.whenAddressedBy.chars.get(channel)):
|
||||||
|
return True
|
||||||
|
elif text[0] in conf.supybot.reply.whenAddressedBy.chars():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def isCommand(irc, text):
|
def isCommand(irc, text):
|
||||||
args = text.lower().split(None, 2)
|
args = text.lower().split(None, 2)
|
||||||
for c in irc.callbacks:
|
for c in irc.callbacks:
|
||||||
@ -768,7 +777,7 @@ class Ircd(object):
|
|||||||
db.commit()
|
db.commit()
|
||||||
if logFunction:
|
if logFunction:
|
||||||
key = '%s|%s' % (kind, mask)
|
key = '%s|%s' % (kind, mask)
|
||||||
if key in ct.smartLog:
|
if key in ct.smartLog and ct.smartLog[key]:
|
||||||
message = 'and marked: %s' % message
|
message = 'and marked: %s' % message
|
||||||
message = '; '.join(ct.smartLog[key] + [message])
|
message = '; '.join(ct.smartLog[key] + [message])
|
||||||
del ct.smartLog[key]
|
del ct.smartLog[key]
|
||||||
@ -869,10 +878,10 @@ class Ircd(object):
|
|||||||
(uid, channel, kind, mask, begin_at, end_at) = L[0]
|
(uid, channel, kind, mask, begin_at, end_at) = L[0]
|
||||||
chan = self.getChan(irc, channel)
|
chan = self.getChan(irc, channel)
|
||||||
current = time.time()
|
current = time.time()
|
||||||
if begin_at == end_at and seconds < 0:
|
if begin_at == end_at:
|
||||||
|
if seconds < 0:
|
||||||
c.close()
|
c.close()
|
||||||
return True
|
return True
|
||||||
if begin_at == end_at:
|
|
||||||
text = 'was set forever'
|
text = 'was set forever'
|
||||||
else:
|
else:
|
||||||
text = 'ended [%s] for %s' % (
|
text = 'ended [%s] for %s' % (
|
||||||
@ -912,7 +921,6 @@ class Ircd(object):
|
|||||||
else:
|
else:
|
||||||
message = '[%s] [#%s +%s %s] edited by %s: %s' % (
|
message = '[%s] [#%s +%s %s] edited by %s: %s' % (
|
||||||
channel, uid, kind, mask, prefix.split('!')[0], expires)
|
channel, uid, kind, mask, prefix.split('!')[0], expires)
|
||||||
key = '%s|%s' % (kind, mask)
|
|
||||||
if key in ct.smartLog:
|
if key in ct.smartLog:
|
||||||
ct.smartLog[key].append(message)
|
ct.smartLog[key].append(message)
|
||||||
else:
|
else:
|
||||||
@ -952,8 +960,9 @@ class Ircd(object):
|
|||||||
db.commit()
|
db.commit()
|
||||||
if logFunction:
|
if logFunction:
|
||||||
if ct.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
if ct.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
||||||
logFunction(irc, channel, '[%s] [%s] %s removed: %s' % (
|
logFunction(irc, channel, '[%s] [%s] %s removed: %s' % (ircutils.bold(
|
||||||
ircutils.bold(channel), ircutils.mircColor(mode, 'green'), commits, ' '.join(msgs)))
|
channel), ircutils.bold(ircutils.mircColor(mode, 'green')),
|
||||||
|
commits, ' '.join(msgs)))
|
||||||
else:
|
else:
|
||||||
logFunction(irc, channel, '[%s] [%s] %s removed: %s' % (
|
logFunction(irc, channel, '[%s] [%s] %s removed: %s' % (
|
||||||
channel, mode, commits, ' '.join(msgs)))
|
channel, mode, commits, ' '.join(msgs)))
|
||||||
@ -1172,7 +1181,7 @@ class Chan(object):
|
|||||||
(removed_at, by, int(i.uid)))
|
(removed_at, by, int(i.uid)))
|
||||||
i.removed_by = by
|
i.removed_by = by
|
||||||
i.removed_at = removed_at
|
i.removed_at = removed_at
|
||||||
self._lists[mode].pop(value)
|
del self._lists[mode][value]
|
||||||
return i
|
return i
|
||||||
|
|
||||||
def addpattern(self, prefix, limit, life, mode, duration, pattern, regexp, db):
|
def addpattern(self, prefix, limit, life, mode, duration, pattern, regexp, db):
|
||||||
@ -1339,7 +1348,7 @@ class Nick(object):
|
|||||||
|
|
||||||
def addLog(self, target, message):
|
def addLog(self, target, message):
|
||||||
if len(self.logs) == self.logSize:
|
if len(self.logs) == self.logSize:
|
||||||
self.logs.pop(0)
|
del self.logs[0]
|
||||||
self.logs.append([time.time(), target, message])
|
self.logs.append([time.time(), target, message])
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -1411,33 +1420,14 @@ addConverter('getPatternAndMatcher', getPatternAndMatcher)
|
|||||||
|
|
||||||
|
|
||||||
# Taken from plugins.Time.seconds
|
# Taken from plugins.Time.seconds
|
||||||
|
_SECONDS_RE = re.compile(r'-?[0-9]+[ywdhms]')
|
||||||
def getTs(irc, msg, args, state):
|
def getTs(irc, msg, args, state):
|
||||||
"""[<years>y] [<weeks>w] [<days>d] [<hours>h] [<minutes>m] [<seconds>s]
|
seconds = None
|
||||||
|
secs = _SECONDS_RE.findall(args[0])
|
||||||
Returns the number of seconds in the number of <years>, <weeks>,
|
for sec in secs:
|
||||||
<days>, <hours>, <minutes>, and <seconds> given. An example usage is
|
(i, kind) = int(sec[:-1]), sec[-1]
|
||||||
"seconds 2h 30m", which would return 9000, which is '3600*2 + 30*60'.
|
if seconds is None:
|
||||||
Useful for scheduling events at a given number of seconds in the
|
seconds = 0
|
||||||
future.
|
|
||||||
"""
|
|
||||||
# here there is some glitch / ugly hack to allow any('getTs'), with rest('test') after...
|
|
||||||
# TODO: check that bot can't kill itself with loop
|
|
||||||
seconds = -1
|
|
||||||
items = list(args)
|
|
||||||
for arg in items:
|
|
||||||
if not (arg and arg[-1] in 'ywdhms'):
|
|
||||||
try:
|
|
||||||
n = int(arg)
|
|
||||||
state.args.append(n)
|
|
||||||
except:
|
|
||||||
state.args.append(float(seconds))
|
|
||||||
raise callbacks.ArgumentError
|
|
||||||
(s, kind) = arg[:-1], arg[-1]
|
|
||||||
try:
|
|
||||||
i = int(s)
|
|
||||||
except ValueError:
|
|
||||||
state.args.append(float(seconds))
|
|
||||||
raise callbacks.ArgumentError
|
|
||||||
if kind == 'y':
|
if kind == 'y':
|
||||||
seconds += i*31536000
|
seconds += i*31536000
|
||||||
elif kind == 'w':
|
elif kind == 'w':
|
||||||
@ -1449,13 +1439,10 @@ def getTs(irc, msg, args, state):
|
|||||||
elif kind == 'm':
|
elif kind == 'm':
|
||||||
seconds += i*60
|
seconds += i*60
|
||||||
elif kind == 's':
|
elif kind == 's':
|
||||||
if i == 0:
|
|
||||||
i = 1
|
|
||||||
seconds += i
|
seconds += i
|
||||||
elif kind == '-':
|
if seconds is None:
|
||||||
state.args.append(float(seconds))
|
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
args.pop(0)
|
del args[0]
|
||||||
state.args.append(float(seconds))
|
state.args.append(float(seconds))
|
||||||
|
|
||||||
|
|
||||||
@ -1479,7 +1466,7 @@ addConverter('proba', getProba)
|
|||||||
def getDuration(seconds):
|
def getDuration(seconds):
|
||||||
if not len(seconds):
|
if not len(seconds):
|
||||||
return -1
|
return -1
|
||||||
return seconds[0]
|
return sum(seconds)
|
||||||
|
|
||||||
|
|
||||||
def getWrapper(name):
|
def getWrapper(name):
|
||||||
@ -1541,11 +1528,11 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
toNag = mode
|
toNag = mode
|
||||||
break
|
break
|
||||||
if len(toNag):
|
if len(toNag):
|
||||||
message = '[%s] has %s mode' % (channel, toNag)
|
|
||||||
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
||||||
message = '[%s] has %s mode' % (
|
self._logChan(irc, channel, '[%s] has %s mode' % (
|
||||||
ircutils.bold(channel), ircutils.mircColor(toNag, 'red'))
|
ircutils.bold(channel), ircutils.bold(ircutils.mircColor(toNag, 'red'))))
|
||||||
self._logChan(irc, channel, message)
|
else:
|
||||||
|
self._logChan(irc, channel, '[%s] has %s mode' % (channel, toNag))
|
||||||
if self.registryValue('announceNagInterval') > 0:
|
if self.registryValue('announceNagInterval') > 0:
|
||||||
schedule.addEvent(self.checkNag, time.time() +
|
schedule.addEvent(self.checkNag, time.time() +
|
||||||
self.registryValue('announceNagInterval'), 'ChanTracker')
|
self.registryValue('announceNagInterval'), 'ChanTracker')
|
||||||
@ -1650,11 +1637,16 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
break
|
break
|
||||||
if b:
|
if b:
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
|
self.hasAskedItems(irc, msg.prefix, remove=True, prompt=False)
|
||||||
|
found = self.hasAskedItems(irc, msg.prefix, remove=False, prompt=True)
|
||||||
|
if found:
|
||||||
|
i.askedItems[msg.prefix][found[0]][6] = True
|
||||||
|
i.lowQueue.enqueue(ircmsgs.privmsg(msg.nick, found[5]))
|
||||||
else:
|
else:
|
||||||
irc.reply('item not found, already removed or not enough rights to modify it')
|
irc.reply('item not found, already removed or not enough rights to modify it')
|
||||||
self.forceTickle = True
|
self.forceTickle = True
|
||||||
self._tickle(irc)
|
self._tickle(irc)
|
||||||
editandmark = wrap(editandmark, ['user', commalist('int'), any('getTs', True), optional('text')])
|
editandmark = wrap(editandmark, ['user', commalist('int'), many('getTs', True), rest('text')])
|
||||||
|
|
||||||
def edit(self, irc, msg, args, user, ids, seconds):
|
def edit(self, irc, msg, args, user, ids, seconds):
|
||||||
"""<id>[,<id>] [<years>y] [<weeks>w] [<days>d] [<hours>h] [<minutes>m] [<seconds>s]
|
"""<id>[,<id>] [<years>y] [<weeks>w] [<days>d] [<hours>h] [<minutes>m] [<seconds>s]
|
||||||
@ -1690,7 +1682,7 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
irc.reply('item not found, already removed or not enough rights to modify it')
|
irc.reply('item not found, already removed or not enough rights to modify it')
|
||||||
self.forceTickle = True
|
self.forceTickle = True
|
||||||
self._tickle(irc)
|
self._tickle(irc)
|
||||||
edit = wrap(edit, ['user', commalist('int'), any('getTs')])
|
edit = wrap(edit, ['user', commalist('int'), many('getTs')])
|
||||||
|
|
||||||
def info(self, irc, msg, args, user, uid):
|
def info(self, irc, msg, args, user, uid):
|
||||||
"""<id>
|
"""<id>
|
||||||
@ -2118,11 +2110,12 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
return
|
return
|
||||||
if not text:
|
if not text:
|
||||||
text = ''
|
text = ''
|
||||||
schannel = channel
|
|
||||||
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
||||||
schannel = ircutils.bold(channel)
|
|
||||||
self._logChan(irc, channel, "[%s] %s wants attention from ops (%s)" % (
|
self._logChan(irc, channel, "[%s] %s wants attention from ops (%s)" % (
|
||||||
schannel, msg.prefix, text))
|
ircutils.bold(channel), msg.prefix, text))
|
||||||
|
else:
|
||||||
|
self._logChan(irc, channel, "[%s] %s wants attention from ops (%s)" % (
|
||||||
|
channel, msg.prefix, text))
|
||||||
self.forceTickle = True
|
self.forceTickle = True
|
||||||
self._tickle(irc)
|
self._tickle(irc)
|
||||||
ops = wrap(ops, ['channel', optional('text')])
|
ops = wrap(ops, ['channel', optional('text')])
|
||||||
@ -3016,7 +3009,7 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
s = s.replace('$channel', channel)
|
s = s.replace('$channel', channel)
|
||||||
s = s.replace('$hostmask', value)
|
s = s.replace('$hostmask', value)
|
||||||
i.queue.enqueue(ircmsgs.IrcMsg(s))
|
i.queue.enqueue(ircmsgs.IrcMsg(s))
|
||||||
chan.queue.pop(index)
|
del chan.queue[index]
|
||||||
index += 1
|
index += 1
|
||||||
if not irc.state.channels[channel].isHalfopPlus(irc.nick):
|
if not irc.state.channels[channel].isHalfopPlus(irc.nick):
|
||||||
chan.deopAsked = False
|
chan.deopAsked = False
|
||||||
@ -3436,8 +3429,12 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
clones.append(nick)
|
clones.append(nick)
|
||||||
if len(clones) > permit:
|
if len(clones) > permit:
|
||||||
if self.registryValue('cloneMode', channel=channel, network=irc.network) == 'd':
|
if self.registryValue('cloneMode', channel=channel, network=irc.network) == 'd':
|
||||||
|
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
||||||
self._logChan(irc, channel, '[%s] clones (%s) detected (%s)' % (
|
self._logChan(irc, channel, '[%s] clones (%s) detected (%s)' % (
|
||||||
ircutils.bold(channel), best, ', '.join(clones)))
|
ircutils.bold(channel), best, ', '.join(clones)))
|
||||||
|
else:
|
||||||
|
self._logChan(irc, channel, '[%s] clones (%s) detected (%s)' % (
|
||||||
|
channel, best, ', '.join(clones)))
|
||||||
else:
|
else:
|
||||||
(m, p) = self.getIrcdMode(irc, self.registryValue(
|
(m, p) = self.getIrcdMode(irc, self.registryValue(
|
||||||
'cloneMode', channel=channel, network=irc.network), best)
|
'cloneMode', channel=channel, network=irc.network), best)
|
||||||
@ -3474,8 +3471,8 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
if reason.startswith('requested by') \
|
if reason.startswith('requested by') \
|
||||||
and self.registryValue('announceKick', channel=channel, network=irc.network):
|
and self.registryValue('announceKick', channel=channel, network=irc.network):
|
||||||
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
||||||
self._logChan(irc, channel, '[%s] %s has left (%s)' % (
|
self._logChan(irc, channel, '[%s] %s has left (%s)' % (ircutils.bold(
|
||||||
ircutils.bold(channel), ircutils.mircColor(msg.prefix, 'light blue'), reason))
|
channel), ircutils.mircColor(msg.prefix, 'light blue'), reason))
|
||||||
else:
|
else:
|
||||||
self._logChan(irc, channel, '[%s] %s has left (%s)' % (
|
self._logChan(irc, channel, '[%s] %s has left (%s)' % (
|
||||||
channel, msg.prefix, reason))
|
channel, msg.prefix, reason))
|
||||||
@ -4145,9 +4142,9 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
break
|
break
|
||||||
if found:
|
if found:
|
||||||
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
||||||
message = '[%s] [#%s +%s %s] <%s> %s' % (
|
message = '[%s] [#%s %s %s] <%s> %s' % (
|
||||||
ircutils.bold(channel), found[0].uid,
|
ircutils.bold(channel), found[0].uid,
|
||||||
ircutils.mircColor(found[0].mode, 'red'),
|
ircutils.bold(ircutils.mircColor('+%s' % found[0].mode, 'red')),
|
||||||
ircutils.mircColor(found[0].value, 'light blue'),
|
ircutils.mircColor(found[0].value, 'light blue'),
|
||||||
msg.nick, text)
|
msg.nick, text)
|
||||||
else:
|
else:
|
||||||
@ -4156,25 +4153,22 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
msg.nick, text)
|
msg.nick, text)
|
||||||
if message:
|
if message:
|
||||||
self._logChan(irc, channel, message)
|
self._logChan(irc, channel, message)
|
||||||
elif irc.nick == channel and not isCommand(irc, text):
|
elif irc.nick == channel and not (checkAddressed(irc, text, channel)
|
||||||
found = self.hasAskedItems(irc, msg.prefix, True)
|
or isCommand(irc, text)):
|
||||||
|
found = self.hasAskedItems(irc, msg.prefix, remove=False, prompt=False)
|
||||||
if found:
|
if found:
|
||||||
tokens = callbacks.tokenize('ChanTracker editAndMark %s %s' % (found[0], text))
|
tokens = callbacks.tokenize('ChanTracker editAndMark %s %s' % (found[0], text))
|
||||||
self.Proxy(irc.irc, msg, tokens)
|
self.Proxy(irc.irc, msg, tokens)
|
||||||
found = self.hasAskedItems(irc, msg.prefix, False)
|
|
||||||
if found:
|
|
||||||
i.askedItems[msg.prefix][found[0]][6] = True
|
|
||||||
i.lowQueue.enqueue(ircmsgs.privmsg(msg.nick, found[5]))
|
|
||||||
self.forceTickle = True
|
|
||||||
self._tickle(irc)
|
self._tickle(irc)
|
||||||
|
|
||||||
def hasAskedItems(self, irc, prefix, remove):
|
def hasAskedItems(self, irc, prefix, remove, prompt):
|
||||||
i = self.getIrc(irc)
|
i = self.getIrc(irc)
|
||||||
if prefix in i.askedItems:
|
if prefix in i.askedItems:
|
||||||
found = None
|
found = None
|
||||||
for item in i.askedItems[prefix]:
|
for item in list(i.askedItems[prefix].values()):
|
||||||
if not found or (item < found[0] and not found[6]):
|
if (not found or item[0] < found[0]) \
|
||||||
found = i.askedItems[prefix][item]
|
and not (prompt and item[6]):
|
||||||
|
found = item
|
||||||
if found:
|
if found:
|
||||||
chan = self.getChan(irc, found[3])
|
chan = self.getChan(irc, found[3])
|
||||||
items = chan.getItemsFor(found[1])
|
items = chan.getItemsFor(found[1])
|
||||||
@ -4204,13 +4198,14 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
i.askedItems[prefix][data[0]][6] = True
|
i.askedItems[prefix][data[0]][6] = True
|
||||||
i.lowQueue.enqueue(ircmsgs.privmsg(nick, data[5]))
|
i.lowQueue.enqueue(ircmsgs.privmsg(nick, data[5]))
|
||||||
self.forceTickle = True
|
self.forceTickle = True
|
||||||
|
self._tickle(irc)
|
||||||
def unAsk():
|
def unAsk():
|
||||||
if prefix in i.askedItems:
|
if prefix in i.askedItems:
|
||||||
if data[0] in i.askedItems[prefix]:
|
if data[0] in i.askedItems[prefix]:
|
||||||
del i.askedItems[prefix][data[0]]
|
del i.askedItems[prefix][data[0]]
|
||||||
if not len(list(i.askedItems[prefix])):
|
if not len(list(i.askedItems[prefix])):
|
||||||
del i.askedItems[prefix]
|
del i.askedItems[prefix]
|
||||||
found = self.hasAskedItems(irc, prefix, False)
|
found = self.hasAskedItems(irc, prefix, remove=False, prompt=True)
|
||||||
if found:
|
if found:
|
||||||
i.askedItems[prefix][found[0]][6] = True
|
i.askedItems[prefix][found[0]][6] = True
|
||||||
i.lowQueue.enqueue(ircmsgs.privmsg(nick, found[5]))
|
i.lowQueue.enqueue(ircmsgs.privmsg(nick, found[5]))
|
||||||
@ -4333,7 +4328,7 @@ class ChanTracker(callbacks.Plugin, plugins.ChannelDBHandler):
|
|||||||
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
if self.registryValue('useColorForAnnounces', channel=channel, network=irc.network):
|
||||||
message = message % (
|
message = message % (
|
||||||
ircutils.mircColor(item.uid, 'yellow', 'black'),
|
ircutils.mircColor(item.uid, 'yellow', 'black'),
|
||||||
ircutils.bold(ircutils.mircColor('+%s' % m, 'green')),
|
ircutils.bold(ircutils.mircColor('+%s' % m, 'red')),
|
||||||
ircutils.mircColor(value, 'light blue'), channel, len(item.affects))
|
ircutils.mircColor(value, 'light blue'), channel, len(item.affects))
|
||||||
else:
|
else:
|
||||||
message = message % (
|
message = message % (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user