Example #1
0
async def set_prefix(message: discord.Message, prefix: str = None):
    """ Set the bot prefix. **The prefix is case sensitive and may not include spaces.** """
    config.set_server_config(message.server, "command_prefix",
                             utils.split(prefix)[0] if prefix else None)

    pre = config.default_command_prefix if prefix is None else prefix
    await client.say(message, "Set the server prefix to `{}`.".format(pre))
Example #2
0
def on_message(client: discord.Client, message: discord.Message):
    """ Perform lambda commands. """
    args = utils.split(message.content)

    # Check if the command is a lambda command and is not disabled (in the blacklist)
    if args[0] in lambdas.data and args[0] not in lambda_config.data["blacklist"]:
        def say(msg, m=message):
            asyncio.async(client.say(m, msg))

        def arg(i, default=0):
            if len(args) > i:
                return args[i]
            else:
                return default

        code_globals.update(dict(arg=arg, say=say, args=args, message=message, client=client))

        # Execute the command
        try:
            exec(lambdas.data[args[0]], code_globals)
        except Exception as e:
            if utils.is_owner(message.author):
                say("```" + utils.format_exception(e) + "```")
            else:
                logging.warn("An exception occurred when parsing lambda command:"
                             "\n{}".format(utils.format_exception(e)))

        return True
Example #3
0
async def on_message(message: discord.Message):
    """ What to do on any message received.

    The bot will handle all commands in plugins and send on_message to plugins using it. """
    # Make sure the client is ready before processing commands
    await client.wait_until_ready()
    start_time = datetime.now()

    # We don't care about channels we can't write in as the bot usually sends feedback
    if message.server and message.server.owner and not message.server.me.permissions_in(
            message.channel).send_messages:
        return

    # Don't accept commands from bot accounts
    if message.author.bot:
        return

    # Split content into arguments by space (surround with quotes for spaces)
    cmd_args = utils.split(message.content)

    # Get command name
    if cmd_args[0].startswith(config.command_prefix) and len(
            cmd_args[0]) > len(config.command_prefix):
        cmd = cmd_args[0][len(config.command_prefix):]
    else:
        return

    # Try finding a command object
    command = plugins.get_command(cmd)
    if not command:
        return

    # Parse the command with the user's arguments
    try:
        parsed_command, args, kwargs = await parse_command(
            command, cmd_args, message)
    except AssertionError as e:  # Return any feedback given from the command via AssertionError, or the command help
        await client.send_message(
            message.channel,
            str(e) or utils.format_help(command, no_subcommand=True))
        log_message(message)
        return

    if not parsed_command:
        return

    log_message(message)
    client.loop.create_task(
        execute_command(parsed_command, message, *args,
                        **kwargs))  # Run command

    # Log time spent parsing the command
    stop_time = datetime.now()
    time_elapsed = (stop_time - start_time).total_seconds() / 1000
    logging.debug("Time spent parsing command: {elapsed:.6f}ms".format(
        elapsed=time_elapsed))
Example #4
0
async def on_message(message: discord.Message):
    """ Perform lambda commands. """
    args = utils.split(message.content)

    # Check if the command is a lambda command and is not disabled (in the blacklist)
    if args[0] in lambdas.data and args[0] not in lambda_config.data[
            "blacklist"]:

        def arg(i, default=0):
            if len(args) > i:
                return args[i]
            else:
                return default

        code_globals.update(
            dict(arg=arg,
                 args=args,
                 message=message,
                 client=client,
                 author=message.author,
                 server=message.server,
                 channel=message.channel))
        python_code = lambdas.data[args[0]]

        # Create an async function so that we can await it using the result of eval
        python_code = "async def lambda_session():\n    " + "\n    ".join(
            line for line in python_code.split("\n"))
        try:
            exec(python_code, code_globals)
        except SyntaxError as e:
            if plugins.is_owner(message.author):
                await client.say(message,
                                 "```" + utils.format_syntax_error(e) + "```")
            else:
                logging.warning(
                    "An exception occurred when parsing lambda command:"
                    "\n{}".format(utils.format_syntax_error(e)))
            return True

        # Execute the command
        try:
            await eval("lambda_session()", code_globals)
        except AssertionError as e:  # Send assertion errors to the core module
            raise AssertionError(e)
        except Exception as e:
            if plugins.is_owner(message.author):
                await client.say(message,
                                 "```" + utils.format_exception(e) + "```")
            else:
                logging.warning(
                    "An exception occurred when parsing lambda command:"
                    "\n{}".format(utils.format_exception(e)))

        return True
