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

如何创建可记录消息、编辑等内容到文本文件的Python Discord机器人?

社团Discord日志机器人实现方案

嘿,我来帮你搞定这个用于社团服务器的日志机器人!既然你已经了解on_message()的基本用法,那咱们直接切入正题,一步步实现全量内容的记录功能。

1. 基础准备

首先确保你已经安装了discord.py库(推荐用v2.x版本,API更稳定):

pip install discord.py

另外,机器人需要在Discord开发者平台开启以下核心权限(邀请机器人时务必勾选):

  • 读取消息/查看频道
  • 查看服务器邀请
  • 消息内容意图(这个是读取消息文本的关键,必须在开发者平台的"Privileged Gateway Intents"里手动开启)

2. 捕获并记录普通消息

在on_message()事件里,message对象包含了所有你需要的消息细节,直接调用属性就能获取:

  • message.content: 消息的文本内容
  • message.author: 发送者的用户信息(用户名、ID等)
  • message.channel: 消息所在频道(名称、ID)
  • message.created_at: 消息发送时间

写入日志时用追加模式,避免覆盖历史记录,同时指定utf-8编码防止乱码:

import discord
from datetime import datetime

# 配置机器人意图,必须开启消息内容和消息相关权限
intents = discord.Intents.default()
intents.message_content = True
intents.messages = True

client = discord.Client(intents=intents)

# 封装日志写入函数,复用性更强
def write_log(log_content):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    with open("discord_guild_logs.txt", "a", encoding="utf-8") as f:
        f.write(f"[{timestamp}] {log_content}\n")

@client.event
async def on_message(message):
    # 跳过机器人自己的消息,避免循环记录
    if message.author.bot:
        return
    
    # 构造结构化日志内容,方便教师查看
    log_text = f"普通消息 | 用户: {message.author.name}({message.author.id}) | 频道: {message.channel.name}({message.channel.id}) | 内容: {message.content}"
    write_log(log_text)

# 替换成你的机器人TOKEN
client.run("你的机器人TOKEN")

3. 记录消息编辑操作

用on_message_edit事件捕获编辑行为,它会返回编辑前(before)和编辑后(after)的消息对象,只有内容真正变化时才记录:

@client.event
async def on_message_edit(before, after):
    if before.author.bot:
        return
    
    if before.content != after.content:
        log_text = f"消息编辑 | 用户: {before.author.name}({before.author.id}) | 频道: {before.channel.name}({before.channel.id}) | 原内容: {before.content} | 新内容: {after.content}"
        write_log(log_text)

4. 记录消息删除操作

通过on_message_delete事件捕获被删除的消息,直接提取消息的历史内容:

@client.event
async def on_message_delete(message):
    if message.author.bot:
        return
    
    log_text = f"消息删除 | 用户: {message.author.name}({message.author.id}) | 频道: {message.channel.name}({message.channel.id}) | 被删内容: {message.content}"
    write_log(log_text)

5. 捕获邀请链接(两种场景)

场景1:用户发送的邀请链接

在on_message里用正则匹配消息中的Discord邀请链接:

import re

@client.event
async def on_message(message):
    if message.author.bot:
        return
    
    # 匹配所有格式的Discord邀请链接
    invite_pattern = r"(https?://)?(discord\.gg|discord\.com/invite)/([a-zA-Z0-9]+)"
    invites = re.findall(invite_pattern, message.content)
    if invites:
        # 拼接完整的邀请链接
        full_invites = [f"{prefix}{domain}/{code}" for prefix, domain, code in invites]
        invite_log = f"邀请链接发送 | 用户: {message.author.name}({message.author.id}) | 频道: {message.channel.name}({message.channel.id}) | 链接: {', '.join(full_invites)}"
        write_log(invite_log)
    
    # 别忘了记录普通消息
    message_log = f"普通消息 | 用户: {message.author.name}({message.author.id}) | 频道: {message.channel.name}({message.channel.id}) | 内容: {message.content}"
    write_log(message_log)

场景2:新创建的服务器邀请

如果要捕获管理员后台创建的邀请(不管有没有发到频道),需要开启服务器意图,用on_invite_create事件:

intents.guilds = True  # 开启服务器相关意图

@client.event
async def on_invite_create(invite):
    creator = invite.inviter.name if invite.inviter else "未知用户"
    creator_id = invite.inviter.id if invite.inviter else "未知ID"
    log_text = f"邀请链接创建 | 创建者: {creator}({creator_id}) | 服务器: {invite.guild.name}({invite.guild.id}) | 链接: {invite.url} | 有效期: {invite.max_age//3600}小时 | 最大使用次数: {invite.max_uses}"
    write_log(log_text)

6. 日志优化建议

  • 按日期分割日志文件(比如每天生成discord_logs_20240520.txt),避免单文件过大
  • 给日志文件设置权限,确保只有授权教师能读取
  • 如果需要更规范的格式,可以用JSON格式写入日志,方便后续导出分析

完整整合代码

把所有功能整合起来,就是一个开箱即用的日志机器人:

import discord
import re
from datetime import datetime

intents = discord.Intents.default()
intents.message_content = True
intents.messages = True
intents.guilds = True

client = discord.Client(intents=intents)

def write_log(log_content):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    with open("discord_guild_logs.txt", "a", encoding="utf-8") as f:
        f.write(f"[{timestamp}] {log_content}\n")

@client.event
async def on_ready():
    print(f"已登录为 {client.user},开始记录社团服务器日志...")
    write_log(f"机器人上线 | 账号: {client.user.name}({client.user.id})")

@client.event
async def on_message(message):
    if message.author.bot:
        return
    
    # 检测邀请链接
    invite_pattern = r"(https?://)?(discord\.gg|discord\.com/invite)/([a-zA-Z0-9]+)"
    invites = re.findall(invite_pattern, message.content)
    if invites:
        full_invites = [f"{prefix}{domain}/{code}" for prefix, domain, code in invites]
        write_log(f"邀请链接发送 | 用户: {message.author.name}({message.author.id}) | 频道: {message.channel.name}({message.channel.id}) | 链接: {', '.join(full_invites)}")
    
    # 记录普通消息
    write_log(f"普通消息 | 用户: {message.author.name}({message.author.id}) | 频道: {message.channel.name}({message.channel.id}) | 内容: {message.content}")

@client.event
async def on_message_edit(before, after):
    if before.author.bot or before.content == after.content:
        return
    write_log(f"消息编辑 | 用户: {before.author.name}({before.author.id}) | 频道: {before.channel.name}({before.channel.id}) | 原内容: {before.content} | 新内容: {after.content}")

@client.event
async def on_message_delete(message):
    if message.author.bot:
        return
    write_log(f"消息删除 | 用户: {message.author.name}({message.author.id}) | 频道: {message.channel.name}({message.channel.id}) | 被删内容: {message.content}")

@client.event
async def on_invite_create(invite):
    creator = invite.inviter.name if invite.inviter else "未知用户"
    creator_id = invite.inviter.id if invite.inviter else "未知ID"
    write_log(f"邀请链接创建 | 创建者: {creator}({creator_id}) | 服务器: {invite.guild.name}({invite.guild.id}) | 链接: {invite.url} | 有效期: {invite.max_age//3600}小时 | 最大使用次数: {invite.max_uses}")

client.run("YOUR_BOT_TOKEN_HERE")

最后提醒:部署前一定要确认学校的隐私政策,确保日志记录符合相关规定,只对授权教师开放日志访问权限哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:38:55