Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
325 views
in Technique[技术] by (71.8m points)

python - Why doesn't multiple on_message events work?

Why can't I have multiple on_message events?

import discord

client = discord.Client()

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

@client.event
async def on_message(message):
    print("in on_message #1")

@client.event
async def on_message(message):
    print("in on_message #2")

@client.event
async def on_message(message):
    print("in on_message #3")

client.run("TOKEN")

For example, if I typed anything in discord, it's always only the last on_message that gets triggered. How can I get all three to work?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...