3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-12-26 04:32:51 +01:00
PyLink/plugins/relay_clientbot.py

119 lines
5.3 KiB
Python

# relay_clientbot.py: Clientbot extensions for Relay
import string
from pylinkirc import utils, conf, world
from pylinkirc.log import log
default_styles = {'MESSAGE': '\x02[$colored_netname]\x02 <$colored_nick> $text',
'KICK': '\x02[$colored_netname]\x02 -$colored_nick$identhost has kicked $target_nick from $channel ($text)',
'PART': '\x02[$colored_netname]\x02 -$colored_nick$identhost has left $channel ($text)',
'JOIN': '\x02[$colored_netname]\x02 -$colored_nick$identhost has joined $channel',
'NICK': '\x02[$colored_netname]\x02 -$colored_nick$identhost is now known as $newnick',
'QUIT': '\x02[$colored_netname]\x02 -$colored_nick$identhost has quit ($text)',
'ACTION': '\x02[$colored_netname]\x02 * $colored_nick $text',
'NOTICE': '\x02[$colored_netname]\x02 * Notice from $colored_nick: $text',
}
def color_text(s):
"""
Returns a colorized version of the given text based on a simple hash algorithm
(sum of all characters).
"""
colors = ('02', '03', '04', '05', '06', '07', '08', '09', '10', '11',
'12', '13')
num = sum([ord(char) for char in s])
num = num % len(colors)
return "\x03%s%s\x03" % (colors[num], s)
def cb_relay_core(irc, source, command, args):
"""
This function takes Clientbot actions and outputs them to a channel as regular text.
"""
real_command = command.split('_')[-1]
relay = world.plugins.get('relay')
if irc.pseudoclient and relay:
try:
sourcename = irc.getFriendlyName(source)
except KeyError: # User has left due to /quit
sourcename = args['userdata'].nick
# Special case for CTCPs.
if real_command == 'MESSAGE':
# CTCP action, format accordingly
if (not args.get('is_notice')) and args['text'].startswith('\x01ACTION ') and args['text'].endswith('\x01'):
args['text'] = args['text'][8:-1]
real_command = 'ACTION'
# Other CTCPs are ignored
elif args['text'].startswith('\x01'):
return
elif args.get('is_notice'): # Different syntax for notices
real_command = 'NOTICE'
# .get() chains are lovely. Try to fetch the format for the given command from the
# relay:clientbot_format:$command key, falling back to one defined in default_styles
# above, and then nothing if not found.
text_template = conf.conf.get('relay', {}).get('clientbot_format', {}).get(real_command,
default_styles.get(real_command, ''))
text_template = string.Template(text_template)
if text_template:
# Get the original client that the relay client source was meant for.
try:
origuser = relay.getOrigUser(irc, source) or args['userdata'].remote
except (AttributeError, KeyError):
return
netname = origuser[0]
try: # Try to get the full network name
netname = conf.conf['servers'][netname]['netname']
except KeyError:
pass
# Figure out where the message is destined to.
target = args.get('channel') or args.get('target')
if target is None or not utils.isChannel(target):
# Quit and nick messages are not channel specific. Figure out all channels that the
# sender shares over the relay, and relay them that way.
userdata = args.get('userdata') or irc.users.get(source)
assert userdata, "Got a channel-less message from bad UID %s" % source
channels = [channel for channel in userdata.channels if relay.getRelay((irc.name, channel))]
else:
# Pluralize the channel so that we can iterate over it.
channels = [target]
if source in irc.users:
try:
identhost = irc.getHostmask(source).split('!')[-1]
except KeyError: # User got removed due to quit
identhost = '%s@%s' % (args['olduser'].ident, args['olduser'].host)
# This is specifically spaced so that ident@host is only shown for users that have
# one, and not servers.
identhost = ' (%s)' % identhost
else:
identhost = ''
# Convert the target for kicks, etc. from a UID to a nick
if args.get("target") in irc.users:
target_nick = irc.getFriendlyName(args['target'])
else:
target_nick = ''
args.update({'netname': netname, 'nick': sourcename, 'identhost': identhost,
'colored_nick': color_text(sourcename), 'colored_netname': color_text(netname),
'target_nick': target_nick})
text = text_template.substitute(args)
for channel in channels:
irc.proto.message(irc.pseudoclient.uid, channel, text)
utils.add_hook(cb_relay_core, 'CLIENTBOT_MESSAGE')
utils.add_hook(cb_relay_core, 'CLIENTBOT_KICK')
utils.add_hook(cb_relay_core, 'CLIENTBOT_PART')
utils.add_hook(cb_relay_core, 'CLIENTBOT_JOIN')
utils.add_hook(cb_relay_core, 'CLIENTBOT_QUIT')
utils.add_hook(cb_relay_core, 'CLIENTBOT_NICK')