Discord.py如何让机器人定时给用户发DM?ctx未定义问题怎么解决
问题原因
ctx是Discord.py触发命令、事件时自动生成的上下文对象,仅在对应回调函数的作用域内有效。你编写的定时任务是独立运行的异步任务,默认不持有ctx对象,强行传入会因为找不到实例报错,且这个场景下你完全不需要依赖ctx实现功能。
解决方案
不需要硬传ctx参数,直接通过bot实例获取你需要的用户、频道对象即可,修改逻辑如下:
- 提前准备好两个ID:你要生成邀请的目标频道ID、目标用户KexoTV#8921的用户ID(开启Discord开发者模式后右键对应对象即可复制)
- 在bot的
on_ready事件触发后再启动定时任务,避免bot未完成资源加载时找不到对应对象
修正后的参考代码:
import discord from discord.ext import tasks, commands import time import asyncio # 替换为你自己的实际ID TARGET_USER_ID = 123456789012345678 # 替换为KexoTV#8921的用户ID TARGET_CHANNEL_ID = 987654321098765432 # 替换为你要生成邀请的频道ID bot = commands.Bot(command_prefix='!', intents=discord.Intents.all()) async def timecheck(): tm = time.localtime() if tm[6] == 6: # 每周日触发 # 直接通过bot获取用户对象 member = bot.get_user(TARGET_USER_ID) if not member: # 缓存里没找到就主动拉取 member = await bot.fetch_user(TARGET_USER_ID) # 获取目标频道对象 channel = bot.get_channel(TARGET_CHANNEL_ID) if not channel: channel = await bot.fetch_channel(TARGET_CHANNEL_ID) # 生成邀请链接 invitelink = await channel.create_invite(max_uses=1, unique=True) # 发送私信 await member.send(invitelink) @tasks.loop(seconds=60) async def mainloop(): await timecheck() # 等bot启动完成后再启动定时任务 @bot.event async def on_ready(): print(f'登录成功:{bot.user}') if not mainloop.is_running(): mainloop.start() bot.run('你的机器人Token')
注意事项
- 确保你给机器人开启了足够的权限:对应频道的创建邀请权限、发送私信的权限
- 不推荐使用用户名+识别码的方式匹配用户,用户改名后规则会直接失效,用固定ID兼容性更强
- 如果需要适配多个频道/多个目标用户,直接扩展对应的ID配置即可
内容的提问来源于stack exchange,提问作者Kexo
相关产品推荐
相关产品推荐

