pycord icon indicating copy to clipboard operation
pycord copied to clipboard

BridgeOption converts discord.Member wrong with ext command

Open Revnoplex opened this issue 1 year ago • 15 comments

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 avatar Mar 15 '24 10:03 Revnoplex

@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)}")

Paillat-dev avatar Oct 24 '24 14:10 Paillat-dev

Can you confirm you tried running the command as a prefix command and not a slash command?

Revnoplex avatar Oct 24 '24 23:10 Revnoplex

@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 ?

Paillat-dev avatar Oct 24 '24 23:10 Paillat-dev

I have been testing on the somewhat latest commit past 2.6.1, I will have to investigate further

Revnoplex avatar Oct 24 '24 23:10 Revnoplex

Actually, could you install from the latest github master branch ? pip install git+https://github.com/Pycord-Development/pycord ?

Paillat-dev avatar Oct 24 '24 23:10 Paillat-dev

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

Revnoplex avatar Oct 24 '24 23:10 Revnoplex

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")

Screenshot_20241025_110745

If you still can't reproduce it, Im trying to setup a new environment on another machine where I will test there as well

Revnoplex avatar Oct 25 '24 00:10 Revnoplex

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

Revnoplex avatar Oct 25 '24 00:10 Revnoplex

what about python 3.12 or below?

NeloBlivion avatar Oct 25 '24 00:10 NeloBlivion

Nope, still the same for python 3.12.7 using the code in https://github.com/Pycord-Development/pycord/issues/2394#issuecomment-2436548316

Revnoplex avatar Oct 25 '24 02:10 Revnoplex

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?

Revnoplex avatar Oct 26 '24 00:10 Revnoplex

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.

NeloBlivion avatar Oct 26 '24 02:10 NeloBlivion

Can you assign me pls ?

Paillat-dev avatar Oct 26 '24 09:10 Paillat-dev

Finish the other prs / issues first please

Lulalaby avatar Oct 26 '24 09:10 Lulalaby

@Lulalaby I think all are ready for review

Paillat-dev avatar Oct 26 '24 09:10 Paillat-dev

Can confirm fixed by #2775

Revnoplex avatar Aug 03 '25 10:08 Revnoplex