def test_apostrophes():
    assert argsplit("foo bar") == ["foo", "bar"]
    assert argsplit("'foo bar'") == ["foo bar"]
    assert argsplit("foo's bar") == ["foo's", "bar"]
    assert argsplit('''"foo's bar"''') == ["foo's bar"]
    assert argsplit("el'ven'ame") == ["el'ven'ame"]
    assert argsplit("darius'") == ["darius'"]
    assert argsplit("Samus' Armor") == ["Samus'", "Armor"]
    with pytest.raises(ExpectedClosingQuoteError):
        argsplit("'tis")
    assert argsplit("'tis Jack's") == ["tis Jacks"]  # weird
def test_argsplit():
    assert argsplit("""foo bar "two words" yay!""") == [
        "foo", "bar", "two words", "yay!"
    ]
    assert argsplit("""'some string here' in quotes""") == [
        "some string here", "in", "quotes"
    ]
    assert argsplit(""""partial quoted"blocks""") == ["partial quotedblocks"]
    assert argsplit('''"'nested quotes'"''') == ["'nested quotes'"]
    assert argsplit("""-phrase "She said, \\"Hello world\\"" """) == [
        "-phrase", 'She said, "Hello world"'
    ]
Example #3
0
async def parse_snippets(args, ctx) -> str:
    """
    Parses user and server snippets.
    :param args: The string to parse. Will be split automatically
    :param ctx: The Context.
    :return: The string, with snippets replaced.
    """
    # make args a list of str
    if isinstance(args, str):
        args = argsplit(args)
    if not isinstance(args, list):
        args = list(args)

    for index, arg in enumerate(args):  # parse snippets
        server_invoker = False

        # personal snippet/servsnippet
        the_snippet = await get_personal_snippet_named(ctx, arg)
        if the_snippet is None and ctx.guild is not None:
            the_snippet = await get_server_snippet_named(ctx, arg)
            server_invoker = True

        if isinstance(the_snippet, WorkshopSnippet):
            await workshop_entitlements_check(ctx, the_snippet)

        if the_snippet:
            args[index] = the_snippet.code
            # analytics
            await the_snippet.log_invocation(ctx, server_invoker)
        elif ' ' in arg:
            args[index] = argquote(arg)
    return " ".join(args)
Example #4
0
    async def handle_alias_arguments(self, command, message):
        """Takes an alias name, alias value, and message and handles percent-encoded args.
        Returns: string"""
        prefix = await self.bot.get_server_prefix(message)
        rawargs = " ".join(message.content[len(prefix):].split(' ')[1:])
        args = argsplit(rawargs)
        tempargs = args[:]
        new_command = command
        if '%*%' in command:
            new_command = new_command.replace('%*%', argquote(rawargs))
            tempargs = []
        if '&*&' in command:
            new_command = new_command.replace('&*&', rawargs.replace("\"", "\\\""))
            tempargs = []
        if '&ARGS&' in command:
            new_command = new_command.replace('&ARGS&', str(args))
            tempargs = []
        for index, value in enumerate(args):
            key = '%{}%'.format(index + 1)
            to_remove = False
            if key in command:
                new_command = new_command.replace(key, argquote(value))
                to_remove = True
            key = '&{}&'.format(index + 1)
            if key in command:
                new_command = new_command.replace(key, value.replace("\"", "\\\""))
                to_remove = True
            if to_remove:
                try:
                    tempargs.remove(value)
                except ValueError:
                    pass

        quoted_args = ' '.join(map(argquote, tempargs))
        return f"{prefix}{new_command} {quoted_args}".strip()
Example #5
0
async def parse_snippets(args, ctx, statblock=None, character=None) -> str:
    """
    Parses user and server snippets, including any inline scripting.

    :param args: The string to parse. Will be split automatically
    :param ctx: The Context.
    :param statblock: The statblock to populate locals from.
    :param character: If passed, provides the base character to use character-scoped functions against.
    :return: The string, with snippets replaced.
    """
    # make args a list of str
    if isinstance(args, str):
        args = argsplit(args)
    if not isinstance(args, list):
        args = list(args)

    # set up the evaluator
    evaluator = await evaluators.ScriptingEvaluator.new(ctx)
    if character is not None:
        evaluator.with_character(character)
    elif statblock is not None:
        evaluator.with_statblock(statblock)

    try:
        for index, arg in enumerate(args):  # parse snippets
            server_invoker = False

            # personal snippet/servsnippet
            the_snippet = await get_personal_snippet_named(ctx, arg)
            if the_snippet is None and ctx.guild is not None:
                the_snippet = await get_server_snippet_named(ctx, arg)
                server_invoker = True

            if isinstance(the_snippet, WorkshopSnippet):
                await workshop_entitlements_check(ctx, the_snippet)

            if the_snippet:
                # enter the evaluator
                execution_scope = ExecutionScope.SERVER_SNIPPET if server_invoker else ExecutionScope.PERSONAL_SNIPPET
                args[index] = await evaluator.transformed_str_async(
                    the_snippet.code,
                    execution_scope=execution_scope,
                    invoking_object=the_snippet)
                # analytics
                await the_snippet.log_invocation(ctx, server_invoker)
            else:
                # in case the user is using old-style on the fly templating
                arg = await evaluator.transformed_str_async(
                    arg, execution_scope=ExecutionScope.PERSONAL_SNIPPET)
                args[index] = argquote(arg)
    finally:
        await evaluator.run_commits()
    return " ".join(args)
