When I tried adding a Cog for my bot it gives me a TypeError
module() takes at most 2 arguments (3 given)
class Commands(commands.cog):
def __init__(self, client):
self.client = client
self.song_queue = {}
self.setup()
def setup(self):
for guild in self.client.guilds():
self.song_queue[guild.id] = []
I also set it up using
async def setup():
client.add_cog(Commands(client))
client.loop.create_task(setup())
guilds is a list, you can't call it, and self.client.guilds will always be empty, you'll need to find another way to have a setup function when the bot is "ready" –
Taku
Related
I finished a bot after a couple of hours and while trying to run it I get this error message 'discord.ext.commands.errors.CommandNotFound: Command "play" is not found' I don't know why/ how to fix this could anyone help?
The chunk of code with the error will be below this text:
#commands.command()
async def play(self,ctx,url):
ctx.voice_client.stop()
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
YDL_OPTIONS = {'format':"bestaudio"}
vc = ctx.voice_client
ask me if you need more of the code/more of the terminal output
I tried running the bot multiple times and I've looked around overflow for an answer and found nothing :/
(Comments mentioned you didn't load your cogs)
discord.py can't just "know" that it has to load your cogs, you have to do this yourself. This works through the process of extensions.
Extensions are loaded using load_extension. The best place to do this is setup_hook (don't use something like on_ready!). An extension is a file with a setup() method, which is invoked by the library when you call load_extension(). You can use this function to attach the cog to your bot.
Loading the extension in your bot's file:
class MyBot(commands.Bot):
...
async def setup_hook(self):
# This is typically done by looping over a directory of Cog files
# instead of 1 by 1, but this is just an example
await self.load_extension("path.to.your.extension")
Attaching the Cog in your extension's file:
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
async def setup(bot):
await bot.add_cog(MyCog(bot))
So, I'm new to python and even more to coding bots on discord. At the moment I'm using discord.py and red-bot (https://docs.discord.red/en/stable/index.html).
At the moment I'm trying to make the bot listen to a new message and print something in response to it, but I just can't figure it out. Since I'm using red-bot I didn't go through the steps of using client = discord.Client() and setting a token on the code itself so using #client.event() doesn't seem to work, nor #bot.event(), and I can't really find any other way to make the bot listen for an on_message() event.
Edit with part of my code:
import discord
from discord.ext import commands
from redbot.core import commands
class MyCog(commands.Cog):
client = discord.Client()
def __init__(self, bot):
self.bot = bot
#bot.event()
async def on_message(self, message):
if 'test' in message.content:
await self.send_message(message.channel, 'it works!')
Console returns that bot in #bot.event() is not defined.
Also a separate initialization file, it's done this way to follow Red's guide of how to make a cog.
from .remind import MyCog
def setup(bot):
bot.add_cog(MyCog(bot))
Here is an example of a cog that replies to a specific word mentioned. It also has a cooldown to prevent the bot spamming which I find absolutely neccesary to include.
from curses.panel import bottom_panel
import discord
from discord.ext import commands
class brilliant(commands.Cog):
def __init__(self, bot):
self.bot = bot
self._cd = commands.CooldownMapping.from_cooldown(1, 60.0, commands.BucketType.member) # Change accordingly
# rate, per, BucketType
def ratelimit_check(self, message):
"""Returns the ratelimit left"""
bucket = self._cd.get_bucket(message)
return bucket.update_rate_limit()
#commands.Cog.listener()
async def on_message(self, message):
if message.author == self.bot.user:
return
msg = message.content.lower()
brilliant = ['brilliant', 'Brilliant', 'brilliant!', 'Brilliant!']
if any(word in msg for word in brilliant):
retry_after = self.ratelimit_check(message)
if retry_after is None:
await message.channel.send("Brilliant!")
await self.bot.process_commands(message)
else:
return
async def setup(bot):
await bot.add_cog(brilliant(bot))
If you want it in the main file, you can put something a lot simpler:
brilliant = ['brilliant', 'Brilliant', 'brilliant!', 'Brilliant!']
#bot.event
async def on_message(message):
if message.author == bot.user:
return
msg = message.content.lower()
if any(word in msg for word in brilliant):
await message.channel.send("Brilliant!")
await bot.process_commands(message)
Hope it helps.
When I try to run my cog it gives an error "No value for argument 'arg' in function call'. Can someone help please?
from discord.ext import commands
from discord.ext.commands import Bot
import asyncio
import os
import datetime
import random
import wikipedia
class wiki(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.Cog.listener()
async def on_ready(self):
print("Wikipedia Cog has been loaded\n-----")
#commands.command()
async def wiki(self,ctx,word):
def viki_sum(self,arg):
definition = wikipedia.summary(arg,sentences=3,chars=1000)
return definition
embed = discord.Embed(title="***Wiki'de Bulduklarım:***",description=viki_sum(word))
await ctx.send(embed=embed)
def setup(bot):
bot.add_cog(wiki(bot))```
Hello and welcome to Stack Overflow!
It seems that the error you are getting comes from this section of the code:
#commands.command()
async def wiki(self, ctx, word):
def viki_sum(self, arg):
definition = wikipedia.summary(arg, sentences=3, chars=1000)
return definition
The viki_sum function is a nested function. Even though its enclosing function is a class method and requires using self as the first argument, any nested functions do not require that argument.
So, to overcome the error, you need to remove the self argument from the viki_sum function.
Best of luck!
So I am writing commands with a cooldown on every single one. Like this:
#client.command()
#commands.cooldown(...)
async def bot_command(ctx):
pass
The problem with that is that the cooldown applies to every user. However, I want the cooldown to not apply to the bot developers (IDS are stored in a list). How can I do that in the more efficient way?
You can catch the exception in an exception handler, and invoke the command manually from there.
#client.command()
#commands.cooldown(...)
async def bot_command(ctx):
pass
#bot_command.error
async def bot_command_error(ctx, error):
if isinstance(error, CommandOnCooldown):
if ctx.author.id in list_of_ids:
args = ()
kwargs = {}
await ctx.invoke(ctx.command, *args, **kwargs)
else:
raise error
Note that Context.invoke doesn't do anything but call the callback with the arguments provided. You'll have to handle all the input conversion, pre/post invoke hooks, etc on your own.
So, on my bot.py main file, I have:
class Bot(commands.Bot):
# BOT ATTRIBUTES
class default_cooldown:
maxcommands = ...
seconds = ...
mode = ...
class my_exception(commmands.CommandError): pass
def my_check(self):
def predicate(ctx):
if ctx.author in a_list: return True
raise self.my_exception
bot = Bot(...)
Now I also have a cog file where I want to use the Bot().my_check() check and my Bot().default_cooldown() class:
class Cog(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.command()
#self.bot.my_check()
#commands.cooldown(self.bot.default_cooldown().maxcommands, self.bot.default_cooldown().seconds, self.bot.default_cooldown().mode)
async def a_command(self, ctx):
pass
But I get an error, saying that self is not defined on my check and cooldown. Can anyone please help me fix this problem?
Methods are created once when the class object is created, not individually for each instance. You have a couple of options:
Factor out the code that need to appear in both places to a third module that contains just that code, then import that into both of your other files
Move your Bot definition into a separate module from the execution of your bot, and make my_check a staticmethod. Then you can access it through Bot.my_check instead of through the specific instance.
Define your cog inside setup so that the class is aware of the bot instance when it is created.