You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Discord.py中实现按服务器独立变更状态变量(命令触发)

解决Discord答题机器人跨服务器状态冲突的方案

首先要指出你代码里的两个关键问题:

  1. 全局变量var的共享问题:单一全局变量会被所有服务器共用,导致一个服务器启动答题后,其他服务器也会收到"A round has already begun."的提示,这就是你遇到的跨服干扰问题。
  2. stopg命令的语法错误:if var = 1是赋值操作,不是比较,应该改成if var == 1,否则运行时会抛出语法错误。

接下来给你两种实用的解决方案,从简单到扩展性强:


方案一:用字典按服务器ID存储状态

这是最直接的修改方式,用字典的键存储服务器ID(ctx.guild.id),值存储对应服务器的答题状态(0=未开始,1=进行中),每个服务器的状态完全独立。

修改后的代码示例:

# 初始化空字典,存储每个服务器的答题状态
server_states = {}

@client.command()
async def question1(ctx):
    guild_id = ctx.guild.id
    # 获取当前服务器的状态,默认是0(未开始)
    current_state = server_states.get(guild_id, 0)
    
    if current_state == 0:
        server_states[guild_id] = 1
        try:
            # 这里放你的第一题发送逻辑
            await ctx.send("第一题开始!")
        except Exception as e:
            # 出错后要把状态改回0,避免卡住
            server_states[guild_id] = 0
            await ctx.send(f"启动答题出错:{str(e)}")
    else:
        await ctx.send("A round has already begun.")

# 同理修改question2和question3命令
@client.command()
async def question2(ctx):
    guild_id = ctx.guild.id
    current_state = server_states.get(guild_id, 0)
    
    if current_state == 0:
        server_states[guild_id] = 1
        try:
            await ctx.send("第二题开始!")
        except Exception as e:
            server_states[guild_id] = 0
            await ctx.send(f"启动答题出错:{str(e)}")
    else:
        await ctx.send("A round has already begun.")

@client.command()
async def question3(ctx):
    guild_id = ctx.guild.id
    current_state = server_states.get(guild_id, 0)
    
    if current_state == 0:
        server_states[guild_id] = 1
        try:
            await ctx.send("第三题开始!")
        except Exception as e:
            server_states[guild_id] = 0
            await ctx.send(f"启动答题出错:{str(e)}")
    else:
        await ctx.send("A round has already begun.")

@client.command()
async def stopg(ctx):
    guild_id = ctx.guild.id
    current_state = server_states.get(guild_id, 0)
    
    if current_state == 1:
        server_states[guild_id] = 0
        await ctx.send("Round has been stopped")
    else:
        await ctx.send("You can only use this command if a round is running.")

方案二:用类封装服务器答题会话(扩展性更强)

如果以后你想给答题机器人添加更多功能(比如记录用户分数、当前题目序号、答题类别等),用类来封装每个服务器的答题状态会更清晰易维护。

代码示例:

# 定义答题会话类,封装所有相关状态
class QuizSession:
    def __init__(self):
        self.is_running = False
        # 可以添加更多属性,比如:
        # self.current_question = 0
        # self.user_scores = {}
        # self.category = None

# 用字典存储每个服务器的QuizSession实例
server_quizzes = {}

@client.command()
async def question1(ctx):
    guild_id = ctx.guild.id
    # 获取或创建当前服务器的答题会话
    quiz = server_quizzes.setdefault(guild_id, QuizSession())
    
    if not quiz.is_running:
        quiz.is_running = True
        try:
            await ctx.send("第一题开始!")
            # 这里添加你的第一题逻辑
        except Exception as e:
            quiz.is_running = False
            await ctx.send(f"启动答题出错:{str(e)}")
    else:
        await ctx.send("A round has already begun.")

# 其他question命令和stopg命令同理修改
@client.command()
async def stopg(ctx):
    guild_id = ctx.guild.id
    quiz = server_quizzes.get(guild_id, QuizSession())
    
    if quiz.is_running:
        quiz.is_running = False
        await ctx.send("Round has been stopped")
    else:
        await ctx.send("You can only use this command if a round is running.")

额外优化建议

  • 减少代码重复:三个question命令的逻辑几乎一样,可以把状态检查的逻辑抽成一个辅助函数或者装饰器,避免重复代码。比如:
    async def prepare_quiz(ctx):
        guild_id = ctx.guild.id
        quiz = server_quizzes.setdefault(guild_id, QuizSession())
        if quiz.is_running:
            await ctx.send("A round has already begun.")
            return None
        quiz.is_running = True
        return quiz
    
    @client.command()
    async def question1(ctx):
        quiz = await prepare_quiz(ctx)
        if quiz:
            await ctx.send("第一题开始!")
            # 你的第一题逻辑
    
  • 持久化状态:如果机器人重启,字典里的状态会丢失。如果需要持久化,可以用简单的SQLite数据库或者JSON文件存储服务器状态,不过临时开发的话可以暂时忽略。
  • 异常处理:一定要在出错时把状态改回初始值,避免某个服务器的状态一直卡在“进行中”,导致无法再次启动答题。

内容的提问来源于stack exchange,提问作者Mario Arquette

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 23:04:05