discord.py 将上下文和自我传递给 class 中的函数

discord.py Passing context and self to function in class

我正在尝试创建一个机器人,它使用 discord.py 的 VoiceClient。

问题是,当您在一个函数中命名一个变量时,它不会传递给其他函数。所以变量 voicebot 不会传递给其他函数(用于让机器人离开或说话)

intents = discord.Intents.all()
bot = commands.Bot(command_prefix=commands.when_mentioned_or("~"),intents=intents, owner_id=587573816360960022)

...Other functions...

@bot.command(name='join', help='Joins the voice channel you are in')
async def JoinVoiceofAuthor(ctx):
   vchannel = ctx.message.author.voice
   if vchannel != None:
       if "voicebot" not in globals():
           global voicebot
           voicebot = await vchannel.channel.connect()
       else:
           if voicebot.is_connected():
                   return
           if vchannel != None:
               voicebot = await vchannel.channel.connect()
       await ctx.send('Joining you, '+str(ctx.message.author.mention)+', in voice channel "'+str(vchannel.channel)+'"')
   else:
       await ctx.send('Sorry,'+str(ctx.message.author.mention)+', you are not in a voice channel')

...Other functions...

我尝试将 voicebot 设为全局变量,但发现您无法从函数更改全局变量。 所以我的下一个想法是让机器人成为 class:

class TheBot(commands.Bot):
    def __init__(self):
        intents = discord.Intents.all()

        super().__init__(intents=intents, command_prefix='~',  owner_id=587573816360960022)
        members = inspect.getmembers(self)
        for name, member in members:
            if isinstance(member, commands.Command):
                if member.parent is None:
                    self.add_command(member)

...Other functions...

    @commands.command(name='join', help='Joins the voice channel you are in')
    async def JoinVoiceofAuthor(self, ctx):
        vchannel = ctx.message.author.voice
        if vchannel != None:
            if "voicebot" not in globals():
                self.voicebot = await vchannel.channel.connect()
            else:
                if self.voicebot.is_connected():
                        return
                if vchannel != None:
                    self.voicebot = await vchannel.channel.connect()
            await ctx.send('Joining you, '+str(ctx.message.author.mention)+', in voice channel "'+str(vchannel.channel)+'"')
        else:
            await ctx.send('Sorry,'+str(ctx.message.author.mention)+', you are not in a voice channel')

...Other functions...

但这也没有用,因为 Context 也传递给了 self 而不是 ctx

有人对此有解决方案吗?

如果要从函数更改全局变量,必须在函数内部使用 global 关键字:

x = 50
def add_to_x(num):
    global x
    x += num

print(x)
add_to_x(10)
print(x)


#The Output is this:
50
60

discord.py 中的实现是:

x = 50
@bot.command()
async def add_to_x(ctx,amount):
    global x
    print(x)
    x += int(amount)
    print(x)

正如遮阳伞柯比所说,你需要使用global关键字。为了适应您的情况,我们需要进行一些更改。

要使 voicebot 变量成为全局变量,只需在命令顶部添加 global voicebot。这样你就可以在每个函数中使用这个变量。

然后检查机器人是否已经连接到语音通道,我们不需要使用 voicebot 变量。如果机器人在这样的语音通道中,您可以创建一个 returns True 的函数:

def is_connected(ctx):
    voice_client = discord.utils.get(ctx.bot.voice_clients, guild=ctx.guild)
    return voice_client and voice_client.is_connected()

现在要检查机器人是否未从命令中连接到语音通道,只需使用 is_connected 函数并“传入”上下文。

if not is_connected(ctx):

所以完整的代码如下所示:

def is_connected(ctx):
    voice_client = discord.utils.get(ctx.bot.voice_clients, guild=ctx.guild)
    return voice_client and voice_client.is_connected()

@bot.command(name='join', help='Joins the voice channel you are in')
async def JoinVoiceofAuthor(ctx):
    global voicebot

    vchannel = ctx.message.author.voice
    if vchannel != None:
        if not is_connected(ctx):
            voicebot = await vchannel.channel.connect()
            await ctx.send('Joining you, '+str(ctx.message.author.mention)+', in voice channel "'+str(vchannel.channel)+'"')