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); }
问题根源
- 缓存未刷新:
Context.Guild.Users获取的是Bot本地缓存数据,不会自动同步Discord服务器的用户最新状态,导致移除字符串后仍读取旧状态。 - 逻辑冗余且顺序错误:先执行角色移除判断,再执行添加判断,即使状态已变更,缓存旧数据仍会触发添加操作;且未判断角色当前状态,导致无意义的重复操作。
- 线程阻塞:
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
相关产品推荐
相关产品推荐

