#Help with autocomplete and JSON.

38 messages · Page 1 of 1 (latest)

ashen tinsel
#

This code searches within 3 JSONS (This will change at the end) it searches the keys "text" (name) and "reference" (Page in book.)

As it is I need to type the exact word for the search, I would like to use the autocomplete feature but it needs to search within the jsons. The search system I did only searches the exact words. They could help me with that. ?

const fs = require("fs");
const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");

function filtrarDadosComPalavraChave(objetos, palavraChave, resultados) {
  objetos.forEach((objeto) => {
    if (objeto.children) {
      filtrarDadosComPalavraChave(objeto.children, palavraChave, resultados);
    } else {
      // Verifique se as propriedades 'text' e 'reference' existem antes de acessá-las
      if (
        objeto.text &&
        objeto.reference &&
        (objeto.text.includes(palavraChave) ||
          objeto.reference.includes(palavraChave))
      ) {
        resultados.push(objeto);
      }
    }
  });
}

function carregarDados() {
  const dadosPadrao = require("../JSONS/rules.json");
  const dadosMas = require("../JSONS/rules_ma.json");
  const dadosMagic = require("../JSONS/rules_m.json");

  const dadosCombinados = [
    ...dadosPadrao.rows,
    ...dadosMas.rows,
    ...dadosMagic.rows,
  ];

  return dadosCombinados;
}

