Skip to content

Commit

Permalink
chore: general refactoring, error message utility; user installation …
Browse files Browse the repository at this point in the history
…support
  • Loading branch information
espimarisa committed Aug 25, 2024
1 parent bf2c207 commit 6168269
Show file tree
Hide file tree
Showing 21 changed files with 285 additions and 358 deletions.
10 changes: 8 additions & 2 deletions locales/en-US/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@
"COMMAND_IPINFO_DESCRIPTION": "Returns information and abuse data about an IP address.",
"COMMAND_IPINFO_OPTION_0_NAME": "ip",
"COMMAND_IPINFO_OPTION_0_DESCRIPTION": "The IP to get information about. IPV4 and IPV6 both supported.",
"COMMAND_IPINFO_INVALID": "Either the IP specified was invalid, or no information was found about it.",
"COMMAND_IPINFO_INVALID_IPV6": "Either the IP specified was invalid, or no information was found about it. If you provided an IPV6 address, the host may not support IPV6.",
"COMMAND_IPINFO_INVALID": "Either the IP specified was invalid, or no information was found about it. If you provided an IPV6 address, the host may not support IPV6.",
"COMMAND_IPINFO_HOSTNAME": "Hostname",
"COMMAND_IPINFO_ASN": "ASN",
"COMMAND_IPINFO_USAGETYPE": "Usage Type",
Expand All @@ -95,6 +94,13 @@
"COMMAND_IPINFO_TOR": "TOR",
"COMMAND_IPINFO_INFOFOR": "Information for {{ ip }}",

"COMMAND_PACKAGE_NAME": "Package",
"COMMAND_PACKAGE_DESCRIPTION": "Returns information about a package from a specified package database.",
"COMMAND_PACKAGE_OPTION_0_NAME": "aur",
"COMMAND_PACKAGE_OPTION_0_DESCRIPTION": "Gets information about a package from the Arch User Repository (AUR).",
"COMMAND_PACKAGE_SUBCOMMAND_0_OPTION_0_NAME": "package",
"COMMAND_PACKAGE_SUBCOMMAND_0_OPTION_0_DESCRIPTION": "The package to return information about.",

"COMMAND_PING_NAME": "Ping",
"COMMAND_PING_DESCRIPTION": "Checks the current status and latency.",
"COMMAND_PING_PING_LATENCY": "This message took {{latency}}ms to send. All seems OK!",
Expand Down
7 changes: 6 additions & 1 deletion src/classes/Command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { HibikiClient } from "$classes/Client.ts";
import type { PossibleCommandInteractionType } from "$events/CommandInteraction.ts";
import type { API_KEYS } from "$utils/env.ts";
import { type APIApplicationCommandOption, ApplicationCommandType } from "discord-api-types/v10";
import type { PossibleCommandInteractionType } from "../events/CommandInteraction";

// Paramaters to remove from setting in individual command files. Prevents overriding loader-handled data.
type LockedParamaters = "name" | "description" | "name_localizations" | "description_localizations";
Expand All @@ -28,6 +28,8 @@ export interface RESTCommandOptions {
options?: APIApplicationCommandOption[];
type: ApplicationCommandType;
nsfw?: boolean;
integration_types?: number[];
contexts?: number[];
}