Example #5
0
File: alias.py Project: stoz/PCBOT
async def on_message(message: discord.Message):
    success = False

    # User alias check
    if message.author.id in aliases.data:
        user_aliases = aliases.data[message.author.id]

        # Check any aliases
        for name, command in user_aliases.items():
            execute = False
            msg = message.content
            args = utils.split(msg)

            if not command.get("case_sensitive", False):
                msg = msg.lower()

            if command.get("anywhere", False):
                if name in msg:
                    execute = True
            else:
                if name == args[0]:
                    execute = True

            if execute:
                if command.get("delete_message", False):
                    if message.server.me.permissions_in(
                            message.channel).manage_messages:
                        client.loop.create_task(client.delete_message(message))

                text = command["text"]
                pre = config.server_command_prefix(message.server)

                # Execute the command if it is one
                if text.startswith(pre):
                    await plugins.execute(
                        utils.split(text)[0][len(pre):], message)
                else:
                    await client.say(message, text)
                success = True

    return success
Example #6
0
def parse_annotation(param: inspect.Parameter, default, arg: str, index: int, message: discord.Message):
    """ Parse annotations and return the command to use.

    index is basically the arg's index in shelx.split(message.content) """
    if default is param.empty:
        default = None

    if param.annotation is not param.empty:  # Any annotation is a function or Annotation enum
        anno = param.annotation

        # Valid enum checks
        if isinstance(anno, utils.Annotate):
            content = lambda s: utils.split(s, maxsplit=index)[-1].strip("\" ")

            if anno is utils.Annotate.Content:  # Split and get raw content from this point
                return content(message.content) or default
            elif anno is utils.Annotate.LowerContent:  # Lowercase of above check
                return content(message.content).lower() or default
            elif anno is utils.Annotate.CleanContent:  # Split and get clean raw content from this point
                return content(message.clean_content) or default
            elif anno is utils.Annotate.LowerCleanContent:  # Lowercase of above check
                return content(message.clean_content).lower() or default
            elif anno is utils.Annotate.Member:  # Checks member names or mentions
                return utils.find_member(message.server, arg) or default_self(anno, default, message)
            elif anno is utils.Annotate.Channel:  # Checks channel names or mentions
                return utils.find_channel(message.server, arg) or default_self(anno, default, message)
            elif anno is utils.Annotate.Code:  # Works like Content but extracts code
                return utils.get_formatted_code(utils.split(message.content, maxsplit=index)[-1]) or default

        try:  # Try running as a method
            result = anno(arg)
            return result if result is not None else default
        except TypeError:
            raise TypeError("Command parameter annotation must be either pcbot.utils.Annotate or a callable")
        except:  # On error, eg when annotation is int and given argument is str
            return None

    return str(arg) or default  # Return str of arg if there was no annotation
Example #7
0
async def on_message(message: discord.Message):
    """ What to do on any message received.

    The bot will handle all commands in plugins and send on_message to plugins using it. """
    # Make sure the client is ready before processing commands
    await client.wait_until_ready()

    start_time = datetime.now()

    # We don't care about channels we can't write in as the bot usually sends feedback
    if not message.channel.is_private and not message.server.me.permissions_in(message.channel).send_messages:
        return

    # Don't accept commands from bot accounts
    if message.author.bot:
        return

    # Split content into arguments by space (surround with quotes for spaces)
    cmd_args = utils.split(message.content)

    # Get command name
    cmd = ""
    if cmd_args[0].startswith(config.command_prefix) and len(cmd_args[0]) > len(config.command_prefix):
        cmd = cmd_args[0][len(config.command_prefix):]

    # Handle commands
    for plugin in plugins.all_values():
        # If there was a command and the bot can send messages in the channel, parse the command
        if not cmd:
            continue
        command = plugins.get_command(plugin, cmd)

        if command:
            parsed_command, args, kwargs = await parse_command(command, cmd_args, message)

            if parsed_command:
                log_message(message)  # Log the command
                client.loop.create_task(execute_command(parsed_command, message, *args, **kwargs))  # Run command

                # Log time spent parsing the command
                stop_time = datetime.now()
                time_elapsed = (stop_time - start_time).total_seconds() / 1000
                logging.debug("Time spent parsing command: {elapsed:.6f}ms".format(elapsed=time_elapsed))
