def _get_channels_per_network(cfg): hooks = cfg.get('hooks', {}) network_info = copy.deepcopy(cfg['networks']) for net_key in network_info: network_info[net_key]['channels'] = [] for hook in hooks: network = hook['network'] if network not in network_info: raise Exception("Network '{network}' not configured" .format(network=network)) reports = hook['reports'] for ch in reports: current_channels = network_info[network]['channels'] if is_channel(ch) and ch not in current_channels: print("Appending {channel} ({network})" .format(channel=ch, network=network)) network_info[network]['channels'].append(ch) watchers = cfg.get('watchers', {}) print(watchers) for watcher in watchers: network = watcher['network'] channel = watcher['channel'] current_channels = network_info[network]['channels'] if channel not in current_channels: print("Appending {channel} ({network})" .format(channel=channel, network=network)) network_info[network]['channels'].append(channel) return network_info
def do_part(self, connection, event): """Part a channel target given by the bot controller.""" arguments = event.arguments[0].split() try: if is_channel(arguments[1]): connection.part(arguments[1]) except IndexError: pass
def join_channel(self, params): """Join a channel.""" channel = params.split(" ", 1) self.log.info("Joining %s" % channel[0]) if irclib.is_channel(channel[0]): self.channels.append(channel[0]) if len(channel) > 1: self.connection.join(channel[0], channel[1]) else: self.connection.join(channel[0])
def join_channel(self, params): """Join a channel.""" channel = params.split(" ", 1) self.reply("Joining %s" % channel[0]) if irclib.is_channel(channel[0]): self.channels.append(channel[0]) if len(channel) > 1: self.connection.join(channel[0], channel[1]) else: self.connection.join(channel[0])
def dispatch(self, reply): """Dispatch message as notice.""" _reply = self._mangle_msg(reply) for line in _reply: self.irc.notice(self.target, line) if irclib.is_channel(self.target): self.log.info("-%s- <%s> %s" % (self.target, self.irc.nick, line)) else: self.log.info("<%s> %s" % (self.irc.nick, line))
def on_welcome(self, connection, _event): """Join channels upon successful connection.""" if self.identify_password: self.privmsg("NickServ", "IDENTIFY %s" % self.identify_password) for channel in self.channels: channel = channel.split(" ", 1) if irclib.is_channel(channel[0]): if len(channel) > 1: connection.join(channel[0], channel[1]) else: connection.join(channel[0])
def post_to_irc(msg, host, port, nick, ident, realname, target): """ Log into an IRC server and send a message to a channel. """ global IRC_CLIENT, IRC_SERVER if IRC_CLIENT is None: IRC_CLIENT = client.Reactor() IRC_SERVER = IRC_CLIENT.server() IRC_SERVER.connect(host, port, nick) if client.is_channel(target): IRC_SERVER.join(target) IRC_SERVER.privmsg(target, msg)
def is_configured(cls): if not (hasattr(settings, 'IRC') and hasattr(settings, 'IRC_SOCKET_PATH') and hasattr(settings, 'IRC_ALLOWED_CHAR')): return False for conf in settings.IRC: if not (conf.get('nick') and conf.get('server') and conf.get('channels')): return False for chan in conf['channels']: if not ('name' in chan and is_channel(chan['name'])): return False return True
def post_to_irc(msg, host, port, nick, ident, realname, target): """ Log into an IRC server and send a message to a channel. """ global IRC_CLIENT, IRC_SERVER if IRC_CLIENT is None: IRC_CLIENT = client.Reactor() IRC_SERVER = IRC_CLIENT.server() IRC_SERVER.connect(host, port, nick) if client.is_channel(target): IRC_SERVER.join(target) for line in msg.splitlines(): IRC_SERVER.privmsg(target, line)
def do_join(self, connection, event): """Join a channel target given by the bot controller.""" arguments = event.arguments[0].split() usage_msg = [ "Usage: join <channel name> <invite_threshold> <part_threshold>", "Example: join #test 15 12" ] try: if is_channel(arguments[1]): connection.join(arguments[1]) except IndexError: for line in usage_msg: connection.notice(event.source.nick, line) try: if arguments[1] not in self.config and is_channel(arguments[1]): self.config[arguments[1]] = Registrar(arguments[1], int(arguments[2]), int(arguments[3])) self.config.save() except IndexError: for line in usage_msg: connection.notice(event.source.nick, line) connection.names(arguments[1])
def do_join(self, connection, event): """Join a channel specified by the bot controller.""" arguments = event.arguments[0].split() try: if is_channel(arguments[1]): connection.join(arguments[1]) self._channel_table[arguments[1].lower()] = Pomodoro( connection, arguments[1].lower()) else: connection.notice(event.source.nick, "'" + arguments[1] + "' is not a channel.") except IndexError: usage_msg = "Usage: join <channel> Example: join #test" connection.notice(event.source.nick, usage_msg)
def dispatch(self, reply): """dispatch message as a reply.""" _reply = self._mangle_msg(reply) for line in _reply: if self.irc.addressed: source = self.source.split("!")[0] self.irc.privmsg(self.target, "%s: %s" % (source, line)) self.log.info("-%s- <%s> %s: %s" % (self.target, self.irc.nick, source, line)) else: self.irc.privmsg(self.target, line) if irclib.is_channel(self.target): self.log.info("-%s- <%s> %s" % (self.target, self.irc.nick, line)) else: self.log.info("<%s> %s" % (self.irc.nick, line))
def on_privmsg(self, c, e): logging.debug("on_privmsg") source = e.source.nick target = e.target if is_channel( e.target ) else source message = e.arguments[0] self.__module_handle('privmsg', source=source, target=target, message=message) try: self.__process_command( c, e ) except BotExitException as e: raise e except BotReloadException as e: self.connection.disconnect( "Reloading bot..." ) self.modules.unload() raise e except Exception as e: logging.exception( 'Error in __process_command: %s', e )
def wrapper(self, bot, connection, event): line = ''.join(event.arguments) speaker = event.source addressee, message = parse_line(line) public = ic.is_channel(event.target) to_self = is_self(bot, addressee) or not public if public and to_self: reply = Reply(speaker.nick, event.target, connection) elif public and not to_self: reply = Reply(addressee, event.target, connection) elif not public: addressee = bot._nickname reply = PrivateReply(event.source.nick, connection) else: log.warn("Couldn't determine speaker for event: %r", event) return method(self, bot, speaker, addressee, message, reply)
def __process_command( self, c, e ): """Process a message coming from the server.""" message = e.arguments[0] # commands have to start with ! if message[0] != '!': return # strip the ! off, and split the message args = message[1:].split() # cmd is the first item cmd = args.pop(0).strip() # test for admin admin = e.source.userhost in self.admin if not admin: if e.target in self.admin_channels and e.target in self.channel_ops and e.source.nick in self.channel_ops[ e.target ]: admin = True # nick is the sender of the message, target is either a channel or the sender. source = e.source.nick target = e.target if is_channel(e.target) else source # see if there is a module that is willing to handle this, and make it so. logging.debug( '__process_command (src: %s; tgt: %s; cmd: %s; args: %s; admin: %s)', source, target, cmd, args, admin ) # handle die outside of module (in case module is dead :( ) if admin: if cmd == 'die': self.notice( source, 'Goodbye cruel world!' ) raise BotExitException elif cmd == 'jump': self.jump_server() elif cmd == 'restart_class': raise BotReloadException # config commands elif cmd == 'get_config' and len( args ) <= 2: if len( args ) == 2: try: value = self.get_config( args[0], args[1] ) self.notice( source, 'config[{0}][{1}] = {2}'.format( args[0], args[1], value ) ) except: self.notice( source, 'config[{0}][{1}] not set'.format( *args ) ) elif len( args ) == 1: try: values = self.get_config( args[0] ) if len( values ) > 0: self.notice( source, 'config[{}]: '.format( args[0] ) + ', '.join( [ '{}: "{}"'.format( k,v ) for ( k, v ) in values.items() ] ) ) else: self.notice( source, 'config[{}] is empty'.format( args[0] ) ) except: self.notice( source, 'config[{}] not set'.format( args[0] ) ) else: try: self.notice( source, 'config groups: ' + ', '.join( self.get_config_groups() ) ) except Exception as e: self.notice( source, 'No config groups: {}'.format( e ) ) elif cmd == 'set_config' and len( args ) >= 2: if len( args ) >= 3: config_val = ' '.join( args[2:] ) else: config_val = None try: self.set_config( args[0], args[1], config_val ) self.notice( source, 'Set config setting' if config_val else 'Cleared config setting' ) except Exception as e: self.notice( source, 'Failed setting/clearing config setting: {0}'.format( e ) ) # other base admin commands elif cmd == 'raw': self.connection.send_raw( ' '.join( args ) ) return elif cmd == 'admins': self.notice( source, 'Current operators:' ) self.notice( source, ' - global: {0}'.format( ' '.join( self.admin ) ) ) for chan in [ chan for chan in self.admin_channels if chan in self.channel_ops ]: self.notice( source, ' - {0}: {1}'.format( chan, ' '.join( self.channel_ops[ chan ] ) ) ) return if cmd == 'help': if len( args ) > 0: if args[0] == 'module': if len( args ) < 2: pass elif self.modules.module_is_loaded( args[1] ): module = self.modules.get_module( args[1] ) self.notice( target, module.__doc__ ) else: for ( module_name, module ) in self.modules.get_loaded_modules(): if module.has_cmd( args[0] ): self.notice( target, module.get_cmd( args[0] ).__doc__ ) else: self.notice( target, '!help: this help text (send !help <command> for command help, send !help module <module> for module help)' ) for ( module_name, module ) in [ lst for lst in self.modules.get_loaded_modules() if lst[1].has_commands and not lst[1].admin_only ]: cmds = module.get_cmd_list() self.notice( target, ' * {0}: {1}'.format( module_name, ', '.join( cmds ) if len( cmds ) > 0 else 'No commands' ) ) elif admin and cmd == 'admin_help': if len( args ) > 0: for ( module_name, module ) in self.modules.get_loaded_modules(): if module.has_admin_cmd( args[0] ): self.notice( source, module.get_admin_cmd( args[0] ).__doc__ ) else: self.notice( source, '!admin_help: this help text (send !admin_help <command> for command help' ) self.notice( source, '!die: kill the bot' ) self.notice( source, '!raw: send raw irc command' ) self.notice( source, '!admins: see who are admin' ) self.notice( source, '!restart_class: restart the main Bot class' ) for ( module_name, module ) in self.modules.get_loaded_modules(): cmds = module.get_admin_cmd_list() if len( cmds ) > 0: self.notice( source, ' * {0}: {1}'.format( module_name, ', '.join( cmds ) ) ) else: for ( module_name, module ) in self.modules.get_loaded_modules(): try: if module.has_cmd( cmd ): lines = module.get_cmd( cmd )(args=args, source=source, target=target, admin=admin) if lines: for line in lines: self.notice( target, line ) elif admin and module.has_admin_cmd( cmd ): lines = module.get_admin_cmd(cmd)(args=args, source=source, target=target, admin=admin) if lines: for line in lines: self.notice( source, line ) except Exception as e: logging.exception( "Module '{0}' handle error: {1}".format( module_name, e ) )
def on_pubmsg(self, c, e): nick = e.source.nick target = e.target if is_channel(e.target) else nick line = e.arguments[0]
def on_pubmsg(self, c, e): nick = e.source.nick target = e.target if is_channel(e.target) else nick def reply(msg): self.send(target, msg) def dm(msg): self.send(nick, msg) line = UnicodeDammit(e.arguments[0]).unicode_markup log(' \033[37m{}→{}\033[0m'.format(nick, line)) a = line.split(":", 1) if len(a) > 1 and a[0].lower() == self.nick: self.do_command(e, a[1].strip().lower(), nick, target, reply, dm) return # zeltofilter if 'zeltoph' in nick: return foo = settings.VIPS.get(nick, 0) if random() < foo: self.kick(nick) match = re.match('.*┻━┻.*', line) if match: reply('┬─┬ノ(ಠ_ಠノ)') return match = re.match('^({} *:)? *chaos-?([☆★☼☀*]|sternchen) *: ?(.*)$'.format(self.nick), line) if match: newcs = match.group(3) self.chaossternchen.append(newcs) self.sendchan('Chaos-☆ Nr. {} notiert: {}'.format(len(self.chaossternchen), newcs)) return if line.startswith('.wiki '): wikipage = line[len('.wiki '):].strip() if re.match('^[-_+\w]+$', wikipage): wikiurl = 'http://afra-berlin.de/dokuwiki/doku.php?id={}'.format(wikipage) if 'Dieses Thema existiert noch nicht' in requests.get(wikiurl).text: reply("I'm sorry, I can't find a wiki page with that name.") else: reply(wikiurl) else: reply('Try to troll somebot else.') return if line == 'wat?': reply("I don't have a clue.") return if re.match('^hail eris[.!]* ', line.lower()): reply("All Hail Discordia!") return m = re.findall('(^|\s)?(gh?ah?nh?dh?ih?)(\s|$)?', line, re.IGNORECASE) for _1,match,_2 in m: if not re.match('(^|\s)?gandhi(\s|$)?', match, re.IGNORECASE): self.kick(nick, "It's spelled Gandhi") return if re.search('https?://[-a-z0-9.]*facebook.com', line.lower()): reply('A facebook link? srsly? Get some self-respect!') return match = re.search('https?://pr0gramm.com/#(newest/\*/[0-9/]*)', line.lower()) if match: reply('Fixed that pr0gramm link for you: http://pr0gramm.com/static/'+match.group(1)) return if line == 'moin': self.moincount += 1 if self.moincount == 5: reply('moin') return else: self.moincount = 0 if line.lstrip('.!#').startswith('eta '): eta = line[4:].strip() with self.db as db: db.execute("DELETE FROM etas WHERE nick=?", (nick,)) if eta: db.execute("INSERT INTO etas VALUES (DATETIME('now'), ?, ?)", (nick, eta)) dm('ETA registered. Thanks!') return m = re.findall(URL_REGEX, line.lower()) for url,*_ in m: res = requests.get(url) if res.status_code == requests.codes.ok: soup = BeautifulSoup(res.text) reply(soup.title.string) m = re.findall('(^|\s)(afra)(\s|$)', line, re.IGNORECASE) for _1,match,_2 in m: if match != 'AfRA' and match != 'afra' and random() < 0.1: reply("I'm sure you meant AfRA, not "+match) return
def need_join(self): """Return True if this channel needs to be joined""" return is_channel(self.name) and not self._is_joined
def on_connect(connection, event): if client.is_channel(target): connection.join(target) return main_loop(connection)
def __process_command(self, c, e): """Process a message coming from the server.""" message = e.arguments[0] # commands have to start with ! if message[0] != '!': return # strip the ! off, and split the message into command and arguments split_message = message[1:].split(None, 1) cmd = split_message.pop(0).strip() raw_args = split_message[0] if len(split_message) else '' arglist = raw_args.split() # test for admin admin = e.source.userhost in self.admin if not admin: if e.target in self.admin_channels and e.target in self.channel_ops and e.source.nick in self.channel_ops[ e.target]: admin = True # nick is the sender of the message, target is either a channel or the sender. source = e.source.nick target = e.target if is_channel(e.target) else source # see if there is a module that is willing to handle this, and make it so. logging.debug( '__process_command (src: %s; tgt: %s; cmd: %s; args: %s; admin: %s)', source, target, cmd, raw_args, admin) # handle die outside of module (in case module is dead :( ) if admin: if cmd == 'die': self.notice(source, 'Goodbye cruel world!') raise BotExitException elif cmd == 'jump': self.jump_server() elif cmd == 'restart_class': self.notice(source, 'Restarting...') raise BotReloadException # config commands elif cmd == 'get_config' and len(arglist) <= 2: if len(arglist) == 2: try: value = self.get_config(arglist[0], arglist[1]) self.notice( source, 'config[{0}][{1}] = {2}'.format( arglist[0], arglist[1], value)) except: self.notice( source, 'config[{0}][{1}] not set'.format(*arglist)) elif len(arglist) == 1: try: values = self.get_config(arglist[0]) if len(values) > 0: self.notice( source, 'config[{}]: '.format(arglist[0]) + ', '.join([ '{}: "{}"'.format(k, v) for (k, v) in values.items() ])) else: self.notice( source, 'config[{}] is empty'.format(arglist[0])) except: self.notice(source, 'config[{}] not set'.format(arglist[0])) else: try: self.notice( source, 'config groups: ' + ', '.join(self.get_config_groups())) except Exception as e: self.notice(source, 'No config groups: {}'.format(e)) elif cmd == 'set_config' and len(arglist) >= 2: if len(arglist) >= 3: config_val = ' '.join(arglist[2:]) else: config_val = None try: self.set_config(arglist[0], arglist[1], config_val) self.notice( source, 'Set config setting' if config_val else 'Cleared config setting') except Exception as e: self.notice( source, 'Failed setting/clearing config setting: {0}'.format( e)) # other base admin commands elif cmd == 'raw': self.connection.send_raw(raw_args) return elif cmd == 'admins': self.notice(source, 'Current operators:') self.notice(source, ' - global: {0}'.format(' '.join(self.admin))) for chan in [ chan for chan in self.admin_channels if chan in self.channel_ops ]: self.notice( source, ' - {0}: {1}'.format(chan, ' '.join(self.channel_ops[chan]))) return if False and cmd == 'help': if len(arglist) > 0: if arglist[0] == 'module': if len(arglist) < 2: pass elif self.modules.module_is_loaded(arglist[1]): module = self.modules.get_module(arglist[1]) self.notice(target, module.__doc__) else: for (module_name, module) in self.modules.get_loaded_modules(): if module.has_cmd(arglist[0]): self.notice(target, module.get_cmd(arglist[0]).__doc__) else: self.notice( target, '!help: this help text (send !help <command> for command help, send !help module <module> for module help)' ) for (module_name, module) in [ lst for lst in self.modules.get_loaded_modules() if lst[1].has_commands and not lst[1].admin_only ]: cmds = module.get_cmd_list() self.notice( target, ' * {0}: {1}'.format( module_name, ', '.join(cmds) if len(cmds) > 0 else 'No commands')) elif False and admin and cmd == 'admin_help': if len(arglist) > 0: for (module_name, module) in self.modules.get_loaded_modules(): if module.has_admin_cmd(arglist[0]): self.notice(source, module.get_admin_cmd(arglist[0]).__doc__) else: self.notice( source, '!admin_help: this help text (send !admin_help <command> for command help' ) self.notice( source, '!die: kill the bot') self.notice( source, '!raw: send raw irc command' ) self.notice( source, '!admins: see who are admin' ) self.notice( source, '!restart_class: restart the main Bot class' ) for (module_name, module) in self.modules.get_loaded_modules(): cmds = module.get_admin_cmd_list() if len(cmds) > 0: self.notice( source, ' * {0}: {1}'.format(module_name, ', '.join(cmds))) else: for (module_name, module) in self.modules.get_loaded_modules(): try: if module.has_cmd(cmd): lines = module.get_cmd(cmd)(args=arglist, arglist=arglist, raw_args=raw_args, source=source, target=target, admin=admin) if lines: for line in lines: self.notice(target, line) elif admin and module.has_admin_cmd(cmd): lines = module.get_admin_cmd(cmd)(args=arglist, arglist=arglist, raw_args=raw_args, source=source, target=target, admin=admin) if lines: for line in lines: self.notice(source, line) except Exception as e: logging.exception("Module '{0}' handle error: {1}".format( module_name, e))
def on_connect(self, connection: Connection, event: Event) -> None: if is_channel(self.channel): connection.join(self.channel) return self.main_loop(connection)
def is_channel(self): return client.is_channel(self.target)
def __process_command(self, c, e): """Process a message coming from the server.""" message = e.arguments[0] # commands have to start with ! if message[0] != "!": return # strip the ! off, and split the message into command and arguments split_message = message[1:].split(None, 1) cmd = split_message.pop(0).strip() raw_args = split_message[0] if len(split_message) else "" arglist = raw_args.split() # test for admin admin = e.source.userhost in self.admin if not admin: if ( e.target in self.admin_channels and e.target in self.channel_ops and e.source.nick in self.channel_ops[e.target] ): admin = True # nick is the sender of the message, target is either a channel or the sender. source = e.source.nick target = e.target if is_channel(e.target) else source # see if there is a module that is willing to handle this, and make it so. logging.debug( "__process_command (src: %s; tgt: %s; cmd: %s; args: %s; admin: %s)", source, target, cmd, raw_args, admin ) # handle die outside of module (in case module is dead :( ) if admin: if cmd == "die": self.notice(source, "Goodbye cruel world!") raise BotExitException elif cmd == "jump": self.jump_server() elif cmd == "restart_class": self.notice(source, "Restarting...") raise BotReloadException # config commands elif cmd == "get_config" and len(arglist) <= 2: if len(arglist) == 2: try: value = self.get_config(arglist[0], arglist[1]) self.notice(source, "config[{0}][{1}] = {2}".format(arglist[0], arglist[1], value)) except: self.notice(source, "config[{0}][{1}] not set".format(*arglist)) elif len(arglist) == 1: try: values = self.get_config(arglist[0]) if len(values) > 0: self.notice( source, "config[{}]: ".format(arglist[0]) + ", ".join(['{}: "{}"'.format(k, v) for (k, v) in values.items()]), ) else: self.notice(source, "config[{}] is empty".format(arglist[0])) except: self.notice(source, "config[{}] not set".format(arglist[0])) else: try: self.notice(source, "config groups: " + ", ".join(self.get_config_groups())) except Exception as e: self.notice(source, "No config groups: {}".format(e)) elif cmd == "set_config" and len(arglist) >= 2: if len(arglist) >= 3: config_val = " ".join(arglist[2:]) else: config_val = None try: self.set_config(arglist[0], arglist[1], config_val) self.notice(source, "Set config setting" if config_val else "Cleared config setting") except Exception as e: self.notice(source, "Failed setting/clearing config setting: {0}".format(e)) # other base admin commands elif cmd == "raw": self.connection.send_raw(raw_args) return elif cmd == "admins": self.notice(source, "Current operators:") self.notice(source, " - global: {0}".format(" ".join(self.admin))) for chan in [chan for chan in self.admin_channels if chan in self.channel_ops]: self.notice(source, " - {0}: {1}".format(chan, " ".join(self.channel_ops[chan]))) return if False and cmd == "help": if len(arglist) > 0: if arglist[0] == "module": if len(arglist) < 2: pass elif self.modules.module_is_loaded(arglist[1]): module = self.modules.get_module(arglist[1]) self.notice(target, module.__doc__) else: for (module_name, module) in self.modules.get_loaded_modules(): if module.has_cmd(arglist[0]): self.notice(target, module.get_cmd(arglist[0]).__doc__) else: self.notice( target, "!help: this help text (send !help <command> for command help, send !help module <module> for module help)", ) for (module_name, module) in [ lst for lst in self.modules.get_loaded_modules() if lst[1].has_commands and not lst[1].admin_only ]: cmds = module.get_cmd_list() self.notice( target, " * {0}: {1}".format(module_name, ", ".join(cmds) if len(cmds) > 0 else "No commands") ) elif False and admin and cmd == "admin_help": if len(arglist) > 0: for (module_name, module) in self.modules.get_loaded_modules(): if module.has_admin_cmd(arglist[0]): self.notice(source, module.get_admin_cmd(arglist[0]).__doc__) else: self.notice(source, "!admin_help: this help text (send !admin_help <command> for command help") self.notice(source, "!die: kill the bot") self.notice(source, "!raw: send raw irc command") self.notice(source, "!admins: see who are admin") self.notice(source, "!restart_class: restart the main Bot class") for (module_name, module) in self.modules.get_loaded_modules(): cmds = module.get_admin_cmd_list() if len(cmds) > 0: self.notice(source, " * {0}: {1}".format(module_name, ", ".join(cmds))) else: for (module_name, module) in self.modules.get_loaded_modules(): try: if module.has_cmd(cmd): lines = module.get_cmd(cmd)( args=arglist, arglist=arglist, raw_args=raw_args, source=source, target=target, admin=admin ) if lines: for line in lines: self.notice(target, line) elif admin and module.has_admin_cmd(cmd): lines = module.get_admin_cmd(cmd)( args=arglist, arglist=arglist, raw_args=raw_args, source=source, target=target, admin=admin ) if lines: for line in lines: self.notice(source, line) except Exception as e: logging.exception("Module '{0}' handle error: {1}".format(module_name, e))