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

基于Python的Discord机器人问题:定时消息与命令响应异常

Discord机器人问题修复方案

问题描述

开发了基于Python的Discord机器人,目标是每天指定时间向服务器频道发送消息。机器人已添加至服务器并拥有管理员权限,但目前仅能在私聊中响应?ping命令,服务器频道内无响应,定时发送消息功能也未生效。

问题原因分析

  1. Intents权限不足:Discord.py v2.0+需要显式开启message_content意图才能读取服务器频道内的消息内容,否则无法触发命令响应。
  2. 定时任务启动时机错误:bot.start(TOKEN)是阻塞式协程,后续的bot.loop.create_task(time_check(bot))代码永远不会执行,导致定时任务从未启动。
  3. 频道对象获取逻辑缺陷:机器人未完全就绪时提前获取频道对象,可能导致message_channel为None,无法发送消息。

修复后的完整代码

import discord
import asyncio
from datetime import datetime, timedelta
from discord.ext import commands
import pytz

TOKEN = 'my token'
BOT_PREFIX = '?'
SEND_TIME = '16:40'  # 24小时制时间
MESSAGE_CHANNEL_ID = mychannelid  # 目标频道ID
SERVER_ID = myserverid  # 服务器ID

# 配置正确的Intents
intents = discord.Intents.default()
intents.members = True
intents.message_content = True  # 关键:开启消息内容读取权限
tz = pytz.timezone("US/Eastern")

async def time_check(bot):
    await bot.wait_until_ready()
    while not bot.is_closed():
        now = datetime.now(tz)
        current_time_str = now.strftime('%H:%M')
        print('当前时间:', current_time_str)
        
        if current_time_str == SEND_TIME:
            print('准备发送消息...')
            try:
                # 每次发送前重新获取频道对象,避免缓存失效
                message_channel = bot.get_channel(MESSAGE_CHANNEL_ID)
                if not message_channel:
                    message_channel = await bot.fetch_channel(MESSAGE_CHANNEL_ID)
                await message_channel.send("这是定时发送的消息。")
                print('消息发送成功')
            except Exception as e:
                print(f"发送消息出错: {e}")
            
            # 计算距离下一次发送的时间(等待24小时减去20秒,避免重复触发)
            next_run = now + timedelta(days=1)
            next_run = next_run.replace(hour=int(SEND_TIME.split(':')[0]), minute=int(SEND_TIME.split(':')[1]), second=0)
            wait_seconds = (next_run - now).total_seconds() - 20
            await asyncio.sleep(wait_seconds)
        else:
            # 每分钟检查一次,减少资源消耗(原1秒一次太频繁)
            await asyncio.sleep(60)

class MyCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def ping(self, ctx):
        await ctx.send('pong')

async def main():
    bot = commands.Bot(command_prefix=BOT_PREFIX, intents=intents)

    @bot.event
    async def on_ready():
        print(f"已登录为 {bot.user}")
        await bot.change_presence(activity=discord.Game(name="测试定时任务"))
        # 在机器人就绪后启动定时任务
        bot.loop.create_task(time_check(bot))

    await bot.add_cog(MyCog(bot))
    await bot.start(TOKEN)

if __name__ == '__main__':
    asyncio.run(main())

关键修复点说明

  • Intents配置:添加intents.message_content = True,并确保在Discord开发者后台的机器人页面开启"Message Content Intent"权限。
  • 定时任务启动:将time_check任务的启动移至on_ready事件中,确保机器人完全就绪后再启动定时任务。
  • 频道获取优化:每次发送消息前重新获取频道对象,优先使用缓存的get_channel,失败时用fetch_channel从API拉取,避免因缓存失效导致发送失败。
  • 时间等待优化:发送消息后计算下一次发送的时间差,避免短时间内重复发送,同时将检查频率从1秒一次改为1分钟一次,减少资源占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:23:15