简体   繁体   中英

on_message won't work with command discord.py

I'm not sure if the code won't work because of the on_message(ctx) or not, either way, is what I have done:

import discord 
from discord.ext import commands 
import pymongo 
import os
from pymongo import MongoClient

mango_url = "mongodb+srv://<usernamehere>:<password>@discordbot.kllv6.mongodb.net/discordbot? 
retryWrites=true&w=majority"
cluster = MongoClient(mango_url)
db = cluster["discordbot"]
collection = db["discordbot"]

client = commands.Bot(command_prefix = '$')

@client.event
async def on_ready():
    print("bot is online")


@client.command()
async def _ping(ctx):
    await ctx.send('discord sucks :(')

@client.event
async def on_message(ctx):
    author_id = ctx.author.id
    guild_id = ctx.guild.id 
    author = ctx.author
    user_id = {"_id": author_id}

    if ctx.author == client.user:
        return

    if ctx.author.bot:
        return

    if(collection.count_documents({}) == 0):
        user_info = {"_id": author_id, "GuildID": guild_id, "Level": 1, "XP": 0}
        collection.insert_one(user_info)

    if(collection.count_documents(user_id) == 0):
        user_info = {"_id": author_id, "GuildID": guild_id, "Level": 1, "XP": 0}
        collection.insert_one(user_info)

    exp = collection.find(user_id)
    for xp in exp:
        cur_xp = xp["XP"]

        new_xp = cur_xp + 1 

    collection.update_one({"_id": author_id}, {"$set":{"XP":new_xp}}, upsert=True)

    #await ctx.channel.send("1 xp up")

    lvl = collection.find(user_id)
    for levl in lvl:
        lvl_start = levl["Level"]

        new_level = lvl_start + 1

    if cur_xp >= round(5 * (lvl_start ** 4 / 5)):
        collection.update_one({"_id": author_id}, {"$set":{"Level":new_level}}, upsert=True)
        await ctx.channel.send(f"{author.name} has leveled up to {new_level}!")

        await bot.process_commands(ctx)



client.run("token")

If I remove everything inside the on_message(ctx) (also the event) then it works.

I have tried everything but it won't work.

Example:

await bot.process_commands(message)

That does not work either because I am using ctx not message . I think...

If you have an answer to this please help me with this.

There's several issues with your on_message event:

  1. on_message comes with a message , not a ctx
  2. Your bot client is called client , not bot
  3. The process_commands line is indented too far. It needs to be on the outmost indentation layer of the event definition, otherwise it can end up not being triggered for each message, which leads the bot to ignore some or all commands (in your case, the only time the bot would recognize a command is if the user levelled up in the same message)

You can fix your code by making it something like the below:

@client.event
async def on_message(message):
    author_id = message.author.id
    guild_id = message.guild.id 
    author = message.author
    user_id = {"_id": author_id}

    if message.author.bot:
        return
    
    # rest of your code goes here

    # notice the indentation layer. This needs to be at the top layer of your function
    await client.process_commands(message)

Side note: you don't need to check if the message author is your bot separately, as the message.author.bot check will ignore it anyway

Your code shows a straight error.

When we use event then the argument: message is used and then we use command() then the argument: ctx is used.

You are using the ctx argument for an event in your bot. It won't simply work.

You need to change it to message .

Also the statement:

await bot.process_command(ctx)

Here too ctx has to be changed to message and it should be used with else and not inside if .

Your bot is not bot variable but is client . So replace the bot in on_message to client

After all of the above changes the code is:

@client.event
async def on_message(message):
    author_id = message.author.id
    guild_id = message.guild.id 
    author = message.author
    user_id = {"_id": author_id}

    if message.author == client.user:
        return

    if message.author.bot:
        return

    if(collection.count_documents({}) == 0):
        user_info = {"_id": author_id, "GuildID": guild_id, "Level": 1, "XP": 0}
        collection.insert_one(user_info)

    if(collection.count_documents(user_id) == 0):
        user_info = {"_id": author_id, "GuildID": guild_id, "Level": 1, "XP": 0}
        collection.insert_one(user_info)

    exp = collection.find(user_id)
    for xp in exp:
        cur_xp = xp["XP"]

        new_xp = cur_xp + 1 

    collection.update_one({"_id": author_id}, {"$set":{"XP":new_xp}}, upsert=True)

    await message.channel.send("1 xp up")

    lvl = collection.find(user_id)
    for levl in lvl:
        lvl_start = levl["Level"]

        new_level = lvl_start + 1

    if cur_xp >= round(5 * (lvl_start ** 4 / 5)):
        collection.update_one({"_id": author_id}, {"$set":{"Level":new_level}}, upsert=True)
        await message.channel.send(f"{author.name} has leveled up to {new_level}!")
    
    await client.process_commands(message)

Hope this helps. Thank You: :D

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM