Clonexy
Clonexy

Reputation: 188

Discord.on_message() missing 1 required positional argument: 'ctx'

I'm working on user level system and now I'm having a big problems with starting my Discord leveling up code and I don't know and don't have any ideas how to fix it.

Here is my code:

import discord
import asyncio
import json
from discord.ext import commands

сlass Levels:

    def __init__(self, client):
        self.bot = client

        self.bot.loop.create_task(self.save_users())

        with open(r'C:\Users\conex_000\PycharmProjects\Shirochka\users.json', 'r') as f:
           self.users = json.load(f)

    async def save_users(self):
        await self.bot.wait_until_ready()
        while not self.bot.is_closed():
            with open(r'C:\Users\conex_000\PycharmProjects\Shirochka\users.json', 'w') as f:
                json.dump(self.users, f, indent=4)

            await asyncio.sleep(5)

    def lvl_up(self, author_id):
        cur_xp = self.users[author_id]['exp']
        cur_lvl = self.users[author_id]['level']

        if cur_xp >= round((4 * (cur_lvl ** 3)) / 5):
            self.users[author_id]['level'] += 1
            return True
        else:
            return False

    async def on_message(self, message):
        if message.author == self.bot.user:
            return

        author_id = str(message.author.id)

        if not author_id in self.users:
            self.users[author_id] = {}
            self.users[author_id]['level'] = 1
            self.users[author_id]['exp'] = 0

        self.users[author_id]['exp'] += 1

        if self.lvl_up(author_id):
            await message.channel.send(f"{message.author.mention} is now level {self.users[author_id]['level']}")

    @client.command()
    async def level(self, ctx, member: discord.Member = None):
        member = ctx.author if not member else member
        member_id = str(member.id)

        if not member.id in self.users:
            await ctx.send("Can't identify a member")
        else:
            embed = discord.Embed(color=member.color, timestamp=ctx.message.created_at)

            embed.set_author(name=f'Level - {member}', icon_url=client.user.avatar_url)

            embed.add_field(name='Level', value=self.users[member_id]['level'])
            embed.add_field(name='Level', value=self.users[member_id]['exp'])

            await ctx.send(embed=embed)

This code is starting but when I type any message on Discord chat program returns the following error:

TypeError: on_message() missing 1 required positional argument: 'ctx'

Upvotes: 0

Views: 5623

Answers (2)

Clonexy
Clonexy

Reputation: 188

Added subclassing commands.Cog for Levels Cog, marked command and event with decorator and now all is working.

class Levels(commands.Cog):

def __init__(self, client):
    self.bot = client

    self.bot.loop.create_task(self.save_users())

    with open(r'C:\Users\conex_000\PycharmProjects\Shirochka\users.json', 'r') as f:
       self.users = json.load(f)

async def save_users(self):
    await self.bot.wait_until_ready()
    while not self.bot.is_closed():
        with open(r'C:\Users\conex_000\PycharmProjects\Shirochka\users.json', 'w') as f:
            json.dump(self.users, f, indent=4)

        await asyncio.sleep(5)

def lvl_up(self, author_id):
    cur_xp = self.users[author_id]['exp']
    cur_lvl = self.users[author_id]['level']

    if cur_xp >= round((10 * (cur_lvl ** 3)) / 5):
        self.users[author_id]['level'] += 1
        return True
    else:
        return False
@commands.Cog.listener()
async def on_message(self, message):
    if message.author == self.bot.user:
        return

    author_id = str(message.author.id)

    if not author_id in self.users:
        self.users[author_id] = {}
        self.users[author_id]['level'] = 1
        self.users[author_id]['exp'] = 0

    self.users[author_id]['exp'] += 1

    if self.lvl_up(author_id):
        await message.channel.send(f"{message.author.mention} is now level {self.users[author_id]['level']}")

@commands.command()
async def level(self, ctx, member: discord.Member = None):
    member = ctx.author if not member else member
    member_id = str(member.id)

    if not member_id in self.users:
        await ctx.send("Can't identify a member")
    else:
        embed = discord.Embed(color=member.color, timestamp=ctx.message.created_at)

        embed.set_author(name=f'Level - {member}', icon_url=self.bot.user.avatar_url)

        embed.add_field(name='Level', value=self.users[member_id]['level'])
        embed.add_field(name='XP', value=self.users[member_id]['exp'])

        await ctx.send(embed=embed)

def setup(bot):
    bot.add_cog(Levels(bot))

Upvotes: 1

baptiste0928
baptiste0928

Reputation: 135

Inside a cog, you must to add the @commands.Cog.listener() decorator to functions related to an event, otherwise you'll have an error.

Edit : If your class is not a cog, try @client.event.

Upvotes: 0

Related Questions