aboutsummaryrefslogtreecommitdiff
path: root/src/lib/extensions/Util.ts
diff options
context:
space:
mode:
authorIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-06-19 16:43:37 -0400
committerIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-06-19 16:43:37 -0400
commitea64ebfff9aae32deb036643422d3427959dcd24 (patch)
tree5ab83558642bad282515837424637070f547a05e /src/lib/extensions/Util.ts
parentd055e0dbb86ef7fd4ee96a1531b51181e825fb4b (diff)
downloadtanzanite-ea64ebfff9aae32deb036643422d3427959dcd24.tar.gz
tanzanite-ea64ebfff9aae32deb036643422d3427959dcd24.tar.bz2
tanzanite-ea64ebfff9aae32deb036643422d3427959dcd24.zip
feat(*): A bunch of stuff
- Remade logging - updated dependencies - started adding custom crap to the command handler - added emojis to stuff - can't remeber other stuff Note: this is currently broken BREAKING CHANGE:
Diffstat (limited to 'src/lib/extensions/Util.ts')
-rw-r--r--src/lib/extensions/Util.ts598
1 files changed, 0 insertions, 598 deletions
diff --git a/src/lib/extensions/Util.ts b/src/lib/extensions/Util.ts
deleted file mode 100644
index 3913437..0000000
--- a/src/lib/extensions/Util.ts
+++ /dev/null
@@ -1,598 +0,0 @@
-import chalk from 'chalk';
-import { exec } from 'child_process';
-import { ClientUtil, Command } from 'discord-akairo';
-import {
- APIInteractionDataResolvedChannel,
- APIInteractionDataResolvedGuildMember,
- APIRole,
- ApplicationCommandOptionType
-} from 'discord-api-types';
-import {
- ButtonInteraction,
- CommandInteractionOption,
- Constants,
- Guild,
- GuildChannel,
- GuildMember,
- MessageActionRow,
- MessageButton,
- MessageComponentInteraction,
- MessageEmbed,
- MessageOptions,
- Role,
- Snowflake,
- User,
- Util
-} from 'discord.js';
-import got from 'got';
-import { promisify } from 'util';
-import { BushClient } from './BushClient';
-import { BushMessage } from './BushMessage';
-
-interface hastebinRes {
- key: string;
-}
-
-export interface uuidRes {
- uuid: string;
- username: string;
- username_history?: { username: string }[] | null;
- textures: {
- custom: boolean;
- slim: boolean;
- skin: {
- url: string;
- data: string;
- };
- raw: {
- value: string;
- signature: string;
- };
- };
- created_at: string;
-}
-
-export interface SlashCommandOption<T> {
- name: string;
- type: ApplicationCommandOptionType;
- value?: T;
- options?: CommandInteractionOption[];
- user?: User;
- member?: GuildMember | APIInteractionDataResolvedGuildMember;
- channel?: GuildChannel | APIInteractionDataResolvedChannel;
- role?: Role | APIRole;
-}
-
-export class BushUtil extends ClientUtil {
- /**
- * The client of this ClientUtil
- * @type {BushClient}
- */
- public client: BushClient;
- /**
- * The hastebin urls used to post to hastebin, attempts to post in order
- * @type {string[]}
- */
- public hasteURLs = [
- 'https://hst.sh',
- 'https://hasteb.in',
- 'https://hastebin.com',
- 'https://mystb.in',
- 'https://haste.clicksminuteper.net',
- 'https://paste.pythondiscord.com',
- 'https://haste.unbelievaboat.com',
- 'https://haste.tyman.tech'
- ];
- /**
- * A simple promise exec method
- */
- private exec = promisify(exec);
-
- /**
- * Creates this client util
- * @param client The client to initialize with
- */
- constructor(client: BushClient) {
- super(client);
- }
-
- /**
- * Maps an array of user ids to user objects.
- * @param ids The list of IDs to map
- * @returns The list of users mapped
- */
- public async mapIDs(ids: Snowflake[]): Promise<User[]> {
- return await Promise.all(ids.map((id) => this.client.users.fetch(id)));
- }
-
- /**
- * Capitalizes the first letter of the given text
- * @param text The text to capitalize
- * @returns The capitalized text
- */
- public capitalize(text: string): string {
- return text.charAt(0).toUpperCase() + text.slice(1);
- }
-
- /**
- * Runs a shell command and gives the output
- * @param command The shell command to run
- * @returns The stdout and stderr of the shell command
- */
- public async shell(command: string): Promise<{
- stdout: string;
- stderr: string;
- }> {
- return await this.exec(command);
- }
-
- /**
- * Posts text to hastebin
- * @param content The text to post
- * @returns The url of the posted text
- */
- public async haste(content: string): Promise<string> {
- for (const url of this.hasteURLs) {
- try {
- const res: hastebinRes = await got.post(`${url}/documents`, { body: content }).json();
- return `${url}/${res.key}`;
- } catch (e) {
- // pass
- }
- }
- throw new Error('No urls worked. (wtf)');
- }
-
- /**
- * Resolves a user-provided string into a user object, if possible
- * @param text The text to try and resolve
- * @returns The user resolved or null
- */
- public async resolveUserAsync(text: string): Promise<User | null> {
- const idReg = /\d{17,19}/;
- const idMatch = text.match(idReg);
- if (idMatch) {
- try {
- const user = await this.client.users.fetch(text as Snowflake);
- return user;
- } catch {
- // pass
- }
- }
- const mentionReg = /<@!?(?<id>\d{17,19})>/;
- const mentionMatch = text.match(mentionReg);
- if (mentionMatch) {
- try {
- const user = await this.client.users.fetch(mentionMatch.groups.id as Snowflake);
- return user;
- } catch {
- // pass
- }
- }
- const user = this.client.users.cache.find((u) => u.username === text);
- if (user) return user;
- return null;
- }
-
- /**
- * Appends the correct ordinal to the given number
- * @param n The number to append an ordinal to
- * @returns The number with the ordinal
- */
- public ordinal(n: number): string {
- const s = ['th', 'st', 'nd', 'rd'],
- v = n % 100;
- return n + (s[(v - 20) % 10] || s[v] || s[0]);
- }
-
- /**
- * Chunks an array to the specified size
- * @param arr The array to chunk
- * @param perChunk The amount of items per chunk
- * @returns The chunked array
- */
- public chunk<T>(arr: T[], perChunk: number): T[][] {
- return arr.reduce((all, one, i) => {
- const ch = Math.floor(i / perChunk);
- all[ch] = [].concat(all[ch] || [], one);
- return all;
- }, []);
- }
-
- /**
- * The colors used throught the bot
- */
- public colors = {
- default: '#1FD8F1',
- error: '#EF4947',
- warn: '#FEBA12',
- success: '#3BB681',
- red: '#ff0000',
- orange: '#E86100',
- gold: '#b59400',
- yellow: '#ffff00',
- green: '#00ff1e',
- darkGreen: '#008f11',
- aqua: '#00bbff',
- blue: '#0055ff',
- blurple: '#5440cd',
- purple: '#8400ff',
- pink: '#ff00e6',
- white: '#ffffff',
- gray: '#a6a6a6',
- lightGray: '#cfcfcf',
- darkGray: '#7a7a7a',
- black: '#000000'
- };
-
- public emojis = {
- success: '<:checkmark:837109864101707807>',
- warn: '<:warn:848726900876247050> ',
- error: '<:error:837123021016924261>',
- successFull: '<:checkmark_full:850118767576088646>',
- warnFull: '<:warn_full:850118767391539312>',
- errorFull: '<:error_full:850118767295201350>',
- mad: '<:mad:783046135392239626>',
- join: '<:join:850198029809614858>',
- leave: '<:leave:850198048205307919>'
- };
-
- /**
- * A simple utility to create and embed with the needed style for the bot
- */
- public createEmbed(color?: string, author?: User | GuildMember): MessageEmbed {
- if (author instanceof GuildMember) {
- author = author.user; // Convert to User if GuildMember
- }
- let embed = new MessageEmbed().setTimestamp();
- if (author)
- embed = embed.setAuthor(
- author.username,
- author.displayAvatarURL({ dynamic: true }),
- `https://discord.com/users/${author.id}`
- );
- if (color) embed = embed.setColor(color);
- return embed;
- }
-
- public async mcUUID(username: string): Promise<string> {
- const apiRes = (await got.get(`https://api.ashcon.app/mojang/v2/user/${username}`).json()) as uuidRes;
- return apiRes.uuid.replace(/-/g, '');
- }
-
- public async syncSlashCommands(force = false, guild?: Snowflake): Promise<void> {
- let fetchedGuild: Guild;
- if (guild) fetchedGuild = this.client.guilds.cache.get(guild);
- try {
- const registered =
- guild === undefined ? await this.client.application.commands.fetch() : await fetchedGuild.commands.fetch();
- for (const [, registeredCommand] of registered) {
- if (!this.client.commandHandler.modules.find((cmd) => cmd.id == registeredCommand.name)?.execSlash || force) {
- guild === undefined
- ? await this.client.application.commands.delete(registeredCommand.id)
- : await fetchedGuild.commands.delete(registeredCommand.id);
- this.client.logger.verbose(
- chalk`{red Deleted slash command ${registeredCommand.name}${
- guild !== undefined ? ` in guild ${fetchedGuild.name}` : ''
- }}`
- );
- }
- }
-
- for (const [, botCommand] of this.client.commandHandler.modules) {
- if (botCommand.execSlash) {
- const found = registered.find((i) => i.name == botCommand.id);
- Command;
- const slashdata = {
- name: botCommand.id,
- description: botCommand.description.content,
- options: botCommand.options.slashCommandOptions
- };
- botCommand;
-
- if (found?.id && !force) {
- if (slashdata.description !== found.description) {
- guild === undefined
- ? await this.client.application.commands.edit(found.id, slashdata)
- : fetchedGuild.commands.edit(found.id, slashdata);
- this.client.logger.verbose(
- chalk`{yellow Edited slash command ${botCommand.id}${
- guild !== undefined ? ` in guild ${fetchedGuild.name}` : ''
- }}`
- );
- }
- } else {
- guild === undefined
- ? await this.client.application.commands.create(slashdata)
- : fetchedGuild.commands.create(slashdata);
- this.client.logger.verbose(
- chalk`{green Created slash command ${botCommand.id}${
- guild !== undefined ? ` in guild ${fetchedGuild.name}` : ''
- }}`
- );
- }
- }
- }
-
- return this.client.logger.log(
- chalk.green(`Slash commands registered${guild !== undefined ? ` in guild ${fetchedGuild.name}` : ''}`)
- );
- } catch (e) {
- console.log(chalk.red(e.stack));
- return this.client.logger.error(
- chalk`{red Slash commands not registered${
- guild !== undefined ? ` in guild ${fetchedGuild.name}` : ''
- }, see above error.}`
- );
- }
- }
-
- public moulberryBushRoleMap = [
- { name: '*', id: '792453550768390194' },
- { name: 'Admin Perms', id: '746541309853958186' },
- { name: 'Sr. Moderator', id: '782803470205190164' },
- { name: 'Moderator', id: '737308259823910992' },
- { name: 'Helper', id: '737440116230062091' },
- { name: 'Trial Helper', id: '783537091946479636' },
- { name: 'Contributor', id: '694431057532944425' },
- { name: 'Giveaway Donor', id: '784212110263451649' },
- { name: 'Giveaway (200m)', id: '810267756426690601' },
- { name: 'Giveaway (100m)', id: '801444430522613802' },
- { name: 'Giveaway (50m)', id: '787497512981757982' },
- { name: 'Giveaway (25m)', id: '787497515771232267' },
- { name: 'Giveaway (10m)', id: '787497518241153025' },
- { name: 'Giveaway (5m)', id: '787497519768403989' },
- { name: 'Giveaway (1m)', id: '787497521084891166' },
- { name: 'Suggester', id: '811922322767609877' },
- { name: 'Partner', id: '767324547312779274' },
- { name: 'Level Locked', id: '784248899044769792' },
- { name: 'No Files', id: '786421005039173633' },
- { name: 'No Reactions', id: '786421270924361789' },
- { name: 'No Links', id: '786421269356740658' },
- { name: 'No Bots', id: '786804858765312030' },
- { name: 'No VC', id: '788850482554208267' },
- { name: 'No Giveaways', id: '808265422334984203' },
- { name: 'No Support', id: '790247359824396319' }
- ];
-
- private paginateEmojis = {
- begging: '853667381335162910',
- back: '853667410203770881',
- stop: '853667471110570034',
- forward: '853667492680564747',
- end: '853667514915225640'
- };
-
- public async buttonPaginate(
- message: BushMessage,
- embeds: MessageEmbed[],
- text: string | null = null,
- deleteOnExit?: boolean
- ): Promise<void> {
- if (deleteOnExit === undefined) deleteOnExit = true;
- embeds.forEach((_e, i) => {
- embeds[i] = embeds[i].setFooter(`Page ${i + 1}/${embeds.length}`);
- });
-
- const style = Constants.MessageButtonStyles.PRIMARY;
- let curPage = 0;
- if (typeof embeds !== 'object') throw 'embeds must be an object';
- const msg = await message.util.reply({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow()] });
- const filter = (interaction: ButtonInteraction) =>
- interaction.customID.startsWith('paginate_') && interaction.message == msg;
- const collector = msg.createMessageComponentInteractionCollector(filter, { time: 300000 });
- collector.on('collect', async (interaction: MessageComponentInteraction) => {
- if (interaction.user.id == message.author.id || message.client.config.owners.includes(interaction.user.id)) {
- switch (interaction.customID) {
- case 'paginate_beginning': {
- curPage = 0;
- await edit(interaction);
- break;
- }
- case 'paginate_back': {
- curPage--;
- await edit(interaction);
- break;
- }
- case 'paginate_stop': {
- if (deleteOnExit) {
- await interaction.deferUpdate();
- await msg.delete();
- } else {
- await interaction?.update({
- content: `${text ? text + '\n' : ''}Command closed by user.`,
- embeds: [],
- components: []
- });
- }
- return;
- }
- case 'paginate_next': {
- curPage++;
- await edit(interaction);
- break;
- }
- case 'paginate_end': {
- curPage = embeds.length - 1;
- await edit(interaction);
- break;
- }
- }
- } else {
- return await interaction?.deferUpdate();
- }
- });
-
- collector.on('end', async () => {
- await msg.edit({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow(true)] }).catch(() => {});
- });
-
- async function edit(interaction: MessageComponentInteraction): Promise<void> {
- return await interaction?.update({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow()] });
- }
- function getPaginationRow(disableAll = false): MessageActionRow {
- return new MessageActionRow().addComponents(
- new MessageButton({
- style,
- customID: 'paginate_beginning',
- emoji: this.paginateEmojis.begging,
- disabled: disableAll || curPage == 0
- }),
- new MessageButton({
- style,
- customID: 'paginate_back',
- emoji: this.paginateEmojis.back,
- disabled: disableAll || curPage == 0
- }),
- new MessageButton({ style, customID: 'paginate_stop', emoji: this.paginateEmojis.stop, disabled: disableAll }),
- new MessageButton({
- style,
- customID: 'paginate_next',
- emoji: this.paginateEmojis.forward,
- disabled: disableAll || curPage == embeds.length - 1
- }),
- new MessageButton({
- style,
- customID: 'paginate_end',
- emoji: this.paginateEmojis.end,
- disabled: disableAll || curPage == embeds.length - 1
- })
- );
- }
- }
-
- public async sendWithDeleteButton(message: BushMessage, options: MessageOptions): Promise<void> {
- updateOptions();
- const msg = await message.util.reply(options as MessageOptions & { split?: false });
- const filter = (interaction: ButtonInteraction) => interaction.customID == 'paginate__stop' && interaction.message == msg;
- const collector = msg.createMessageComponentInteractionCollector(filter, { time: 300000 });
- collector.on('collect', async (interaction: MessageComponentInteraction) => {
- if (interaction.user.id == message.author.id || message.client.config.owners.includes(interaction.user.id)) {
- await interaction.deferUpdate();
- await msg.delete();
- return;
- } else {
- return await interaction?.deferUpdate();
- }
- });
-
- collector.on('end', async () => {
- updateOptions(true, true);
- await msg.edit(options);
- });
-
- function updateOptions(edit?: boolean, disable?: boolean) {
- if (edit == undefined) edit = false;
- if (disable == undefined) disable = false;
- options.components = [
- new MessageActionRow().addComponents(
- new MessageButton({
- style: Constants.MessageButtonStyles.PRIMARY,
- customID: 'paginate__stop',
- emoji: this.paginateEmojis.stop,
- disabled: disable
- })
- )
- ];
- if (edit) {
- options.reply = undefined;
- }
- }
- }
- /**
- * Surrounds text in a code block with the specified language and puts it in a haste bin if it too long.
- *
- * * Embed Description Limit = 2048 characters
- * * Embed Field Limit = 1024 characters
- */
- public async codeblock(code: string, length: number, language: 'ts' | 'js' | 'sh' | 'json' | '' = ''): Promise<string> {
- let hasteOut = '';
- const tildes = '```';
- const formattingLength = 2 * tildes.length + language.length + 2 * '\n'.length;
- if (code.length + formattingLength > length) hasteOut = 'Too large to display. Hastebin: ' + (await this.haste(code));
-
- const code2 = code.length > length ? code.substring(0, length - (hasteOut.length + '\n'.length + formattingLength)) : code;
- return (
- tildes + language + '\n' + Util.cleanCodeBlockContent(code2) + '\n' + tildes + (hasteOut.length ? '\n' + hasteOut : '')
- );
- }
-}
-
-// I just copy pasted this code from stackoverflow don't yell at me if there is issues for it
-export class CanvasProgressBar {
- private x: number;
- private y: number;
- private w: number;
- private h: number;
- private color: string;
- private percentage: number;
- private p: number;
- private ctx: CanvasRenderingContext2D;
-
- constructor(
- ctx: CanvasRenderingContext2D,
- dimension: { x: number; y: number; width: number; height: number },
- color: string,
- percentage: number
- ) {
- ({ x: this.x, y: this.y, width: this.w, height: this.h } = dimension);
- this.color = color;
- this.percentage = percentage;
- this.p;
- this.ctx = ctx;
- }
-
- draw() {
- // -----------------
- this.p = this.percentage * this.w;
- if (this.p <= this.h) {
- this.ctx.beginPath();
- this.ctx.arc(
- this.h / 2 + this.x,
- this.h / 2 + this.y,
- this.h / 2,
- Math.PI - Math.acos((this.h - this.p) / this.h),
- Math.PI + Math.acos((this.h - this.p) / this.h)
- );
- this.ctx.save();
- this.ctx.scale(-1, 1);
- this.ctx.arc(
- this.h / 2 - this.p - this.x,
- this.h / 2 + this.y,
- this.h / 2,
- Math.PI - Math.acos((this.h - this.p) / this.h),
- Math.PI + Math.acos((this.h - this.p) / this.h)
- );
- this.ctx.restore();
- this.ctx.closePath();
- } else {
- this.ctx.beginPath();
- this.ctx.arc(this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, Math.PI / 2, (3 / 2) * Math.PI);
- this.ctx.lineTo(this.p - this.h + this.x, 0 + this.y);
- this.ctx.arc(this.p - this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, (3 / 2) * Math.PI, Math.PI / 2);
- this.ctx.lineTo(this.h / 2 + this.x, this.h + this.y);
- this.ctx.closePath();
- }
- this.ctx.fillStyle = this.color;
- this.ctx.fill();
- }
-
- // showWholeProgressBar(){
- // this.ctx.beginPath();
- // this.ctx.arc(this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, Math.PI / 2, 3 / 2 * Math.PI);
- // this.ctx.lineTo(this.w - this.h + this.x, 0 + this.y);
- // this.ctx.arc(this.w - this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, 3 / 2 *Math.PI, Math.PI / 2);
- // this.ctx.lineTo(this.h / 2 + this.x, this.h + this.y);
- // this.ctx.strokeStyle = '#000000';
- // this.ctx.stroke();
- // this.ctx.closePath();
- // }
-
- get PPercentage() {
- return this.percentage * 100;
- }
-
- set PPercentage(x) {
- this.percentage = x / 100;
- }
-}