mirror of
https://github.com/keanuplayz/TravBot-v3.git
synced 2024-08-15 02:33:12 +00:00
Tried adding some heuristics to searching emotes
This commit is contained in:
parent
692fd2c164
commit
2017e45403
4 changed files with 53 additions and 29 deletions
|
@ -10,5 +10,5 @@ module.exports = {
|
|||
bracketSpacing: false,
|
||||
jsxBracketSameLine: false,
|
||||
arrowParens: "always",
|
||||
endOfLine: "lf"
|
||||
endOfLine: "auto" // Apparently, the GitHub repository still uses CRLF. I don't know how to force it to use LF, and until someone figures that out, I'm changing this to auto because I don't want more than one line ending commit.
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import {MessageEmbed} from "discord.js";
|
||||
import Command from "../../core/command";
|
||||
import {CommonLibrary} from "../../core/lib";
|
||||
import {queryClosestEmoteByName} from "./subcommands/emote-utils";
|
||||
import {botHasPermission} from "../../core/lib";
|
||||
import {Permissions} from "discord.js";
|
||||
|
||||
export default new Command({
|
||||
description: "Send the specified emote.",
|
||||
run: "Please provide a command name.",
|
||||
any: new Command({
|
||||
description: "The emote to send.",
|
||||
usage: "<emote>",
|
||||
async run($: CommonLibrary): Promise<any> {
|
||||
const search = $.args[0].toLowerCase();
|
||||
const emote = $.client.emojis.cache.find((emote) => emote.name.toLowerCase().includes(search));
|
||||
if (!emote) return $.channel.send("That's not a valid emote name!");
|
||||
$.message.delete();
|
||||
$.channel.send(`${emote}`);
|
||||
description: "The emote(s) to send.",
|
||||
usage: "<emotes...>",
|
||||
async run({guild, channel, message, args}) {
|
||||
let output = "";
|
||||
for (const query of args) output += queryClosestEmoteByName(query).toString();
|
||||
if (botHasPermission(guild, Permissions.FLAGS.MANAGE_MESSAGES)) message.delete();
|
||||
channel.send(output);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Command from "../../core/command";
|
||||
import {CommonLibrary} from "../../core/lib";
|
||||
import {Message, Channel, TextChannel} from "discord.js";
|
||||
import {queryClosestEmoteByName} from "./subcommands/emote-utils";
|
||||
|
||||
export default new Command({
|
||||
description:
|
||||
|
@ -94,26 +95,16 @@ export default new Command({
|
|||
).last();
|
||||
}
|
||||
|
||||
let anyEmoteIsValid = false;
|
||||
|
||||
for (const search of $.args) {
|
||||
const emoji = $.client.emojis.cache.find((emoji) => emoji.name === search);
|
||||
// Even though the bot will always grab *some* emote, the user can choose not to keep that emote there if it isn't what they want
|
||||
const emote = queryClosestEmoteByName(search);
|
||||
const reaction = await target!.react(emote);
|
||||
|
||||
if (emoji) {
|
||||
// Call the delete function only once to avoid unnecessary errors.
|
||||
if (!anyEmoteIsValid && distance !== 0) $.message.delete();
|
||||
anyEmoteIsValid = true;
|
||||
const reaction = await target?.react(emoji);
|
||||
|
||||
// This part is called with a promise because you don't want to wait 5 seconds between each reaction.
|
||||
|
||||
setTimeout(() => {
|
||||
/// @ts-ignore
|
||||
reaction.users.remove($.client.user);
|
||||
}, 5000);
|
||||
}
|
||||
// This part is called with a promise because you don't want to wait 5 seconds between each reaction.
|
||||
setTimeout(() => {
|
||||
// This reason for this null assertion is that by the time you use this command, the client is going to be loaded.
|
||||
reaction.users.remove($.client.user!);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
if (!anyEmoteIsValid && !$.message.deleted) $.message.react("❓");
|
||||
}
|
||||
});
|
||||
|
|
33
src/commands/utilities/subcommands/emote-utils.ts
Normal file
33
src/commands/utilities/subcommands/emote-utils.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import {client} from "../../../index";
|
||||
|
||||
// Calculate and match the list of emotes against the queried emote, then sort the IDs based on calculated priority.
|
||||
export function queryClosestEmoteByName(query: string) {
|
||||
const priorityTable: {[id: string]: number} = {};
|
||||
|
||||
for (const emote of client.emojis.cache.values()) priorityTable[emote.id] = compareEmoteNames(emote.name, query);
|
||||
|
||||
const resultingIDs = Object.keys(priorityTable).sort((a, b) => priorityTable[b] - priorityTable[a]);
|
||||
return client.emojis.cache.get(resultingIDs[0])!;
|
||||
}
|
||||
|
||||
// Compare an emote's name against a query to see how alike the two are. The higher the number, the closer they are. Takes into account length and capitalization.
|
||||
function compareEmoteNames(emote: string, query: string) {
|
||||
let likeness = -Math.abs(emote.length - query.length);
|
||||
const isQueryLonger = query.length > emote.length;
|
||||
|
||||
// Loop through all indexes that the two strings share then compare each letter.
|
||||
for (let i = 0; i < (isQueryLonger ? emote.length : query.length); i++) {
|
||||
const c = emote[i];
|
||||
const q = query[i];
|
||||
|
||||
// If they're the exact same character
|
||||
if (c === q) likeness += 3;
|
||||
// If the query is uppercase but the emote is lowercase
|
||||
else if (c === q.toLowerCase()) likeness += 2;
|
||||
// If the query is lowercase but the emote is uppercase
|
||||
else if (c === q.toUpperCase()) likeness += 1;
|
||||
// Otherwise, if they're different characters, don't add anything (this isn't a spellchecker)
|
||||
}
|
||||
|
||||
return likeness;
|
||||
}
|
Loading…
Reference in a new issue