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

Discord机器人获取公会成员信息报KeyError及实现服务器金币Top10榜单问题

问题1:KeyError报错修复

报错原因

  • 公会配置数据和用户金币数据被混存在同一个mainbank.json文件中,存储结构互相冲突
  • on_guild_join事件存在语法错误:写入文件时"w"参数位置错误,且直接尝试序列化Discord频道对象(JSON格式不支持序列化Discord原生对象)
  • 当前触发命令的公会是机器人添加on_guild_join事件前就加入的,没有触发过数据写入逻辑,因此JSON中不存在对应公会ID的键
  • guild命令中直接将频道对象作为embed参数发送,类型不匹配,即便解决KeyError也会触发新的报错

修复代码

首先拆分存储文件,新增guild_config.json专门存储公会配置,修改后的代码如下:

# 初始化guild_config.json,文件不存在时自动创建空配置
import os
if not os.path.exists("guild_config.json"):
    with open("guild_config.json", "w") as f:
        json.dump({}, f)

@client.event
async def on_guild_join(guild):
    with open("guild_config.json", "r") as f:
        guildInfo = json.load(f)
    # 存储频道ID而非频道对象,避免序列化失败
    guildInfo[str(guild.id)] = guild.text_channels[0].id
    # 修复写入语法错误
    with open("guild_config.json", "w") as f:
        json.dump(guildInfo, f)
         
@client.command(aliases = ['gd'])
async def guild(ctx):
    with open("guild_config.json", "r") as f:
        guildInfo = json.load(f)
    # 增加键不存在的容错处理
    guild_id = str(ctx.guild.id)
    if guild_id not in guildInfo:
        # 无配置时默认使用命令触发的当前频道
        channel = ctx.channel
    else:
        channel = client.get_channel(guildInfo[guild_id])
    # 自行调整embed内容即可
    em = discord.Embed(title="公会配置", description=f"绑定的通知频道为{channel.mention}")
    await ctx.send(embed=em)

问题2:排行榜修改为仅展示当前公会前10名

前置配置

首先需要开启成员意图,否则无法获取公会完整成员列表:

  1. 代码层面开启意图:
intents = discord.Intents.default()
intents.members = True
# 替换为你原来的前缀初始化机器人
client = commands.Bot(command_prefix='你的命令前缀', intents=intents)
  1. 进入Discord开发者后台的Bot设置页,开启Server Members Intent开关。

修改后的排行榜代码

同时修复了原排行榜同金额用户数据被覆盖的问题:

@client.command(aliases = ["lb"])
async def leaderboard(ctx, x = 10):
    users = await get_bank_data()
    # 获取当前公会所有成员ID集合,转成字符串匹配JSON的键格式
    guild_member_ids = {str(member.id) for member in ctx.guild.members}
    leader_board = []
    for user_id in users:
        # 仅统计当前公会内的成员
        if user_id not in guild_member_ids:
            continue
        total_amount = users[user_id]["wallet"] + users[user_id]["bank"]
        leader_board.append((total_amount, user_id))
    # 按总资产降序排序
    leader_board = sorted(leader_board, key=lambda x: x[0], reverse=True)
    em = discord.Embed(title = f"<:emoji_23:886988033872764938> : 本公会富豪榜TOP {x}" , description = "排名依据为钱包+银行总资产",color = discord.Color(0x00FFFC))
    index = 1
    for amt, id_ in leader_board:
        member = ctx.guild.get_member(int(id_))
        # 兼容成员已离开公会的异常情况
        if not member:
            continue
        name = member.display_name
        em.add_field(name = f"{index}. {name}" , value = f"「总资产」❯❯ {amt} 🪙",  inline = False)
        if index == x:
            break
        index += 1
    await ctx.send(embed = em)

内容的提问来源于stack exchange,提问作者Hiresh Verma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:12:02