Why doesn't multiple on_message events work?

后端 未结 2 590
名媛妹妹
名媛妹妹 2020-11-28 16:58

Why can\'t I have multiple on_message events?

import discord

client = discord.Client()

@client.event
async def on_ready():
    print(\'in on_r         


        
相关标签:
2条回答
  • 2020-11-28 17:06

    In python, functions are just objects.

    >>> def foo():
    ...     print ("hi")
    

    defines an object called foo, You can see this using a Python shell.

    >>> foo
    <function foo at 0x...>
    >>> foo()
    hi
    

    If you define a new method after, or redefine the variable foo, you lose access to the initial function.

    >>> foo = "hi"
    >>> foo
    hi
    >>> foo()
    Traceback ...:
        file "<stdin>" ...
    TypeError: 'str' object is not callable
    

    How the @client.event decorator works is it tells your client that new messages should be piped into the messages, and well, if the method gets redefined, it means the old method is lost.

    >>> @bot.event
    ... async def on_message(m):
    ...     print(1)
    ...
    >>> bot.on_message(None) # @bot.event makes the bot define it's own method
    1
    >>> @bot.event
    ... async def on_message(m):
    ...     print(2)
    ...
    >>> bot.on_message(None) # bot's own method was redefined.
    2
    
    0 讨论(0)
  • 2020-11-28 17:31

    It's not possible with the native Client

    You can only have one on_message, if you have multiple, only the last one will be called for the on_message event. You'll just need to combine your three on_message.

    import discord
    
    client = discord.Client()
    
    @client.event
    async def on_message(message):
        print("in on_message #1")
        print("in on_message #2")
        print("in on_message #3")
    
    client.run("TOKEN")
    

    Like any Python variable/function (unless the decorator stores your function, @client.event does it by keeping only the most recent callback), if multiple names are the same, the most recently will be kept, and all others will get overwritten.

    This is a simple example I wrote to give you a broad understanding of how events in discord.py work (note: the actual code isn't exactly like this, as it's rewritten and significantly reduced).

    class Client:
        def event(self, func):               
            if func.__name__ == "on_message":
                self.on_message_handle = func
                return func
    
        def receive_message(self, msg):
            func = getattr(self, "on_message_handle", None)
            if func is not None:
                func(msg)
            else:
                self.process_commands(msg)
    
    client = Client()
    
    @client.event
    def on_message(msg):
        print("in on_message #1")
    
    @client.event
    def on_message(msg):
        print("in on_message #2")
    
    client.receive_message("hello")
    # "in on_message #2"
    

    As you can see client.event only keep one instance of on_message.


    You can with Bot instances

    Alternatively, if you're using the ext.commands extension of discord.py, there is a native way to have multiple on_message callbacks. You do so by using defining them as a listener. You can have at most one on_message event, and infinite amounts of on_message listeners.

    from discord.ext import commands
    
    bot = commands.Bot('.')
    
    @bot.event
    async def on_message(msg):
        print("in on_message #1")
        await bot.process_commands(msg)  # so `Command` instances will still get called
    
    
    @bot.listen()
    async def on_message(msg):
        print("in on_message #2")
    
    
    @bot.listen()
    async def on_message(msg):
        print("in on_message #3")
    
    bot.run("TOKEN")
    

    When a message is received, all on_message #1-3 will all get printed.

    0 讨论(0)
提交回复
热议问题