export abstract class HibikiCommand {
Expand All @@ -41,6 +43,9 @@ export abstract class HibikiCommand {
// An array of command interaction options
options?: HibikiCommandOptions[];

// Whether or not a command is user installable. Defaults to false.
userInstallable = false;

// Whether or not the interaction response can only be seen by the runner. Defaults to false.
ephemeral = false;

Expand Down
10 changes: 7 additions & 3 deletions src/commands/about.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ import { type ChatInputCommandInteraction, type EmbedField, version } from "disc
const startupTimestamp = new Date();

export class AboutCommand extends HibikiCommand {
userInstallable = true;

async runCommand(interaction: ChatInputCommandInteraction) {
// Gets the amount of cached guilds and users
const totalCachedGuilds = await fetchTotalCachedGuilds(this.bot.shard);
const totalCachedUsers = await fetchTotalCachedUsers(this.bot.shard);
const fields: EmbedField[] = [];

// Calculates uptime
const uptime = getTimeSince(startupTimestamp, new Date());
const localizedUptime = localizeTimeSince(uptime, interaction.locale);

Expand All @@ -38,15 +41,16 @@ export class AboutCommand extends HibikiCommand {
});
}

// Sends the embed
await interaction.followUp({
embeds: [
{
title: t("commands:COMMAND_ABOUT_TITLE", {
username: this.bot.user?.username,
username: interaction.client.user.username,
lng: interaction.locale,
}),
description: t("commands:COMMAND_ABOUT_DETAILS", {
username: this.bot.user?.username,
username: interaction.client.user.username,
lng: interaction.locale,
}),
color: HibikiColors.GENERAL,
Expand Down Expand Up @@ -79,7 +83,7 @@ export class AboutCommand extends HibikiCommand {
...fields,
],
thumbnail: {
url: this.bot.user?.displayAvatarURL() ?? "",
url: interaction.client.user.displayAvatarURL(),
},
},
],
Expand Down
40 changes: 17 additions & 23 deletions src/commands/account.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type APIOption, HibikiCommand, type HibikiCommandOptions } from "$classes/Command.ts";
import { HibikiColors } from "$utils/constants.ts";
import { sendErrorReply } from "$utils/error.ts";
import { t } from "$utils/i18n.ts";
import { createFullTimestamp } from "$utils/timestamp.ts";
import { ApplicationCommandOptionType, type ChatInputCommandInteraction, type EmbedField } from "discord.js";
Expand All @@ -26,27 +27,20 @@ export class AvatarCommand extends HibikiCommand {
const idToFetch = memberToFetch?.id ?? interaction.user.id;
const fields: EmbedField[] = [];

// Error handler for no guild
if (!interaction.guild) {
await sendErrorReply("errors:ERROR_SERVER", interaction);
return;
}

// Fetches the member
const member =
interaction.guild!.members.cache.find((m) => m.id === idToFetch) ||
(await interaction.guild!.members.fetch(idToFetch));
interaction.guild.members.cache.find((m) => m.id === idToFetch) ||
(await interaction.guild.members.fetch(idToFetch));

// Error handler
// Error handler for no member
if (!member) {
await interaction.followUp({
embeds: [
{
title: t("errors:ERROR", { lng: interaction.locale }),
description: t("errors:ERROR_ACCOUNT", { lng: interaction.locale }),
color: HibikiColors.ERROR,
footer: {
text: t("errors:ERROR_FOUND_A_BUG", { lng: interaction.locale }),
icon_url: this.bot.user?.displayAvatarURL(),
},
},
],
});

await sendErrorReply("errors:ERROR_ACCOUNT", interaction);
return;
}

Expand Down Expand Up @@ -104,7 +98,7 @@ export class AvatarCommand extends HibikiCommand {
if (member.nickname) {
fields.push({
name: t("global:NICKNAME", { lng: interaction.locale }),
value: member.nickname.toString(),
value: member.nickname,
inline: true,
});
}
Expand All @@ -113,7 +107,7 @@ export class AvatarCommand extends HibikiCommand {
if (member.roles) {
fields.push({
name: t("commands:COMMAND_ACCOUNT_HIGHEST_ROLE", { lng: interaction.locale }),
value: member.roles.highest.name.toString(),
value: member.roles.highest.name,
inline: true,
});
}
Expand All @@ -126,16 +120,16 @@ export class AvatarCommand extends HibikiCommand {
author: {
name: member.user.tag,
icon_url: serverInfo
? member.displayAvatarURL({ size: 1024 })
: member.user.displayAvatarURL({ size: 1024 }),
? member.displayAvatarURL({ size: 2048 })
: member.user.displayAvatarURL({ size: 2048 }),
},
fields: fields,
color: member.user.accentColor ?? HibikiColors.GENERAL,
thumbnail: {
url: serverInfo ? member.displayAvatarURL({ size: 1024 }) : member.user.displayAvatarURL({ size: 1024 }),
url: serverInfo ? member.displayAvatarURL({ size: 2048 }) : member.user.displayAvatarURL({ size: 1024 }),
},
image: {
url: member.user.bannerURL({ size: 1024 }) ?? "",
url: member.user.bannerURL({ size: 2048 }) ?? "",
},
},
],
Expand Down
81 changes: 24 additions & 57 deletions src/commands/animal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HibikiCommand, type HibikiCommandOptions } from "$classes/Command.ts";
import { HibikiColors } from "$utils/constants.ts";
import { sendErrorReply } from "$utils/error.ts";
import { hibikiFetch } from "$utils/fetch.ts";
import { t } from "$utils/i18n.ts";
import { ApplicationCommandOptionType } from "discord-api-types/v10";
Expand All @@ -25,41 +26,16 @@ export class AnimalCommand extends HibikiCommand {
// Gets the subcommand specified
const subcommand = interaction.options.getSubcommand(true);

// Error handler
if (!subcommand) {
await interaction.followUp({
embeds: [
{
title: t("errors:ERROR", { lng: interaction.locale }),
description: t("errors:ERROR_NO_OPTION_PROVIDED", { lng: interaction.locale }),
color: HibikiColors.ERROR,
footer: {
text: t("errors:ERROR_FOUND_A_BUG", { lng: interaction.locale }),
icon_url: this.bot.user?.displayAvatarURL(),
},
},
],
});

await sendErrorReply("errors:ERROR_NO_OPTION_PROVIDED", interaction);
return;
}

// Gets the image relating to the type of animal
const subcommandResponse = await this.getSubCommandResponse!(subcommand, interaction.locale);
if (!subcommandResponse?.length) {
await interaction.followUp({
embeds: [
{
title: t("errors:ERROR", { lng: interaction.locale }),
description: t("errors:ERROR_IMAGE", { lng: interaction.locale }),
color: HibikiColors.ERROR,
footer: {
text: t("errors:ERROR_FOUND_A_BUG", { lng: interaction.locale }),
icon_url: this.bot.user?.displayAvatarURL(),
},
},
],
});

await sendErrorReply("errors:ERROR_IMAGE", interaction);
return;
}

Expand All @@ -71,9 +47,10 @@ export class AnimalCommand extends HibikiCommand {
color: HibikiColors.GENERAL,
image: {
url: `${subcommandResponse[0]}`,
proxy_url: `${subcommandResponse[0]}`,
},
footer: {
icon_url: this.bot.user?.displayAvatarURL(),
icon_url: interaction.client.user.displayAvatarURL(),
text: `${subcommandResponse[2]}`,
},
},
Expand All @@ -85,64 +62,54 @@ export class AnimalCommand extends HibikiCommand {
switch (commandName) {
// Gets a cat picture
case "cat": {
const apiBaseURL = "https://cataas.com";
const response = await hibikiFetch(`${apiBaseURL}/cat?json=true`);

if (!response) {
return;
}
const apiBaseURL = "https://api.thecatapi.com";
const response = await hibikiFetch(`${apiBaseURL}/v1/images/search`);
const body = await response?.json();

const body = await response.json();
if (!body?._id) {
// Error handler
if (!(response && body?.[0]?.url)) {
return;
}

// Returns the URL and strings to use
// Returns data
return [
`${apiBaseURL}/cat/${body._id}`,
body[0].url,
t("commands:COMMAND_ANIMAL_CAT", { lng: locale }),
t("api:API_POWERED_BY", { lng: locale, url: apiBaseURL.replace("https://", "") }),
];
}

// Gets a dog picture
case "dog": {
const apiBaseURL = "https://random.dog";
const response = await hibikiFetch(`${apiBaseURL}/woof.json`);
const apiBaseURL = "https://dog.ceo";
const response = await hibikiFetch(`${apiBaseURL}/api/breeds/image/random`);
const body = await response?.json();

if (!response) {
// Error handler
if (!(response && body?.message) || body?.status !== "success") {
return;
}

const body = await response.json();
if (!body?.url) {
return;
}

// Returns the URL and a string to use for the embed title
// Returns data
return [
body.url,
body.message,
t("commands:COMMAND_ANIMAL_DOG", { lng: locale }),
t("api:API_POWERED_BY", { lng: locale, url: apiBaseURL.replace("https://", "") }),
];
}

// Gets a fox picture
case "fox": {
// todo type
const apiBaseURL = "https://randomfox.ca";
const response = await hibikiFetch(`${apiBaseURL}/floof/`);
const body = await response?.json();

if (!response) {
return;
}

const body = await response.json();
if (!body?.image) {
// Error handler
if (!(response && body?.image)) {
return;
}

// Returns the URL and strings to use
// Returns data
return [
body.image,
t("commands:COMMAND_ANIMAL_FOX", { lng: locale }),
Expand Down
3 changes: 2 additions & 1 deletion src/commands/avatar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class AvatarCommand extends HibikiCommand {
},
] satisfies HibikiCommandOptions[];

// TODO: Allow running this in DMs
async runCommand(interaction: ChatInputCommandInteraction) {
// Gets the member data and/or the server member data for resolving the avatar URL
const memberToFetch = await interaction.options.getUser((this.options as APIOption[])[0]!.name)?.fetch();
Expand All @@ -38,7 +39,7 @@ export class AvatarCommand extends HibikiCommand {
color: HibikiColors.ERROR,
footer: {
text: t("errors:ERROR_FOUND_A_BUG", { lng: interaction.locale }),
icon_url: this.bot.user?.displayAvatarURL(),
icon_url: interaction.client.user.displayAvatarURL(),
},
},
],
Expand Down
Loading

0 comments on commit 6168269

Please sign in to comment.