Example #8
0
async def on_message(message: discord.Message):
    success = False

    # User alias check
    if message.author.id in aliases.data:
        user_aliases = aliases.data[message.author.id]

        # Check any aliases
        for name, command in user_aliases.items():
            execute = False
            msg = message.content

            if not command.get("case_sensitive", False):
                msg = msg.lower()

            if command.get("anywhere", False):
                if name in msg:
                    execute = True
            else:
                if msg.startswith(name):
                    execute = True

            if execute:
                if command.get("delete_message", False):
                    if message.server.me.permissions_in(
                            message.channel).manage_messages:
                        asyncio.ensure_future(client.delete_message(message))

                text = command["text"]
                if text.startswith(config.command_prefix):
                    args = utils.split(text)
                    # try:
                    print(args, "\n", args[0], *args[1:])
                    await plugins.execute(args[0][1:], message, *args[1:])
                    # except:
                    #     pass
                    # else:
                    #     return True

                await client.say(message, text)
                success = True

    return success
Example #9
0
async def on_message(message: discord.Message):
    """ Perform lambda commands. """
    args = utils.split(message.content)

    # Check if the command is a lambda command and is not disabled (in the blacklist)
    if args[0] in lambdas.data and args[0] not in lambda_config.data["blacklist"]:
        def arg(i, default=0):
            if len(args) > i:
                return args[i]
            else:
                return default

        code_globals.update(dict(arg=arg, args=args, message=message, client=client,
                                 author=message.author, server=message.server, channel=message.channel))
        python_code = lambdas.data[args[0]]

        # Create an async function so that we can await it using the result of eval
        python_code = "async def lambda_session():\n    " + "\n    ".join(line for line in python_code.split("\n"))
        try:
            exec(python_code, code_globals)
        except SyntaxError as e:
            if utils.is_owner(message.author):
                await client.say(message, "```" + utils.format_syntax_error(e) + "```")
            else:
                logging.warn("An exception occurred when parsing lambda command:"
                             "\n{}".format(utils.format_syntax_error(e)))
            return True

        # Execute the command
        try:
            await eval("lambda_session()", code_globals)
        except AssertionError as e:  # Send assertion errors to the core module
            raise AssertionError(e)
        except Exception as e:
            if utils.is_owner(message.author):
                await client.say(message, "```" + utils.format_exception(e) + "```")
            else:
                logging.warn("An exception occurred when parsing lambda command:"
                             "\n{}".format(utils.format_exception(e)))
        finally:
            return True
