BridgeOption converts discord.Member wrong with ext command
Summary
BridgeOption converts discord.Member to a discord.User object when using the ext version unlike the slash version. Specifying discord.Member without BridgeOption works fine with both variants of the bridge command
Reproduction Steps
Use a bridge command with an argument that has the BridgeOption converter with discord.Member as an argument.
Minimal Reproducible Code
@bridge.bridge_command(name='test', description="Hello World")
async def test_cmd(
self, ctx: bridge.BridgeContext,
member: BridgeOption(discord.Member, "A server member")
):
await ctx.respond(f"{type(member)}")
Expected Results
For both the ext and slash command version to return a discord.Member objects like using discord.Member without a BridgeOption converter
Actual Results
The ext variant of the command gets a discord.User object instead of a discord.Member object like the slash variant gets or the version without the converter gets.
This can cause unexpected discord.User objects when running the ext variant that can cause problems like
File "bot-root/venv/lib/python3.11/site-packages/discord/ext/commands/core.py", line 180, in wrapped
ret = await coro(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "bot-root/cogs/mod.py", line 1061, in mute_cmd
await member.add_roles(role, reason=reason)
^^^^^^^^^^^^^^^^
AttributeError: 'User' object has no attribute 'add_roles'
Note: traceback not related to minimal reproduction code
Intents
all
System Information
- Python v3.11.8-final
- py-cord v2.5.1-final
- aiohttp v3.9.3
- system info: Linux 6.7.9-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 08 Mar 2024 01:59:01 +0000
Checklist
- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.
Additional Context
No response
@Revnoplex Are you still experiencing this issue ? I cannot reproduce it with the following code:
@bot.bridge_command(name='test', description="Hello World")
@bridge.bridge_option('member', discord.Member, description='A server member')
async def test_cmd(
ctx: bridge.BridgeContext,
member: discord.Member
):
await ctx.respond(f"{type(member)}")
Can you confirm you tried running the command as a prefix command and not a slash command?
@Revnoplex I tried with both slash and prefix, in cogs and outside of cogs. Would you mind trying yourself again with the latest py-cord version - 2.6.1 ?
I have been testing on the somewhat latest commit past 2.6.1, I will have to investigate further
Actually, could you install from the latest github master branch ? pip install git+https://github.com/Pycord-Development/pycord ?
I'm still getting the same results with the following environment:
- Python v3.13.0-final
- py-cord v2.6.1-final (does not reflect version from latest branch)
- aiohttp v3.10.10
- system info: Linux 6.11.5-arch1-1 #1 SMP PREEMPT_DYNAMIC Tue, 22 Oct 2024 18:31:38 +0000
I will try creating a new environment all together and try testing again
Still reproducing it after creating a new project and with the following file:
#!./venv/bin/python3.13
import discord
from discord.ext import bridge
bot = bridge.Bot(command_prefix="ra!", intents=discord.Intents.all())
@bot.event
async def on_ready():
print(f"We have logged in as {bot.user}")
@bot.bridge_command(name='test', description="Hello World")
@bridge.bridge_option('member', discord.Member, description='A server member')
async def test_cmd(
ctx: bridge.BridgeContext,
member: discord.Member
):
await ctx.respond(f"{type(member)}")
bot.run("TOKEN")
If you still can't reproduce it, Im trying to setup a new environment on another machine where I will test there as well
I tested on another machine with the same code as above:
- Python v3.13.0-final
- py-cord v2.6.1-final
- aiohttp v3.10.10
- system info: Linux 6.1.0-25-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.106-3 (2024-08-26)
And still got the same results
what about python 3.12 or below?
Nope, still the same for python 3.12.7 using the code in https://github.com/Pycord-Development/pycord/issues/2394#issuecomment-2436548316
How does the converter actually work? Because I traced the function calls that happen when the ext command runs and I don't see any checks for converting it to member. And I have no idea what functions are used when a slash command is run. From what I understand, the functions called by the bridge option at invoke time for prefix commands was: ext.bridge.core.BridgeOption.convert() where commands.options.Option passes SlashCommandOptionType.user to that function. Note the documentation says that SlashCommandOptionType.user is supposed to be converted to member at some stage. Once SlashCommandOptionType.user is passed to BridgeOption.convert(), it picks UserConverter from BRIDGE_CONVERTER_MAPPING. No where in the file exists MemberConverter, at the end of BridgeOption.convert() it returns discord.User and I can't see where it checks where it is in a guild anywhere???
Can someone please point out where this Member conversion is supposed to happen in the code?
Ok so this is specifically an issue with BridgeOption - Option has no member conversion because it's unnecessary, but BridgeOption should override __init__ to assign a converter and MentionableConverter should check if it's a guild context.
If you typehint the option as discord.Member and do not use BridgeOption, it will convert to Member as you said.
Can you assign me pls ?
Finish the other prs / issues first please
@Lulalaby I think all are ready for review
Can confirm fixed by #2775