2011-01-09 03:02:03 -08:00
|
|
|
###
|
|
|
|
# Copyright (c) 2010, quantumlemur
|
2011-01-09 03:03:18 -08:00
|
|
|
# Copyright (c) 2011, Valentin Lorentz
|
2011-01-09 03:02:03 -08:00
|
|
|
# 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 re
|
|
|
|
import time
|
2011-02-14 09:12:19 -08:00
|
|
|
import copy
|
2011-01-09 03:02:03 -08:00
|
|
|
import string
|
|
|
|
import supybot.conf as conf
|
|
|
|
import supybot.utils as utils
|
|
|
|
import supybot.world as world
|
|
|
|
from supybot.commands import *
|
|
|
|
import supybot.irclib as irclib
|
|
|
|
import supybot.ircmsgs as ircmsgs
|
|
|
|
import supybot.ircutils as ircutils
|
|
|
|
import supybot.callbacks as callbacks
|
2011-01-09 03:40:01 -08:00
|
|
|
from supybot.i18n import PluginInternationalization, internationalizeDocstring
|
2011-01-09 03:02:03 -08:00
|
|
|
|
2011-01-09 03:40:01 -08:00
|
|
|
_ = PluginInternationalization('LinkRelay')
|
|
|
|
|
2011-01-15 06:30:38 -08:00
|
|
|
|
2011-01-09 03:40:01 -08:00
|
|
|
@internationalizeDocstring
|
2011-01-09 03:02:03 -08:00
|
|
|
class LinkRelay(callbacks.Plugin):
|
|
|
|
noIgnore = True
|
|
|
|
threaded = True
|
2011-01-09 03:26:56 -08:00
|
|
|
|
2011-01-09 03:02:03 -08:00
|
|
|
class Relay():
|
2011-01-09 03:26:56 -08:00
|
|
|
def __init__(self, sourceChannel, sourceNetwork, targetChannel,
|
|
|
|
targetNetwork, channelRegex, networkRegex, messageRegex):
|
2011-01-09 03:02:03 -08:00
|
|
|
self.sourceChannel = sourceChannel
|
|
|
|
self.sourceNetwork = sourceNetwork
|
|
|
|
self.targetChannel = targetChannel
|
|
|
|
self.targetNetwork = targetNetwork
|
|
|
|
self.channelRegex = channelRegex
|
|
|
|
self.networkRegex = networkRegex
|
|
|
|
self.messageRegex = messageRegex
|
2011-02-14 09:12:19 -08:00
|
|
|
self.hasTargetIRC = False
|
|
|
|
self.hasSourceIRCChannels = False
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, irc):
|
|
|
|
self.__parent = super(LinkRelay, self)
|
|
|
|
self.__parent.__init__(irc)
|
2011-01-16 05:30:27 -08:00
|
|
|
self._loadFromConfig()
|
2011-02-14 09:12:19 -08:00
|
|
|
self.ircstates = {}
|
2011-01-16 05:30:27 -08:00
|
|
|
for IRC in world.ircs:
|
|
|
|
self.addIRC(IRC)
|
|
|
|
|
|
|
|
def _loadFromConfig(self):
|
2011-01-09 03:02:03 -08:00
|
|
|
self.relays = []
|
2011-01-15 06:30:38 -08:00
|
|
|
for relay in self.registryValue('relays').split(' || '):
|
2011-02-14 09:12:19 -08:00
|
|
|
if relay.endswith('|'):
|
|
|
|
relay += ' '
|
2011-01-15 06:30:38 -08:00
|
|
|
relay = relay.split(' | ')
|
|
|
|
if not len(relay) == 5:
|
|
|
|
continue
|
2011-01-09 03:26:56 -08:00
|
|
|
self.relays.append(self.Relay(relay[0],
|
|
|
|
relay[1],
|
|
|
|
relay[2],
|
|
|
|
relay[3],
|
|
|
|
re.compile('^%s$' % relay[0], re.I),
|
|
|
|
re.compile('^%s$' % relay[1]),
|
|
|
|
re.compile(relay[4])))
|
2011-02-14 09:12:19 -08:00
|
|
|
|
2011-02-14 10:53:20 -08:00
|
|
|
self.nickSubstitutions = {}
|
|
|
|
for substitute in self.registryValue('substitutes').split(' || '):
|
|
|
|
if substitute.endswith('|'):
|
|
|
|
substitute += ' '
|
|
|
|
substitute = substitute.split(' | ')
|
|
|
|
if not len(substitute) == 2:
|
|
|
|
continue
|
|
|
|
self.nickSubstitutions[substitute[0]] = substitute[1]
|
2011-01-16 05:30:27 -08:00
|
|
|
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
|
|
|
|
def simpleHash(self, s):
|
2011-01-09 03:26:56 -08:00
|
|
|
colors = ["\x0305", "\x0304", "\x0303", "\x0309", "\x0302", "\x0312",
|
|
|
|
"\x0306", "\x0313", "\x0310", "\x0311", "\x0307"]
|
2011-01-09 03:02:03 -08:00
|
|
|
num = 0
|
|
|
|
for i in s:
|
|
|
|
num += ord(i)
|
|
|
|
num = num % 11
|
|
|
|
if s == 'xen':
|
|
|
|
num = 5
|
|
|
|
elif s == 'splurk':
|
|
|
|
num = 5
|
|
|
|
return colors[num]
|
|
|
|
|
|
|
|
|
|
|
|
def formatPrivMsg(self, nick, text):
|
|
|
|
color = self.simpleHash(nick)
|
|
|
|
if nick in self.nickSubstitutions:
|
|
|
|
nick = self.nickSubstitutions[nick]
|
|
|
|
if re.match('^\x01ACTION .*\x01$', text):
|
|
|
|
text = text.strip('\x01')
|
|
|
|
text = text[ 7 : ]
|
|
|
|
s = '\x0314*\x03 %s %s' % (nick, text)
|
|
|
|
else:
|
|
|
|
s = '\x0314<%s%s\x0314>\x03 %s' % (color, nick, text)
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
2011-01-09 03:40:01 -08:00
|
|
|
@internationalizeDocstring
|
2011-01-09 03:02:03 -08:00
|
|
|
def list(self, irc, msg, args):
|
|
|
|
"""takes no arguments
|
|
|
|
|
|
|
|
Returns all the defined relay links"""
|
|
|
|
for relay in self.relays:
|
2011-02-14 09:12:19 -08:00
|
|
|
if relay.hasTargetIRC:
|
2011-01-30 05:37:40 -08:00
|
|
|
hasIRC = 'Link healthy!'
|
2011-01-09 03:02:03 -08:00
|
|
|
else:
|
2011-02-15 22:31:17 -08:00
|
|
|
hasIRC = '\x03%sIRC object not scraped yet.\x03' % \
|
|
|
|
self.registryValue('colors.info')
|
2011-01-09 03:26:56 -08:00
|
|
|
irc.sendMsg(ircmsgs.privmsg(msg.args[0],'\x02%s\x02 on \x02%s\x02'
|
|
|
|
'==> \x02%s\x02 on \x02%s\x02. %s' %
|
|
|
|
(relay.sourceChannel,
|
|
|
|
relay.sourceNetwork,
|
|
|
|
relay.targetChannel,
|
|
|
|
relay.targetNetwork,
|
2011-01-30 05:37:40 -08:00
|
|
|
hasIRC)))
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
def doPrivmsg(self, irc, msg):
|
|
|
|
self.addIRC(irc)
|
2011-02-14 09:12:19 -08:00
|
|
|
channel = msg.args[0]
|
|
|
|
s = msg.args[1]
|
|
|
|
if channel not in irc.state.channels: # in private
|
|
|
|
# cuts off the end of commands, so that passwords
|
|
|
|
# won't be revealed in relayed PM's
|
|
|
|
if callbacks.addressed(irc.nick, msg):
|
|
|
|
s = re.sub('(>\x03 \w+) .*',
|
2011-02-16 03:20:39 -08:00
|
|
|
'\\1 \x03%s[%s]' %
|
|
|
|
(_('truncated'),
|
|
|
|
self.registryValue('colors.truncated')),
|
2011-02-14 09:12:19 -08:00
|
|
|
s)
|
|
|
|
s = '(via PM) %s' % s
|
|
|
|
s = self.formatPrivMsg(msg.nick, s)
|
|
|
|
self.sendToOthers(irc, channel, s)
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
|
|
|
|
def outFilter(self, irc, msg):
|
|
|
|
if msg.command == 'PRIVMSG':
|
|
|
|
if not msg.relayedMsg:
|
|
|
|
if msg.args[0] in irc.state.channels:
|
|
|
|
s = self.formatPrivMsg(irc.nick, msg.args[1])
|
2011-02-14 09:12:19 -08:00
|
|
|
self.sendToOthers(irc, msg.args[0], s)
|
2011-01-09 03:02:03 -08:00
|
|
|
return msg
|
2011-01-09 03:26:56 -08:00
|
|
|
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
def doPing(self, irc, msg):
|
|
|
|
self.addIRC(irc)
|
|
|
|
|
|
|
|
def doJoin(self, irc, msg):
|
2011-02-14 09:12:19 -08:00
|
|
|
self.addIRC(irc)
|
2011-02-15 22:31:17 -08:00
|
|
|
s = '\x03%s' % self.registryValue('colors.join') + \
|
|
|
|
_('%s has joined on %s') % (msg.nick, irc.network)
|
2011-02-14 09:12:19 -08:00
|
|
|
self.sendToOthers(irc, msg.args[0], s)
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
def doPart(self, irc, msg):
|
2011-02-14 09:12:19 -08:00
|
|
|
self.addIRC(irc)
|
2011-02-15 22:31:17 -08:00
|
|
|
s = '\x03%s' % self.registryValue('colors.part') + \
|
|
|
|
_('%s has left on %s') % (msg.nick, irc.network)
|
2011-02-14 09:12:19 -08:00
|
|
|
self.sendToOthers(irc, msg.args[0], s)
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
def doKick(self, irc, msg):
|
2011-02-14 09:12:19 -08:00
|
|
|
self.addIRC(irc)
|
2011-02-15 22:31:17 -08:00
|
|
|
s = '\x03%s' % self.registryValue('colors.kick') + \
|
|
|
|
_('%s has been kicked on %s by %s (%s)') % \
|
2011-02-14 11:42:38 -08:00
|
|
|
(msg.args[1],
|
2011-01-09 03:26:56 -08:00
|
|
|
irc.network,
|
|
|
|
msg.nick,
|
|
|
|
msg.args[2])
|
2011-01-09 03:02:03 -08:00
|
|
|
self.sendToOthers(irc, msg, s)
|
|
|
|
|
2011-02-14 09:12:19 -08:00
|
|
|
def doNick(self, irc, msg):
|
|
|
|
self.addIRC(irc)
|
2011-02-15 22:31:17 -08:00
|
|
|
s = '\x03%s' % self.registryValue('colors.nick') + \
|
|
|
|
_('%s (%s) changed his nickname to %s') % (msg.nick,
|
2011-02-14 09:12:19 -08:00
|
|
|
irc.network,
|
|
|
|
msg.args[0])
|
|
|
|
for (channel, c) in irc.state.channels.iteritems():
|
|
|
|
if msg.args[0] in c.users:
|
|
|
|
self.sendToOthers(irc, channel, s)
|
|
|
|
|
|
|
|
def doQuit(self, irc, msg):
|
2011-02-15 22:31:17 -08:00
|
|
|
s = '\x03%s' % self.registryValue('colors.quit') + \
|
|
|
|
_('%s has quit on %s (%s)') % (msg.nick,
|
2011-02-14 11:42:38 -08:00
|
|
|
irc.network,
|
|
|
|
msg.args[0])
|
2011-02-14 09:12:19 -08:00
|
|
|
self.sendToOthers(irc, None, s, msg.nick)
|
|
|
|
self.addIRC(irc)
|
|
|
|
|
|
|
|
def sendToOthers(self, irc, channel, s, nick=None):
|
2011-01-09 03:02:03 -08:00
|
|
|
for relay in self.relays:
|
2011-02-14 09:12:19 -08:00
|
|
|
if channel is None:
|
|
|
|
assert nick is not None
|
|
|
|
found = False
|
|
|
|
for channel in relay.sourceIRCChannels:
|
|
|
|
if nick in relay.sourceIRCChannels[channel].users:
|
|
|
|
found = True
|
|
|
|
break
|
2011-02-14 09:48:47 -08:00
|
|
|
if not found:
|
|
|
|
continue
|
2011-01-09 03:03:18 -08:00
|
|
|
if relay.channelRegex.match(channel) and \
|
|
|
|
relay.networkRegex.match(irc.network) and \
|
2011-02-14 09:12:19 -08:00
|
|
|
relay.messageRegex.search(s):
|
|
|
|
if not relay.hasTargetIRC:
|
2011-01-09 03:26:56 -08:00
|
|
|
self.log.info('LinkRelay: IRC %s not yet scraped.' %
|
|
|
|
relay.targetNetwork)
|
2011-01-09 03:02:03 -08:00
|
|
|
elif relay.targetIRC.zombie:
|
2011-01-09 03:26:56 -08:00
|
|
|
self.log.info('LinkRelay: IRC %s appears to be a zombie'%
|
|
|
|
relay.targetNetwork)
|
2011-01-09 03:02:03 -08:00
|
|
|
elif relay.targetChannel not in relay.targetIRC.state.channels:
|
2011-01-09 03:26:56 -08:00
|
|
|
self.log.info('LinkRelay: I\'m not in in %s on %s' %
|
|
|
|
(relay.targetChannel, relay.targetNetwork))
|
2011-01-09 03:02:03 -08:00
|
|
|
else:
|
|
|
|
msg = ircmsgs.privmsg(relay.targetChannel, s)
|
|
|
|
msg.tag('relayedMsg')
|
|
|
|
relay.targetIRC.sendMsg(msg)
|
|
|
|
|
|
|
|
|
|
|
|
def addIRC(self, irc):
|
|
|
|
match = False
|
|
|
|
for relay in self.relays:
|
2011-02-14 09:12:19 -08:00
|
|
|
if relay.sourceNetwork == irc.network:
|
|
|
|
relay.sourceIRCChannels = copy.deepcopy(irc.state.channels)
|
|
|
|
relay.hasSourceIRCChannels = True
|
|
|
|
if relay.targetNetwork == irc.network and not relay.hasTargetIRC:
|
2011-01-09 03:02:03 -08:00
|
|
|
relay.targetIRC = irc
|
2011-02-14 09:12:19 -08:00
|
|
|
relay.hasTargetIRC = True
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
|
2011-01-09 03:40:01 -08:00
|
|
|
@internationalizeDocstring
|
2011-01-09 03:02:03 -08:00
|
|
|
def nicks(self, irc, msg, args, channel):
|
|
|
|
"""[<channel>]
|
|
|
|
|
|
|
|
Returns the nicks of the people in the linked channels.
|
|
|
|
<channel> is only necessary if the message
|
|
|
|
isn't sent on the channel itself."""
|
|
|
|
for relay in self.relays:
|
2011-01-30 05:37:40 -08:00
|
|
|
if relay.sourceChannel == channel and \
|
|
|
|
relay.sourceNetwork == irc.network:
|
2011-02-14 09:12:19 -08:00
|
|
|
if not relay.hasTargetIRC:
|
2011-02-14 11:42:38 -08:00
|
|
|
irc.reply(_('I haven\'t scraped the IRC object for %s '
|
|
|
|
'yet. Try again in a minute or two.') % \
|
2011-01-09 03:26:56 -08:00
|
|
|
relay.targetNetwork)
|
2011-01-09 03:02:03 -08:00
|
|
|
else:
|
|
|
|
users = []
|
|
|
|
ops = []
|
|
|
|
halfops = []
|
|
|
|
voices = []
|
|
|
|
normals = []
|
|
|
|
numUsers = 0
|
2011-02-14 11:22:07 -08:00
|
|
|
target = relay.targetChannel
|
|
|
|
|
|
|
|
channels = relay.targetIRC.state.channels
|
|
|
|
found = False
|
|
|
|
for key, channel_ in channels.items():
|
|
|
|
if re.match(relay.targetChannel, key):
|
|
|
|
found = True
|
|
|
|
break
|
|
|
|
if not found:
|
2011-01-09 03:02:03 -08:00
|
|
|
continue
|
2011-02-14 11:22:07 -08:00
|
|
|
|
|
|
|
for s in channel_.users:
|
2011-01-09 03:02:03 -08:00
|
|
|
s = s.strip()
|
|
|
|
if not s:
|
|
|
|
continue
|
|
|
|
numUsers += 1
|
2011-02-14 11:22:07 -08:00
|
|
|
if s in channel_.ops:
|
2011-01-09 03:02:03 -08:00
|
|
|
users.append('@%s' % s)
|
2011-02-14 11:22:07 -08:00
|
|
|
elif s in channel_.halfops:
|
2011-01-09 03:02:03 -08:00
|
|
|
users.append('%%%s' % s)
|
2011-02-14 11:22:07 -08:00
|
|
|
elif s in channel_.voices:
|
2011-01-09 03:02:03 -08:00
|
|
|
users.append('+%s' % s)
|
|
|
|
else:
|
|
|
|
users.append(s)
|
|
|
|
#utils.sortBy(ircutils.toLower, ops)
|
|
|
|
#utils.sortBy(ircutils.toLower, halfops)
|
|
|
|
#utils.sortBy(ircutils.toLower, voices)
|
|
|
|
#utils.sortBy(ircutils.toLower, normals)
|
|
|
|
users.sort()
|
|
|
|
msg.tag('relayedMsg')
|
2011-02-14 11:42:38 -08:00
|
|
|
s = _('%d users in %s on %s: %s') % (numUsers,
|
2011-01-30 12:31:45 -08:00
|
|
|
relay.targetChannel,
|
|
|
|
relay.targetNetwork,
|
2011-01-09 03:26:56 -08:00
|
|
|
utils.str.commaAndify(users))
|
2011-01-30 05:41:35 -08:00
|
|
|
irc.reply(s)
|
2011-01-09 03:02:03 -08:00
|
|
|
irc.noReply()
|
|
|
|
nicks = wrap(nicks, ['Channel'])
|
|
|
|
|
|
|
|
|
2011-01-16 05:26:16 -08:00
|
|
|
# The fellowing functions handle configuration
|
|
|
|
def _writeToConfig(self, from_, to, regexp, add):
|
|
|
|
from_, to = from_.split('@'), to.split('@')
|
|
|
|
args = from_
|
|
|
|
args.extend(to)
|
|
|
|
args.append(regexp)
|
|
|
|
s = ' | '.join(args)
|
|
|
|
|
|
|
|
currentConfig = self.registryValue('relays')
|
|
|
|
if add == True:
|
|
|
|
if s in currentConfig.split(' || '):
|
|
|
|
return False
|
|
|
|
if currentConfig == '':
|
|
|
|
self.setRegistryValue('relays', value=s)
|
|
|
|
else:
|
|
|
|
self.setRegistryValue('relays',
|
|
|
|
value=' || '.join((currentConfig,s)))
|
|
|
|
else:
|
|
|
|
newConfig = currentConfig.split(' || ')
|
|
|
|
if s not in newConfig:
|
|
|
|
return False
|
|
|
|
newConfig.remove(s)
|
|
|
|
self.setRegistryValue('relays', value=' || '.join(newConfig))
|
|
|
|
return True
|
|
|
|
|
|
|
|
def _parseOptlist(self, irc, msg, tupleOptlist):
|
2011-01-15 06:30:38 -08:00
|
|
|
optlist = {}
|
|
|
|
for key, value in tupleOptlist:
|
|
|
|
optlist.update({key: value})
|
|
|
|
if 'from' not in optlist and 'to' not in optlist:
|
|
|
|
irc.error(_('You must give at least --from or --to.'))
|
|
|
|
return
|
|
|
|
for name in ('from', 'to'):
|
|
|
|
if name not in optlist:
|
|
|
|
optlist.update({name: '%s@%s' % (msg.args[0], irc.network)})
|
|
|
|
if 'regexp' not in optlist:
|
|
|
|
optlist.update({'regexp': ''})
|
|
|
|
if 'reciprocal' in optlist:
|
|
|
|
optlist.update({'reciprocal': True})
|
|
|
|
else:
|
|
|
|
optlist.update({'reciprocal': False})
|
|
|
|
if not len(optlist['from'].split('@')) == 2:
|
|
|
|
irc.error(_('--from should be like "--from #channel@network"'))
|
|
|
|
return
|
|
|
|
if not len(optlist['to'].split('@')) == 2:
|
|
|
|
irc.error(_('--to should be like "--to #channel@network"'))
|
|
|
|
return
|
2011-01-16 05:26:16 -08:00
|
|
|
return optlist
|
|
|
|
|
|
|
|
@internationalizeDocstring
|
|
|
|
def add(self, irc, msg, args, optlist):
|
|
|
|
"""[--from <channel>@<network>] [--to <channel>@<network>] [--regexp <regexp>] [--reciprocal]
|
|
|
|
|
|
|
|
Adds a relay to the list. You must give at least --from or --to; if
|
|
|
|
one of them is not given, it defaults to the current channel@network.
|
|
|
|
Only messages matching <regexp> will be relayed; if <regexp> is not
|
|
|
|
given, everything is relayed.
|
|
|
|
If --reciprocal is given, another relay will be added automatically,
|
|
|
|
in the opposite direction."""
|
|
|
|
optlist = self._parseOptlist(irc, msg, optlist)
|
|
|
|
if optlist is None:
|
|
|
|
return
|
2011-01-15 06:30:38 -08:00
|
|
|
|
|
|
|
failedWrites = 0
|
2011-01-16 05:26:16 -08:00
|
|
|
if not self._writeToConfig(optlist['from'], optlist['to'],
|
|
|
|
optlist['regexp'], True):
|
2011-01-15 06:30:38 -08:00
|
|
|
failedWrites += 1
|
|
|
|
if optlist['reciprocal']:
|
2011-01-16 05:26:16 -08:00
|
|
|
if not self._writeToConfig(optlist['to'], optlist['from'],
|
|
|
|
optlist['regexp'], True):
|
2011-01-15 06:30:38 -08:00
|
|
|
failedWrites +=1
|
|
|
|
|
2011-01-16 05:30:27 -08:00
|
|
|
self._loadFromConfig()
|
2011-01-15 06:30:38 -08:00
|
|
|
if failedWrites == 0:
|
|
|
|
irc.replySuccess()
|
|
|
|
else:
|
|
|
|
irc.error(_('One (or more) relay(s) already exists and has not '
|
2011-01-16 05:26:16 -08:00
|
|
|
'been added.'))
|
2011-01-15 06:30:38 -08:00
|
|
|
add = wrap(add, [('checkCapability', 'admin'),
|
|
|
|
getopts({'from': 'something',
|
|
|
|
'to': 'something',
|
|
|
|
'regexp': 'regexpMatcher',
|
|
|
|
'reciprocal': ''})])
|
|
|
|
|
2011-01-16 05:26:16 -08:00
|
|
|
@internationalizeDocstring
|
|
|
|
def remove(self, irc, msg, args, optlist):
|
|
|
|
"""[--from <channel>@<network>] [--to <channel>@<network>] [--regexp <regexp>] [--reciprocal]
|
|
|
|
|
|
|
|
Remove a relay from the list. You must give at least --from or --to; if
|
|
|
|
one of them is not given, it defaults to the current channel@network.
|
|
|
|
Only messages matching <regexp> will be relayed; if <regexp> is not
|
|
|
|
given, everything is relayed.
|
|
|
|
If --reciprocal is given, another relay will be removed automatically,
|
|
|
|
in the opposite direction."""
|
|
|
|
optlist = self._parseOptlist(irc, msg, optlist)
|
|
|
|
if optlist is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
failedWrites = 0
|
|
|
|
if not self._writeToConfig(optlist['from'], optlist['to'],
|
|
|
|
optlist['regexp'], False):
|
|
|
|
failedWrites += 1
|
|
|
|
if optlist['reciprocal']:
|
|
|
|
if not self._writeToConfig(optlist['to'], optlist['from'],
|
|
|
|
optlist['regexp'], False):
|
|
|
|
failedWrites +=1
|
|
|
|
|
2011-01-16 05:30:27 -08:00
|
|
|
self._loadFromConfig()
|
2011-01-16 05:26:16 -08:00
|
|
|
if failedWrites == 0:
|
|
|
|
irc.replySuccess()
|
|
|
|
else:
|
|
|
|
irc.error(_('One (or more) relay(s) did not exist and has not '
|
|
|
|
'been removed.'))
|
|
|
|
remove = wrap(remove, [('checkCapability', 'admin'),
|
|
|
|
getopts({'from': 'something',
|
|
|
|
'to': 'something',
|
|
|
|
'regexp': 'regexpMatcher',
|
|
|
|
'reciprocal': ''})])
|
|
|
|
|
2011-01-26 01:11:45 -08:00
|
|
|
def _getSubstitutes(self):
|
|
|
|
# Get a list of strings
|
|
|
|
substitutes = self.registryValue('substitutes').split(' || ')
|
|
|
|
if substitutes == ['']:
|
|
|
|
return {}
|
|
|
|
# Convert it to a list of tuples
|
|
|
|
substitutes = [tuple(x.split(' | ')) for x in substitutes]
|
|
|
|
# Finally, make a dictionnary
|
|
|
|
substitutes = dict(substitutes)
|
|
|
|
|
|
|
|
return substitutes
|
|
|
|
|
|
|
|
def _setSubstitutes(self, substitutes):
|
|
|
|
# Get a list of tuples from the dictionnary
|
|
|
|
substitutes = substitutes.items()
|
|
|
|
# Make it a list of strings
|
|
|
|
substitutes = ['%s | %s' % (x,y) for x,y in substitutes]
|
|
|
|
# Finally, get a string
|
|
|
|
substitutes = ' || '.join(substitutes)
|
|
|
|
|
|
|
|
self.setRegistryValue('substitutes', value=substitutes)
|
|
|
|
|
|
|
|
|
|
|
|
@internationalizeDocstring
|
|
|
|
def substitute(self, irc, msg, args, regexp, to):
|
|
|
|
"""<regexp> <replacement>
|
|
|
|
|
|
|
|
Replaces all nicks that matches the <regexp> by the <replacement>
|
|
|
|
string."""
|
|
|
|
substitutes = self._getSubstitutes()
|
|
|
|
# Don't check if it is already in the config: if will be overriden
|
|
|
|
# automatically and that is a good thing.
|
|
|
|
substitutes.update({regexp: to})
|
|
|
|
self._setSubstitutes(substitutes)
|
|
|
|
self._loadFromConfig()
|
|
|
|
irc.replySuccess()
|
|
|
|
substitute = wrap(substitute, [('checkCapability', 'admin'),
|
|
|
|
'something',
|
|
|
|
'text'])
|
|
|
|
|
|
|
|
@internationalizeDocstring
|
|
|
|
def nosubstitute(self, irc, msg, args, regexp):
|
|
|
|
"""<regexp>
|
|
|
|
|
|
|
|
Undo a substitution."""
|
|
|
|
substitutes = self._getSubstitutes()
|
|
|
|
if regexp not in substitutes:
|
|
|
|
irc.error(_('This regexp was not in the nick substitutions '
|
|
|
|
'database'))
|
|
|
|
return
|
|
|
|
# Don't check if it is already in the config: if will be overriden
|
|
|
|
# automatically and that is a good thing.
|
|
|
|
substitutes.pop(regexp)
|
|
|
|
self._setSubstitutes(substitutes)
|
|
|
|
self._loadFromConfig()
|
|
|
|
irc.replySuccess()
|
|
|
|
nosubstitute = wrap(nosubstitute, [('checkCapability', 'admin'),
|
|
|
|
'something'])
|
|
|
|
|
|
|
|
|
2011-01-15 06:30:38 -08:00
|
|
|
|
2011-01-09 03:02:03 -08:00
|
|
|
Class = LinkRelay
|
|
|
|
|
|
|
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|