Import LinkRelay from quantumlemur repo
parent
98a19e7815
commit
bec8ffbac5
|
@ -0,0 +1 @@
|
|||
Insert a description of your plugin here, with any notes, etc. about using it.
|
|
@ -0,0 +1,61 @@
|
|||
###
|
||||
# Copyright (c) 2010, quantumlemur
|
||||
# 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.
|
||||
###
|
||||
|
||||
"""
|
||||
Handles relaying between arbitrary channels on any network.
|
||||
"""
|
||||
|
||||
import supybot
|
||||
import supybot.world as world
|
||||
|
||||
# Use this for the version of this plugin. You may wish to put a CVS keyword
|
||||
# in here if you're keeping the plugin in CVS or some similar system.
|
||||
__version__ = ""
|
||||
|
||||
__author__ = supybot.Author('quantumlemur', 'quantumlemur',
|
||||
'quantumlemur@users.sourceforge.net')
|
||||
|
||||
# This is a dictionary mapping supybot.Author instances to lists of
|
||||
# contributions.
|
||||
__contributors__ = {}
|
||||
|
||||
import config
|
||||
import plugin
|
||||
reload(plugin) # In case we're being reloaded.
|
||||
# Add more reloads here if you add third-party modules and want them to be
|
||||
# reloaded when this plugin is reloaded. Don't forget to import them as well!
|
||||
|
||||
if world.testing:
|
||||
import test
|
||||
|
||||
Class = plugin.Class
|
||||
configure = config.configure
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
|
@ -0,0 +1,60 @@
|
|||
###
|
||||
# Copyright (c) 2010, quantumlemur
|
||||
# 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 supybot.conf as conf
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.registry as registry
|
||||
|
||||
def configure(advanced):
|
||||
from supybot.questions import output, expect, anything, something, yn
|
||||
conf.registerPlugin('LinkRelay', True)
|
||||
|
||||
|
||||
LinkRelay = conf.registerPlugin('LinkRelay')
|
||||
conf.registerChannelValue(LinkRelay, 'color',
|
||||
registry.Boolean(False, """Determines whether the bot will color Relayed
|
||||
PRIVMSGs so as to make the messages easier to read."""))
|
||||
conf.registerChannelValue(LinkRelay, 'topicSync',
|
||||
registry.Boolean(True, """Determines whether the bot will synchronize
|
||||
topics between networks in the channels it Relays."""))
|
||||
conf.registerChannelValue(LinkRelay, 'hostmasks',
|
||||
registry.Boolean(False, """Determines whether the bot will Relay the
|
||||
hostmask of the person joining or parting the channel when he or she joins
|
||||
or parts."""))
|
||||
conf.registerChannelValue(LinkRelay, 'includeNetwork',
|
||||
registry.Boolean(True, """Determines whether the bot will include the
|
||||
network in Relayed PRIVMSGs; if you're only Relaying between two networks,
|
||||
it's somewhat redundant, and you may wish to save the space."""))
|
||||
conf.registerChannelValue(LinkRelay, 'noticeNonPrivmsgs',
|
||||
registry.Boolean(False, """Determines whether the bot will used NOTICEs
|
||||
rather than PRIVMSGs for non-PRIVMSG Relay messages (i.e., joins, parts,
|
||||
nicks, quits, modes, etc.)"""))
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
|
@ -0,0 +1 @@
|
|||
# Stub so local is a module, used for third-party modules
|
|
@ -0,0 +1,244 @@
|
|||
###
|
||||
# Copyright (c) 2010, quantumlemur
|
||||
# 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
|
||||
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
|
||||
#from supybot.utils.structures import MultiSet, TimeoutQueue
|
||||
|
||||
class LinkRelay(callbacks.Plugin):
|
||||
noIgnore = True
|
||||
threaded = True
|
||||
|
||||
# Put a list of all the relays that you want to add here. Only messages
|
||||
# matching the regex will be relayed.
|
||||
# syntax is [sourceChannel, sourceNetwork, targetChannel, targetNetwork, regex]
|
||||
relaysToAdd = [
|
||||
#['#supybot', 'freenode', '#supybot-bots', 'freenode', ''],
|
||||
#['#supybot-bots', 'freenode', '#supybot', 'freenode', '']
|
||||
]
|
||||
|
||||
# include any nick substitutions that you want to make here
|
||||
# (for example, if a user is in both channels, and doesn't want to get
|
||||
# highlighted every time they say a message)
|
||||
nickSubstitutions = {
|
||||
#'quantumlemur': 'quantu*lemu*'
|
||||
}
|
||||
|
||||
|
||||
class Relay():
|
||||
def __init__(self, sourceChannel, sourceNetwork, targetChannel, targetNetwork, channelRegex, networkRegex, messageRegex):
|
||||
self.sourceChannel = sourceChannel
|
||||
self.sourceNetwork = sourceNetwork
|
||||
self.targetChannel = targetChannel
|
||||
self.targetNetwork = targetNetwork
|
||||
self.channelRegex = channelRegex
|
||||
self.networkRegex = networkRegex
|
||||
self.messageRegex = messageRegex
|
||||
self.hasIRC = False
|
||||
|
||||
|
||||
def __init__(self, irc):
|
||||
self.__parent = super(LinkRelay, self)
|
||||
self.__parent.__init__(irc)
|
||||
self.relays = []
|
||||
for relay in self.relaysToAdd:
|
||||
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])))
|
||||
for IRC in world.ircs:
|
||||
self.addIRC(IRC)
|
||||
|
||||
|
||||
def simpleHash(self, s):
|
||||
colors = ["\x0305", "\x0304", "\x0303", "\x0309", "\x0302", "\x0312", "\x0306", "\x0313", "\x0310", "\x0311", "\x0307"]
|
||||
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
|
||||
|
||||
|
||||
def list(self, irc, msg, args):
|
||||
"""takes no arguments
|
||||
|
||||
Returns all the defined relay links"""
|
||||
for relay in self.relays:
|
||||
if relay.hasIRC:
|
||||
hasIRC = 'Link healthy!'
|
||||
else:
|
||||
hasIRC = '\x0304IRC object not scraped yet.\x03'
|
||||
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, hasIRC)))
|
||||
|
||||
def doPrivmsg(self, irc, msg):
|
||||
self.addIRC(irc)
|
||||
s = self.formatPrivMsg(msg.nick, msg.args[1])
|
||||
self.sendToOthers(irc, msg, s)
|
||||
|
||||
|
||||
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])
|
||||
self.sendToOthers(irc, msg, s)
|
||||
return msg
|
||||
|
||||
|
||||
def doPing(self, irc, msg):
|
||||
self.addIRC(irc)
|
||||
|
||||
def doJoin(self, irc, msg):
|
||||
s = '\x0314%s has joined on %s' % (msg.nick, irc.network)
|
||||
self.sendToOthers(irc, msg, s)
|
||||
|
||||
def doPart(self, irc, msg):
|
||||
s = '\x0314%s has left on %s' % (msg.nick, irc.network)
|
||||
self.sendToOthers(irc, msg, s)
|
||||
|
||||
# def doQuit(self, irc, msg):
|
||||
# for channel in self.ircstates[irc].channels:
|
||||
# if msg.nick in self.ircstates[irc].channels[channel].users:
|
||||
# s = '\x0314%s has quit on %s (%s)' % (msg.nick, irc.network, msg.args[0])
|
||||
# m = msg
|
||||
# self.sendToOthers(irc, msg, s)
|
||||
|
||||
def doKick(self, irc, msg):
|
||||
s = '\x0314%s has been kicked on %s by %s (%s)' % (msg.args[1], irc.network, msg.nick, msg.args[2])
|
||||
self.sendToOthers(irc, msg, s)
|
||||
|
||||
def sendToOthers(self, irc, triggerMsg, s):
|
||||
channel = triggerMsg.args[0]
|
||||
nick = triggerMsg.nick
|
||||
for relay in self.relays:
|
||||
if relay.channelRegex.match(channel) and relay.networkRegex.match(irc.network) and (len(triggerMsg.args[1] < 1 or relay.messageRegex.search(triggerMsg.args[1]))):
|
||||
if not relay.hasIRC:
|
||||
self.log.info('LinkRelay: IRC %s not yet scraped.' % relay.targetNetwork)
|
||||
elif relay.targetIRC.zombie:
|
||||
self.log.info('LinkRelay: IRC %s appears to be a zombie' % relay.targetNetwork)
|
||||
elif relay.targetChannel not in relay.targetIRC.state.channels:
|
||||
self.log.info('LinkRelay: I\'m not in in %s on %s' % (relay.targetChannel, relay.targetNetwork))
|
||||
else:
|
||||
# if re.match('\x0314\w+ has quit on \w+ \(.*\)', s):
|
||||
# pm = False
|
||||
# else:
|
||||
# pm = True
|
||||
# for chan in irc.state.channels:
|
||||
# if re.match('^%s$' % relay.sourceChannel, chan):
|
||||
# pm = False
|
||||
if triggerMsg.args[0] not in irc.state.channels and not re.match('\x0314\w+ has quit on \w+ \(.*\)', s):
|
||||
# cuts off the end of commands, so that passwords won't be revealed in relayed PM's
|
||||
if callbacks.addressed(irc.nick, triggerMsg):
|
||||
s = re.sub('(>\x03 \w+) .*', '\\1 \x0314[truncated]', s)
|
||||
s = '(via PM) %s' % s
|
||||
msg = ircmsgs.privmsg(relay.targetChannel, s)
|
||||
msg.tag('relayedMsg')
|
||||
relay.targetIRC.sendMsg(msg)
|
||||
|
||||
|
||||
def addIRC(self, irc):
|
||||
match = False
|
||||
for relay in self.relays:
|
||||
if relay.targetNetwork == irc.network and not relay.hasIRC:
|
||||
relay.targetIRC = irc
|
||||
relay.hasIRC = True
|
||||
|
||||
|
||||
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:
|
||||
if relay.targetChannel == channel and relay.targetNetwork == irc.network:
|
||||
if not relay.hasIRC:
|
||||
irc.reply('I haven\'t scraped the IRC object for %s yet. Try again in a minute or two.' % relay.targetNetwork)
|
||||
else:
|
||||
users = []
|
||||
ops = []
|
||||
halfops = []
|
||||
voices = []
|
||||
normals = []
|
||||
numUsers = 0
|
||||
try:
|
||||
Channel = relay.targetIRC.state.channels[relay.sourceChannel] #need to do something about this -- right now it won't match a regex channel
|
||||
except KeyError:
|
||||
continue
|
||||
for s in Channel.users:
|
||||
s = s.strip()
|
||||
if not s:
|
||||
continue
|
||||
numUsers += 1
|
||||
if s in Channel.ops:
|
||||
users.append('@%s' % s)
|
||||
elif s in Channel.halfops:
|
||||
users.append('%%%s' % s)
|
||||
elif s in Channel.voices:
|
||||
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')
|
||||
s = '%d users in %s on %s: %s' % (numUsers, relay.sourceChannel, relay.sourceNetwork, utils.str.commaAndify(users))
|
||||
irc.queueMsg(ircmsgs.privmsg(msg.args[0], s))
|
||||
irc.noReply()
|
||||
nicks = wrap(nicks, ['Channel'])
|
||||
|
||||
|
||||
Class = LinkRelay
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
|
@ -0,0 +1,37 @@
|
|||
###
|
||||
# Copyright (c) 2010, quantumlemur
|
||||
# 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.
|
||||
###
|
||||
|
||||
from supybot.test import *
|
||||
|
||||
class LinkRelayTestCase(PluginTestCase):
|
||||
plugins = ('LinkRelay',)
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
||||
|
Loading…
Reference in New Issue