搜索不和谐消息以设置过滤器

时间:2020-09-27 16:00:59

标签: javascript discord discord.js

我正在尝试在Discord消息中搜索匹配的词组,然后使用该词组为过滤后的数组设置过滤器-当我仅搜索一个词组时它可以工作,但对于多个词组却不起作用或没有输入任何短语时(如果没有匹配的短语,我希望它没有过滤器)-任何帮助都将受到赞赏!

module.exports = { 
    name: 'mission', 
    description: 'Randomly selects a mission', 

     execute(message, args) { 

       let missionArray = [
           {
               name: "Incisive Attack",
               size: "Combat Patrol",
               type: "Eternal War",
               source: "BRB",
               page: "286"
               
           },
           {
            name: "Outriders Attack",
            size: "Combat Patrol",
            type: "Eternal War",
            source: "BRB",
            page: "287"
            
        },
       //more missions here
            ];
            if (message.content.match('Combat Patrol')) {
                let filter = {size:"Combat Patrol"};
            } else if (message.content.match('Incursion')) {
                let filter = {size:"Incursion"};
            } else if (message.content.match('Strike Force')) {
                let filter = {size:"Strike Force"}
            } else if (message.content.match('Onslaught')) {
                let filter = {size:"Onslaught"};
                    
                let filteredMission = missionArray.filter(function(item) {
                for (var key in filter) {
                    if (item[key] === undefined || item[key] != filter[key])
                    return false;
                }
                return true;
                });
            
            let mission = filteredMission[Math.floor(Math.random() * filteredMission.length)];
       

       return message.reply(`I have consulted the mission8Ball and you will play:\n**${mission.name}**\nMission Type: ${mission.type}\nBattle Size: ${mission.size}\nSource: ${mission.source}\nPage: ${mission.page}`); 
            }
}
};

我还想为来源和类型设置过滤器。

谢谢!

2 个答案:

答案 0 :(得分:1)

好吧,我基本上已经重写了您的命令,但有些过分了,但是我相信它将使您更轻松地管理和添加新任务。

说明将包含在代码的注释中。如果您有意见,我会尽力回答。需要注意的主要事情是,过滤器仅在option_values中创建的可能选项中才组合数据进行过滤。如果某人想按不存在的功能进行过滤,则不会将其添加到过滤器中,因此,按size = "AAAAAAAAAAAAA"进行过滤与完全不按大小进行过滤相同。

let missionArray = [
           {
               name: "Incisive Attack",
               size: "Combat Patrol",
               type: "Eternal War",
               source: "BRB",
               page: "286"
               
           },
           {
            name: "Outriders Attack",
            size: "Combat Patrol",
            type: "Eternal War",
            source: "BRB",
            page: "287"
            },
                    {   //sorry made my own for testing
                        name: "Test",
                        size: "Incursion",
                        type: "Short war",
                        source: "BRB",
                        page: "300"
                    },
                    {
                        name: "Test2",
                        size: "Incursion",
                        type: "other type",
                        source: "BRB",
                        page: "301"
                    }
];

let options = [ //what our users can enter in a message to set their filters
    "size:", "type:", "source:"
];
//I could've crunched these two into one dictionary but I feel like this way is easier to read and understand
let option_values = { //all the possible values for our filters they can set (ALL LOWERCASE!!!)
    size: [
        "combat Patrol", "incursion", "strike force", "onslaught"
    ],
    source: [
        "brb"
    ],
    type: [
        "eternal war", "other type"
    ], //continue on...
};

//enter array of filtered missions, get one random out
let chooseMission = function (missions) {   //courtesy of user rafaelcastrocouto
    let mission = missions[Math.floor(Math.random() * missions.length)];
    return mission;
}

const regex = new RegExp('"[^"]+"|[\\S]+', 'g'); //We need to parse arguments for filters that might contain multiple words, like "Eternal War". You don't need to understand this exactly. I got it from here https://stackoverflow.com/questions/50671649/capture-strings-in-quotes-as-single-command-argument

