mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 09:19:23 +01:00
a905f74800
Some of the logic was inverted so that the Clientbot would try to kick invalid things like GLolol/ovd, and send clientbot KICK payloads when it's supposed to forward an actual kick. This also fixes KICKs from servers not being relayed by clientbot.
122 lines
5.5 KiB
Python
122 lines
5.5 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):
|
|
try:
|
|
origuser = (irc.servers[source].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')
|
|
|