From 8d7357e4da996d35e1b8c55bca79f62955c96bf7 Mon Sep 17 00:00:00 2001 From: Ashley Graves Date: Thu, 10 Oct 2024 14:48:59 +0200 Subject: [PATCH] BOORU TAG AUTOCOMPLETE --- package.json | 2 +- pnpm-lock.yaml | 48 +++++++++++++++++++++++++----------- src/commands/fun/gelbooru.js | 35 +++++++++++++++++++++++--- src/index.js | 48 ++++++++++++++++++++---------------- 4 files changed, 92 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 3704813..67ec6e0 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "author": "", "license": "MIT", "dependencies": { + "@himeka/booru": "github:asadahimeka/booru-search", "@imgproxy/imgproxy-node": "^1.0.6", - "booru": "^2.6.8", "discord.js": "^14.16.3", "dotenv": "^16.4.5", "groq-sdk": "^0.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2ab526..498cf59 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,12 +8,12 @@ importers: .: dependencies: + '@himeka/booru': + specifier: github:asadahimeka/booru-search + version: https://codeload.github.com/asadahimeka/booru-search/tar.gz/9599c1c7e2ab8467ac6b0ce7d5300c621e4b00b9 '@imgproxy/imgproxy-node': specifier: ^1.0.6 version: 1.0.6 - booru: - specifier: ^2.6.8 - version: 2.6.8 discord.js: specifier: ^14.16.3 version: 14.16.3 @@ -60,6 +60,11 @@ packages: resolution: {integrity: sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==} engines: {node: '>=16.11.0'} + '@himeka/booru@https://codeload.github.com/asadahimeka/booru-search/tar.gz/9599c1c7e2ab8467ac6b0ce7d5300c621e4b00b9': + resolution: {tarball: https://codeload.github.com/asadahimeka/booru-search/tar.gz/9599c1c7e2ab8467ac6b0ce7d5300c621e4b00b9} + version: 2.7.7 + engines: {node: '>=10.0.0'} + '@imgproxy/imgproxy-js-core@1.0.8': resolution: {integrity: sha512-3oBneumj7b/YCeyLteKyKaidQSrDhEHnZMiVBHO0Hshju/YSplbzSeACZGwai7LyD3YMMpsK/kLIodXU6wbtMw==} @@ -105,10 +110,6 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - booru@2.6.8: - resolution: {integrity: sha512-/MN9Q5Yd3jBvOXgG05SLsdbGHFUWx6yoLYKU0xIoTWDsNlliUqM8Aj581pBujqFhg4E/Pi9cHdpMRN/FqustUA==} - engines: {node: '>=10.0.0'} - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -141,8 +142,8 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-xml-parser@4.5.0: - resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==} + fast-xml-parser@4.4.0: + resolution: {integrity: sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==} hasBin: true form-data-encoder@1.7.2: @@ -165,6 +166,9 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + isomorphic-unfetch@3.1.0: + resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} + lodash.snakecase@4.1.1: resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} @@ -225,6 +229,9 @@ packages: resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} engines: {node: '>=18.17'} + unfetch@4.2.0: + resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} + web-streams-polyfill@4.0.0-beta.3: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} @@ -296,6 +303,13 @@ snapshots: - bufferutil - utf-8-validate + '@himeka/booru@https://codeload.github.com/asadahimeka/booru-search/tar.gz/9599c1c7e2ab8467ac6b0ce7d5300c621e4b00b9': + dependencies: + fast-xml-parser: 4.4.0 + isomorphic-unfetch: 3.1.0 + transitivePeerDependencies: + - encoding + '@imgproxy/imgproxy-js-core@1.0.8': {} '@imgproxy/imgproxy-node@1.0.6': @@ -340,11 +354,6 @@ snapshots: asynckit@0.4.0: {} - booru@2.6.8: - dependencies: - fast-xml-parser: 4.5.0 - undici: 6.19.8 - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -381,7 +390,7 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-xml-parser@4.5.0: + fast-xml-parser@4.4.0: dependencies: strnum: 1.0.5 @@ -416,6 +425,13 @@ snapshots: dependencies: ms: 2.1.3 + isomorphic-unfetch@3.1.0: + dependencies: + node-fetch: 2.7.0 + unfetch: 4.2.0 + transitivePeerDependencies: + - encoding + lodash.snakecase@4.1.1: {} lodash@4.17.21: {} @@ -454,6 +470,8 @@ snapshots: undici@6.19.8: {} + unfetch@4.2.0: {} + web-streams-polyfill@4.0.0-beta.3: {} webidl-conversions@3.0.1: {} diff --git a/src/commands/fun/gelbooru.js b/src/commands/fun/gelbooru.js index 69d1504..ef14b72 100644 --- a/src/commands/fun/gelbooru.js +++ b/src/commands/fun/gelbooru.js @@ -1,8 +1,9 @@ const { InteractionContextType, ApplicationIntegrationType, SlashCommandBuilder, EmbedBuilder, escapeMarkdown, bold } = require("discord.js"); +const { stringify } = require("node:querystring"); const { readFileSync } = require("node:fs"); -const { extname } = require("node:path"); const { decode } = require("html-entities"); -const Booru = require('booru'); +const { extname } = require("node:path"); +const Booru = require('@himeka/booru'); const boorus = []; for (const site of Object.keys(Booru.sites)) { @@ -22,14 +23,15 @@ const data = new SlashCommandBuilder() .setName("tags") .setRequired(false) .setDescription("Tags to search for") + .setAutocomplete(true) ) - .addStringOption(builder => + /*.addStringOption(builder => builder // .setName("booru") .setRequired(false) .setDescription("Booru board to search (default: gelbooru)") .addChoices(boorus) - ) + )*/ .addBooleanOption(builder => builder // .setName("nsfw") @@ -169,4 +171,29 @@ module.exports = { ); } }, + async autocomplete(interaction) { + const focusedValue = interaction.options.getFocused(); + const tags = focusedValue.split(" "); + var queryString = stringify({ + "page": "dapi", + "json": "1", + "s": "tag", + "q": "index", + "orderby": "count", + "name_pattern": tags[tags.length - 1] + "%" + }); + const results = await (await fetch(`https://gelbooru.com/index.php?${queryString}`)).json(); + const choices = []; + for (const tag of results.tag) { + if (tag.name == "") continue; + choices.push(tag.name); + } + if (choices.length == 0) { + await interaction.respond(); + return; + } + await interaction.respond( + choices.slice(0, 25).map(choice => ({ name: (tags.length > 1 ? tags.slice(0, tags.length - 1).join(" ") + " " : '') + choice, value: choice })), + ); + }, }; diff --git a/src/index.js b/src/index.js index 6bc768c..252bf73 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -const { REST, Routes, Client, Collection, GatewayIntentBits, Events, Partials } = require("discord.js"); +const { REST, Routes, Client, Collection, GatewayIntentBits, Events, Partials, InteractionType } = require("discord.js"); const { default: Groq } = require("groq-sdk"); const path = require("node:path"); const fs = require("node:fs"); @@ -36,34 +36,40 @@ for (const folder of commandFolders) { } client.on(Events.InteractionCreate, async interaction => { - if (interaction.commandName == undefined) return; const command = interaction.client.commands.get(interaction.commandName); - if (!command) { console.error(`No command matching ${interaction.commandName} was found.`); return; } - var options = ""; - for (const option of interaction.options.data) { - options += option.name + ":" + option.value - } + if (interaction.isAutocomplete()) { + try { + await command.autocomplete(interaction); + } catch (error) { + console.error(error); + } + } else if (interaction.isCommand()) { + var options = ""; + for (const option of interaction.options.data) { + options += option.name + ":" + option.value + } - console.log(`${interaction.user.username} ran /${interaction.commandName} ${options}`); + console.log(`${interaction.user.username} ran /${interaction.commandName} ${options}`); - try { - interaction.defaultModel = "llama-3.1-70b-versatile"; - await command.execute(interaction); - } catch (err) { - console.error(err); - const data = { - content: `${err.name}: ${err.message}`, - ephemeral: true - }; - if (interaction.replied || interaction.deferred) { - await interaction.followUp(data); - } else { - await interaction.reply(data); + try { + interaction.defaultModel = "llama-3.1-70b-versatile"; + await command.execute(interaction); + } catch (err) { + console.error(err); + const data = { + content: `${err.name}: ${err.message}`, + ephemeral: true + }; + if (interaction.replied || interaction.deferred) { + await interaction.followUp(data); + } else { + await interaction.reply(data); + } } } });