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

如何用Discord.py实现频道底部常驻Sticky message并删除旧消息?

实现Discord Bot的粘性消息(Sticky Message)功能

你当前代码的核心问题有两个:一是试图删除Embed对象而非实际发送的Message实例,二是没有持久化存储粘性消息的ID,导致无法动态追踪旧消息。以下是分步解决方案:

1. 修复基础删除逻辑

原代码中new_embed是嵌入消息的对象,并非发送到频道后的消息实例,调用delete()会报错。正确做法是先获取旧的粘性消息实例,发送新消息后删除旧消息:

import discord

@bot.event
async def on_message(message):
    target_channel_id = 1206246422324715580
    if message.channel.id != target_channel_id:
        return
    if message.author == bot.user:
        return
    
    # 硬编码旧粘性消息ID(后续会优化)
    old_sticky_msg_id = 1208866913426473021
    try:
        # 获取旧的粘性消息
        old_sticky_msg = await message.channel.fetch_message(old_sticky_msg_id)
        # 复制嵌入内容
        new_embed = old_sticky_msg.embeds[0].copy()
        # 发送新的粘性消息
        await message.channel.send(embed=new_embed)
        # 删除旧的粘性消息
        await old_sticky_msg.delete()
    except discord.NotFound:
        # 处理旧消息被手动删除的情况
        await message.channel.send(embed=discord.Embed(title="默认粘性消息"))

2. 用JSON持久化优化(替代硬编码)

硬编码消息ID和频道ID扩展性差,用JSON文件存储每个频道对应的粘性消息ID,支持多频道且动态更新:

第一步:创建配置文件

新建sticky_config.json,结构如下:

{
  "1206246422324715580": 1208866913426473021
}

第二步:优化代码

import discord
import json

# 加载配置文件
def load_sticky_config():
    try:
        with open("sticky_config.json", "r", encoding="utf-8") as f:
            return json.load(f)
    except FileNotFoundError:
        return {}

# 保存配置文件
def save_sticky_config(config):
    with open("sticky_config.json", "w", encoding="utf-8") as f:
        json.dump(config, f, indent=2, ensure_ascii=False)

# 初始化配置
sticky_config = load_sticky_config()

@bot.event
async def on_message(message):
    channel_id_str = str(message.channel.id)
    # 只处理配置过的频道
    if channel_id_str not in sticky_config:
        return
    # 忽略Bot自身发送的消息
    if message.author == bot.user:
        return
    
    old_sticky_msg_id = sticky_config[channel_id_str]
    try:
        old_sticky_msg = await message.channel.fetch_message(old_sticky_msg_id)
        # 复制嵌入内容
        new_embed = old_sticky_msg.embeds[0].copy()
        # 发送新消息并记录实例
        new_sticky_msg = await message.channel.send(embed=new_embed)
        # 删除旧消息
        await old_sticky_msg.delete()
        # 更新配置中的消息ID为新的
        sticky_config[channel_id_str] = new_sticky_msg.id
        save_sticky_config(sticky_config)
    except discord.NotFound:
        # 旧消息不存在时,发送默认嵌入并更新配置
        default_embed = discord.Embed(
            title="粘性消息",
            description="此消息会始终保持在频道底部"
        )
        new_sticky_msg = await message.channel.send(embed=default_embed)
        sticky_config[channel_id_str] = new_sticky_msg.id
        save_sticky_config(sticky_config)

3. 进阶:用数据库存储(可选)

如果需要支持大量频道或更稳定的存储,可以用SQLite替代JSON,示例代码片段:

import sqlite3

# 初始化数据库
conn = sqlite3.connect("sticky_messages.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS sticky (channel_id TEXT PRIMARY KEY, message_id INTEGER)")
conn.commit()

# 获取频道对应的粘性消息ID
def get_sticky_msg_id(channel_id):
    cursor.execute("SELECT message_id FROM sticky WHERE channel_id = ?", (str(channel_id),))
    result = cursor.fetchone()
    return result[0] if result else None

# 更新粘性消息ID
def update_sticky_msg_id(channel_id, message_id):
    cursor.execute("REPLACE INTO sticky (channel_id, message_id) VALUES (?, ?)", (str(channel_id), message_id))
    conn.commit()

将上述函数整合到之前的on_message事件中即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 10:02:41