Fix autocomplete bugs, bulk upload

This commit is contained in:
cirroskais 2024-03-04 00:17:06 -05:00
parent 4cd8f68e92
commit 4ec01a6ab9
No known key found for this signature in database
GPG key ID: 5FC73EBF2678E33D
5 changed files with 269 additions and 170 deletions

View file

@ -1,54 +1,58 @@
import { InteractionResponseTypes } from "@discordeno/types"
import REST from "../lib/handlers/RESTHandler"
import { staged } from "../lib/modpack"
import { getAllMods } from "../lib/database"
import { InteractionResponseTypes } from "@discordeno/types";
import REST from "../lib/handlers/RESTHandler";
import { staged } from "../lib/modpack";
import { getAllMods } from "../lib/database";
function search(arr, search) {
if (!search.length) return false
if (!search.length) return false;
var matches = arr.filter(function (str) {
const regex = new RegExp(search, "i")
return str.search(regex) > -1
})
var matches = arr.filter(function (str) {
const regex = new RegExp(search, "i");
return str.search(regex) > -1;
});
return matches.length > 0 ? matches : false
return matches.length > 0 ? matches : false;
}
export default class Autocomplete {
static name = "modify"
static name = "modify";
constructor(data) {}
constructor(data) {}
async run(interaction) {
const entry = interaction.data.options[0].options[0].value
const from_modpack = interaction.data.options[0].options[1]?.value
async run(interaction) {
const entry = interaction.data.options[0].options.find((_) => _.name == "name").value;
const from_modpack = interaction.data.options[0].options.find((_) => _.name == "from_modpack")?.value;
if (!from_modpack) {
const keys = Array.from(staged.keys())
let choices = search(keys, entry)
if (!choices) choices = keys
if (!from_modpack) {
const keys = Array.from(staged.keys());
let choices = search(keys, entry);
if (!choices) choices = keys;
return REST.sendInteractionResponse(interaction.id, interaction.token, {
type: InteractionResponseTypes.ApplicationCommandAutocompleteResult,
data: {
choices: choices.map((_) => {
return { name: _, value: _ }
}),
},
})
} else {
const keys = getAllMods.all().map((_) => _.name)
let choices = search(keys, entry)
if (!choices) choices = keys
return REST.sendInteractionResponse(interaction.id, interaction.token, {
type: InteractionResponseTypes.ApplicationCommandAutocompleteResult,
data: {
choices: choices
.map((_) => {
return { name: _, value: _ };
})
.slice(0, 24),
},
});
} else {
const keys = getAllMods.all().map((_) => _.name);
let choices = search(keys, entry);
if (!choices) choices = keys;
return REST.sendInteractionResponse(interaction.id, interaction.token, {
type: InteractionResponseTypes.ApplicationCommandAutocompleteResult,
data: {
choices: choices.map((_) => {
return { name: _, value: _ }
}),
},
})
}
}
return REST.sendInteractionResponse(interaction.id, interaction.token, {
type: InteractionResponseTypes.ApplicationCommandAutocompleteResult,
data: {
choices: choices
.map((_) => {
return { name: _, value: _ };
})
.slice(0, 24),
},
});
}
}
}

88
src/commands/bulk.js Normal file
View file

@ -0,0 +1,88 @@
import BaseCommand from "../lib/classes/BaseCommand";
import { getModFromId } from "../lib/curseforge";
import { staged } from "../lib/modpack";
function progress(percent) {
return "#".repeat(percent * 25).padEnd(25, "");
}
export default class Command extends BaseCommand {
static type = 1;
static name = "bulk";
static description = "Make changes in builk";
static options = [
{
type: 1,
name: "add",
description: "Add mods in bulk",
options: [
{
type: 11,
name: "file",
description: "A CurseForge manifest file",
required: true,
},
],
},
{
type: 1,
name: "remove",
description: "Remove mods in bulk",
options: [
{
type: 11,
name: "file",
description: "A curseforge manifest file",
required: true,
},
],
},
];
constructor(data) {
super(data);
}
async run(interaction) {
const subcommand = interaction.data.options[0].name;
const subcommandOptions = interaction.data.options[0].options;
const attachmentId = BigInt(subcommandOptions[0].value);
const file = interaction.data.resolved.attachments.get(attachmentId);
let succeeded = [];
let failed = [];
if (subcommand == "add") {
await interaction.defer();
if (file.contentType !== "application/json; charset=utf-8" || file.filename !== "manifest.json")
return interaction.respond("That is not a valid manifest.json file.", { isPrivate: true });
const manifest = await (await fetch(file.url)).json();
for (let i = 0; i < manifest.files.length; i++) {
const { projectID, fileID } = manifest.files[i];
const mod = (await getModFromId(projectID)).data;
if (mod && !staged.get(mod.name)) {
staged.set(mod.name, {
modId: mod.id,
fileId: fileID,
provider: "curseforge",
url: mod.links.websiteUrl,
action: "add",
});
succeeded.push(mod.name);
if (succeeded.length % 5 == 0) await interaction.edit(`[${progress(i / manifest.files.length)}]`);
} else {
failed.push({ modId: projectID });
}
}
return interaction.edit(`Bulk added **${succeeded.length} mods**. (${failed.length} failed)`);
} else if (subcommand == "remove") {
}
}
}

