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

如何用discord.js开发监控FTP日志变动并同步到Discord的机器人

基于discord.js的FTP日志同步机器人实现方案

依赖安装

需要提前安装以下npm包:

  • discord.js@14:Discord机器人核心开发库
  • basic-ftp:轻量FTP服务操作库
  • diff:文本差异对比工具,用于提取日志新增内容

核心逻辑说明

因为FTP协议没有主动推送文件变动的能力,我们采用定时轮询的方案实现变动检测:

  1. Discord机器人登录成功后,缓存目标推送频道的实例
  2. 按设定间隔向FTP服务器发起请求,拉取目标日志文件的最后修改时间、文件大小元信息
  3. 对比本次和上一次拉取的元信息,没有变动直接结束本次轮询
  4. 检测到变动后拉取最新日志内容,和本地存储的上一版日志做差异对比,只提取新增的内容段
  5. 将新增内容按Discord单条消息2000字符的限制做拆分,用代码块格式批量推送到指定频道,同时更新本地存储的日志内容和元信息

核心实现代码

const { Client, GatewayIntentBits } = require('discord.js');
const ftp = require('basic-ftp');
const { diffTrimmedLines } = require('diff');

// 配置项,可根据实际情况修改
const CONFIG = {
  DISCORD_TOKEN: '你的Discord机器人Token',
  TARGET_CHANNEL_ID: '目标推送频道的ID',
  FTP_CONFIG: {
    host: 'FTP服务器地址',
    port: 21,
    user: 'FTP登录用户名',
    password: 'FTP登录密码',
    logPath: '/server/running.log' // FTP上日志文件的完整路径
  },
  POLL_INTERVAL: 5000 // 轮询间隔,单位毫秒,此处为5秒
};

// 初始化Discord客户端
const client = new Client({
  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]
});

let targetChannel;
let lastLogContent = '';
let lastFileMtime = 0;

// 机器人就绪后启动轮询任务
client.on('ready', async () => {
  console.log(`机器人已登录:${client.user.tag}`);
  targetChannel = await client.channels.fetch(CONFIG.TARGET_CHANNEL_ID);
  setInterval(pollFtpLog, CONFIG.POLL_INTERVAL);
});

// FTP日志轮询函数
async function pollFtpLog() {
  const ftpClient = new ftp.Client();
  try {
    await ftpClient.access(CONFIG.FTP_CONFIG);
    // 获取日志文件的最后修改时间
    const currentMtime = (await ftpClient.lastMod(CONFIG.FTP_CONFIG.logPath)).getTime();
    // 文件未变动直接退出
    if (currentMtime === lastFileMtime) return ftpClient.close();
    lastFileMtime = currentMtime;

    // 拉取最新日志内容
    const logBuffer = await ftpClient.downloadToBuffer(CONFIG.FTP_CONFIG.logPath);
    const newLogContent = logBuffer.toString('utf8');
    // 首次拉取只存内容不推送
    if (!lastLogContent) {
      lastLogContent = newLogContent;
      return ftpClient.close();
    }

    // 提取新增日志内容
    const diffResult = diffTrimmedLines(lastLogContent, newLogContent);
    const addedContent = diffResult.filter(item => item.added).map(item => item.value).join('\n');
    
    if (addedContent.trim()) {
      // 按Discord消息长度限制拆分后推送
      const msgChunks = addedContent.match(/[\s\S]{1,1900}/g) || [];
      for (const chunk of msgChunks) {
        await targetChannel.send(`\`\`\`log\n${chunk}\`\`\``);
      }
    }
    lastLogContent = newLogContent;
  } catch (err) {
    console.error('轮询出错:', err);
  } finally {
    ftpClient.close();
  }
}

client.login(CONFIG.DISCORD_TOKEN);

优化建议

  • 轮询间隔不要设置过短,避免给FTP服务器造成过大压力,建议最低设置为3秒以上
  • 如果日志文件体积很大,可改为按字节范围拉取新增内容,对比上一次记录的文件大小,只拉取大于上一次大小的字节段,不需要全量下载
  • 可自行添加日志内容过滤逻辑,去掉不需要推送的无关日志行,减少频道消息噪音
  • 如果日志文件为GBK编码,可引入iconv-lite库对拉取到的Buffer做转码,避免出现乱码
  • 可添加错误重试机制,FTP连接失败或Discord消息推送失败时自动重试

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:09:04