Skip to content

Commit

Permalink
add search to the quote command
Browse files Browse the repository at this point in the history
Signed-off-by: Matthew Sawatzky <[email protected]>
  • Loading branch information
msawatzky75 committed Dec 22, 2023
1 parent 1eb2ab2 commit ef4b2b7
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 9 deletions.
11 changes: 11 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "discord-bot-js",
"version": "2.4.1",
"version": "2.5.0",
"private": true,
"repository": "[email protected]:msawatzky75/discord-bot-js.git",
"author": "Matthew Sawatzky <[email protected]>",
Expand All @@ -18,6 +18,7 @@
"debug": "^4.3.4",
"discord.js": "^14.14.1",
"dotenv": "^16.3.1",
"fuse.js": "^7.0.0",
"typescript": "5.3.3"
},
"devDependencies": {
Expand Down
52 changes: 45 additions & 7 deletions src/commands/quote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@ import {
TextChannel,
} from "discord.js";
import type {Command} from "./index";
import Fuse from "fuse.js";
import type {IFuseOptions} from "fuse.js";
import util from "../util.js";

const d = debug("bot.commands.quote");
const messages = new Collection<Snowflake, Collection<string, Message<true>>>();
const lastUpdate = new Collection<Snowflake, Date>();
const cacheLife = 1000 * 60 * 15; // 15 minutes

const fuseOptions: IFuseOptions<Message<true>> = {
keys: [{name: "content", weight: 1}],
};

const command: Command = {
data: new SlashCommandBuilder()
.addStringOption((b) => b.setName("search").setRequired(false).setDescription("Fuzzy search all quotes"))
.setName("quote")
.setDescription("Sends a random quote from the quote wall."),

Expand All @@ -28,29 +36,55 @@ const command: Command = {

if (!(quoteChannel instanceof TextChannel)) throw new Error("Could not find quote channel");

const serverMessages = messages.get(quoteChannel.guildId);
let serverMessages = messages.get(quoteChannel.guildId);
const timeSinceUpdate = new Date().getTime() - (lastUpdate.get(quoteChannel.guildId)?.getTime() ?? 0);
const search = interaction.options.getString("search");

if (!serverMessages) {
d(`No cache for ${quoteChannel.guild.name}, fetching quotes...`);
interaction.reply("Fetching quotes. This may take some time...");
await util.sendReply(interaction, {
content: "Fetching quotes. This may take some time...",
ephemeral: true,
});
await updateMessages(quoteChannel);
serverMessages = messages.get(quoteChannel.guildId);
} else if (timeSinceUpdate >= cacheLife) {
d(`Cache expired for ${quoteChannel.guild.name}, fetching quotes...`);
await interaction.reply("Cache expired, refreshing. This may take some time...");
await util.sendReply(interaction, {
content: "Cache expired, refreshing. This may take some time...",
ephemeral: true,
});
await updateMessages(quoteChannel);
serverMessages = messages.get(quoteChannel.guildId);
}

const randomMessage = messages.get(quoteChannel.guildId).random();
let selcetedMessage: Message;
if (search && serverMessages) {
await util.sendReply(interaction, {content: "Searching...", ephemeral: true});
const fuse = new Fuse(
serverMessages.map((m) => m),
fuseOptions,
);
const results = fuse.search(search, {limit: 1});
if (results.length) selcetedMessage = getRandom(results).item;
else await util.sendReply(interaction, {content: "Failed to find a match.", ephemeral: true});
}
if (!selcetedMessage) {
selcetedMessage = messages.get(quoteChannel.guildId).random();
}

// replace mentions with their names
const content = randomMessage.content.replace(/<@!?(\d+)>/g, (match) => {
const content = selcetedMessage.content.replace(/<@!?(\d+)>/g, (match) => {
const id = match.replace(/<@!?/, "").replace(/>/, "");
const member = randomMessage.mentions.users.get(id);
const member = selcetedMessage.mentions.users.get(id);
return `**${member.username.trim()}**`;
});

interaction.replied ? await interaction.editReply(content) : await interaction.reply(content);
if (interaction.replied) {
interaction.followUp(content);
} else {
interaction.reply(content);
}
},
};

Expand All @@ -74,4 +108,8 @@ async function updateMessages(quoteChannel: TextChannel) {
lastUpdate.set(quoteChannel.guildId, new Date());
}

function getRandom<T>(items: T[]) {
return items[Math.floor(Math.random() * items.length)];
}

export default command;
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {REST} from "@discordjs/rest";
import commands from "./commands/index.js";
import services from "./services/index.js";
import Config from "./config.js";
import util from "./util.js";

const d = debug("bot.index");

Expand Down Expand Up @@ -51,7 +52,10 @@ client.on("interactionCreate", async (interaction) => {
await command.execute(interaction);
} catch (err) {
d(err);
await interaction.reply({content: "There was an error while executing this command!", ephemeral: true});
await util.sendReply(interaction, {
content: "There was an error while executing this command!",
ephemeral: true,
});
}
});

Expand Down
12 changes: 12 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {ChatInputCommandInteraction, InteractionReplyOptions} from "discord.js";

async function sendReply(
interaction: ChatInputCommandInteraction,
message: string | InteractionReplyOptions,
) {
return interaction.replied ? interaction.editReply(message) : interaction.reply(message);
}

export default {
sendReply,
};
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,7 @@ __metadata:
eslint: "npm:^8.56.0"
eslint-config-prettier: "npm:^9.1.0"
eslint-plugin-import: "npm:^2.29.1"
fuse.js: "npm:^7.0.0"
nodemon: "npm:^3.0.2"
prettier: "npm:^3.1.1"
rimraf: "npm:^5.0.5"
Expand Down Expand Up @@ -1572,6 +1573,13 @@ __metadata:
languageName: node
linkType: hard

"fuse.js@npm:^7.0.0":
version: 7.0.0
resolution: "fuse.js@npm:7.0.0"
checksum: d75d35f2d61afa85b8248f9cbfc7d4df29ae47ea574a15ad5c3c2a41930c5ed78668346295508b59ec4929fcb1a5cd6d9a8c649b5a3bc8b18e515f4e4cb9809d
languageName: node
linkType: hard

"gauge@npm:~2.7.3":
version: 2.7.4
resolution: "gauge@npm:2.7.4"
Expand Down

0 comments on commit ef4b2b7

Please sign in to comment.