提问者:小点点

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


我正在建立一个不和机器人,这将允许用户创建自定义命令。

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

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

注意:

>

  • Client.on监听频道,每次有人在聊天中说什么时,内容就会运行。

    !addcommand似乎运行正常,我能够确认这些行正在按预期写入文件。

    我不知道还能尝试什么。

    主文件:

    //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

    actual:commandList首次填充语句被触发


  • 共1个答案

    匿名用户

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

    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!");
    });