View file

@ -1,24 +1,25 @@
import BaseCommand from "../lib/classes/BaseCommand"
import { staged } from "../lib/modpack"
import BaseCommand from "../lib/classes/BaseCommand";
import { staged } from "../lib/modpack";
export default class Command extends BaseCommand {
static type = 1
static name = "changes"
static description = "Get staged changes to the modpack"
static type = 1;
static name = "changes";
static description = "Get staged changes to the modpack";
constructor(data) {
super(data)
}
constructor(data) {
super(data);
}
async run(interaction) {
let text = ""
async run(interaction) {
let text = "";
if (!staged.size) return interaction.respond("No changes to the modpack have been staged.")
if (!staged.size) return interaction.respond("No changes to the modpack have been staged.");
for (let [key, value] of staged.entries()) {
text += (value.action == "add" ? "+" : "-") + " " + key + " (" + value.url + ")\n"
}
for (let [key, value] of staged.entries()) {
text += (value.action == "add" ? "+" : "-") + " " + key + " (" + value.url + ")\n";
}
interaction.respond("```diff\n" + text + "\n```")
}
if (text.length >= 2000) return interaction.respond("Too many changes to display.");
interaction.respond("```diff\n" + text + "\n```");
}
}

View file

@ -1,106 +1,108 @@
import BaseCommand from "../lib/classes/BaseCommand"
import { staged } from "../lib/modpack"
import * as curseforge from "../lib/curseforge"
import { getMod } from "../lib/database"
import BaseCommand from "../lib/classes/BaseCommand";
import { staged } from "../lib/modpack";
import * as curseforge from "../lib/curseforge";
import { getMod } from "../lib/database";
export default class Command extends BaseCommand {
static type = 1
static name = "modify"
static description = "Modify the modpack"
static options = [
{
type: 1,
name: "add",
description: "Add a mod",
options: [
{
type: 3,
name: "url",
description: "A link to a Modrinth/Curseforge mod",
required: true,
},
],
},
{
type: 1,
name: "remove",
description: "Remove a mod",
options: [
{
type: 5,
name: "from_modpack",
description: "Toggle removal from staging or the modpack",
required: true,
},
{
type: 3,
name: "name",
description: "The name of the mod",
autocomplete: true,
required: true,
},
],
},
]
static type = 1;
static name = "modify";
static description = "Modify the modpack";
static options = [
{
type: 1,
name: "add",
description: "Add a mod",
options: [
{
type: 3,
name: "url",
description: "A link to a Modrinth/Curseforge mod",
required: true,
},
],
},
{
type: 1,
name: "remove",
description: "Remove a mod",
options: [
{
type: 5,
name: "from_modpack",
description: "Toggle removal from staging or the modpack",
required: true,
},
{
type: 3,
name: "name",
description: "The name of the mod",
autocomplete: true,
required: true,
},
],
},
];
constructor(data) {
super(data)
}
constructor(data) {
super(data);
}
async run(interaction) {
const subcommand = interaction.data.options[0].name
const subcommandOptions = interaction.data.options[0].options
async run(interaction) {
const subcommand = interaction.data.options[0].name;
const subcommandOptions = interaction.data.options[0].options;
if (subcommand == "add") {
const url = subcommandOptions.find((_) => _.name == "url").value
const parsedUrl = new URL(url)
if (subcommand == "add") {
const url = subcommandOptions.find((_) => _.name == "url").value;
const parsedUrl = new URL(url);
if (parsedUrl.host.includes("curseforge.com")) {
const mod = await curseforge.getMod(url)
if (!mod) return interaction.respond("Mod not found.")
if (parsedUrl.host.includes("curseforge.com")) {
const mod = await curseforge.getMod(url);
if (!mod) return interaction.respond("Mod not found.");
const file = await curseforge.getModFiles(mod.id)
const file = await curseforge.getModFiles(mod.id);
if (staged.get(mod.name)) return interaction.respond(`**${mod.name}** is already in the staged mods.`, { isPrivate: true })
if (getMod.get(mod.name)) return interaction.respond(`**${mod.name}** is already in the modpack.`, { isPrivate: true })
if (staged.get(mod.name))
return interaction.respond(`**${mod.name}** is already in the staged mods.`, { isPrivate: true });
if (getMod.get(mod.name))
return interaction.respond(`**${mod.name}** is already in the modpack.`, { isPrivate: true });
staged.set(mod.name, {
modId: mod.id,
fileId: file.id,
provider: "curseforge",
url: mod.links.websiteUrl,
action: "add",
})
staged.set(mod.name, {
modId: mod.id,
fileId: file.id,
provider: "curseforge",
url: mod.links.websiteUrl,
action: "add",
});
interaction.respond(`Added **${mod.name}** to the staged mods.`)
} else if (parsedUrl.host.includes("modrinth.com")) {
console.log("Modrinth mod detected")
}
} else if (subcommand == "remove") {
const name = subcommandOptions.find((_) => _.name == "name").value
const from_modpack = subcommandOptions.find((_) => _.name == "from_modpack")?.value
interaction.respond(`Added **${mod.name}** to the staged mods.`);
} else if (parsedUrl.host.includes("modrinth.com")) {
console.log("Modrinth mod detected");
}
} else if (subcommand == "remove") {
const name = subcommandOptions.find((_) => _.name == "name").value;
const from_modpack = subcommandOptions.find((_) => _.name == "from_modpack")?.value;
if (!from_modpack) {
const mod = staged.get(name)
if (!mod) return interaction.respond("Mod not found.")
if (!from_modpack) {
const mod = staged.get(name);
if (!mod) return interaction.respond("Mod not found.");
staged.delete(name)
staged.delete(name);
interaction.respond(`Removed **${name}** from the staged mods.`)
} else {
const mod = getMod.get(name)
if (!mod) return interaction.respond("Mod not found.")
const modData = await curseforge.getModFromId(mod.modId)
interaction.respond(`Removed **${name}** from the staged mods.`);
} else {
const mod = getMod.get(name);
if (!mod) return interaction.respond("Mod not found.");
const modData = await curseforge.getModFromId(mod.modId);
staged.set(mod.name, {
modId: mod.modId,
url: modData.data.links.websiteUrl,
provider: "curseforge",
action: "remove",
})
staged.set(mod.name, {
modId: mod.modId,
url: modData.data.links.websiteUrl,
provider: "curseforge",
action: "remove",
});
interaction.respond(`Staged the removal of **${name}**.`)
}
}
}
interaction.respond(`Staged the removal of **${name}**.`);
}
}
}
}