Example #6
0
async def parse_snippets(args, ctx) -> str:
    """
    Parses user and server snippets.
    :param args: The string to parse. Will be split automatically
    :param ctx: The Context.
    :return: The string, with snippets replaced.
    """
    if isinstance(args, str):
        args = argsplit(args)
    if not isinstance(args, list):
        args = list(args)
    servsnippets = await get_servsnippets(ctx)
    snippets = await get_snippets(ctx)
    for index, arg in enumerate(args):  # parse snippets
        snippet = snippets.get(arg)
        snippet_value = None
        if snippet:
            await ctx.bot.mdb.analytics_alias_events.insert_one({
                "type":
                "snippet",
                "object_id":
                snippet['_id'],
                "timestamp":
                datetime.datetime.utcnow(),
                "user_id":
                ctx.author.id
            })
            snippet_value = snippet['snippet']
        else:
            snippet = servsnippets.get(arg)
            if snippet:
                await ctx.bot.mdb.analytics_alias_events.insert_one({
                    "type":
                    "servsnippet",
                    "object_id":
                    snippet['_id'],
                    "timestamp":
                    datetime.datetime.utcnow(),
                    "user_id":
                    ctx.author.id
                })
                snippet_value = snippet['snippet']

        if snippet_value:
            args[index] = snippet_value
        elif ' ' in arg:
            args[index] = argquote(arg)
    return " ".join(args)
Example #7
0
async def parse_snippets(args, ctx) -> str:
    """
    Parses user and server snippets.
    :param args: The string to parse. Will be split automatically
    :param ctx: The Context.
    :return: The string, with snippets replaced.
    """
    if isinstance(args, str):
        args = argsplit(args)
    if not isinstance(args, list):
        args = list(args)
    snippets = await get_servsnippets(ctx)
    snippets.update(await get_snippets(ctx))
    for index, arg in enumerate(args):  # parse snippets
        snippet_value = snippets.get(arg)
        if snippet_value:
            args[index] = snippet_value
        elif ' ' in arg:
            args[index] = argquote(arg)
    return " ".join(args)
Example #8
0
async def handle_alias_arguments(command, ctx):
    """Takes an alias name, alias value, and message and handles percent-encoded args.
    Returns: string"""
    prefix = ctx.prefix
    rawargs = ctx.view.read_rest().strip()

    args = argsplit(rawargs)
    tempargs = args[:]
    new_command = command
    if '%*%' in command:
        new_command = new_command.replace('%*%', argquote(rawargs))
        tempargs = []
    if '&*&' in command:
        new_command = new_command.replace('&*&', rawargs.replace("\"", "\\\""))
        tempargs = []
    if '&ARGS&' in command:
        new_command = new_command.replace('&ARGS&', str(args))
        tempargs = []
    for index, value in enumerate(args):
        key = '%{}%'.format(index + 1)
        to_remove = False
        if key in command:
            new_command = new_command.replace(key, argquote(value))
            to_remove = True
        key = '&{}&'.format(index + 1)
        if key in command:
            new_command = new_command.replace(key, value.replace("\"", "\\\""))
            to_remove = True
        if to_remove:
            try:
                tempargs.remove(value)
            except ValueError:
                pass

    quoted_args = ' '.join(map(argquote, tempargs))
    return f"{prefix}{new_command} {quoted_args}".strip()
def test_argquote():
    assert argquote("foo") == "foo"
    assert argquote("foo bar") == '"foo bar"'
    assert argquote('one "two three"') == '"one \\"two three\\""'
    assert argsplit(argquote('one "two three"')) == ['one "two three"']