You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Discord.js实现忽略标点检测末尾独立完整单词及代码优化

优化Discord机器人的触发逻辑:精准匹配句末/独立消息的目标单词

问题描述

我想要实现一个Discord机器人,当消息包含特定单词(满足位于句末、单独成消息,忽略标点)时触发响应,但如果单词和其他单词粘连(比如"Eyes"里的"yes")则不响应。举个例子:目标单词是"yes"时,"I said yes !"、"Yes"会触发,"Eyes"不会。

我当前的实现代码如下:

const Discord = require('discord.js');
const client = new Discord.Client();
client.once('ready', () => {
 console.log(`Online`);
});
const responseObject = { "yes": "ok !", "no": "potato !" };
client.on('message', message => {
 var regex = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;
 var regexx = /[ \t]+$/g;
 message.content = message.content.toLowerCase();
 message.content = message.content.replace(regex, '')
 message.content = message.content.replace(regexx, '')
 if(responseObject[message.content]) {
 message.channel.send(responseObject[message.content]);
 }
});

想问问有没有更优的代码优化方案?


优化方案

嘿,你的思路方向是对的,但确实有更简洁、更健壮的优化方式,主要可以从正则匹配的精准性和代码简洁性入手:

1. 用单个正则完成精准匹配,减少冗余操作

你的现有代码是通过多次字符串替换来清理内容,再做完全匹配,但其实可以直接用一个正则表达式,一次性判断目标单词是否是消息的最后一个有效部分——不管后面有没有标点或空格,同时还能避免匹配粘连的单词。

优化后的代码如下:

const Discord = require('discord.js');
const client = new Discord.Client();

client.once('ready', () => {
 console.log(`Online`);
});

const responseObject = { "yes": "ok !", "no": "potato !" };
// 提取所有目标单词,构建动态正则
const targetWords = Object.keys(responseObject);
// 正则说明:
// ^.*? :非贪婪匹配开头的任意内容(避免吃掉前面的字符)
// \b(${targetWords.join('|')})\b :匹配完整的目标单词(\b是词边界,防止粘连)
// [\s\p{P}]*$ :匹配末尾任意数量的空格或Unicode标点(覆盖所有语言的标点)
// 'i' :忽略大小写,不用手动转小写
const matchRegex = new RegExp(
  `^.*?\\b(${targetWords.join('|')})\\b[\\s\\p{P}]*$`,
  'i'
);

client.on('message', message => {
  // 跳过机器人自身的消息,防止循环触发
  if (message.author.bot) return;

  const matchResult = message.content.match(matchRegex);
  if (matchResult) {
    // 转小写后匹配响应对象
    const matchedWord = matchResult[1].toLowerCase();
    message.channel.send(responseObject[matchedWord]);
  }
});

// 别忘了加上登录逻辑(实际运行需要你的token)
// client.login('YOUR_BOT_TOKEN');

2. 关键优化点拆解

  • 词边界\b:这是避免匹配粘连单词的核心——它会确保匹配的是独立单词,像"Eyes"里的"yes"就不会被触发,完美符合你的需求。
  • Unicode标点\p{P}:比你手动列举的标点全面得多,能覆盖中文、日文等各种语言的标点符号,不用再担心漏处理特殊标点。
  • 忽略大小写标志i:直接让正则处理大小写匹配,省去了手动将整个消息转小写的步骤,代码更简洁。
  • 跳过机器人消息:新增的if (message.author.bot) return;能避免机器人自己发送的消息触发响应,防止出现无限循环的问题。
  • 动态正则构建:如果后续要添加更多目标单词,只需要修改responseObject,正则会自动更新,扩展性更强。

3. 额外的小建议

  • 始终使用const/let代替var,符合现代JavaScript规范,避免变量提升带来的潜在问题。
  • 记得补充机器人的登录代码(client.login('YOUR_BOT_TOKEN')),不然机器人无法上线运行。

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

火山引擎 最新活动