Example #10
0
File: bot.py Project: stoz/PCBOT
async def parse_annotation(param: inspect.Parameter, default, arg: str,
                           index: int, message: discord.Message):
    """ Parse annotations and return the command to use.

    index is basically the arg's index in shelx.split(message.content) """
    if default is param.empty:
        default = None

    if param.annotation is not param.empty:  # Any annotation is a function or Annotation enum
        anno = override_annotation(param.annotation)
        content = lambda s: utils.split(s, maxsplit=index)[-1].strip("\" ")

        # Valid enum checks
        if isinstance(anno, utils.Annotate):
            if anno is utils.Annotate.Content:  # Split and get raw content from this point
                return content(message.content) or default
            elif anno is utils.Annotate.LowerContent:  # Lowercase of above check
                return content(message.content).lower() or default
            elif anno is utils.Annotate.CleanContent:  # Split and get clean raw content from this point
                return content(message.clean_content) or default
            elif anno is utils.Annotate.LowerCleanContent:  # Lowercase of above check
                return content(message.clean_content).lower() or default
            elif anno is utils.Annotate.Member:  # Checks member names or mentions
                return utils.find_member(message.server, arg) or default_self(
                    anno, default, message)
            elif anno is utils.Annotate.Channel:  # Checks text channel names or mentions
                return utils.find_channel(message.server, arg) or default_self(
                    anno, default, message)
            elif anno is utils.Annotate.VoiceChannel:  # Checks voice channel names or mentions
                return utils.find_channel(message.server,
                                          arg,
                                          channel_type="voice")
            elif anno is utils.Annotate.Code:  # Works like Content but extracts code
                return utils.get_formatted_code(
                    utils.split(message.content,
                                maxsplit=index)[-1]) or default

        try:  # Try running as a method
            if getattr(anno, "allow_spaces", False):
                arg = content(message.content)

            # Pass the message if the argument has this specified
            if getattr(anno, "pass_message", False):
                result = anno(message, arg)
            else:
                result = anno(arg)

            # The function can be a coroutine
            if inspect.isawaitable(result):
                result = await result

            return result if result is not None else default
        except TypeError:
            raise TypeError(
                "Command parameter annotation must be either pcbot.utils.Annotate, a callable or a coroutine"
            )
        except AssertionError as e:  # raise the error in order to catch it at a lower level
            raise AssertionError(e)
        except:  # On error, eg when annotation is int and given argument is str
            return None

    return str(arg) or default  # Return str of arg if there was no annotation
Example #11
0
async def on_message(message: discord.Message):
    """ What to do on any message received.

    The bot will handle all commands in plugins and send on_message to plugins using it. """
    # Make sure the client is ready before processing commands
    await client.wait_until_ready()
    start_time = datetime.utcnow()

    # Make a local copy of the message since some attributes are changed and they shouldn't be overridden
    # in plugin based on_message events
    original_message = message
    message = copy(message)

    # We don't care about channels we can't write in as the bot usually sends feedback
    if message.server and message.server.owner and not message.server.me.permissions_in(
            message.channel).send_messages:
        return

    # Don't accept commands from bot accounts
    if message.author.bot:
        return

    # Find server specific settings
    command_prefix = config.server_command_prefix(message.server)
    case_sensitive = config.server_case_sensitive_commands(message.server)

    # Check that the message is a command
    if not message.content.startswith(command_prefix):
        return

    # Remove the prefix and make sure that a command was actually specified
    message.content = message.content[len(command_prefix):]
    if not message.content or message.content.startswith(" "):
        return

    # Split content into arguments by space (surround with quotes for spaces)
    cmd_args = utils.split(message.content)

    # Try finding a command object using the command name (first argument)
    command = plugins.get_command(cmd_args[0], case_sensitive=case_sensitive)
    if not command:
        return

    try:
        # Find the subcommand if there is one
        command = plugins.get_sub_command(command,
                                          *cmd_args[1:],
                                          case_sensitive=case_sensitive)

        # Check that the author is allowed to use the command
        if not plugins.can_use_command(command, message.author,
                                       message.channel):
            return

        # Parse the command with the user's arguments
        parsed_command, args, kwargs = await parse_command(
            command, cmd_args, message)
    except AssertionError as e:  # Return any feedback given from the command via AssertionError, or the command help
        await client.send_message(
            message.channel,
            str(e) or plugins.format_help(
                command, message.server, no_subcommand=True))
        log_message(message)
        return

    if not parsed_command:
        return

    # Log the command executed and execute said command
    log_message(original_message)
    client.loop.create_task(
        execute_command(parsed_command, original_message, *args, **kwargs))

    # Manually dispatch an event for when commands are requested
    client.dispatch("command_requested", message, parsed_command, *args,
                    **kwargs)

    # Log time spent parsing the command
    stop_time = datetime.utcnow()
    time_elapsed = (stop_time - start_time).total_seconds() * 1000
    logging.debug("Time spent parsing command: {elapsed:.6f}ms".format(
        elapsed=time_elapsed))
Example #12
0
File: bot.py Project: Jeglet/pcbot
 def content(s):
     return utils.split(s, maxsplit=index)[-1].strip("\" ")