class BotTooper(sleekxmpp.ClientXMPP): def __init__(self, jid, password, room, nick): sleekxmpp.ClientXMPP.__init__(self, jid, password) self.room = room self.nick = nick self.add_event_handler("session_start", self.session_start) self.add_event_handler("groupchat_message", self.groupchat_message, threaded=True) self.add_event_handler("message", self.direct_message, threaded=True) self.commands = CommandMap() self.commands.load_plugins() self.commands.map_command(".help", self.help) def session_start(self, event): """Process the session_start event.""" logger.debug("RECV session_start") self.send_presence() self.plugin['xep_0045'].joinMUC(self.room, self.nick, wait=True) def direct_message(self, msg): """Process incoming message stanzas from any user.""" if msg['type'] in ('chat', 'normal'): responses = self.get_responses(msg) if responses: if len(responses) > 1: responses = ["\n".join([""] + responses)] for response in responses: self.send_message(mto=msg['from'], mfrom=msg['to'], mbody=response) def groupchat_message(self, msg): """Process incoming message stanzas from any chat room.""" # Infinite loops are bad. Don't reply to self. if msg['mucnick'] != self.nick and msg['type'] == 'groupchat': responses = self.get_responses(msg) if responses: if len(responses) > 1: responses = ["\n".join([""] + responses)] for response in responses: self.send_message(mto=msg['from'].bare, mfrom=msg['to'], mbody=response, mtype='groupchat') def get_responses(self, msg): """Return a list of responses to initialized triggers if any. Return an empty list if not.""" message = msg["body"].split(None, 1) command = self.commands.get_command(message[0]) if command: try: if len(message) > 1 and command.arity > 1: return command.func(message[1]) else: return command.func() except Exception as e: logger.debug("Unhandled exception: {}".format(e)) self.disconnect() sys.exit() else: return None def help(self): return ["Available commands: {}".format(', '.join(sorted(self.commands.triggers())))]
class BotTooper(irc.IRCClient): def __init__(self, nickname): self.nickname = nickname self.commands = CommandMap() self.commands.load_plugins(exclude=('towers_plugin', 'timers_plugin')) self.commands.map_command(".help", self.help) def signedOn(self): # called on connect logger.debug("Welcome received, joining channel.") self.join(self.factory.channel) if self.factory.operuser and self.factory.operpass: logger.debug("Operator credentials set, sending OPER.") self.sendLine("OPER {} {}".format(self.factory.operuser, self.factory.operpass)) def kickedFrom(self, channel, kicker, message): logger.debug("Kicked from {} by {} because {}.".format(channel, kicker, message)) logger.debug("Waiting 10 seconds before rejoin.") time.sleep(10) self.join(self.factory.channel) def privmsg(self, user, channel, message): logger.debug("RECV user={} channel={} message={}".format(repr(user), repr(channel), repr(message))) reactor.callInThread(self.respond_to_commands, message, self.get_reply_target(channel, user.split('!', 1)[0])) def get_reply_target(self, channel, user): if self.is_private_message(channel): return user elif self.is_channel_message(channel): return channel def respond_to_commands(self, message, reply_to): # TODO: "before_commands" callback for history ignore plugin? message = message.split(None, 1) command = self.commands.get_command(message[0]) if command: if len(message) > 1 and command.arity > 1: self.send_responses(command.func(message[1]), reply_to) else: self.send_responses(command.func(), reply_to) def send_responses(self, responses, reply_to): if responses: for line in responses: logger.debug("SEND reply_to={} line={}".format(reply_to, line)) self.msg(reply_to, line) def is_private_message(self, channel): return channel == self.nickname def is_channel_message(self, channel): return channel == self.factory.channel def help(self): return ["Available commands: {}".format(', '.join(sorted(self.commands.triggers())))]