Как я могу обновить ключи / значения объекта, если оператор if запущен? - PullRequest
0 голосов
/ 24 марта 2019

Я создаю бот Discord, который позволит пользователям создавать собственные команды.

Он работает таким образом, что пользователь вводит "! Addcommand! Commandname: command value".Затем программа разделит строку и добавит! Commandname: command value в текстовый файл.Всякий раз, когда кто-то вводит! Commandname в разногласия, бот выводит «значение команды» в чат.

Программа должна проверять, существует ли новая команда при каждом запуске оператора if.Однако, похоже, что это проверка только при первом запуске программы, что приводит к тому, что новые команды не распознаются, пока программа не будет перезапущена.

Примечание:

  1. Client.on прослушивает канал, и его содержимое запускается каждый раз, когда кто-то что-то говорит в чате.

  2. ! Команда 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 заполняется каждый раз, если операторtriggered

Actual: commandList заполняется при первом запуске оператора

1 Ответ

0 голосов
/ 24 марта 2019

Вы записываете в файл каждый раз, когда приходит новая команда, однако вы только один раз читаете из него при запуске сервера, поэтому вы не будете отслеживать изменения (пока вы не перезапустите сервер, который снова прочитает файл). Теперь вы можете теоретически прислушиваться к файловым обменам и перезагружать их, но это слишком усложняет ситуацию, файловая система не предназначена для этого. Вместо этого просто сохраните ваши команды в объекте и экспортируйте несколько методов для добавления / проверки:

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!");
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...