View file

@ -1,33 +1,37 @@
import { createBot, Intents, logger } from "@discordeno/bot"
import { createBot, Intents, logger } from "@discordeno/bot";
import EventHandler from "./lib/handlers/EventHandler"
import EventHandler from "./lib/handlers/EventHandler";
export default async function discord() {
const client = createBot({
token: import.meta.env.DISCORD_TOKEN,
// intents: [],
})
const client = createBot({
token: import.meta.env.DISCORD_TOKEN,
// intents: [],
});
client.events = await new EventHandler(client).load()
client.events = await new EventHandler(client).load();
client.transformers.desiredProperties.message.content = true
client.transformers.desiredProperties.message.author = true
client.transformers.desiredProperties.message.content = true;
client.transformers.desiredProperties.message.author = true;
client.transformers.desiredProperties.user.id = true
client.transformers.desiredProperties.user.username = true
client.transformers.desiredProperties.user.avatar = true
client.transformers.desiredProperties.user.id = true;
client.transformers.desiredProperties.user.username = true;
client.transformers.desiredProperties.user.avatar = true;
client.transformers.desiredProperties.member.user = true
client.transformers.desiredProperties.member.roles = true
client.transformers.desiredProperties.member.permissions = true
client.transformers.desiredProperties.member.user = true;
client.transformers.desiredProperties.member.roles = true;
client.transformers.desiredProperties.member.permissions = true;
client.transformers.desiredProperties.interaction.id = true
client.transformers.desiredProperties.interaction.type = true
client.transformers.desiredProperties.interaction.data = true
client.transformers.desiredProperties.interaction.token = true
client.transformers.desiredProperties.interaction.guildId = true
client.transformers.desiredProperties.interaction.channelId = true
client.transformers.desiredProperties.interaction.member = true
client.transformers.desiredProperties.interaction.id = true;
client.transformers.desiredProperties.interaction.type = true;
client.transformers.desiredProperties.interaction.data = true;
client.transformers.desiredProperties.interaction.token = true;
client.transformers.desiredProperties.interaction.guildId = true;
client.transformers.desiredProperties.interaction.channelId = true;
client.transformers.desiredProperties.interaction.member = true;
client.start()
client.transformers.desiredProperties.attachment.contentType = true;
client.transformers.desiredProperties.attachment.filename = true;
client.transformers.desiredProperties.attachment.url = true;
client.start();
}