Discord.py Guild.bans() missing 1 required positional argument: 'self' - discord

Code:
#tree.command(name="unban",description="Unbans a member.",guild=discord.Object(id=guildid))
async def unban(ctx,member:str):
bannedusers = await discord.Guild.bans()
membername,memberdiscriminator = member.split("#")
for banentry in bannedusers:
user = banentry.user
if (user.name, user.discriminator) == (membername, memberdiscriminator):
await ctx.guild.unban(user)
Error:
Guild.bans() missing 1 required positional argument: 'self'
I tried also use discord.Guild.unban and discord.Member.unban, both give the same error

You're calling discord.Guild which is a class and thus not instantiated. Try ctx.guild.bans()
API Reference: https://discordpy.readthedocs.io/en/stable/api.html?highlight=guild#discord.Guild.bans

Related

Discord.py exception "Missing 1 required positional argument: 'ctx' " although I included 'ctx' as one of the function parameters

so I'm having an issue while creating a discord music bot and I've been trying to solve it for a while now, but I can't find any solution.
Here's the constructor and three functions to search and play music that are necessary for the command to actually work (I'll only include the skip command since I get the same exception with the rest of the commands)
class music(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.is_playing = False
self.is_paused = False
self.music_queue = []
self.YDL_OPTIONS = {"format": "bestaudio", "noplaylist": "True"}
self.FFMPEG_OPTIONS = {"before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5", "options": "-vn"}
self.vc = None
async def play_music(self, ctx):
if len(self.music_queue) > 0:
self.is_playing = True
m_url = self.music_queue[0][0]["source"]
if self.vc == None or not self.vc.is_connected():
self.vc == await self.music_queue[0][1].connect()
if self.vc == None:
await ctx.send("I'm sorry, but I can't join the voice channel")
return
else:
await self.vc.move_to(self.music_queue[0][1])
self.music_queue.pop(0)
self.vc.play(discord.FFmpegPCMAudio(m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())
else:
self.is_playing = False
def play_next(self):
if len(self.music_queue) > 0:
self.is_playing = True
m_url = self.music_queue[0][0]["source"]
self.music_queue.pop(0)
self.vc.play(discord.FFmpegPCMAudio(m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())
else:
self.is_playing = False
def search(self, item):
with YoutubeDL(self.YDL_OPTIONS) as ydl:
try:
info = ydl.extract_info("ytsearch:{0}".format(item), download=False)["entries"][0]
except Exception:
return False
return {"source": info["formats"][0]["url"], "title": info["title"]}
async def setup(client):
await client.add_cog(music(client))
bot.py with setup_hook and the command
class MyBot(commands.Bot):
async def setup_hook(self):
await self.load_extension("dustobot")
#commands.command(aliases=["s"], help="Skips the current song that is being played")
async def skip(self, ctx, *args):
if self.vc != None and self.vc:
self.vc.stop()
await self.play_music(ctx) #Calling a function that plays the next song in a queue
And this is the error I get:
2023-01-21 12:28:37 ERROR discord.ext.commands.bot Ignoring exception in command skip
Traceback (most recent call last):
File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 229, in wrapped
ret = await coro(*args, **kwargs)
TypeError: music.skip() missing 1 required positional argument: 'ctx'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\bot.py", line 1349, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 1023, in invoke
await injected(*ctx.args, **ctx.kwargs) # type: ignore
File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 238, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: music.skip() missing 1 required positional argument: 'ctx'
Is it because I'm using a deprecated discord.py syntax?
Thanks in advance for taking your time to help me, I really appreciate it.
Btw this is my main.py:
import os
import discord
from dustobot import music #This imports the music class
from dotenv import load_dotenv
from discord.ext import commands
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
intents = discord.Intents.default()
intents.message_content = True
client = commands.Bot(command_prefix="!", intents=intents)
client.remove_command("help") #I have my own help command
if __name__ == "__main__":
client.run(TOKEN)
The issue is caused by the way you created the command:
#client refers to the bot
#client.command(aliases=["s"], help="Skips the current song that is being played")
The decorator doesn't expect this to be a method in a class. As such, it's not invoked as a method either, so self won't be passed automatically and the Context will be the first argument (self). As a result, the library won't pass a value for ctx, which results in your error.
In cogs, commands should be created using #commands.command instead of #<Bot_instance>.command, the reason being that you shouldn't have your Bot instance available to you in that scope.
You could've also gotten this by reading the manual for Cogs...
Every command is marked with the commands.command() decorator.

on_member_update nickname change doesn't work out as intended

I was trying to set events for my bot, however, it always returns this error after trying to edit the nickname on my server:
#commands.Cog.listener()
async def on_member_update(self, ctx, member_before, member_after):
nickname_after = f"{member_after.nickname}" if not member_after.nickname else member_after.nickname
nickname_before = f"{member_before.nickname}" if not member_before.nickname else member_before.nickname
embed = discord.Embed(timestamp = ctx.message.created_at , color = discord.Colour.random() ,
title = "Member Update")
embed.add_field(name = "Nickname before:" , value = f"{nickname_before}" , inline = True)
embed.add_field(name = "Nickname after:" , value = f"{nickname_after}" , inline = True)
embed.set_thumbnail(url = f"{member_after.avatar.url}")
embed.set_author(name = f"{self.osamu.user}" , icon_url = f"{self.osamu.avatar.url}")
channel = self.osamu.get_channel(898199584726188042)
return await channel.send(embed = embed)
The following traceback has been detected:
Ignoring exception in on_member_update
Traceback (most recent call last):
File "/home/ohnezahn/.local/lib/python3.9/site-packages/discord/client.py", line 352, in _run_event
await coro(*args, **kwargs)
TypeError: on_member_update() missing 1 required positional argument: 'member_after'
What I'm trying to achieve: if the user is editing his nickname the bot shall send the embed in the Channel which I've set (channel = self.osamu.get_channel(898199584726188042)). However, the response is the traceback, no embed whatsoever...
According to the docs, on_member_update only takes 2 parameters: before and after. Since your listener seems to be in a class you also need to use self as the first argument.
So if you remove the ctx from your arguments it should work properly.
#commands.Cog.listener()
async def on_member_update(self, member_before, member_after):
https://discordpy.readthedocs.io/en/master/api.html?highlight=on_member_update#discord.on_member_update

How to check if a user has permission to use a command? Discordpy

I am creating a custom help command and I have a problem. The default help command can somehow hide commands that are not available for a user that invoked the command. I was looking everywhere and I can't find any solution. I tried using hidden attribute of a command object but it is not working. The best solution would be a method like Member.can_use(command) that would return True or False but there is nothing like that in docs. Or at least I cannot find it.
Help would be appreciated.
Use the Command.can_run method, an example would be:
#bot.command()
async def can_it_run(ctx, command_name: str):
command = bot.get_command(command_name)
can_use = await command.can_run(ctx)
if can_use:
await ctx.send(f"You can use {command_name}")
else:
await ctx.send(f"You can't use {command_name}")
Sadly if a check raises an exception (like commands.guild_only) the exception(s) won't be suppressed, also if you want to check if someone else (not the invoker) can use the command you have to overwrite Context.author, a handy function would be:
async def can_run(ctx, command_name: str, member: discord.Member=None) -> bool:
command = bot.get_command(command_name)
if command is None: # Command doesn't exist / invalid command name
return False # Or raise an exception
if member is not None: # If a member is passed overwrite the attribute
ctx.author = member
try:
return await command.can_run(ctx)
except Exception:
return False
#bot.command()
async def can_it_run(ctx, command_name: str, member: discord.Member=None):
resp = await can_run(ctx, command_name, member)
await ctx.send(resp)
You could just check if the user countains a certain id by doing the following:
if (message.author.id == "WHoever ID1" || message.author.id == "Whoever ID2"):
#Do Something
If you want to put a bunch of ID's in then just do the following:
bool = false;
arr = ["ID1", "ID2", "ID3"]
for x in arr:
if(x == message.author.id):
bool = true;
if(bool):
#Do stuff
bool = false;
This is very vague code but it should be something similar to this

javascript evaluation failed- karate

I am trying to call an API in second feature file , passing arguments from first feature file . These has to be passed as a param for second API
* def activeDetails =
"""
function(times){
for(i=0;i<=times;i++){
karate.log('Run test round: '+(i+1));
karate.call('getActiveRouteDetails.feature', { token: token, currentPage: i });
}
java.lang.Thread.sleep(1*1000);
}
"""
* call activeDetails totalPages
In my second feature , I am able to print the values passed , Getting error while passing it as a param 'no step-definition method match found for: param pageNumber'
And print currentPage
And print token
And param pageNumber = '#currentPage'
And param token = token
Watch the white space around the = sign. Normally if you use IDE support you can avoid these issues. You seem to have an extra space after pageNumber.
So make this change:
And param pageNumber = currentPage
I request you to please read the docs and examples. You are still un-necessarily making 2 calls. And over complicating your test.

Pass session expression language variable in ELFileBody

I encounter an issue using Gatling EL in ELFileBody.
I have the following exec :
exec(myFunction("${myEmail}", otherParameters))
and the function :
def myFunction((email: String) = {
exec((s: Session) => s.set("email", email))
.exec(http("MyFunction")
.put("/myUrl")
.headers(Headers.basic_headers_json)
.body(ElFileBody("LinkToMyJsonFile"))
.asJson
.check(status.is(200)))
}
my myEmail is set in session. Yet, when the exec runs myFunction, the variable is replaced in the json by "${myEmail}" instead of beeing evaluated.
Have you an idea how I can resolve it be able to pass myEmail session variable in the exec through myFunction?
Thanks a lot in advance
JF
your function takes a string and you are then putting that string into a session variable - so when you pass in "${myEmail}" gatling is putting that string literal into the session var. So when gatling does the substitution in the ELFile body it's using exactly what you've specified.
I'm assuming you already have the email you want in the ${myEmail} session var - why not just edit the file to use ${myEmail} in place of "${email}"?
a more idiomatic approach would be to pass in an Expression[String], validate it and set the result into the ${email} var
def myFunction((email: Expression[String]) = {
exec((s: Session) => email.apply(s) match {
case Success(address) => s.set("email", address)
case Failure(error) => {
println(s"There was an error: $error")
s
}
}
...
This will retrieve the value of ${myEmail} if there is one or just the string literal if that's the case, and put it in the ${email} var. The error would be thrown if you provided a session var for which there was no value

Resources