2

So, I'm implementing a Discord Bot using discord.py, and I'm trying to dynamically call functions based on commands. I was able to test dynamic function calls with exec() fine, but they seem to fall apart with the async calls needed for discord.py.

So what I'm trying to do with this example would be to call the hello function and print Hello World into discord by typing !hello in chat.

@client.event
async def on_message(message):
    call = 'await ' + message.content.lower()[1:] + '(message)'
    exec(call)

async def hello(message):
    await client.send_message(message.channel, 'Hello World')

Unfortunately, this code doesn't seem to do anything, I'm assuming because of how exec() handles async calls. Any help would be appreciated.

1 Answer 1

1

Instead of exec() use globals() to get your function:

import asyncio


async def main():
    s = "foo"
    param = "hello"
    coro = globals().get(s)
    if coro:
        result = await coro(param)
        print("got:", result)
    else:
        print("unknown function:", s)


async def foo(param):
    print(param)
    await asyncio.sleep(0.11)
    return ":-)"


loop = asyncio.get_event_loop()
response = loop.run_until_complete(main())
loop.close()

However, allowing the user to access anything in globals() might bwe dangerous, instead it would be much better to whitelist your commands, for example using:

import asyncio

my_commands = {}


def register(cmd):
    my_commands[cmd.__name__] = cmd
    return cmd


async def main():
    s = "foo"
    param = "hello"
    coro = my_commands.get(s)
    if coro:
        result = await coro(param)
        print("got:", result)
    else:
        print("unknown function:", s)


@register
async def foo(param):
    """I am the mighty foo command!"""
    print(param)
    await asyncio.sleep(0.11)
    return ":-)"



loop = asyncio.get_event_loop()
response = loop.run_until_complete(main())
loop.close()

See also:

for k, v in my_commands.items():
    print("{}: {}".format(k, v.__doc__ or "no docs"))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.