def mode(irc, event, args): """[<channel>] <modes> Sets <modes> in <channel>. <channel> is only necessary if the command isn't sent in the channel itself. """ try: if utils.is_private(event) or irc.is_channel(args[0]): if args[0] in irc.state["channels"]: channel = args[0] setmodes = utils.split_modes(args[1:]) elif not utils.is_private(event): channel = event.target setmodes = utils.split_modes(args) else: irc.reply(event, utils.gethelp("mode")) return else: channel = event.target setmodes = utils.split_modes(args) except IndexError: irc.reply(event, utils.gethelp("mode")) else: if utils.is_allowed(irc, event.source, channel): already_op = irc.is_opped(irc.get_nick(), channel) if not already_op: setmodes.append("-o {}".format(irc.get_nick())) gotop = utils.getop(irc, channel) if gotop: for modes in utils.unsplit_modes(setmodes): irc.mode(channel, modes)
def squiet(irc, event, args): """[<channel>] <nick|hostmask> [<nick|hostmask>...] Quiets <nick> in <channel> using services. <channel> is only necessary if the command isn't sent in the channel itself. """ try: if utils.is_private(event): channel = args[0] nicks = args[1:] else: if irc.is_channel(args[0]): channel = args[0] nicks = args[1:] else: channel = event.target nicks = args except IndexError: irc.reply(event, utils.gethelp("squiet")) else: if utils.is_allowed(irc, event.source, channel): try: if irc.channels[channel].get("chanserv", irc.chanserv): irc.privmsg("ChanServ", "QUIET {} {}".format(channel, " ".join(nicks))) except KeyError: pass
def unquiet(irc, event, args): """[<channel>] [<nick|hostmask>...] Unquiets <nick> (or yourself if no <nick> is specified) in <channel>. <channel> is only necessary if the command isn't sent in the channel itself. """ setmodes = [] try: if utils.is_private(event): channel = args[0] if len(args) > 1: nicks = args[1:] else: nicks = [event.source.nick] else: if len(args) > 0: if irc.is_channel(args[0]): channel = args[0] if len(args) > 1: nicks = args[1:] else: nicks = [event.source.nick] else: channel = event.target nicks = args else: channel = event.target nicks = [event.source.nick] except IndexError: irc.reply(event, utils.gethelp("unquiet")) else: if utils.is_allowed(irc, event.source, channel): for nick in nicks: if utils.is_hostmask(nick): hmask = nick else: hmask = utils.gethm(irc, nick) if hmask and channel in irc.state["channels"]: for bmask in irc.state["channels"][channel]["quiets"]: if fnmatch(utils.irclower(hmask), utils.irclower(bmask)): setmodes.append("-q {}".format(bmask)) else: return if len(setmodes) == 0: return already_op = irc.is_opped(irc.get_nick(), channel) if not already_op: setmodes.append("-o {}".format(irc.get_nick())) gotop = utils.getop(irc, channel) if gotop: for mode in utils.unsplit_modes(setmodes): irc.mode(channel, mode)
def seen(irc, event, args): """<nick> Returns the last action by <nick> that the bot has seen and how long ago. """ try: nick = args[0] except IndexError: irc.reply(event, utils.gethelp("seen")) else: try: last = irc.state["users"][nick]["lastmsg"] hmask = irclib.NickMask(utils.gethm(irc, nick)) if last["command"] == "pubmsg" or last["command"] == "pubnotice": # \? irc.reply( event, '{} ({}@{}) was last seen {} ago in {} saying "{}"'.format( nick, hmask.user, hmask.host, timesince(last["time"]), last["channel"], last["message"].strip() ), ) elif last["command"] == "join": irc.reply( event, "{} ({}@{}) was last seen {} ago joining {}".format( nick, hmask.user, hmask.host, timesince(last["time"]), last["channel"] ), ) elif last["command"] == "part": irc.reply( event, "{} ({}@{}) was last seen {} ago leaving {} ({})".format( nick, hmask.user, hmask.host, timesince(last["time"]), last["channel"], last["message"] ), ) elif last["command"] == "kick": irc.reply( event, "{} ({}@{}) was last seen {} ago being kicked from {} ({})".format( nick, hmask.user, hmask.host, timesince(last["time"]), last["channel"], last["message"] ), ) elif last["command"] == "quit": irc.reply( event, "{} ({}@{}) was last seen {} ago quitting ({})".format( nick, hmask.user, hmask.host, timesince(last["time"]), last["message"] ), ) except KeyError: irc.reply(event, "I have not seen {}".format(nick))
def enforce(irc, event, args): """[<channel>] <modes> <nick> Enforces a mode to <nick> in the current channel if no channel argument is given. """ message = event.arguments[0].split() try: if irc.is_channel(message[1]): unrecognised_modes = [] unset_modes = [] set_modes = [] mode_diff = "+" for pos, mode in enumerate(message[2]): if mode in utils.argmodes["set"] or mode in utils.argmodes["unset"] or mode in ["+", "-"]: pass else: # What on earth is that mode? unrecognised_modes.append(mode) for mode in message[2]: if mode == "+": mode_diff = "+" elif mode == "-": mode_diff = "-" else: if mode_diff == "+": if mode in unset_modes: irc.reply(event, "This mode {} is already set and could not be unset for {}".format(mode, message[3])) else: set_modes.append(mode) elif mode_diff == "-": # else but who cares? if mode in set_modes: irc.reply(event, "This mode {} is already set and could not be set for {}".format(mode, message[3])) else: unset_modes.append(mode) if unrecognised_modes: irc.reply(event, "I could not recognise these modes: {}".format("".join(unrecognised_modes))) else: if len(message) >= 4: if not "enforce" in irc.channels[message[1]]: irc.channels[message[1]]["enforce"] = {} irc.channels[message[1]]["enforce"][message[3]] = { "set": set_modes or "", "unset": unset_modes or "" } else: irc.reply(event, "You didn't specify a nick to enforce modes to") except IndexError: irc.reply(event, utils.gethelp("enforce"))
def quiet(irc, event, args): """[<channel>] <nick|hostmask> [<nick|hostmask>...] Quiets <nick> in <channel>. <channel> is only necessary if the command isn't sent in the channel itself. """ setmodes = [] affected = [] try: if utils.is_private(event): channel = args[0] nicks = args[1:] else: if irc.is_channel(args[0]): channel = args[0] nicks = args[1:] else: channel = event.target nicks = args except IndexError: irc.reply(event, utils.gethelp("quiet")) else: if utils.is_allowed(irc, event.source, channel): for nick in nicks: if utils.is_hostmask(nick): bmask = nick else: bmask = utils.banmask(irc, nick) setmodes.append("+q {}".format(bmask)) for affect in utils.ban_affects(irc, channel, bmask): if affect not in affected and affect != irc.get_nick(): affected.append(affect) for nick in affected: if irc.is_opped(nick, channel): setmodes.append("-o {}".format(nick)) if irc.is_voiced(nick, channel): setmodes.append("-v {}".format(nick)) if len(setmodes) == 0: return already_op = irc.is_opped(irc.get_nick(), channel) if not already_op: setmodes.append("-o {}".format(irc.get_nick())) gotop = utils.getop(irc, channel) if gotop: for mode in utils.unsplit_modes(setmodes): irc.mode(channel, mode)
def extract(irc, event, args): try: html = requests.get(args[0]).text soup = BeautifulSoup(html) for script in soup(["script", "style"]): script.extract() text = soup.get_text() lines = (line.strip() for line in text.splitlines()) chunks = (phrase.strip() for line in lines for phrase in line.split(" ")) text = '\n'.join(chunk for chunk in chunks if chunk) text = text.encode('ascii', 'ignore') irc.reply(event, (text[:350] + '..') if len(text) > 350 else text) except IndexError: irc.reply(event, utils.gethelp("extract")) except: irc.reply(event, "Error extracting informations")
def kick(irc, event, args): """[<channel>] <nick> [<nick>...] [:][<reason>] Kicks <nick> in <channel>. <channel> is only necessary if the command isn't sent in the channel itself. It is recommended to use ':' as a seperator between <nick> and <reason>, otherwise, if there's a nick in the channel matching the first word in reason it will be kicked. """ prepare_nicks = [] reason = None try: if utils.is_private(event): channel = args[0] nicks = args[1:] else: if irc.is_channel(args[0]): channel = args[0] nicks = args[1:] else: channel = event.target nicks = args except IndexError: irc.reply(event, utils.gethelp("kick")) else: if utils.is_allowed(irc, event.source, channel): for nick in nicks: if nick in irc.state["channels"][channel]["names"] and nick not in prepare_nicks and not nick.startswith(":"): prepare_nicks.append(nick) else: reason = " ".join(nicks[len(prepare_nicks):]).lstrip(": ") break nicks = prepare_nicks already_op = irc.is_opped(irc.get_nick(), channel) gotop = utils.getop(irc, channel) if gotop: for nick in nicks: if reason: irc.kick(channel, nick, reason) else: irc.kick(channel, nick) if not already_op: irc.mode(channel, "-o {}".format(irc.get_nick()))
def deop(irc, event, args): """[<channel>] [<nick>...] Deops <nick> (or yourself if no <nick> is specified) in <channel>. <channel> is only necessary if the command isn't set in the channel itself. """ setmodes = [] try: if len(args) == 0: nicks = [event.source.nick] channel = event.target elif irc.is_channel(args[0]): channel = args[0] if len(args) > 1: nicks = args[1:] else: nicks = [event.source.nick] else: nicks = args channel = event.target except IndexError: irc.reply(event, utils.gethelp("deop")) else: if utils.is_allowed(irc, event.source, channel): already_op = irc.is_opped(irc.get_nick(), channel) if "*" in nicks: nicks = irc.state["channels"][channel]["names"] if irc.get_nick() in nicks: nicks.remove(irc.get_nick()) if irc.channels[channel].get("chanserv", irc.chanserv) and "ChanServ" in nicks: nicks.remove("ChanServ") for nick in nicks: if irc.is_opped(nick, channel): setmodes.append("-o {}".format(nick)) if len(setmodes) == 0: return if not already_op: setmodes.append("-o {}".format(irc.get_nick())) gotop = utils.getop(irc, channel) if gotop: for mode in utils.unsplit_modes(setmodes): irc.mode(channel, mode)
def sdevoice(irc, event, args): """[<channel>] [<nick>...] Devoices <nick> (or the bot if no <nick> is given) in <channel> using services. <channel> is only necessary if the command isn't sent in the channel itself. """ try: if utils.is_private(event): channel = args[0] if len(args) > 1: nicks = args[1:] else: nicks = [irc.get_nick()] else: if len(args) > 0: if irc.is_channel(args[0]): channel = args[0] if len(args) > 1: nicks = args[1:] else: nicks = [irc.get_nick()] else: channel = event.target nicks = args else: channel = event.target nicks = [irc.get_nick()] except IndexError: irc.reply(event, utils.gethelp("sdevoice")) else: if utils.is_allowed(irc, event.source, channel): try: if irc.channels[channel].get("chanserv", irc.chanserv): for nick in nicks: if not irc.is_voiced(nick, channel): nicks.remove(nick) if len(nicks) > 0: irc.privmsg("ChanServ", "DEVOICE {} {}".format(channel, " ".join(nicks))) except KeyError: pass
def factoid(irc, event, args): """<add|remove|list> [<channel>] <factoid> [<text>] Adds or removes a factoid for <channel> or globally. <channel> is only necessary if the command isn't sent in the channel itself, <text> is only necessary if adding a factoid. Global factoids are modified by sending the command in private with no <channel> specified. """ try: if args[0] == "add": if irc.is_channel(args[1]): channel = args[1] factoid = args[2] text = " ".join(args[3:]) elif irc.is_channel(event.target): channel = event.target factoid = args[1] text = " ".join(args[2:]) else: channel = None factoid = args[1] text = " ".join(args[2:]) if channel: if utils.is_allowed(irc, event.source, channel): if "factoids" not in irc.channels[channel]: irc.channels[channel]["factoids"] = {} irc.channels[channel]["factoids"][factoid] = text irc.reply(event, "Factoid {} added for '{}' in {}".format(factoid, text, channel)) else: if utils.is_allowed(irc, event.source): irc.factoids[factoid] = text irc.reply(event, "Global factoid {} added for '{}'".format(factoid, text)) elif args[0] == "remove": if irc.is_channel(args[1]): channel = args[1] factoid = args[2] elif irc.is_channel(event.target): channel = event.target factoid = args[1] else: channel = None factoid = args[1] if channel: if utils.is_allowed(irc, event.source, channel): if "factoids" not in irc.channels[channel]: irc.reply(event, "ERROR: No factoids exist for {}".format(channel)) elif factoid in irc.channels[channel]["factoids"]: del (irc.channels[channel]["factoids"][factoid]) irc.reply(event, "Factoid {} deleted in {}".format(factoid, channel)) else: if utils.is_allowed(irc, event.source): if factoid in irc.factoids: del (irc.factoids[factoid]) irc.reply(event, "Global factoid {} deleted".format(factoid)) else: irc.reply(event, "ERROR: No global factoids named {} were found".format(factoid)) elif args[0] == "list": if len(args) > 1: if irc.is_channel(args[1]): channel = args[1] elif irc.is_channel(event.target): channel = event.target elif irc.is_channel(event.target): channel = event.target else: channel = None if channel: if "factoids" in irc.channels[channel]: irc.reply( event, "Factoids for {} are: {}".format( channel, ", ".join(['"{}"'.format(x) for x in irc.channels[channel]["factoids"]]) ), ) else: irc.reply(event, "No factoids were found for {}".format(channel)) else: irc.reply(event, "Global factoids are: {}".format(", ".join(['"{}"'.format(x) for x in irc.factoids]))) except (KeyError, IndexError): irc.reply(event, utils.gethelp("factoid"))
def alias(irc, event, args): """<add|remove|list> [<channel>] <alias> [<command>] Adds or removes an alias for <channel> or globally. <channel> is only necessary if the command isn't sent in the channel itself, <command> is only necessary if adding an alias. Global aliases are modified by sending the command in private with no <channel> specified. """ try: if args[0] == "add": if irc.is_channel(args[1]): channel = args[1] alias = args[2] command = " ".join(args[3:]) elif irc.is_channel(event.target): channel = event.target alias = args[1] command = " ".join(args[2:]) else: channel = None alias = args[1] command = " ".join(args[2:]) if channel: if utils.is_allowed(irc, event.source, channel): if len(command) >= 2 and command.split()[0] in utils.commands: #and alias.lower() not in utils.commands: if "aliases" not in irc.channels[channel]: irc.channels[channel]["aliases"] = {} if alias != alias.lower(): irc.reply(event, "The alias name has to be lowercase. Changing alias name...") alias = alias.lower() if alias in utils.commands: irc.reply(event, "Alias \"{}\" is a command and cannot be overwritten".format(alias)) else: irc.channels[channel]["aliases"][alias] = command irc.reply(event, "Alias \"{}\" with arguments \"{}\" added for command \"{}\" in \"{}\"".format(alias, " ".join(command.split()[1:]), command.split()[0], channel)) elif command.split()[0] in utils.commands and alias not in utils.commands: if "aliases" not in irc.channels[channel]: irc.channels[channel]["aliases"] = {} if alias != alias.lower(): irc.reply(event, "The alias name has to be lowercase. Changing alias name...") alias = alias.lower() irc.reply(event, "testing") irc.channels[channel]["aliases"][alias] = command irc.reply(event, "Alias \"{}\" added for command \"{}\" in \"{}\"".format(alias, command, channel)) elif alias in utils.commands: irc.reply(event, "A command with the name \"{}\" already exists".format(alias)) elif not command.split()[0] in utils.commands: irc.reply(event, "No command called \"{}\" exists".format(command.split()[0])) else: if utils.is_allowed(irc, event.source) and command in utils.commands and alias not in utils.commands: irc.aliases[alias] = command irc.reply(event, "Global alias \"{}\" added for command \"{}/\"".format(alias, command)) elif alias in utils.commands: irc.reply(event, "A command with the name \"{}\" already exists".format(command)) elif not command in utils.commands: irc.reply(event, "No command called \"{}\" exists".format(command)) elif args[0] == "remove": if irc.is_channel(args[1]): channel = args[1] alias = args[2] elif irc.is_channel(event.target): channel = event.target alias = args[1] else: channel = None alias = args[1] if channel: if utils.is_allowed(irc, event.source, channel): if "aliases" not in irc.channels[channel]: irc.reply(event, "ERROR: No aliases exist for \"{}\"".format(channel)) elif alias not in irc.channels[channel]["aliases"]: irc.reply(event, "Alias \"{}\" does not exist in \"{}\"".format(alias, channel)) elif alias in irc.channels[channel]["aliases"]: del(irc.channels[channel]["aliases"][alias]) irc.reply(event, "Alias \"{}\" deleted in \"{}\"".format(alias, channel)) else: if utils.is_allowed(irc, event.source): if alias in irc.aliases: del(irc.aliases[alias]) irc.reply(event, "Global alias {} deleted".format(alias)) else: irc.reply(event, "ERROR: No global aliases named {} were found".format(alias)) elif args[0] == "list": if len(args) > 1: if irc.is_channel(args[1]): channel = args[1] elif irc.is_channel(event.target): channel = event.target elif irc.is_channel(event.target): channel = event.target else: channel = None if channel: if "aliases" in irc.channels[channel]: irc.reply(event, "Aliases for {} are: {}".format(channel, ", ".join(["\"{}\"".format(x) for x in irc.channels[channel]["aliases"]]))) else: irc.reply(event, "No aliases were found for {}".format(channel)) else: irc.reply(event, "Global aliases are: {}".format(", ".join(["\"{}\"".format(x) for x in irc.aliases]))) except (KeyError, IndexError): irc.reply(event, utils.gethelp("alias"))
def kban(irc, event, args): """[<channel>] <nick|hostmask> [<nick|hostmask>...] [:][<reason>] Bans <nick> in <channel> and kicks anyone affected using <reason> as the kick message if specified. <channel> is only necessary if the command isn't sent in the channel itself. It is recommended to use ':' as a seperator between <nick> and <reason>, otherwise, if there's a nick in the channel matching the first word in reason it will be kicked. """ prepare_nicks = [] setmodes = [] affected = [] reason = None try: if utils.is_private(event): channel = args[0] nicks = args[1:] else: if irc.is_channel(args[0]): channel = args[0] nicks = args[1:] else: channel = event.target nicks = args except IndexError: irc.reply(event, utils.gethelp("kban")) else: if utils.is_allowed(irc, event.source, channel): for nick in nicks: if nick in irc.state["channels"][channel]["names"] and nick not in prepare_nicks and not nick.startswith(":"): prepare_nicks.append(nick) elif utils.is_hostmask(nick): prepare_nicks.append(nick) else: reason = " ".join(nicks[len(prepare_nicks):]).lstrip(": ") break nicks = prepare_nicks for nick in nicks: if utils.is_hostmask(nick): bmask = nick else: bmask = utils.banmask(irc, nick) setmodes.append("+b {}".format(bmask)) for affect in utils.ban_affects(irc, channel, bmask): if affect not in affected and affect != irc.get_nick(): if irc.is_opped(affect, channel): setmodes.append("-o {}".format(affect)) if irc.is_voiced(affect, channel): setmodes.append("-v {}".format(affect)) affected.append(affect) if len(setmodes) == 0: return already_op = irc.is_opped(irc.get_nick(), channel) gotop = utils.getop(irc, channel) if gotop: for mode in utils.unsplit_modes(setmodes): irc.mode(channel, mode) for nick in affected: if reason: irc.kick(channel, nick, reason) else: irc.kick(channel, nick) if not already_op: irc.mode(channel, "-o {}".format(irc.get_nick()))