Discord.py角色重分配报错NotFound(10011)求解决方案
问题分析与解决方案
核心错误原因
- 角色获取函数调用错误:你误用了
discord.utils.get_role,这个函数并不存在,正确获取角色的方式是member.guild.get_role(role_id)或者discord.utils.get(member.guild.roles, id=role_id)。 - CSV数据格式不一致:当用户属于试用角色时,你写入CSV的是字符串格式的角色ID(
"934070928281841664"),其他场景则写入整数ID列表。ast.literal_eval解析后,字符串ID无法匹配整数类型的角色ID,导致找不到对应角色。 - CSV读取方式错误:你用
csv.DictReader读取CSV,但写入时未添加表头,DictReader会把第一行数据当成表头,导致后续行的索引匹配完全错误,应该用csv.reader读取无表头的CSV文件。
修正后的代码
import discord import asyncio import csv import ast intents = discord.Intents().all() client = discord.Client(intents=intents) async def background_task(member, role): await asyncio.sleep(30) # 测试用30秒,正式环境改成86400*14对应14天 new_role = member.guild.get_role(934070928281841664) # 用ID获取角色更可靠 if new_role: await member.remove_roles(role) await member.add_roles(new_role) print(f'User {member} has been taken off trial') else: print("Trader角色不存在,无法完成切换") @client.event async def on_member_join(member): print(f"User joined: {member.id}") has_record = False # 用csv.reader读取无表头的CSV with open("roles.csv", "r", encoding="utf-8") as csv_file: reader = csv.reader(csv_file) print("CSV was opened") for row in reader: if not row: # 跳过空行避免报错 continue str_member = str(member.id) if row[0] == str_member: has_record = True print(row[0], str_member) print(f"row[1]: {row[1]}") try: role_ids = ast.literal_eval(row[1]) # 处理单个ID的情况,统一转为列表格式 if not isinstance(role_ids, (list, tuple)): role_ids = [role_ids] # 强制转换为整数ID,避免字符串匹配失败 roles = [] for rid in role_ids: rid = int(rid) role = member.guild.get_role(rid) if role: roles.append(role) print(f"Roles: {roles}") if roles: await member.add_roles(*roles) print(f"User found, roles restored") else: print("No valid roles found for this user") except Exception as e: print(f"解析角色数据出错: {e}") break # 找到用户后直接跳出循环,减少不必要的遍历 # 只有无记录时才分配试用角色 if not has_record: role = discord.utils.get(member.guild.roles, name="Insider Trial") if role: await member.add_roles(role) asyncio.create_task(background_task(member, role)) print("New user assigned trial role") else: print("Insider Trial角色不存在,无法分配") @client.event async def on_member_remove(member): trial_removal = "Insider Trial" roles = [role.name for role in member.roles] print(f"{member.name} had the following roles: {', '.join(roles)}") with open("roles.csv", "a", newline="", encoding="utf-8") as csv_file: writer = csv.writer(csv_file) if trial_removal in roles: # 统一用整数ID列表格式写入,避免类型混乱 writer.writerow([member.id, [934070928281841664]]) print("This user was on trial") else: # 过滤掉默认的@everyone角色(ID等于服务器ID),避免无效数据 role_ids = [role.id for role in member.roles if role.id != member.guild.id] writer.writerow([member.id, role_ids]) print("User's roles were recorded!") client.run('YOUR_BOT_KEY_HERE')
额外优化说明
- 增加了异常处理,避免解析CSV数据时程序崩溃
- 统一CSV写入格式为整数ID列表,彻底解决类型不匹配问题
- 使用
guild.get_role获取角色,比discord.utils.get效率更高 - 找到用户记录后立即跳出循环,减少不必要的遍历开销
- 过滤默认的@everyone角色,避免存储无效数据
内容的提问来源于stack exchange,提问作者Slade
相关产品推荐
相关产品推荐

