aboutsummaryrefslogtreecommitdiff
path: root/src/commands/utilities
diff options
context:
space:
mode:
authorIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-07-17 10:25:46 -0400
committerIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-07-17 10:25:46 -0400
commitd1724227abfb8f0fcd9e573f7e9772cf0be8257a (patch)
tree52c9dbae1fbbbd3c777d9c16ab643c477141ae21 /src/commands/utilities
parent53d2b18f7f73d5696fb7cd86d1c164a790dfdcc3 (diff)
downloadtanzanite-d1724227abfb8f0fcd9e573f7e9772cf0be8257a.tar.gz
tanzanite-d1724227abfb8f0fcd9e573f7e9772cf0be8257a.tar.bz2
tanzanite-d1724227abfb8f0fcd9e573f7e9772cf0be8257a.zip
honestly no idea what I did at this point
Diffstat (limited to 'src/commands/utilities')
-rw-r--r--src/commands/utilities/_whoHasRole.ts0
-rw-r--r--src/commands/utilities/hash.ts42
-rw-r--r--src/commands/utilities/price.ts220
-rw-r--r--src/commands/utilities/viewraw.ts2
-rw-r--r--src/commands/utilities/whoHasRole.ts53
5 files changed, 316 insertions, 1 deletions
diff --git a/src/commands/utilities/_whoHasRole.ts b/src/commands/utilities/_whoHasRole.ts
deleted file mode 100644
index e69de29..0000000
--- a/src/commands/utilities/_whoHasRole.ts
+++ /dev/null
diff --git a/src/commands/utilities/hash.ts b/src/commands/utilities/hash.ts
new file mode 100644
index 0000000..4b5b01c
--- /dev/null
+++ b/src/commands/utilities/hash.ts
@@ -0,0 +1,42 @@
+import crypto from 'crypto';
+import { Constants } from 'discord-akairo';
+import got from 'got';
+import { BushCommand, BushMessage } from '../../lib';
+
+export default class HashCommand extends BushCommand {
+ constructor() {
+ super('hash', {
+ aliases: ['hash'],
+ category: 'utilities',
+ description: {
+ content: 'Gets the file hash of the given discord link',
+ usage: 'hash <file url>',
+ examples: ['hash https://cdn.discordapp.com/emojis/782630946435366942.png?v=1'] //nice
+ },
+ args: [
+ {
+ id: 'url',
+ type: Constants.ArgumentTypes.URL,
+ match: Constants.ArgumentMatches.PHRASE,
+ prompt: {
+ start: 'What url would you like to find the hash of?',
+ retry: '{error} Enter a valid url.'
+ }
+ }
+ ],
+ clientPermissions: ['SEND_MESSAGES']
+ });
+ }
+
+ public async exec(message: BushMessage, { url }: { url: string }): Promise<void> {
+ try {
+ const req = await got.get(url);
+ const rawHash = crypto.createHash('md5');
+ rawHash.update(req.rawBody.toString('binary'));
+ const hash = rawHash.digest('hex');
+ await message.util.reply(`\`${hash}\``);
+ } catch {
+ await message.util.reply('Unable to calculate hash.');
+ }
+ }
+}
diff --git a/src/commands/utilities/price.ts b/src/commands/utilities/price.ts
new file mode 100644
index 0000000..231930c
--- /dev/null
+++ b/src/commands/utilities/price.ts
@@ -0,0 +1,220 @@
+import { Constants } from 'discord-akairo';
+import { ColorResolvable, MessageEmbed } from 'discord.js';
+import Fuse from 'fuse.js';
+import got from 'got';
+import { BushCommand, BushMessage } from '../../lib';
+
+interface Summary {
+ amount: number;
+ pricePerUnit: number;
+ orders: number;
+}
+
+interface Bazaar {
+ success: boolean;
+ lastUpdated: number;
+ products: {
+ [key: string]: {
+ product_id: string;
+ sell_summary: Summary[];
+ buy_summary: Summary[];
+ quick_status: {
+ productId: string;
+ sellPrice: number;
+ sellVolume: number;
+ sellMovingWeek: number;
+ sellOrders: number;
+ buyPrice: number;
+ buyVolume: number;
+ buyMovingWeek: number;
+ buyOrders: number;
+ };
+ };
+ };
+}
+
+interface LowestBIN {
+ [key: string]: number;
+}
+
+interface AuctionAverages {
+ [key: string]: {
+ price?: number;
+ count?: number;
+ sales?: number;
+ clean_price?: number;
+ clean_sales?: number;
+ };
+}
+
+export default class PriceCommand extends BushCommand {
+ public constructor() {
+ super('price', {
+ aliases: ['price'],
+ category: 'utilities',
+ clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES'],
+ description: {
+ usage: 'price <item id>',
+ examples: ['price ASPECT_OF_THE_END'],
+ content: 'Finds the price information of an item.'
+ },
+ ratelimit: 4,
+ cooldown: 4000,
+ typing: true,
+ args: [
+ {
+ id: 'item',
+ match: Constants.ArgumentMatches.CONTENT,
+ type: Constants.ArgumentTypes.STRING,
+ prompt: {
+ start: 'What item would you like to find the price of?',
+ retry: '{error} Choose a valid item.'
+ }
+ },
+ {
+ id: 'strict',
+ match: Constants.ArgumentMatches.FLAG,
+ flag: '--strict',
+ default: false
+ }
+ ],
+ slash: true,
+ slashOptions: [
+ {
+ name: 'item',
+ description: 'The item that you would you like to find the price of.',
+ type: 'STRING',
+ required: true
+ },
+ {
+ name: 'strict',
+ description: 'Whether or not to bypass the fuzzy search.',
+ type: 'BOOLEAN',
+ required: false
+ }
+ ]
+ });
+ }
+
+ public async exec(message: BushMessage, { item, strict }: { item: string; strict: boolean }): Promise<unknown> {
+ const errors = new Array<string>();
+ const bazaar: Bazaar = await get('https://api.hypixel.net/skyblock/bazaar').catch(() => errors.push('bazaar'));
+ const currentLowestBIN: LowestBIN = await get('https://moulberry.codes/lowestbin.json').catch(() =>
+ errors.push('current lowest BIN')
+ );
+ const averageLowestBIN: LowestBIN = await get('https://moulberry.codes/auction_averages_lbin/3day.json').catch(() =>
+ errors.push('average Lowest BIN')
+ );
+ const auctionAverages: AuctionAverages = await get('https://moulberry.codes/auction_averages/3day.json').catch(() =>
+ errors.push('auction average')
+ );
+ // adds _ to item name
+ let parsedItem = item.toString().toUpperCase().replace(/ /g, '_').replace(/'S/g, '');
+ const priceEmbed = new MessageEmbed();
+
+ if (errors?.length) {
+ priceEmbed.setFooter;
+ }
+
+ //combines all the item names from each
+ const itemNames = Array.from(
+ new Set(
+ (averageLowestBIN ? Object.keys(averageLowestBIN) : []).concat(
+ currentLowestBIN ? Object.keys(currentLowestBIN) : [],
+ auctionAverages ? Object.keys(auctionAverages) : [],
+ bazaar?.products ? Object.keys(bazaar.products) : []
+ )
+ )
+ );
+
+ // fuzzy search
+ if (!strict) {
+ parsedItem = new Fuse(itemNames)?.search(parsedItem)[0]?.item;
+ }
+
+ // If bazaar item then it there should not be any ah data
+ if (bazaar['products'][parsedItem]) {
+ const bazaarPriceEmbed = new MessageEmbed()
+ .setColor(
+ errors?.length
+ ? (this.client.util.emojis.warn as ColorResolvable)
+ : (this.client.util.colors.success as ColorResolvable)
+ )
+ .setTitle(`Bazaar Information for \`${parsedItem}\``)
+ .addField('Sell Price', Bazaar('sellPrice', 2, true))
+ .addField('Buy Price', Bazaar('buyPrice', 2, true))
+ .addField('Margin', (Number(Bazaar('buyPrice', 2, false)) - Number(Bazaar('sellPrice', 2, false))).toLocaleString())
+ .addField('Current Sell Orders', Bazaar('sellOrders', 0, true))
+ .addField('Current Buy Orders', Bazaar('buyOrders', 0, true));
+ return await message.util.reply({ embeds: [bazaarPriceEmbed] });
+ }
+
+ // Checks if the item exists in any of the action information otherwise it is not a valid item
+ if (currentLowestBIN?.[parsedItem] || averageLowestBIN?.[parsedItem] || auctionAverages?.[parsedItem]) {
+ priceEmbed
+ .setColor(this.client.util.colors.success)
+ .setTitle(`Price Information for \`${parsedItem}\``)
+ .setFooter('All information is based on the last 3 days.');
+ } else {
+ const errorEmbed = new MessageEmbed();
+ errorEmbed
+ .setColor(this.client.util.colors.error)
+ .setDescription(
+ `${this.client.util.emojis.error} \`${parsedItem}\` is not a valid item id, or it has no auction data.`
+ );
+ return await message.util.reply({ embeds: [errorEmbed] });
+ }
+
+ if (currentLowestBIN?.[parsedItem]) {
+ const currentLowestBINPrice = currentLowestBIN[parsedItem].toLocaleString();
+ priceEmbed.addField('Current Lowest BIN', currentLowestBINPrice);
+ }
+ if (averageLowestBIN?.[parsedItem]) {
+ const averageLowestBINPrice = averageLowestBIN[parsedItem].toLocaleString();
+ priceEmbed.addField('Average Lowest BIN', averageLowestBINPrice);
+ }
+ if (auctionAverages?.[parsedItem]?.price) {
+ const auctionAveragesPrice = auctionAverages[parsedItem].price.toLocaleString();
+ priceEmbed.addField('Average Auction Price', auctionAveragesPrice);
+ }
+ if (auctionAverages?.[parsedItem]?.count) {
+ const auctionAveragesCountPrice = auctionAverages[parsedItem].count.toLocaleString();
+ priceEmbed.addField('Average Auction Count', auctionAveragesCountPrice);
+ }
+ if (auctionAverages?.[parsedItem]?.sales) {
+ const auctionAveragesSalesPrice = auctionAverages[parsedItem].sales.toLocaleString();
+ priceEmbed.addField('Average Auction Sales', auctionAveragesSalesPrice);
+ }
+ if (auctionAverages?.[parsedItem]?.clean_price) {
+ const auctionAveragesCleanPrice = auctionAverages[parsedItem].clean_price.toLocaleString();
+ priceEmbed.addField('Average Auction Clean Price', auctionAveragesCleanPrice);
+ }
+ if (auctionAverages?.[parsedItem]?.clean_sales) {
+ const auctionAveragesCleanSales = auctionAverages[parsedItem].clean_sales.toLocaleString();
+ priceEmbed.addField('Average Auction Clean Sales', auctionAveragesCleanSales);
+ }
+ return await message.util.reply({ embeds: [priceEmbed] });
+
+ //Helper functions
+ function Bazaar(Information: string, digits: number, commas: boolean): string {
+ const price = bazaar?.products[parsedItem]?.quick_status?.[Information];
+ const a = Number(Number(price).toFixed(digits));
+ return commas ? a?.toLocaleString() : a?.toString();
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async function get(url: string): Promise<any> {
+ const data = await got.get(url).catch((error) => {
+ this.client.console.warn('PriceCommand', `There was an problem fetching data from <<${url}>> with error:\n${error}`);
+ throw 'Error Fetching price data';
+ });
+ try {
+ const json = JSON.parse(data.body);
+ return json;
+ } catch (error) {
+ this.client.console.warn('PriceCommand', `There was an problem parsing data from <<${url}>> with error:\n${error}`);
+ throw 'json error';
+ }
+ }
+ }
+}
diff --git a/src/commands/utilities/viewraw.ts b/src/commands/utilities/viewraw.ts
index 7642b2a..3658bde 100644
--- a/src/commands/utilities/viewraw.ts
+++ b/src/commands/utilities/viewraw.ts
@@ -7,7 +7,7 @@ export default class ViewRawCommand extends BushCommand {
public constructor() {
super('viewraw', {
aliases: ['viewraw'],
- category: 'info',
+ category: 'utilities',
clientPermissions: ['EMBED_LINKS'],
description: {
usage: 'viewraw <message id> <channel>',
diff --git a/src/commands/utilities/whoHasRole.ts b/src/commands/utilities/whoHasRole.ts
new file mode 100644
index 0000000..1828c95
--- /dev/null
+++ b/src/commands/utilities/whoHasRole.ts
@@ -0,0 +1,53 @@
+import { BushCommand, BushMessage, BushSlashMessage } from '@lib';
+import { MessageEmbed, Role, Util } from 'discord.js';
+
+export default class WhoHasRoleCommand extends BushCommand {
+ public constructor() {
+ super('whohasrole', {
+ aliases: ['whohasrole'],
+ category: 'utilities',
+ description: {
+ content: 'Allows you to view what users have a certain role.',
+ usage: 'template <requiredArg> [optionalArg]',
+ examples: ['template 1 2']
+ },
+ args: [
+ {
+ id: 'role',
+ type: 'role',
+ prompt: {
+ start: 'What role would you like to find the users of?',
+ retry: '{error} Pick a valid role.',
+ optional: false
+ }
+ }
+ ],
+ slash: true,
+ slashOptions: [
+ {
+ name: 'role',
+ description: 'What role would you like to find the users of?',
+ type: 'ROLE',
+ required: true
+ }
+ ],
+ channel: 'guild',
+ clientPermissions: ['SEND_MESSAGES'],
+ userPermissions: ['SEND_MESSAGES']
+ });
+ }
+ public async exec(message: BushMessage | BushSlashMessage, args: { role: Role }): Promise<unknown> {
+ const roleMembers = args.role.members.map((member) => `${member.user} (${Util.escapeMarkdown(member.user.tag)})`);
+
+ const chunkedRoleMembers = this.client.util.chunk(roleMembers, 30);
+ const embedPages = chunkedRoleMembers.map(
+ (chunk) =>
+ new MessageEmbed({
+ title: `${args.role.name}'s Members`,
+ description: chunk.join('\n'),
+ color: this.client.util.colors.default
+ })
+ );
+ return await this.client.util.buttonPaginate(message, embedPages, null, true);
+ }
+}