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
|
2011-07-01 02:24:16 -07:00
|
|
|
import supybot.log as log
|
2011-01-09 03:02:03 -08:00
|
|
|
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
|
2011-07-01 02:24:16 -07:00
|
|
|
import supybot.registry as registry
|
2011-01-09 03:02:03 -08:00
|
|
|
import supybot.callbacks as callbacks
|
2011-02-28 10:01:19 -08:00
|
|
|
try:
|
|
|
|
from supybot.i18n import PluginInternationalization
|
|
|
|
from supybot.i18n import internationalizeDocstring
|
|
|
|
_ = PluginInternationalization('LinkRelay')
|
|
|
|
except:
|
|
|
|
# This are useless functions that's allow to run the plugin on a bot
|
|
|
|
# without the i18n plugin
|
|
|
|
_ = lambda x:x
|
|
|
|
internationalizeDocstring = lambda x:x
|
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):
|
2013-08-13 06:51:29 -07:00
|
|
|
"""Advanced message relay between channels."""
|
2011-01-09 03:02:03 -08:00
|
|
|
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.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-07-01 02:14:56 -07:00
|
|
|
try:
|
|
|
|
conf.supybot.plugins.LinkRelay.substitutes.addCallback(
|
|
|
|
self._loadFromConfig)
|
|
|
|
conf.supybot.plugins.LinkRelay.relays.addCallback(
|
|
|
|
self._loadFromConfig)
|
2011-07-01 02:24:16 -07:00
|
|
|
except registry.NonExistentRegistryEntry:
|
|
|
|
log.error("Your version of Supybot is not compatible with "
|
2011-07-01 02:14:56 -07:00
|
|
|
"configuration hooks. So, LinkRelay won't be able "
|
|
|
|
"to reload the configuration if you use the Config "
|
|
|
|
"plugin.")
|
2011-01-16 05:30:27 -08:00
|
|
|
|
2012-08-03 04:27:36 -07:00
|
|
|
def _loadFromConfig(self, name=None):
|
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
|
2012-05-31 12:52:24 -07:00
|
|
|
try:
|
|
|
|
self.relays.append(self.Relay(relay[0],
|
2011-01-09 03:26:56 -08:00
|
|
|
relay[1],
|
|
|
|
relay[2],
|
|
|
|
relay[3],
|
|
|
|
re.compile('^%s$' % relay[0], re.I),
|
|
|
|
re.compile('^%s$' % relay[1]),
|
|
|
|
re.compile(relay[4])))
|
2012-05-31 12:52:24 -07:00
|
|
|
except:
|
|
|
|
log.error('Failed adding relay: %r' % relay)
|
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
|
|
|
|
return colors[num]
|
|
|
|
|
|
|
|
|
2011-08-28 08:10:02 -07:00
|
|
|
def getPrivmsgData(self, channel, nick, text, colored):
|
2011-01-09 03:02:03 -08:00
|
|
|
color = self.simpleHash(nick)
|
|
|
|
if nick in self.nickSubstitutions:
|
|
|
|
nick = self.nickSubstitutions[nick]
|
2012-12-27 11:14:02 -08:00
|
|
|
if not self.registryValue('nicks', channel):
|
|
|
|
nick = ''
|
2011-01-09 03:02:03 -08:00
|
|
|
if re.match('^\x01ACTION .*\x01$', text):
|
|
|
|
text = text.strip('\x01')
|
|
|
|
text = text[ 7 : ]
|
2011-05-13 08:38:15 -07:00
|
|
|
if colored:
|
2012-04-21 11:23:18 -07:00
|
|
|
return ('* \x03%(color)s%(nick)s%(network)s\017 %(text)s',
|
2011-08-28 08:10:02 -07:00
|
|
|
{'nick': nick, 'color': color, 'text': text})
|
2011-05-13 08:38:15 -07:00
|
|
|
else:
|
2011-10-22 04:50:33 -07:00
|
|
|
return ('* %(nick)s%(network)s %(text)s',
|
2011-08-28 08:10:02 -07:00
|
|
|
{'nick': nick, 'text': text})
|
2011-01-09 03:02:03 -08:00
|
|
|
else:
|
2011-05-13 08:38:15 -07:00
|
|
|
if colored:
|
2012-02-06 09:19:26 -08:00
|
|
|
return ('<\x03%(color)s%(nick)s%(network)s\017> %(text)s',
|
2011-08-28 08:10:02 -07:00
|
|
|
{'color': color, 'nick': nick, 'text': text})
|
2011-05-13 08:38:15 -07:00
|
|
|
else:
|
2011-08-28 08:10:02 -07:00
|
|
|
return ('<%(nick)s%(network)s> %(text)s',
|
|
|
|
{'nick': nick, 'text': text})
|
2011-01-09 03:02:03 -08:00
|
|
|
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"""
|
2013-02-25 07:37:21 -08:00
|
|
|
if not self.relays:
|
|
|
|
irc.reply(_('This is no relay enabled. Use "linkrelay add" to '
|
|
|
|
'add one.'))
|
|
|
|
return
|
2013-07-07 04:25:07 -07:00
|
|
|
replies = []
|
2011-01-09 03:02:03 -08:00
|
|
|
for relay in self.relays:
|
2013-07-07 04:18:28 -07:00
|
|
|
if world.getIrc(relay.targetNetwork):
|
2011-01-30 05:37:40 -08:00
|
|
|
hasIRC = 'Link healthy!'
|
2011-01-09 03:02:03 -08:00
|
|
|
else:
|
2013-07-07 04:18:28 -07:00
|
|
|
hasIRC = '\x03%sNot connected to network.\017' % \
|
2011-07-11 05:23:03 -07:00
|
|
|
self.registryValue('colors.info', msg.args[0])
|
2011-05-13 08:38:15 -07:00
|
|
|
s ='\x02%s\x02 on \x02%s\x02 ==> \x02%s\x02 on \x02%s\x02. %s'
|
2011-07-11 05:23:03 -07:00
|
|
|
if not self.registryValue('color', msg.args[0]):
|
2011-05-13 08:38:15 -07:00
|
|
|
s = s.replace('\x02', '')
|
2013-07-07 04:25:07 -07:00
|
|
|
replies.append(s %
|
2011-01-09 03:26:56 -08:00
|
|
|
(relay.sourceChannel,
|
|
|
|
relay.sourceNetwork,
|
|
|
|
relay.targetChannel,
|
|
|
|
relay.targetNetwork,
|
2011-05-13 09:25:40 -07:00
|
|
|
hasIRC))
|
2013-07-07 04:25:07 -07:00
|
|
|
irc.replies(replies)
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
def doPrivmsg(self, irc, msg):
|
2011-02-14 09:12:19 -08:00
|
|
|
channel = msg.args[0]
|
|
|
|
s = msg.args[1]
|
2011-08-28 08:10:02 -07:00
|
|
|
s, args = self.getPrivmsgData(channel, msg.nick, s,
|
2011-05-13 09:25:40 -07:00
|
|
|
self.registryValue('color', channel))
|
2011-02-14 09:12:19 -08:00
|
|
|
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):
|
2011-05-13 08:38:15 -07:00
|
|
|
if self.registryValue('color', channel):
|
2011-07-11 05:23:03 -07:00
|
|
|
color = '\x03' + self.registryValue('colors.truncated',
|
|
|
|
channel)
|
2012-02-06 09:19:26 -08:00
|
|
|
match = '(>\017 \w+) .*'
|
2011-05-13 08:38:15 -07:00
|
|
|
else:
|
|
|
|
color = ''
|
2011-05-13 09:04:59 -07:00
|
|
|
match = '(> \w+) .*'
|
|
|
|
s = re.sub(match, '\\1 %s[%s]' % (color, _('truncated')), s)
|
2011-02-14 09:12:19 -08:00
|
|
|
s = '(via PM) %s' % s
|
2011-08-28 08:10:02 -07:00
|
|
|
self.sendToOthers(irc, channel, s, args, isPrivmsg=True)
|
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:
|
2011-08-28 08:10:02 -07:00
|
|
|
s, args = self.getPrivmsgData(msg.args[0], irc.nick, msg.args[1],
|
2011-05-13 09:25:40 -07:00
|
|
|
self.registryValue('color', msg.args[0]))
|
2011-08-28 08:10:02 -07:00
|
|
|
self.sendToOthers(irc, msg.args[0], s, args, isPrivmsg=True)
|
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
|
|
|
|
2011-02-19 03:42:50 -08:00
|
|
|
def doMode(self, irc, msg):
|
2011-08-29 07:45:23 -07:00
|
|
|
args = {'nick': msg.nick, 'channel': msg.args[0],
|
|
|
|
'mode': ' '.join(msg.args[1:]), 'color': ''}
|
2011-05-13 08:38:15 -07:00
|
|
|
if self.registryValue('color', msg.args[0]):
|
2011-08-30 13:34:41 -07:00
|
|
|
args['color'] = '\x03%s' % self.registryValue('colors.mode', msg.args[0])
|
2011-08-29 07:45:23 -07:00
|
|
|
s = '%(color)s' + _('*/* %(nick)s changed mode on '
|
|
|
|
'%(channel)s%(network)s to %(mode)s')
|
|
|
|
self.sendToOthers(irc, msg.args[0], s, args)
|
2011-02-19 03:42:50 -08:00
|
|
|
|
2011-01-09 03:02:03 -08:00
|
|
|
def doJoin(self, irc, msg):
|
2011-08-29 07:45:23 -07:00
|
|
|
args = {'nick': msg.nick, 'channel': msg.args[0], 'color': ''}
|
2011-05-13 08:38:15 -07:00
|
|
|
if self.registryValue('color', msg.args[0]):
|
2011-08-29 07:45:23 -07:00
|
|
|
args['color'] = '\x03%s' % self.registryValue('colors.join', msg.args[0])
|
2011-12-16 15:39:29 -08:00
|
|
|
if self.registryValue('hostmasks', msg.args[0]):
|
|
|
|
args['nick'] = msg.prefix
|
2011-08-29 07:45:23 -07:00
|
|
|
s = '%(color)s' + _('--> %(nick)s has joined %(channel)s%(network)s')
|
|
|
|
self.sendToOthers(irc, msg.args[0], s, args)
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
def doPart(self, irc, msg):
|
2011-08-29 07:45:23 -07:00
|
|
|
args = {'nick': msg.nick, 'channel': msg.args[0], 'color': ''}
|
2011-05-13 08:38:15 -07:00
|
|
|
if self.registryValue('color', msg.args[0]):
|
2011-08-29 07:45:23 -07:00
|
|
|
args['color'] = '\x03%s' % self.registryValue('colors.part', msg.args[0])
|
2011-12-16 15:39:29 -08:00
|
|
|
if self.registryValue('hostmasks', msg.args[0]):
|
|
|
|
args['nick'] = msg.prefix
|
2011-08-29 07:45:23 -07:00
|
|
|
s = '%(color)s' + _('<-- %(nick)s has left %(channel)s%(network)s')
|
|
|
|
self.sendToOthers(irc, msg.args[0], s, args)
|
2011-01-09 03:02:03 -08:00
|
|
|
|
|
|
|
def doKick(self, irc, msg):
|
2011-08-29 07:45:23 -07:00
|
|
|
args = {'kicked': msg.args[1], 'channel': msg.args[0],
|
|
|
|
'kicker': msg.nick, 'message': msg.args[2], 'color': ''}
|
2011-05-13 08:38:15 -07:00
|
|
|
if self.registryValue('color', msg.args[0]):
|
2011-08-29 07:45:23 -07:00
|
|
|
args['color'] = '\x03%s' % self.registryValue('colors.kick',
|
|
|
|
msg.args[0])
|
2011-10-22 05:12:28 -07:00
|
|
|
s = '%(color)s' + _('<-- %(kicked)s has been kicked from '
|
|
|
|
'%(channel)s%(network)s by %(kicker)s (%(message)s)')
|
2011-08-29 07:45:23 -07:00
|
|
|
self.sendToOthers(irc, msg.args[0], s, args)
|
2011-01-09 03:02:03 -08:00
|
|
|
|
2011-02-14 09:12:19 -08:00
|
|
|
def doNick(self, irc, msg):
|
2011-08-29 07:45:23 -07:00
|
|
|
args = {'oldnick': msg.nick, 'network': irc.network,
|
|
|
|
'newnick': msg.args[0], 'color': ''}
|
2011-05-13 08:38:15 -07:00
|
|
|
if self.registryValue('color', msg.args[0]):
|
2011-08-29 07:45:23 -07:00
|
|
|
args['color'] = '\x03%s' % self.registryValue('colors.nick', msg.args[0])
|
2013-04-15 16:04:25 -07:00
|
|
|
s = _('*/* %(oldnick)s (%(network)s) changed their nickname to '
|
2011-08-29 07:45:23 -07:00
|
|
|
'%(newnick)s')
|
2013-05-11 01:13:05 -07:00
|
|
|
for (channel, c) in irc.state.channels.items():
|
2011-02-14 09:12:19 -08:00
|
|
|
if msg.args[0] in c.users:
|
2011-08-29 07:45:23 -07:00
|
|
|
self.sendToOthers(irc, channel, s, args)
|
2011-02-14 09:12:19 -08:00
|
|
|
|
|
|
|
def doQuit(self, irc, msg):
|
2011-08-29 07:45:23 -07:00
|
|
|
args = {'nick': msg.nick, 'network': irc.network,
|
|
|
|
'message': msg.args[0], 'color': ''}
|
2011-05-13 08:38:15 -07:00
|
|
|
if self.registryValue('color', msg.args[0]):
|
2011-08-29 07:45:23 -07:00
|
|
|
args['color'] = '\x03%s' % self.registryValue('colors.quit', msg.args[0])
|
|
|
|
s = _('<-- %(nick)s has quit on %(network)s (%(message)s)')
|
|
|
|
self.sendToOthers(irc, None, s, args, msg.nick)
|
2011-02-14 09:12:19 -08:00
|
|
|
|
2011-08-28 08:10:02 -07:00
|
|
|
def sendToOthers(self, irc, channel, s, args, nick=None, isPrivmsg=False):
|
2011-02-18 09:51:27 -08:00
|
|
|
assert channel is not None or nick is not None
|
2012-02-18 07:31:59 -08:00
|
|
|
def format_(relay, s, args):
|
|
|
|
if 'network' not in args:
|
|
|
|
if self.registryValue('includeNetwork', relay.targetChannel):
|
|
|
|
args['network'] = '@' + irc.network
|
|
|
|
else:
|
|
|
|
args['network'] = ''
|
|
|
|
return s % args
|
2011-07-01 01:46:38 -07:00
|
|
|
def send(s):
|
2013-07-07 04:18:28 -07:00
|
|
|
targetIRC = world.getIrc(relay.targetNetwork)
|
|
|
|
if not targetIRC:
|
|
|
|
self.log.info('LinkRelay: Not connected to network %s.' %
|
2011-02-19 07:56:47 -08:00
|
|
|
relay.targetNetwork)
|
2013-07-07 04:18:28 -07:00
|
|
|
elif targetIRC.zombie:
|
2011-02-19 07:56:47 -08:00
|
|
|
self.log.info('LinkRelay: IRC %s appears to be a zombie'%
|
|
|
|
relay.targetNetwork)
|
2012-05-30 13:13:52 -07:00
|
|
|
elif irc.isChannel(relay.targetChannel) and \
|
2013-07-07 04:18:28 -07:00
|
|
|
relay.targetChannel not in targetIRC.state.channels:
|
2011-02-19 07:56:47 -08:00
|
|
|
self.log.info('LinkRelay: I\'m not in in %s on %s' %
|
|
|
|
(relay.targetChannel, relay.targetNetwork))
|
|
|
|
else:
|
2011-05-13 08:47:20 -07:00
|
|
|
if isPrivmsg or \
|
|
|
|
self.registryValue('nonPrivmsgs', channel) == 'privmsg':
|
2013-08-02 07:13:26 -07:00
|
|
|
f = ircmsgs.privmsg
|
2011-05-13 08:47:20 -07:00
|
|
|
elif self.registryValue('nonPrivmsgs', channel) == 'notice':
|
2013-08-02 07:13:26 -07:00
|
|
|
f = ircmsgs.notice
|
2011-05-13 08:47:20 -07:00
|
|
|
else:
|
2011-05-13 09:25:40 -07:00
|
|
|
return
|
2013-08-02 07:13:26 -07:00
|
|
|
allowedLength = conf.get(conf.supybot.reply.mores.length,
|
|
|
|
relay.targetChannel) or 470
|
|
|
|
cont = _('(continuation)')
|
|
|
|
remainingLength = allowedLength - len(cont) - 1
|
|
|
|
head = s[0:allowedLength]
|
|
|
|
tail = [cont + ' ' + s[i:i+remainingLength] for i in
|
|
|
|
range(allowedLength, len(s), remainingLength)]
|
|
|
|
for s in [head] + tail:
|
|
|
|
msg = f(relay.targetChannel, s)
|
|
|
|
msg.tag('relayedMsg')
|
|
|
|
targetIRC.sendMsg(msg)
|
2011-02-19 07:56:47 -08:00
|
|
|
|
2011-02-23 10:03:52 -08:00
|
|
|
if channel is None:
|
|
|
|
for relay in self.relays:
|
2012-10-02 09:04:32 -07:00
|
|
|
if not relay.hasSourceIRCChannels:
|
|
|
|
continue
|
2011-02-14 09:12:19 -08:00
|
|
|
for channel in relay.sourceIRCChannels:
|
2012-02-18 07:31:59 -08:00
|
|
|
new_s = format_(relay, s, args)
|
2011-02-18 09:51:27 -08:00
|
|
|
if nick in relay.sourceIRCChannels[channel].users and \
|
2011-02-19 07:56:47 -08:00
|
|
|
relay.channelRegex.match(channel) and \
|
|
|
|
relay.networkRegex.match(irc.network)and \
|
2012-02-18 07:31:59 -08:00
|
|
|
relay.messageRegex.search(new_s):
|
|
|
|
send(new_s)
|
2011-02-23 10:03:52 -08:00
|
|
|
else:
|
|
|
|
for relay in self.relays:
|
2012-02-18 07:31:59 -08:00
|
|
|
new_s = format_(relay, s, args)
|
2011-02-19 07:56:47 -08:00
|
|
|
if relay.channelRegex.match(channel) and \
|
|
|
|
relay.networkRegex.match(irc.network)and \
|
2012-02-18 07:31:59 -08:00
|
|
|
relay.messageRegex.search(new_s):
|
|
|
|
send(new_s)
|
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:
|
2013-07-07 04:18:28 -07:00
|
|
|
if not world.getIrc(relay.targetNetwork):
|
|
|
|
irc.reply(_('Not connected to network %s.') %
|
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
|
|
|
|
|
2013-07-07 04:18:28 -07:00
|
|
|
channels = world.getIrc(relay.targetNetwork).state.channels
|
2011-02-14 11:22:07 -08:00
|
|
|
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')
|
2013-08-06 07:51:17 -07:00
|
|
|
config = list(map(ircutils.IrcString, currentConfig.split(' || ')))
|
2011-01-16 05:26:16 -08:00
|
|
|
if add == True:
|
2013-08-06 07:51:17 -07:00
|
|
|
if s in config:
|
2011-01-16 05:26:16 -08:00
|
|
|
return False
|
|
|
|
if currentConfig == '':
|
|
|
|
self.setRegistryValue('relays', value=s)
|
|
|
|
else:
|
|
|
|
self.setRegistryValue('relays',
|
2013-08-06 07:51:17 -07:00
|
|
|
value=' || '.join((currentConfig, s)))
|
2011-01-16 05:26:16 -08:00
|
|
|
else:
|
2013-08-06 07:51:17 -07:00
|
|
|
if s not in config:
|
2011-01-16 05:26:16 -08:00
|
|
|
return False
|
2013-08-06 07:51:17 -07:00
|
|
|
config.remove(s)
|
|
|
|
self.setRegistryValue('relays', value=' || '.join(config))
|
2011-01-16 05:26:16 -08:00
|
|
|
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',
|
2012-02-18 07:31:59 -08:00
|
|
|
'regexp': 'something',
|
2011-01-15 06:30:38 -08:00
|
|
|
'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',
|
2012-02-18 12:26:12 -08:00
|
|
|
'regexp': 'something',
|
2011-01-16 05:26:16 -08:00
|
|
|
'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:
|