module.exports = {
  data: new SlashCommandBuilder()
    .setName("rules")
    .setDescription("Verificar página relacionada com a regra.")
    .addStringOption((option) =>
      option
        .setName("rule")
        .setDescription("A palavra-chave para pesquisa.")
        .setRequired(true)
    ),

  async execute(interaction) {
    const palavraChave = interaction.options.getString("rule");

    const dados = carregarDados();

    const resultados = [];
    filtrarDadosComPalavraChave(dados, palavraChave, resultados);

    if (resultados.length === 0) {
      const embed = new EmbedBuilder()
   
indigo hatchBOT
#
  • What's your exact discord.js npm list discord.js and node node -v version?
  • Not a discord.js issue? Check out #1081585952654360687.
  • Consider reading #how-to-get-help to improve your question!
  • Explain what exactly your issue is.
  • Post the full error stack trace, not just the top part!
  • Show your code!
  • Issue solved? Press the button!
elder stump
#

You already use includes; that should match part of the word too, unless they are arrays?

silver viperBOT
#

mdn String.prototype.includes()
The includes() method of String values performs a case-sensitive search to determine whether a given string may be found within this string, returning true or false as appropriate.

ashen tinsel
# elder stump You already use includes; that should match part of the word too, unless they ar...

they are nested

{
    "type": "note_list",
    "version": 4,
    "rows": [
        {
            "id": "1f05daa9-67cc-4d3f-a0b9-96185664f7e8",
            "type": "note_container",
            "open": true,
            "children": [
                {
                    "id": "c07164b3-b73b-4428-945b-300078bd5255",
                    "type": "note",
                    "text": "When to Roll",
                    "reference": "BX343"
                },
                {
                    "id": "eeabb12c-4329-474c-8b2d-eadba1ca0ad7",
                    "type": "note",
                    "text": "Base Skill vs Effective Skill",
                    "reference": "BX344"
                },
                {
                    "id": "346b3eae-5212-4e37-b861-55209aef86ba",
                    "type": "note",
                    "text": "Modifiers",
                    "reference": "BX344"
                },
                {
                    "id": "33bbd880-7778-4860-bcb1-05f752ee984b",
                    "type": "note",
                    "text": "Sidebar: Default Rolls",
                    "reference": "BX344"
                },
....

#

I tryied it more simple

const { SlashCommandBuilder } = require("discord.js");
const fs = require("fs");

function extractTextFromNotes(notes, result = []) {
  notes.forEach((note) => {
    if (note.type === "note") {
      result.push(note.text);
    } else if (note.children) {
      extractTextFromNotes(note.children, result);
    }
  });
}

module.exports = {
  data: new SlashCommandBuilder()
    .setName("autocomplete")
    .setDescription("autocomplete")
    .addStringOption((option) =>
      option
        .setName("query")
        .setDescription("Input a query")
        .setRequired(true)
        .setAutocomplete(true)
    ),
  async autocomplete(interaction) {
    const value = interaction.options.getString("query").toLowerCase();

    // Carrega o conteúdo do arquivo JSON
    const jsonData = fs.readFileSync("../JSONS/rules.json", "utf8");
    const jsonObject = JSON.parse(jsonData);

    const choices = [];
    extractTextFromNotes(jsonObject.rows, choices);

    const filtered = choices
      .filter((choice) => choice.toLowerCase().includes(value))
      .slice(0, 25);

    if (!interaction.replied) return;

    await interaction.reply(
      filtered.map((choice) => ({ name: choice, value: choice }))
    );
  },

  async execute(interaction) {
    const query = interaction.options.getString("query");
    await interaction.reply({
      content: `You Selected ${query}`,
      ephemeral: true,
    });
  },
};

and nothing!

elder stump
#

You should do that fileRead and parsing outside of the autocomplete and filter through the loaded results when the AutocompleteInteraction happens. Else that slows your response down by having to wait for read and parse on each interaction

ashen tinsel
#

let me try it

#
const { SlashCommandBuilder } = require("discord.js");
const fs = require("fs");

function extractTextFromNotes(notes, result = []) {
  notes.forEach((note) => {
    if (note.type === "note") {
      result.push(note.text);
    } else if (note.children) {
      extractTextFromNotes(note.children, result);
    }
  });
}

// Carrega o conteúdo do arquivo JSON uma vez
const jsonData = fs.readFileSync("./JSONS/rules.json", "utf8");
const jsonObject = JSON.parse(jsonData);

// Extrai os valores de "text" e armazena em um array
const choices = [];
extractTextFromNotes(jsonObject.rows, choices);

module.exports = {
  data: new SlashCommandBuilder()
    .setName("autocomplete")
    .setDescription("autocomplete")
    .addStringOption((option) =>
      option
        .setName("query")
        .setDescription("Input a query")
        .setRequired(true)
        .setAutocomplete(true)
    ),
  async autocomplete(interaction) {
    const value = interaction.options.getString("query").toLowerCase();

    // Filtra as opções de autocompletar a partir do array choices
    const filtered = choices
      .filter((choice) => choice.toLowerCase().includes(value))
      .slice(0, 25);

    if (!interaction.replied) return;

    await interaction.reply(
      filtered.map((choice) => ({ name: choice, value: choice }))
    );
  },

  async execute(interaction) {
    const query = interaction.options.getString("query");
    await interaction.reply({
      content: `You Selected ${query}`,
      ephemeral: true,
    });
  },
};

no way

#

the path is ok too

elder stump
#

You return if you didn’t reply to the interaction… so it’ll never reach the next line

silver viperBOT
elder stump
#

Also you need to use this for autocomplete response, reply doesn’t exist there

ashen tinsel
#
const { SlashCommandBuilder } = require("discord.js");
const fs = require("fs");

function extractTextFromNotes(notes, result = []) {
  notes.forEach((note) => {
    if (note.type === "note") {
      result.push(note.text);
    } else if (note.children) {
      extractTextFromNotes(note.children, result);
    }
  });
}

// Carrega o conteúdo do arquivo JSON uma vez
let jsonData;
try {
  jsonData = fs.readFileSync("./JSONS/rules.json");
} catch (error) {
  console.error("Erro ao ler o arquivo JSON:", error);
}
const jsonObject = JSON.parse(jsonData);

// Extrai os valores de "text" e armazena em um array
const choices = [];
extractTextFromNotes(jsonObject.rows, choices);

module.exports = {
  data: new SlashCommandBuilder()
    .setName("autocomplete")
    .setDescription("autocomplete")
    .addStringOption((option) =>
      option
        .setName("query")
        .setDescription("Input a query")
        .setRequired(true)
        .setAutocomplete(true)
    ),
  async autocomplete(interaction) {
    const value = interaction.options.getString("query").toLowerCase();

    console.log("Choices:", choices);

    // Filtra as opções de autocompletar a partir do array choices
    const filtered = choices
      .filter((choice) => choice.toLowerCase().includes(value))
      .slice(0, 25);

    if (!interaction) return;

    await interaction.respond(
      filtered.map((choice) => ({ name: choice, value: choice }))
    );
  },

  async execute(interaction) {
    const query = interaction.options.getString("query");
    await interaction.reply({
      content: `You Selected ${query}`,
      ephemeral: true,
    });
  },
};

Sorry, i can't go further,,, it's too hard for me!

elder stump
#

That’s code. And what happens when that code is ran?

ashen tinsel
#

no errors in console. the json is fine...

elder stump
#

What about your console.log, anything in console?

ashen tinsel
#

nothing!

elder stump
#

So your autocomplete function doesn’t even get called

ashen tinsel
#

yeah!

elder stump
#

Then show the code that is supposed to call it

#

Won’t find the issue in a function that doesn’t even get called

ashen tinsel
#
//index.js
client.on(Event.InteractionCreate, async (interaction) => {
  if (interaction.isAutocomplete()) {
    const command = interaction.client.commands.het(interaction.command.Name);
    if (!command) {
      return;
    }
    try {
      await command.autocomplete(interaction);
    } catch (err) {
      return;
    }
  }
});
#

am i missing something?

elder stump
#

You catch and silently ignore errors there… at least console.log them in the catch

#

And .het definitely is not a function, should probably be .get

#

Which also should error, so you silently ignore errors in more places probably

ashen tinsel
#

yeah now i got first error

(node:176340) DeprecationWarning: BaseInteraction#isSelectMenu() is deprecated. Use BaseInteraction#isStringSelectMenu() instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
Error executing autocomplete
DiscordAPIError[10062]: Unknown interaction
    at handleErrors (C:\Users\cefas\OneDrive\Documentos\beah-bot\node_modules\@discordjs\rest\dist\index.js:687:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async BurstHandler.runRequest (C:\Users\cefas\OneDrive\Documentos\beah-bot\node_modules\@discordjs\rest\dist\index.js:786:23)
    at async _REST.request (C:\Users\cefas\OneDrive\Documentos\beah-bot\node_modules\@discordjs\rest\dist\index.js:1218:22)
    at async ChatInputCommandInteraction.reply (C:\Users\cefas\OneDrive\Documentos\beah-bot\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:111:5)
    at async Object.execute (C:\Users\cefas\OneDrive\Documentos\beah-bot\commands\rulestest.js:57:5)
    at async Object.execute (C:\Users\cefas\OneDrive\Documentos\beah-bot\events\interactionCreate.js:33:7) {
  requestBody: { files: [], json: { type: 4, data: [Object] } },
  rawError: { message: 'Unknown interaction', code: 10062 },
  code: 10062,
  status: 404,
  method: 'POST',
  url: 'https://discord.com/api/v10/interactions/1145383132602839070/aW50ZXJhY3Rpb246MTE0NTM4MzEzMjYwMjgzOTA3MDpuZU1uTTJ3TklLOU9MakcyODJFNDg3ZGY3cUVDc2NoUXdobUZSekM2cVJjSWloODBtU3lETkFlb2FLYzRoUVp5SzI1MXN1dU9WVjhWZ1hEOUdwc1hPQnpOTXBFVldKR2lhVThlbUFsM3N5UlR3TDJ4Vnl1MHgyODlYblUzbk8wcg/callback'
}

elder stump
#

That is a reply to a ChatInputCommandInteraction. Why does it say error in autocomplete there?

#

rulestest.js line 57?

#

And interactionCreate.js should handle both ChatInputCommandInteraction and AutocompleteInteraction, not have two seperate events for those

ashen tinsel
#

hunnn it was a reply to chat

elder stump
#

But it took too long apparently (more than 3s) or you tried to reply to it twice

#

Now that you finally receive errors and not ignore them you can start to fix them

ashen tinsel
#

Dude. thank you very much but i really have no much idea what i'm doing here. it's my fisrt rodeo coding a bot to discord. I'll share the enritre project in github to someone take a look for me.

#

Thanks for all the help.