module.exports = { 
    name: 'mission', 
    description: 'Randomly selects a mission', 
        execute(message, args) { 
            //this snippet parses our arguments to allow multi words like 'Eternal War'.
            args = [];
            message.content.match(regex).forEach(arg => {
                if (!arg) return;
                args.push(arg.replace(/"/g, ''));
            });

            let filter = {} //create a dictionary of information we'll filter by later
            for (let i = 0; i < args.length; i++) { //loop over each argument
                let cmd = args[i];  //This entire block will define that the message !mission size: "Combat Patrol" type: "Eternal War"
                                    //will be parsed as cmd = "size:", param = "Combat Patrol" in one loop then cmd = "type:", param = "Eternal War" in the next
                if (options.includes(cmd)) {    //if our argument is one of our predefined options ("size:", "type:")
                    let param = args[i+1]; 
                    let key = cmd.slice(0, -1).toLowerCase(); //cut off the last character of our cmd (":"), make it lower for safety
                    if (option_values[key].includes(param.toLowerCase())) { //if the parameter we gave ("Incursion", etc) is an option we can use for our filter (size, etc)
                        filter[key] = param;    //use key as the key in our filter dictionary to match size to size.
                    } else {
                        message.reply(`Unknown parameter for ${key}: ${param}`)
                    }
                }
            }
            let filtered = missionArray.filter(item => { //item is a mission that contains properties like size, type...
                for (let key in filter) {   //our keys are already lowercase, try to keep them that way
                    if (item[key] === undefined || item[key].toLowerCase() != filter[key].toLowerCase())
                        return false;
                }
                return true;
            });

            if (filtered.length == 0) { //if nothing passed the filter (note: this only counts if someone passed a valid option. If someone passes gibberish like "anafbia" for size, the filter wont try and search for matching sizes.
                filtered = missionArray; //select our pool of "filtered" missions to be the entire array
                message.reply("Can't find a mission matching your parameters.");
            }
            let mission = chooseMission(filtered);
            message.reply(`I have consulted the mission8Ball and you will play:\n**${mission.name}**\nMission Type: ${mission.type}\nBattle Size: ${mission.size}\nSource: ${mission.source}\nPage: ${mission.page}`);
    }
};

这是我测试命令的结果:

//set: these inputs should come back with missions
input:
!mission type: "other type" size: "incursion"

output:
@Allister, I have consulted the mission8Ball and you will play:
Test2
Mission Type: other type
Battle Size: Incursion
Source: BRB
Page: 301

input:
!mission type size: incursion type: "other type"

output:
@Allister, I have consulted the mission8Ball and you will play:
Test2
Mission Type: other type
Battle Size: Incursion
Source: BRB
Page: 301

//set: this input should only filter by eternal war due to malformed parameters
input:
!mission type size: wrong thing type: "eternal war"

output:
@Allister, Unknown parameter for size: wrong
@Allister, I have consulted the mission8Ball and you will play:
Incisive Attack
Mission Type: Eternal War
Battle Size: Combat Patrol
Source: BRB
Page: 286


//set: this input provides a correct parameter but there are no missions that match it, so it returns random
input:
!mission size: "Strike Force"

output:
@Allister, Can't find a mission matching your parameters.
@Allister, I have consulted the mission8Ball and you will play:
Incisive Attack
Mission Type: Eternal War
Battle Size: Combat Patrol
Source: BRB
Page: 286

and of course, !mission alone will just return a random mission as well.

答案 1 :(得分:0)

这是使用简单的for循环解决您的问题的一种方法。 我还将随机选择移到一个函数(chooseMission)中,以避免在“无内容”情况下重复代码。

module = {};
module.exports = {
  name: 'mission',
  description: 'Randomly selects a mission',

  execute(message, args) {

    let missionArray = [{
        name: "Incisive Attack",
        size: "Combat Patrol",
        type: "Eternal War",
        source: "BRB",
        page: "286"

      },
      {
        name: "Outriders Attack",
        size: "Combat Patrol",
        type: "Eternal War",
        source: "BRB",
        page: "287"

      },
      {
        name: "Incursion Attack",
        size: "Incursion",
        type: "Eternal War",
        source: "BRB",
        page: "287"

      }
    ];
    
    let filters = [
      'Combat Patrol',
      'Incursion',
      'Strike Force',
      'Onslaught'
    ];
    
    let chooseMission = function (missions) {
      let mission = missions[Math.floor(Math.random() * missions.length)];
      return message.reply(`I have consulted the mission8Ball and you will play:\n**${mission.name}**\nMission Type: ${mission.type}\nBattle Size: ${mission.size}\nSource: ${mission.source}\nPage: ${mission.page}`);
    }

    for (let f=0; f<filters.length; f++) {
      let filterStr = filters[f];
      
      if (!message.content) {
        return chooseMission(missionArray);
        
      } else if (message.content.match(filterStr)) {
        let filter = {
          size: filterStr
        };

        let filteredMission = missionArray.filter(function(item) {
          for (var key in filter) {
            if (item[key] === undefined || item[key] != filter[key])
              return false;
          }
          return true;
        });

        return chooseMission(filteredMission);
      }
    }
  }
};

module.exports.execute({
  content: '',
  reply: function (mission) {
    console.log(mission);
  }
});