Discord.py循环实现:持有特定角色一段时间后自动踢出成员
实现角色持有时长达标后自动踢出功能
你的原始代码会直接踢出所有拥有指定角色的成员,但要实现「持有角色达到一定时长再踢」,需要解决两个核心问题:记录用户获得角色的时间,以及定期循环检查时长是否达标。下面是具体实现方案:
1. 准备基础存储与事件监听
我们需要先记录每个用户获得目标角色的时间,这里先用内存字典临时存储(如果Bot重启后不想丢失数据,可以换成JSON文件或数据库):
import discord from discord.ext import tasks, commands from datetime import datetime, timedelta intents = discord.Intents.default() intents.members = True # 必须开启成员意图,否则无法监听角色变动 bot = commands.Bot(command_prefix="!", intents=intents) # 存储用户ID和对应的角色获得时间(键:用户ID,值:datetime对象) role_add_time = {} TARGET_ROLE_ID = 1066518590813118494 # 你的目标角色ID KICK_AFTER = timedelta(hours=2) # 设置需要达到的时长,比如2小时
然后监听角色添加事件,记录时间:
@bot.event async def on_member_role_add(member, role): if role.id == TARGET_ROLE_ID: role_add_time[member.id] = datetime.now() print(f"记录用户 {member.name} 获得角色时间:{role_add_time[member.id]}")
2. 用定时循环实现定期检查
使用tasks.loop创建一个定时任务,比如每分钟检查一次(可自行调整间隔),这就是你需要的「循环执行逻辑」:
@tasks.loop(minutes=1) async def check_kick_condition(): # 遍历所有存储的用户记录 for user_id, add_time in list(role_add_time.items()): # 计算当前时间与角色获得时间的差值 time_elapsed = datetime.now() - add_time if time_elapsed >= KICK_AFTER: try: member = bot.get_user(user_id) or await bot.fetch_user(user_id) # 确认用户还在服务器且仍持有目标角色 if member.guild and TARGET_ROLE_ID in [r.id for r in member.roles]: await member.kick(reason=f"持有目标角色超过{KICK_AFTER.total_seconds()/3600}小时") del role_add_time[user_id] # 踢完后移除记录 print(f"已踢出用户 {member.name}") except discord.Forbidden: print(f"没有权限踢用户 {member.name}") except discord.NotFound: del role_add_time[user_id] # 用户已离开服务器,移除记录 # 启动Bot时同时启动定时任务 @bot.event async def on_ready(): print(f"Bot已登录:{bot.user}") check_kick_condition.start()
3. 关键逻辑说明
- 迭代循环的作用:
tasks.loop会按设置的间隔自动重复执行检查函数,函数内部的for循环遍历所有记录的用户,逐一判断是否满足踢人条件——这是两层迭代逻辑:外层是定时循环重复触发检查,内层是遍历用户列表做时长判断。 - 持久化存储:如果Bot重启后不想丢失已记录的角色时间,可以把
role_add_time字典的内容写入JSON文件,启动时再读取,用json.dump()和json.load()即可实现。 - 权限注意:确保Bot拥有「踢出成员」的服务器权限,且Bot的角色位置高于目标角色,否则会踢人失败。
内容的提问来源于stack exchange,提问作者Heeryun Cho
相关产品推荐
相关产品推荐

