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

Discord.Net Bot状态检测异常:移除指定字符串后仍重复添加角色

问题:Discord Bot状态检测与角色同步异常

需求与异常表现

  • 需求:执行statuson命令后,Bot每隔10秒遍历服务器所有用户,若用户自定义状态包含.gg/anime-club则添加指定角色;当用户移除该字符串时,自动移除对应角色。
  • 异常:
    • 用户添加状态字符串后,Bot每次循环都会重复执行添加角色操作;
    • 用户移除状态字符串后,Bot仍持续添加角色,未正确获取用户最新状态信息。

原代码

[Command("statuson")]
[Alias("x")]
public async Task StatusOn()
{
    while (true)
    {
        Console.WriteLine("req refresh");
        await JaLOL();
        Thread.Sleep(10000);
    }
}
public int count = 0;
public async Task JaLOL()
{
    IReadOnlyCollection<SocketGuildUser> users = null;
    IReadOnlyCollection<IActivity> userActivities = null;
    IReadOnlyCollection<ulong> roles = null;

    Console.WriteLine("refresh");
    users = Context.Guild.Users;
    foreach (IGuildUser user in users)
    {
        userActivities = user.Activities;
        roles = user.RoleIds;
        foreach (ulong role in roles)
        {
            if (role == 1020762686323167303)
            {
                foreach (var activity in userActivities)
                {
                    if (activity.Type == ActivityType.CustomStatus)
                    {
                        if (!activity.ToString().Contains(".gg/anime-club"))
                        {
                            await user.RemoveRoleAsync(1020762686323167303);
                            Console.WriteLine("remove " + user.DisplayName);
                        }
                    }
                }
            }
        }
        foreach (var activity in userActivities)
        {
            if (activity.Type == ActivityType.CustomStatus)
            {
                if (activity.ToString().Contains(".gg/anime-club"))
                {
                    await user.AddRoleAsync(1020762686323167303);
                    Console.WriteLine("add " + user.DisplayName);
                }
            }
        }
    }
    count++;
    Console.WriteLine("end   " + count);
}

问题根源

  1. 缓存未刷新:Context.Guild.Users获取的是Bot本地缓存数据,不会自动同步Discord服务器的用户最新状态,导致移除字符串后仍读取旧状态。
  2. 逻辑冗余且顺序错误:先执行角色移除判断,再执行添加判断,即使状态已变更,缓存旧数据仍会触发添加操作;且未判断角色当前状态,导致无意义的重复操作。
  3. 线程阻塞:Thread.Sleep(10000)会阻塞异步任务线程,影响Bot其他功能响应。

修正方案与代码

[Command("statuson")]
[Alias("x")]
public async Task StatusOn()
{
    while (true)
    {
        Console.WriteLine("req refresh");
        await JaLOL();
        // 用异步延迟替代Thread.Sleep,避免阻塞线程
        await Task.Delay(10000);
    }
}

public int count = 0;
public async Task JaLOL()
{
    Console.WriteLine("refresh");
    var targetRoleId = 1020762686323167303UL;
    var users = Context.Guild.Users;

    foreach (var user in users)
    {
        // 主动请求用户最新数据,刷新本地缓存
        await user.DownloadAsync();
        
        // 判断用户状态是否包含目标字符串
        bool hasTargetString = user.Activities
            .Any(a => a.Type == ActivityType.CustomStatus && a.ToString().Contains(".gg/anime-club"));
        
        // 判断用户当前是否拥有目标角色
        bool hasTargetRole = user.RoleIds.Contains(targetRoleId);

        // 仅在状态与角色不匹配时执行操作
        if (hasTargetString && !hasTargetRole)
        {
            await user.AddRoleAsync(targetRoleId);
            Console.WriteLine($"add {user.DisplayName}");
        }
        else if (!hasTargetString && hasTargetRole)
        {
            await user.RemoveRoleAsync(targetRoleId);
            Console.WriteLine($"remove {user.DisplayName}");
        }
    }

    count++;
    Console.WriteLine($"end   {count}");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:10:45