Custom prefix command with MongoDB

724 Views Asked by At

I am trying to create a setprefix command, which changes the server prefix. However, I am getting the following error:

    raise TypeError("command_prefix must be plain string, iterable of strings, or callable "
TypeError: command_prefix must be plain string, iterable of strings, or callable returning either of these, not coroutine

My code:

Main.py

#------importing packages

import keep_alive
import os
import discord
from discord.ext import commands
import pymongo
from pymongo import MongoClient
import asyncio
import motor
import motor.motor_asyncio
import prefixes
from prefixes import Prefixes

### MongoDB Variables ###
mongo_url = os.environ['Mongodb_url']
cluster = motor.motor_asyncio.AsyncIOMotorClient(str(mongo_url))
db = cluster['Database']
collection = db['prefixes']


bot = commands.Bot(command_prefix = Prefixes.setprefix(), case_insensitive=True)

bot.remove_command('help')
my_token = os.environ['Token']

#------When bot is online


@bot.event
async def on_ready():

    #status
    #playing game status

    await bot.change_presence(activity=discord.Game(
        name=f'On {len(bot.guilds)} Servers | -help'))

    print('Bot is Ready')


initial_extensions = ['help', 'math1', 'mod', 'anime', 'prefixes']

if __name__ == '__main__':
    for extension in initial_extensions:
        bot.load_extension(extension)


#ping latency....
@bot.command()
async def ping(ctx):
    await ctx.send(f'Pong\n{round(bot.latency * 1000)}ms')




#------Running the bot
keep_alive.keep_alive()
bot.run(my_token)

Prefixes cog file

import discord
from discord.ext import commands
import asyncio
import motor
import motor.motor_asyncio
import os


class Prefixes(commands.Cog):
    def __init__(self, bot):
        self.bot = bot


    #custom prefix
    @commands.command()
    @commands.has_permissions(administrator = True)
    async def setprefix(self, ctx, prefix):

        ### MongoDB Variables ###
        mongo_url = os.environ['Mongodb_url']
        cluster = motor.motor_asyncio.AsyncIOMotorClient(str(mongo_url))
        db = cluster['Database']
        collection = db['prefixes']

        guild_id = ctx.guild.id
        server_prefix = prefix

        if (await collection.count_documents({})) == 0:

            prefix_info = {'GuildId': guild_id, 'Prefix': server_prefix}
            await collection.insert_one(prefix_info)

        else:
            prefix_info = {'GuildId': guild_id, 'Prefix': server_prefix}
            await collection.update_one({'GuildId': guild_id}, {'$set': {'Prefix': prefix}})

        await ctx.send(f'My prefix is now {prefix}')

        finding_prefix = await collection.find_one({'Prefix': {'$eq': prefix}})

        view_finding_prefix = finding_prefix.values()
        iterate_view = iter(view_finding_prefix)
        first_value = next(iterate_view)

        self.bot(command_prefix = str(first_value), case_insesitive = True)



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

I do not understand why there is a TypeError. I am using motor as it supports async. In motor documentation it says that when using find_one() It give as a dictionary. Which is why I did this as you can see in the code above:

        finding_prefix = await collection.find_one({'Prefix': {'$eq': prefix}})

        view_finding_prefix = finding_prefix.values()
        iterate_view = iter(view_finding_prefix)
        first_value = next(iterate_view)

        self.bot(command_prefix = str(first_value), case_insesitive = True)

I did that to get the first value of the key Prefix. If there is another to do this, please tell me.

1

There are 1 best solutions below

0
Pranjal Prakarsh On

This is simple if you understand the logic , firstly code though

import os

import discord
import motor.motor_asyncio
import nest_asyncio
from discord.ext import commands
from discord.ext.commands import BucketType, cooldown
from pymongo import MongoClient

nest_asyncio.apply()

mongo_url = os.environ.get("MONGO_URL")

cluster = motor.motor_asyncio.AsyncIOMotorClient(mongo_url)

predb = cluster["discord"]["prefix"]


class Prefix(commands.Cog):
    def __init__(self, client):
        self.client = client

    @commands.Cog.listener()
    async def on_ready(self):
        print("Prefix cog loaded successfully")

    @commands.command(
        cooldown_after_parsing=True, description="Changes Bot prefix for this server"
    )
    @cooldown(1, 10, BucketType.user)
    @commands.has_permissions(administrator=True)
    async def setprefix(self, ctx, new_prefix):
        if len(new_prefix) > 3:
            embed = discord.Embed(
                timestamp=ctx.message.created_at,
                title="Error",
                description="Looks like the prefix is very big ",
                color=0xFF0000,
            )
            await ctx.send(embed=embed)
        else:

            new_prefix = str(new_prefix)
            stats = await predb.find_one({"guild": ctx.guild.id})

            if stats is None:
                updated = {"guild": ctx.guild.id, "prefix": new_prefix}
                await predb.insert_one(updated)
                embed = discord.Embed(
                    title="Prefix",
                    description=f"This server prefix is now {new_prefix}",
                    color=0xFF0000,
                )
                await ctx.send(embed=embed)

            else:
                await predb.update_one(
                    {"guild": ctx.guild.id}, {"$set": {"prefix": new_prefix}}
                )

                embed = discord.Embed(
                    timestamp=ctx.message.created_at,
                    title="Prefix",
                    description=f"This server prefix is now {new_prefix}",
                    color=0xFF0000,
                )
                await ctx.send(embed=embed)


def setup(client):
    client.add_cog(Prefix(client))

What it does and how it works?

  1. IT FIRSTLY check if the prefix is too long because no one wants people to mess and forgot the prefix which happens with long prefixes you can remove it if you dont want it next in the first else condition if server is already registered i.e if the prefix is changed before it will update it else make a new entry , Hope this helps and please mark this as answer if it works fine for you and you're happy :)