# fantasy.py: Adds FANTASY command support, to allow calling commands in channels from pylinkirc import utils, world, conf from pylinkirc.log import log def handle_fantasy(irc, source, command, args): """Fantasy command handler.""" if not irc.connected.is_set(): # Break if the IRC network isn't ready. return channel = args['target'] orig_text = args['text'] if irc.is_channel(channel) and not irc.is_internal_client(source): # The following conditions must be met for an incoming message for # fantasy to trigger: # 1) The message target is a channel. # 2) A PyLink service client exists in the channel. # 3) The message starts with one of our fantasy prefixes. # 4) The sender is NOT a PyLink client (this prevents infinite # message loops). for botname, sbot in world.services.copy().items(): if botname not in world.services: # Bot was removed during iteration continue # Check respond to nick options in this order: # 1) The service specific "respond_to_nick" option # 2) The global "pylink::respond_to_nick" option # 3) The (deprecated) global "bot::respondtonick" option. respondtonick = conf.conf.get(botname, {}).get('respond_to_nick', conf.conf['pylink'].get("respond_to_nick", conf.conf['pylink'].get("respondtonick"))) log.debug('(%s) fantasy: checking bot %s', irc.name, botname) servuid = sbot.uids.get(irc.name) if servuid in irc.channels[channel].users: # Look up a string prefix for this bot in either its own configuration block, or # in bot::prefixes::. prefixes = [conf.conf.get(botname, {}).get('prefix', conf.conf['pylink'].get('prefixes', {}).get(botname))] # If responding to nick is enabled, add variations of the current nick # to the prefix list: "," and ":" nick = irc.to_lower(irc.users[servuid].nick) nick_prefixes = [nick+',', nick+':'] if respondtonick: prefixes += nick_prefixes if not any(prefixes): # No prefixes were set, so skip. continue lowered_text = irc.to_lower(orig_text) for prefix in filter(None, prefixes): # Cycle through the prefixes list we finished with. if lowered_text.startswith(prefix): # Cut off the length of the prefix from the text. text = orig_text[len(prefix):] # HACK: don't trigger on commands like "& help" to prevent false positives. # Weird spacing like "PyLink: help" and "/msg PyLink help" should still # work though. if text.startswith(' ') and prefix not in nick_prefixes: log.debug('(%s) fantasy: skipping trigger with text prefix followed by space', irc.name) continue # Finally, call the bot command and loop to the next bot. sbot.call_cmd(irc, source, text, called_in=channel) continue utils.add_hook(handle_fantasy, 'PRIVMSG')