mirror of
https://github.com/artiemis/artemis.js.git
synced 2026-02-14 02:11:55 +00:00
133 lines
3.4 KiB
TypeScript
133 lines
3.4 KiB
TypeScript
import * as cheerio from "cheerio";
|
|
import { execa } from "execa";
|
|
import { customAlphabet } from "nanoid";
|
|
import { URL_REGEX } from "./constants";
|
|
import {
|
|
ChannelType,
|
|
Message,
|
|
MessageContextMenuCommandInteraction,
|
|
MessageFlags,
|
|
ModalSubmitInteraction,
|
|
type ChatInputCommandInteraction,
|
|
} from "discord.js";
|
|
import { abort } from "./error";
|
|
|
|
export const nanoid = customAlphabet("1234567890abcdef");
|
|
export const shell = execa({ reject: false });
|
|
const languageNames = new Intl.DisplayNames(["en"], { type: "language" });
|
|
|
|
export function noop() {}
|
|
|
|
export function pickRandom<T>(arr: T[]): T {
|
|
return arr[Math.floor(Math.random() * arr.length)];
|
|
}
|
|
|
|
export function sleep(ms: number) {
|
|
return new Promise<void>(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
export function chunk<T>(arr: T[], size: number): T[][];
|
|
export function chunk(arr: string, size: number): string[];
|
|
export function chunk(arr: any, size: number): any[] {
|
|
return Array.from({ length: Math.ceil(arr.length / size) }, (_, i) =>
|
|
arr.slice(i * size, i * size + size)
|
|
);
|
|
}
|
|
|
|
export function stripHtml(html: string) {
|
|
return cheerio.load(html).text();
|
|
}
|
|
|
|
export function pluralize(
|
|
value: number,
|
|
singular: string,
|
|
plural = singular + "s"
|
|
) {
|
|
return value === 1 ? `${value} ${singular}` : `${value} ${plural}`;
|
|
}
|
|
|
|
export function run<T>(fn: () => T): T {
|
|
return fn();
|
|
}
|
|
|
|
export async function silently<T extends Promise<any>>(p?: T) {
|
|
try {
|
|
return await p;
|
|
} catch {}
|
|
}
|
|
|
|
export function lazy<T>(cb: () => T) {
|
|
let defaultValue: T;
|
|
|
|
return () => (defaultValue ??= cb());
|
|
}
|
|
|
|
export function trim(str: string, maxLength: number) {
|
|
return str.length > maxLength ? str.slice(0, maxLength) + "…" : str;
|
|
}
|
|
|
|
export function findUrls(text: string) {
|
|
return text.match(URL_REGEX) ?? [];
|
|
}
|
|
|
|
export function findFirstUrl(text: string) {
|
|
return findUrls(text)[0];
|
|
}
|
|
|
|
export function capitalize(str: string) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
|
|
export function getImageUrlFromChatInteraction(
|
|
interaction: ChatInputCommandInteraction,
|
|
attachmentName = "image",
|
|
urlName = "url"
|
|
) {
|
|
const attachment = interaction.options.getAttachment(attachmentName);
|
|
const url = interaction.options.getString(urlName);
|
|
|
|
return (
|
|
(attachment?.contentType?.startsWith("image/") && attachment.url) ||
|
|
(url && findFirstUrl(url)) ||
|
|
abort("You must provide a valid image or image URL!")
|
|
);
|
|
}
|
|
|
|
export function getImageUrlFromMessage(message: Message): string {
|
|
const attachment = message.attachments.first();
|
|
|
|
return (
|
|
(attachment?.contentType?.startsWith("image/") && attachment.url) ||
|
|
message.embeds[0]?.image?.url ||
|
|
message.embeds[0]?.thumbnail?.url ||
|
|
findFirstUrl(message.content) ||
|
|
abort("No valid image found!")
|
|
);
|
|
}
|
|
|
|
export function languageCodeToName(code: string) {
|
|
try {
|
|
return languageNames.of(code);
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
// deferReply helper with flag heuristics
|
|
export async function defer(
|
|
interaction:
|
|
| MessageContextMenuCommandInteraction
|
|
| ModalSubmitInteraction
|
|
| ChatInputCommandInteraction
|
|
) {
|
|
const isDMBased = interaction.channel?.isDMBased();
|
|
const isBotDM =
|
|
isDMBased &&
|
|
interaction.channel.type === ChannelType.DM &&
|
|
interaction.channel.recipientId === interaction.client.user.id;
|
|
|
|
await interaction.deferReply({
|
|
flags: isDMBased && !isBotDM ? MessageFlags.Ephemeral : undefined,
|
|
});
|
|
}
|