如果触发语句,如何更新对象键/值?

时间:2019-03-24 11:14:18

标签: javascript node.js object discord.js

我正在构建一个Discord机器人,该机器人将允许用户创建自定义命令。

它以这种方式工作,用户输入“!addcommand!commandname:command value”。然后,程序将拆分字符串,并将!commandname:command值添加到txt文件中。每当有人将!commandname键入不和谐时,该机器人就会将“命令值”输出到聊天中。

该程序应该在每当触发if语句时检查新命令是否存在。但是,这似乎只是在第一次运行程序时进行检查,这导致除非重新启动程序,否则无法识别新命令。

注意:

  1. Client.on收听频道,每次有人在聊天中说出内容时,内容就会运行。

  2. !add命令似乎正常运行,并且我能够确认这些行是否已按预期写入文件。

我不知道还能尝试什么。

主文件:

//Assume that requires etc are included


client.on('message', message => {

  const pingCheck = message.content.charAt(0);
  const commandCheck = message.content.split(" ");

  if (pingCheck === "!") {
    //Populates the list of custom commands. Must be done on every check, or new commands will not be recognized.
    //Currently, this seems to only update once the service/program is restarted
    var commandList = customCommands.returnPhrase();

    //If the commandList object contains the correct key (stored in commandCheck[0]) such as !commandname, the bot will send the value "command value" as a string to the discord chat.
    if (commandList.hasOwnProperty(commandCheck[0])) {
      message.channel.send(commandList[commandCheck[0]]);
    } 

    //If the key does not exist, the program then checks predefined commands. Other commands exist here, but for the purposes of this question I'll show only the !addcommand, which is used to create a new custom command.
    else {
            switch (commandCheck[0]) {
        case "!addcommand":

        //This checks that the command is formatted properly, "!commandname:commandvalue". If it does not start with ! or contain : somewhere in the string, it's probably an invalid format.
        //Technically this still allows for a !:commandvalue format. I haven't implemented a check for this yet.
                if (commandCheck[1].startsWith("!") && commandCheck[1].includes(":")) {

                  //While loop reconstructs the command key to be passed in, ignores slot 0 as this is the !addcommand
                  var gs = "";
                  var x = 1;

                  while (x < commandCheck.length) {
                      gs += gs +commandCheck[x] + " ";
                      x++;
                  }

                  gs = gs.slice(0,-1)+"\r\n"; //removes the last " " from the input string, and adds line-break

                  addCommands.addPhrase(gs);//passes reconstructed command to be added to commandlist.txt
                  message.channel.send("I have added " + commandCheck[1] + " to the command list.");

          break;
          }

        default:
          message.channel.send("I dont recognize that command.");

      }
    }
  }      
});

添加命令的模块:

const fs = require('fs');

var createCommand = {

    addPhrase: function(x) {
        fs.appendFile("commandlist.txt", x, function(err){
            if(err) throw err;
            console.log(err)
        });
    }

}

module.exports = createCommand;

填充自定义命令列表的模块:

const fs = require('fs');

var commandFile = fs.readFileSync('commandlist.txt','utf8');
var dataSplit = commandFile.split("\r\n");

var readCommand = {
    returnPhrase: function(){
        var splitSplit = {};
        var i = 0;

        //populates splitSplit with keys and values based on text file
        while (i<dataSplit.length){
            var newKey = dataSplit[i].split(':');
            splitSplit[newKey[0]] = newKey[1];
            i++
        };

        return splitSplit;
    },
};

module.exports = readCommand;

更好的可读性:https://repl.it/repls/DarkvioletDeafeningAutomaticparallelization

预期:每次触发语句时都会填充commandList

实际:commandList会在第一次触发语句时填充

1 个答案:

答案 0 :(得分:0)

只要有新命令出现,您就写入文件,但是在服务器启动时只从文件中读取一次,因此不会跟踪更改(直到重新启动服务器后,它将再次读取文件)。现在,从理论上讲,您现在可以侦听文件更改,然后重新加载,但这使事情变得过于复杂,文件系统并不能实现这一目标。而是将命令保留在一个对象中,并导出一些添加/检查的方法:

let commands = {};

// ¹

module.exports = {
 addCommand(key, value) {
   commands[key] = value;
   // ²
 },
 getValue(key) {
   return commands[key];
 }
};

现在,当您添加命令时,它会直接添加到对象中,然后可以直接将其读出。


现在,由于对象在重新启动后不会持久存在,因此您将丢失所有命令。但这很容易解决:只要将对象更新,就可以将其反映到文件中,然后在每次启动时将其加载。与其为此创建自定义格式,不如使用JSON。上面的代码可以轻松扩展:

// ¹
try {
 commands = JSON.parse( fs.readFileSync("commands.txt") );
} catch(e) { /* ignore if file doesnt exist yet */ }

// ²
fs.writeFile("commands.txt", JSON.stringify(commands), err => {
  if(err) console.error(err);
});

我如何编写机器人:

const playerCommands = require("./commands.js");

const defaultCommands = {
   addCommand(...pairs) {
    let result = "";
    for(const pair of pairs) {
       const [name, value] = pair.split(":");
       playerCommands.addCommand(name, value);
       result += `${name} added with value ${value}\n`;
    }
   return result;     
   }
};

client.on('message', ({ content, channel }) => {     
  if(content[0] !== "!") return; // ignore non-commandd

  const [commandName, ...args] = content.slice(1).split(" ");

  if(defaultCommands[commandName]) 
    return channel.send(defaultCommands[commandName](...args));

  const value = playerCommands.getValue(commandName);
  if(value) return channel.send(value);

  return channel.send("Command not found!");
});