diff --git a/src/class/Client.ts b/src/class/Client.ts index ef01bed..075d6dd 100644 --- a/src/class/Client.ts +++ b/src/class/Client.ts @@ -88,6 +88,14 @@ export default class Client extends eris.Client { const cmdFiles = Object.values(commandFiles); for (const Cmd of cmdFiles) { const command = new Cmd(this); + if (command.subcmds.length) { + command.subcmds.forEach((C) => { + const cmd: Command = new C(this); + command.subcommands.add(cmd.name, cmd); + this.util.signale.success(`Successfully loaded subcommand ${cmd.name} under ${command.name}`); + }); + } + delete command.subcmds; this.commands.add(command.name, command); this.util.signale.success(`Successfully loaded command: ${command.name}`); } diff --git a/src/class/Command.ts b/src/class/Command.ts index a7cd877..e84a501 100644 --- a/src/class/Command.ts +++ b/src/class/Command.ts @@ -1,5 +1,5 @@ import { Member, Message, TextableChannel } from 'eris'; -import { Client } from '.'; +import { Client, Collection } from '.'; export default class Command { public client: Client; @@ -44,6 +44,11 @@ export default class Command { /** * Determines if the command is enabled or not. */ + + public subcommands?: Collection; + + public subcmds?: any[]; + public enabled: boolean; public run(message: Message, args: string[]): Promise { return Promise.resolve(); } @@ -52,6 +57,10 @@ export default class Command { this.client = client; this.aliases = []; + + this.subcommands = new Collection(); + + this.subcmds = []; } get mainGuild() { diff --git a/src/class/Util.ts b/src/class/Util.ts index 7512762..f21e474 100644 --- a/src/class/Util.ts +++ b/src/class/Util.ts @@ -43,7 +43,7 @@ export default class Util { * @param query Command input * @param message Only used to check for errors */ - public resolveCommand(query: string | string[]): Promise<{cmd: Command, args: string[] }> { + /* public resolveCommand(query: string | string[]): Promise<{cmd: Command, args: string[] }> { try { if (typeof query === 'string') query = query.split(' '); const commands = this.client.commands.toArray(); @@ -56,6 +56,36 @@ export default class Util { return Promise.reject(error); } } + */ + + /** + * Resolves a command + * @param query Command input + * @param message Only used to check for errors + */ + public resolveCommand(query: string | string[], message?: Message): Promise<{cmd: Command, args: string[] }> { + try { + let resolvedCommand: Command; + if (typeof query === 'string') query = query.split(' '); + const commands = this.client.commands.toArray(); + resolvedCommand = commands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase())); + + if (!resolvedCommand) return Promise.resolve(null); + query.shift(); + while (resolvedCommand.subcommands.size && query.length) { + const subCommands = resolvedCommand.subcommands.toArray(); + const found = subCommands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase())); + if (!found) break; + resolvedCommand = found; + query.shift(); + } + return Promise.resolve({ cmd: resolvedCommand, args: query }); + } catch (error) { + if (message) this.handleError(error, message); + else this.handleError(error); + return Promise.reject(error); + } + } public resolveGuildChannel(query: string, { channels }: Guild, categories = false): AnyGuildChannel | undefined { const ch: AnyGuildChannel[] = channels.filter((c) => (!categories ? c.type !== 4 : true)); diff --git a/src/commands/help.ts b/src/commands/help.ts index cc19db1..103658e 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -15,24 +15,27 @@ export default class Help extends Command { public async run(message: Message, args: string[]) { try { if (args.length > 0) { - const command = this.client.commands.get(args[0].toLowerCase()); - if (!command) return this.error(message.channel, 'The command you provided doesn\'t exist.'); + const resolved = await this.client.util.resolveCommand(args, message); + if (!resolved) return this.error(message.channel, 'The command you provided doesn\'t exist.'); + const { cmd } = resolved; const embed = new RichEmbed(); - embed.setTitle(`${this.client.config.prefix}${command.name}`); - embed.addField('Description', command.description ?? '-'); - embed.addField('Usage', command.usage ?? '-'); - if (command.aliases.length > 0) { - embed.addField('Aliases', command.aliases.map((alias) => `${this.client.config.prefix}${alias}`).join(', ')); + const subcommands = cmd.subcommands.size ? `\n**Subcommands:** ${cmd.subcommands.map((s) => `${cmd.name} ${s.name}`).join(', ')}` : ''; + embed.setTitle(`${this.client.config.prefix}${cmd.name}`); + embed.addField('Description', cmd.description ?? '-'); + embed.addField('Usage', cmd.usage ?? '-'); + if (subcommands) embed.addField('Sub-commands', subcommands); + if (cmd.aliases.length > 0) { + embed.addField('Aliases', cmd.aliases.map((alias) => `${this.client.config.prefix}${alias}`).join(', ')); } let description: string = ''; - if (!command.enabled) { + if (!cmd.enabled) { description += 'This command is disabled.'; } - if (command.guildOnly) { + if (cmd.guildOnly) { description += 'This command can only be ran in a guild.'; } embed.setDescription(description); - switch (command.permissions) { + switch (cmd.permissions) { case 0: break; case 1: @@ -64,7 +67,13 @@ export default class Help extends Command { return message.channel.createMessage({ embed }); } const cmdList: Command[] = []; - this.client.commands.forEach((c) => cmdList.push(c)); + this.client.commands.forEach((c) => { + if (c.permissions !== 0 && c.guildOnly) { + const check = c.checkCustomPermissions(message.member, c.permissions); + if (!check) return; + } + cmdList.push(c); + }); const commands = this.client.commands.map((c) => { const aliases = c.aliases.map((alias) => `${this.client.config.prefix}${alias}`).join(', '); let perm: string; diff --git a/src/commands/score.ts b/src/commands/score.ts index c612753..10c0882 100644 --- a/src/commands/score.ts +++ b/src/commands/score.ts @@ -1,18 +1,20 @@ /* eslint-disable no-continue */ /* eslint-disable default-case */ import moment from 'moment'; -import { median, mode, mean } from 'mathjs'; import { v4 as uuid } from 'uuid'; -import { createPaginationEmbed } from 'eris-pagination'; import { Message, User, TextChannel } from 'eris'; import { Client, Command, RichEmbed } from '../class'; +import Score_Hist from './score_hist'; +import Score_Notify from './score_notify'; +import Score_Pref from './score_pref'; export default class Score extends Command { constructor(client: Client) { super(client); this.name = 'score'; - this.description = 'Pulls a hard score report for a member.'; - this.usage = `${this.client.config.prefix}score :\n${this.client.config.prefix}score hist \n${this.client.config.prefix}score notify \n${this.client.config.prefix}score \n${this.client.config.prefix}score hist`; + this.description = 'Retreives your Community Report'; + this.usage = `${this.client.config.prefix}score\n${this.client.config.prefix}score :`; + this.subcmds = [Score_Hist, Score_Notify, Score_Pref]; this.permissions = 0; this.guildOnly = false; this.enabled = true; @@ -22,347 +24,6 @@ export default class Score extends Command { try { let check = false; let user: User; - if (args[0] === 'hist') { - if (!args[1] || !this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) { - user = message.author; - if (!user) return this.error(message.channel, 'Member not found.'); - const hists = await this.client.db.ScoreHistorical.find({ userID: user.id }).lean().exec(); - if (!hists) return this.error(message.channel, 'No history found.'); - const histArray: [{ name: string, value: string }?] = []; - const totalArray: number[] = []; - const activityArray: number[] = []; - const moderationArray: number[] = []; - const roleArray: number[] = []; - const cloudServicesArray: number[] = []; - const otherArray: number[] = []; - const miscArray: number[] = []; - for (const hist of hists.reverse()) { - totalArray.push(hist.report.total); - activityArray.push(hist.report.activity); - moderationArray.push(hist.report.moderation); - roleArray.push(hist.report.roles); - cloudServicesArray.push(hist.report.cloudServices); - otherArray.push(hist.report.other); - miscArray.push(hist.report.staff); - let totalScore = '0'; - let activityScore = '0'; - let moderationScore = '0'; - let roleScore = '0'; - let cloudServicesScore = '0'; - let otherScore = '0'; - let miscScore = '0'; - - if (hist.report.total < 200) totalScore = '---'; - else if (hist.report.total > 800) totalScore = '800'; - else totalScore = `${hist.report.total}`; - - if (hist.report.activity < 10) activityScore = '---'; - else if (hist.report.activity > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityScore = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); - else activityScore = `${hist.report.activity}`; - - if (hist.report.roles <= 0) roleScore = '---'; - else if (hist.report.roles > 54) roleScore = '54'; - else roleScore = `${hist.report.roles}`; - - moderationScore = `${hist.report.moderation}`; - - if (hist.report.other === 0) otherScore = '---'; - else otherScore = `${hist.report.other}`; - - if (hist.report.staff <= 0) miscScore = '---'; - else miscScore = `${hist.report.staff}`; - - if (hist.report.cloudServices === 0) cloudServicesScore = '---'; - else if (hist.report.cloudServices > 10) cloudServicesScore = '10'; - else cloudServicesScore = `${hist.report.cloudServices}`; - - let data = ''; - let hardInquiries = 0; - if (hist.report?.inquiries?.length > 0) { - hist.report.inquiries.forEach((inq) => { - const testDate = (new Date(new Date(inq.date).setHours(1460))); - // eslint-disable-next-line no-plusplus - if (testDate > new Date()) hardInquiries++; - }); - data += `__CommScore™:__ ${totalScore}\n__Activity:__ ${activityScore}\n__Roles:__ ${roleScore}\n__Moderation:__ ${moderationScore}\n__Cloud Services:__ ${cloudServicesScore}\n__Other:__ ${otherScore}\n__Misc:__ ${miscScore}\n\n__Hard Inquiries:__ ${hardInquiries}\n__Soft Inquiries:__ ${hist.report.softInquiries?.length ?? '0'}`; - histArray.push({ name: moment(hist.date).calendar(), value: data }); - } - } - - const stat = { - totalMean: mean(totalArray), - totalMode: mode(totalArray), - totalMedian: median(totalArray), - activityMean: mean(activityArray), - rolesMean: mean(roleArray), - moderationMean: mean(moderationArray), - cloudServicesMean: mean(cloudServicesArray), - otherMean: mean(otherArray), - miscMean: mean(miscArray), - }; - const splitHist = this.client.util.splitFields(histArray); - const cmdPages: RichEmbed[] = []; - splitHist.forEach((split) => { - const embed = new RichEmbed(); - embed.setTitle('Historical Community Report'); - let totalMean = '0'; - let totalMedian = '0'; - let totalMode = '0'; - let activityMean = '0'; - let moderationMean = '0'; - let roleMean = '0'; - let cloudServicesMean = '0'; - let otherMean = '0'; - let miscMean = '0'; - - if (stat.totalMean < 200) totalMean = '---'; - else if (stat.totalMean > 800) totalMean = '800'; - else totalMean = `${stat.totalMean}`; - - if (stat.totalMedian < 200) totalMedian = '---'; - else if (stat.totalMedian > 800) totalMedian = '800'; - else totalMedian = `${stat.totalMedian}`; - - if (stat.totalMode < 200) totalMode = '---'; - else if (stat.totalMode > 800) totalMode = '800'; - else totalMode = `${stat.totalMode}`; - - if (stat.activityMean < 10) activityMean = '---'; - else if (stat.activityMean > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityMean = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); - else activityMean = `${stat.activityMean}`; - - if (stat.rolesMean <= 0) roleMean = '---'; - else if (stat.rolesMean > 54) roleMean = '54'; - else roleMean = `${stat.rolesMean}`; - - moderationMean = `${stat.moderationMean}`; - - if (stat.otherMean === 0) otherMean = '---'; - else otherMean = `${stat.otherMean}`; - - if (stat.miscMean <= 0) miscMean = '---'; - else miscMean = `${stat.miscMean}`; - - if (stat.cloudServicesMean === 0) cloudServicesMean = '---'; - else if (stat.cloudServicesMean > 10) cloudServicesMean = '10'; - else cloudServicesMean = `${stat.cloudServicesMean}`; - - embed.setDescription(`__**Statistical Averages**__\n**CommScore™ Mean:** ${totalMean} | **CommScore™ Mode:** ${totalMode} | **CommScore™ Median:** ${totalMedian}\n\n**Activity Mean:** ${activityMean}\n**Roles Mean:** ${roleMean}\n**Moderation Mean:** ${moderationMean}\n**Cloud Services Mean:** ${cloudServicesMean}\n**Other Mean:** ${otherMean}\n**Misc Mean:** ${miscMean}`); - embed.setAuthor(user.username, user.avatarURL); - embed.setThumbnail(user.avatarURL); - embed.setTimestamp(); - embed.setFooter(this.client.user.username, this.client.user.avatarURL); - split.forEach((c) => embed.addField(c.name, c.value)); - return cmdPages.push(embed); - }); - const name = `${user.username} VIA DISCORD - [HISTORICAL]`; - await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name: name.toUpperCase(), date: new Date() } } }); - const embed2 = new RichEmbed(); - embed2.setTitle('Inquiry Notification'); - embed2.setColor('#00FFFF'); - embed2.addField('Member', `${user.username}#${user.discriminator} | <@${user.id}>`, true); - embed2.addField('Type', 'SOFT', true); - embed2.addField('Department/Service', name.toUpperCase(), true); - embed2.setTimestamp(); - embed2.setFooter(this.client.user.username, this.client.user.avatarURL); - const log = this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849'); - log.createMessage({ embed: embed2 }).catch(() => {}); - - - if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] }); - return createPaginationEmbed(message, cmdPages); - } if (args[1] && this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) { - user = this.client.util.resolveMember(args[1], this.mainGuild)?.user; - if (!user) { - const sc = await this.client.db.Score.findOne({ pin: [Number(args[0].split('-')[0]), Number(args[0].split('-')[1]), Number(args[0].split('-')[2])] }); - user = this.client.util.resolveMember(sc.userID, this.mainGuild)?.user; - } - if (!user) return this.error(message.channel, 'Member not found.'); - const hists = await this.client.db.ScoreHistorical.find({ userID: user.id }).lean().exec(); - if (!hists) return this.error(message.channel, 'No history found.'); - const histArray: [{ name: string, value: string }?] = []; - const totalArray: number[] = []; - const activityArray: number[] = []; - const moderationArray: number[] = []; - const roleArray: number[] = []; - const cloudServicesArray: number[] = []; - const otherArray: number[] = []; - const miscArray: number[] = []; - for (const hist of hists.reverse()) { - totalArray.push(hist.report.total); - activityArray.push(hist.report.activity); - moderationArray.push(hist.report.moderation); - roleArray.push(hist.report.roles); - cloudServicesArray.push(hist.report.cloudServices); - otherArray.push(hist.report.other); - miscArray.push(hist.report.staff); - let totalScore = '0'; - let activityScore = '0'; - let moderationScore = '0'; - let roleScore = '0'; - let cloudServicesScore = '0'; - let otherScore = '0'; - let miscScore = '0'; - - if (hist.report.total < 200) totalScore = '---'; - else if (hist.report.total > 800) totalScore = '800'; - else totalScore = `${hist.report.total}`; - - if (hist.report.activity < 10) activityScore = '---'; - else if (hist.report.activity > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityScore = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); - else activityScore = `${hist.report.activity}`; - - if (hist.report.roles <= 0) roleScore = '---'; - else if (hist.report.roles > 54) roleScore = '54'; - else roleScore = `${hist.report.roles}`; - - moderationScore = `${hist.report.moderation}`; - - if (hist.report.other === 0) otherScore = '---'; - else otherScore = `${hist.report.other}`; - - if (hist.report.staff <= 0) miscScore = '---'; - else miscScore = `${hist.report.staff}`; - - if (hist.report.cloudServices === 0) cloudServicesScore = '---'; - else if (hist.report.cloudServices > 10) cloudServicesScore = '10'; - else cloudServicesScore = `${hist.report.cloudServices}`; - - let data = ''; - let hardInquiries = 0; - if (hist.report?.inquiries?.length > 0) { - hist.report.inquiries.forEach((inq) => { - const testDate = (new Date(new Date(inq.date).setHours(1460))); - // eslint-disable-next-line no-plusplus - if (testDate > new Date()) hardInquiries++; - }); - data += `__CommScore™:__ ${totalScore}\n__Activity:__ ${activityScore}\n__Roles:__ ${roleScore}\n__Moderation:__ ${moderationScore}\n__Cloud Services:__ ${cloudServicesScore}\n__Other:__ ${otherScore}\n__Misc:__ ${miscScore}\n\n__Hard Inquiries:__ ${hardInquiries}\n__Soft Inquiries:__ ${hist.report.softInquiries?.length ?? '0'}`; - histArray.push({ name: moment(hist.date).calendar(), value: data }); - } - } - - const stat = { - totalMean: mean(totalArray), - totalMode: mode(totalArray), - totalMedian: median(totalArray), - activityMean: mean(activityArray), - rolesMean: mean(roleArray), - moderationMean: mean(moderationArray), - cloudServicesMean: mean(cloudServicesArray), - otherMean: mean(otherArray), - miscMean: mean(miscArray), - }; - const splitHist = this.client.util.splitFields(histArray); - const cmdPages: RichEmbed[] = []; - splitHist.forEach((split) => { - const embed = new RichEmbed(); - embed.setTitle('Historical Community Report'); - let totalMean = '0'; - let totalMedian = '0'; - let totalMode = '0'; - let activityMean = '0'; - let moderationMean = '0'; - let roleMean = '0'; - let cloudServicesMean = '0'; - let otherMean = '0'; - let miscMean = '0'; - - if (stat.totalMean < 200) totalMean = '---'; - else if (stat.totalMean > 800) totalMean = '800'; - else totalMean = `${stat.totalMean}`; - - if (stat.totalMedian < 200) totalMedian = '---'; - else if (stat.totalMedian > 800) totalMedian = '800'; - else totalMedian = `${stat.totalMedian}`; - - if (stat.totalMode < 200) totalMode = '---'; - else if (stat.totalMode > 800) totalMode = '800'; - else totalMode = `${stat.totalMode}`; - - if (stat.activityMean < 10) activityMean = '---'; - else if (stat.activityMean > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityMean = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); - else activityMean = `${stat.activityMean}`; - - if (stat.rolesMean <= 0) roleMean = '---'; - else if (stat.rolesMean > 54) roleMean = '54'; - else roleMean = `${stat.rolesMean}`; - - moderationMean = `${stat.moderationMean}`; - - if (stat.otherMean === 0) otherMean = '---'; - else otherMean = `${stat.otherMean}`; - - if (stat.miscMean <= 0) miscMean = '---'; - else miscMean = `${stat.miscMean}`; - - if (stat.cloudServicesMean === 0) cloudServicesMean = '---'; - else if (stat.cloudServicesMean > 10) cloudServicesMean = '10'; - else cloudServicesMean = `${stat.cloudServicesMean}`; - - embed.setDescription(`__**Statistical Averages**__\n**CommScore™ Mean:** ${totalMean} | **CommScore™ Mode:** ${totalMode} | **CommScore™ Median:** ${totalMedian}\n\n**Activity Mean:** ${activityMean}\n**Roles Mean:** ${roleMean}\n**Moderation Mean:** ${moderationMean}\n**Cloud Services Mean:** ${cloudServicesMean}\n**Other Mean:** ${otherMean}\n**Misc Mean:** ${miscMean}`); - embed.setAuthor(user.username, user.avatarURL); - embed.setThumbnail(user.avatarURL); - embed.setTimestamp(); - embed.setFooter(this.client.user.username, this.client.user.avatarURL); - split.forEach((c) => embed.addField(c.name, c.value)); - return cmdPages.push(embed); - }); - - let name = ''; - for (const role of this.client.util.resolveMember(message.author.id, this.mainGuild).roles.map((r) => this.mainGuild.roles.get(r)).sort((a, b) => b.position - a.position)) { - name = `Library of Code sp-us | ${role.name} - [HISTORICAL]`; - break; - } - await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name, date: new Date() } } }); - const embed2 = new RichEmbed(); - embed2.setTitle('Inquiry Notification'); - embed2.setColor('#00FFFF'); - const mem = this.client.util.resolveMember(user.id, this.client.guilds.get(this.client.config.guildID)); - embed2.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${user.id}>`, true); - embed2.addField('Type', 'SOFT', true); - embed2.addField('Department/Service', name.toUpperCase(), true); - embed2.setTimestamp(); - embed2.setFooter(this.client.user.username, this.client.user.avatarURL); - const log = this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849'); - log.createMessage({ embed: embed2 }).catch(() => {}); - - - if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] }); - return createPaginationEmbed(message, cmdPages); - } - } - if (args[0] === 'notify') { - user = message.author; - if (!user) return this.error(message.channel, 'Member not found.'); - const score = await this.client.db.Score.findOne({ userID: message.author.id }); - if (!score) return this.error(message.channel, 'Score not calculated yet.'); - if (!score.notify) await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { notify: false } }); - switch (args[1]) { - case 'on': - await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { notify: true } }); - return this.success(message.channel, 'You will now be sent notifications whenever your score is hard-pulled.'); - case 'off': - await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { notify: false } }); - return this.success(message.channel, 'You will no longer be sent notifications when your score is hard-pulled.'); - default: - return this.error(message.channel, 'Invalid option. Valid options are `yes` and `no`.'); - } - } - if (args[0] === 'lock' || args[0] === 'unlock') { - user = message.author; - if (!user) return this.error(message.channel, 'Member not found.'); - const score = await this.client.db.Score.findOne({ userID: message.author.id }); - if (!score) return this.error(message.channel, 'Score not calculated yet.'); - if (!score.locked) await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { locked: false } }); - switch (args[0]) { - case 'lock': - await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { locked: true } }); - return this.success(message.channel, 'Your report is now locked.'); - case 'unlock': - await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { locked: false } }); - return this.success(message.channel, 'Your report is now unlocked.'); - } - } if (!args[0] || !this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) { user = message.author; if (!user) return this.error(message.channel, 'Member not found.'); @@ -537,7 +198,7 @@ export default class Score extends Command { if (args[1] === 'hard' && this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 6)) { await message.channel.createMessage({ embed }); await message.channel.createMessage('***===BEGIN ADDITIONAL INFORMATION===***'); - await this.client.commands.get('score').run(message, ['hist', user.id]); + await this.client.commands.get('score').subcommands.get('hist').run(message, [user.id]); await this.client.commands.get('whois').run(message, [user.id]); await this.client.commands.get('notes').run(message, [user.id]); const whoisMessage = await message.channel.createMessage(`=whois ${user.id} --full`); diff --git a/src/commands/score_hist.ts b/src/commands/score_hist.ts new file mode 100644 index 0000000..c7c299f --- /dev/null +++ b/src/commands/score_hist.ts @@ -0,0 +1,336 @@ +/* eslint-disable no-continue */ +/* eslint-disable default-case */ +import moment from 'moment'; +import { median, mode, mean } from 'mathjs'; +import { createPaginationEmbed } from 'eris-pagination'; +import { Message, User, TextChannel } from 'eris'; +import { Client, Command, RichEmbed } from '../class'; + +export default class Score_Hist extends Command { + constructor(client: Client) { + super(client); + this.name = 'hist'; + this.description = 'Pulls your Community Report history.'; + this.usage = `${this.client.config.prefix}score hist \n${this.client.config.prefix}score hist`; + this.permissions = 0; + this.guildOnly = false; + this.enabled = true; + } + + public async run(message: Message, args: string[]) { + try { + let user: User; + + if (!args[0] || !this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) { + user = message.author; + if (!user) return this.error(message.channel, 'Member not found.'); + const hists = await this.client.db.ScoreHistorical.find({ userID: user.id }).lean().exec(); + if (!hists) return this.error(message.channel, 'No history found.'); + const histArray: [{ name: string, value: string }?] = []; + const totalArray: number[] = []; + const activityArray: number[] = []; + const moderationArray: number[] = []; + const roleArray: number[] = []; + const cloudServicesArray: number[] = []; + const otherArray: number[] = []; + const miscArray: number[] = []; + for (const hist of hists.reverse()) { + totalArray.push(hist.report.total); + activityArray.push(hist.report.activity); + moderationArray.push(hist.report.moderation); + roleArray.push(hist.report.roles); + cloudServicesArray.push(hist.report.cloudServices); + otherArray.push(hist.report.other); + miscArray.push(hist.report.staff); + let totalScore = '0'; + let activityScore = '0'; + let moderationScore = '0'; + let roleScore = '0'; + let cloudServicesScore = '0'; + let otherScore = '0'; + let miscScore = '0'; + + if (hist.report.total < 200) totalScore = '---'; + else if (hist.report.total > 800) totalScore = '800'; + else totalScore = `${hist.report.total}`; + + if (hist.report.activity < 10) activityScore = '---'; + else if (hist.report.activity > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityScore = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); + else activityScore = `${hist.report.activity}`; + + if (hist.report.roles <= 0) roleScore = '---'; + else if (hist.report.roles > 54) roleScore = '54'; + else roleScore = `${hist.report.roles}`; + + moderationScore = `${hist.report.moderation}`; + + if (hist.report.other === 0) otherScore = '---'; + else otherScore = `${hist.report.other}`; + + if (hist.report.staff <= 0) miscScore = '---'; + else miscScore = `${hist.report.staff}`; + + if (hist.report.cloudServices === 0) cloudServicesScore = '---'; + else if (hist.report.cloudServices > 10) cloudServicesScore = '10'; + else cloudServicesScore = `${hist.report.cloudServices}`; + + let data = ''; + let hardInquiries = 0; + if (hist.report?.inquiries?.length > 0) { + hist.report.inquiries.forEach((inq) => { + const testDate = (new Date(new Date(inq.date).setHours(1460))); + // eslint-disable-next-line no-plusplus + if (testDate > new Date()) hardInquiries++; + }); + data += `__CommScore™:__ ${totalScore}\n__Activity:__ ${activityScore}\n__Roles:__ ${roleScore}\n__Moderation:__ ${moderationScore}\n__Cloud Services:__ ${cloudServicesScore}\n__Other:__ ${otherScore}\n__Misc:__ ${miscScore}\n\n__Hard Inquiries:__ ${hardInquiries}\n__Soft Inquiries:__ ${hist.report.softInquiries?.length ?? '0'}`; + histArray.push({ name: moment(hist.date).calendar(), value: data }); + } + } + + const stat = { + totalMean: mean(totalArray), + totalMode: mode(totalArray), + totalMedian: median(totalArray), + activityMean: mean(activityArray), + rolesMean: mean(roleArray), + moderationMean: mean(moderationArray), + cloudServicesMean: mean(cloudServicesArray), + otherMean: mean(otherArray), + miscMean: mean(miscArray), + }; + const splitHist = this.client.util.splitFields(histArray); + const cmdPages: RichEmbed[] = []; + splitHist.forEach((split) => { + const embed = new RichEmbed(); + embed.setTitle('Historical Community Report'); + let totalMean = '0'; + let totalMedian = '0'; + let totalMode = '0'; + let activityMean = '0'; + let moderationMean = '0'; + let roleMean = '0'; + let cloudServicesMean = '0'; + let otherMean = '0'; + let miscMean = '0'; + + if (stat.totalMean < 200) totalMean = '---'; + else if (stat.totalMean > 800) totalMean = '800'; + else totalMean = `${stat.totalMean}`; + + if (stat.totalMedian < 200) totalMedian = '---'; + else if (stat.totalMedian > 800) totalMedian = '800'; + else totalMedian = `${stat.totalMedian}`; + + if (stat.totalMode < 200) totalMode = '---'; + else if (stat.totalMode > 800) totalMode = '800'; + else totalMode = `${stat.totalMode}`; + + if (stat.activityMean < 10) activityMean = '---'; + else if (stat.activityMean > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityMean = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); + else activityMean = `${stat.activityMean}`; + + if (stat.rolesMean <= 0) roleMean = '---'; + else if (stat.rolesMean > 54) roleMean = '54'; + else roleMean = `${stat.rolesMean}`; + + moderationMean = `${stat.moderationMean}`; + + if (stat.otherMean === 0) otherMean = '---'; + else otherMean = `${stat.otherMean}`; + + if (stat.miscMean <= 0) miscMean = '---'; + else miscMean = `${stat.miscMean}`; + + if (stat.cloudServicesMean === 0) cloudServicesMean = '---'; + else if (stat.cloudServicesMean > 10) cloudServicesMean = '10'; + else cloudServicesMean = `${stat.cloudServicesMean}`; + + embed.setDescription(`__**Statistical Averages**__\n**CommScore™ Mean:** ${totalMean} | **CommScore™ Mode:** ${totalMode} | **CommScore™ Median:** ${totalMedian}\n\n**Activity Mean:** ${activityMean}\n**Roles Mean:** ${roleMean}\n**Moderation Mean:** ${moderationMean}\n**Cloud Services Mean:** ${cloudServicesMean}\n**Other Mean:** ${otherMean}\n**Misc Mean:** ${miscMean}`); + embed.setAuthor(user.username, user.avatarURL); + embed.setThumbnail(user.avatarURL); + embed.setTimestamp(); + embed.setFooter(this.client.user.username, this.client.user.avatarURL); + split.forEach((c) => embed.addField(c.name, c.value)); + return cmdPages.push(embed); + }); + const name = `${user.username} VIA DISCORD - [HISTORICAL]`; + await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name: name.toUpperCase(), date: new Date() } } }); + const embed2 = new RichEmbed(); + embed2.setTitle('Inquiry Notification'); + embed2.setColor('#00FFFF'); + embed2.addField('Member', `${user.username}#${user.discriminator} | <@${user.id}>`, true); + embed2.addField('Type', 'SOFT', true); + embed2.addField('Department/Service', name.toUpperCase(), true); + embed2.setTimestamp(); + embed2.setFooter(this.client.user.username, this.client.user.avatarURL); + const log = this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849'); + log.createMessage({ embed: embed2 }).catch(() => {}); + + + if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] }); + return createPaginationEmbed(message, cmdPages); + } if (args[0] && this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) { + user = this.client.util.resolveMember(args[0], this.mainGuild)?.user; + if (!user) { + const sc = await this.client.db.Score.findOne({ pin: [Number(args[0].split('-')[0]), Number(args[0].split('-')[1]), Number(args[0].split('-')[2])] }); + user = this.client.util.resolveMember(sc.userID, this.mainGuild)?.user; + } + if (!user) return this.error(message.channel, 'Member not found.'); + const hists = await this.client.db.ScoreHistorical.find({ userID: user.id }).lean().exec(); + if (!hists) return this.error(message.channel, 'No history found.'); + const histArray: [{ name: string, value: string }?] = []; + const totalArray: number[] = []; + const activityArray: number[] = []; + const moderationArray: number[] = []; + const roleArray: number[] = []; + const cloudServicesArray: number[] = []; + const otherArray: number[] = []; + const miscArray: number[] = []; + for (const hist of hists.reverse()) { + totalArray.push(hist.report.total); + activityArray.push(hist.report.activity); + moderationArray.push(hist.report.moderation); + roleArray.push(hist.report.roles); + cloudServicesArray.push(hist.report.cloudServices); + otherArray.push(hist.report.other); + miscArray.push(hist.report.staff); + let totalScore = '0'; + let activityScore = '0'; + let moderationScore = '0'; + let roleScore = '0'; + let cloudServicesScore = '0'; + let otherScore = '0'; + let miscScore = '0'; + + if (hist.report.total < 200) totalScore = '---'; + else if (hist.report.total > 800) totalScore = '800'; + else totalScore = `${hist.report.total}`; + + if (hist.report.activity < 10) activityScore = '---'; + else if (hist.report.activity > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityScore = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); + else activityScore = `${hist.report.activity}`; + + if (hist.report.roles <= 0) roleScore = '---'; + else if (hist.report.roles > 54) roleScore = '54'; + else roleScore = `${hist.report.roles}`; + + moderationScore = `${hist.report.moderation}`; + + if (hist.report.other === 0) otherScore = '---'; + else otherScore = `${hist.report.other}`; + + if (hist.report.staff <= 0) miscScore = '---'; + else miscScore = `${hist.report.staff}`; + + if (hist.report.cloudServices === 0) cloudServicesScore = '---'; + else if (hist.report.cloudServices > 10) cloudServicesScore = '10'; + else cloudServicesScore = `${hist.report.cloudServices}`; + + let data = ''; + let hardInquiries = 0; + if (hist.report?.inquiries?.length > 0) { + hist.report.inquiries.forEach((inq) => { + const testDate = (new Date(new Date(inq.date).setHours(1460))); + // eslint-disable-next-line no-plusplus + if (testDate > new Date()) hardInquiries++; + }); + data += `__CommScore™:__ ${totalScore}\n__Activity:__ ${activityScore}\n__Roles:__ ${roleScore}\n__Moderation:__ ${moderationScore}\n__Cloud Services:__ ${cloudServicesScore}\n__Other:__ ${otherScore}\n__Misc:__ ${miscScore}\n\n__Hard Inquiries:__ ${hardInquiries}\n__Soft Inquiries:__ ${hist.report.softInquiries?.length ?? '0'}`; + histArray.push({ name: moment(hist.date).calendar(), value: data }); + } + } + + const stat = { + totalMean: mean(totalArray), + totalMode: mode(totalArray), + totalMedian: median(totalArray), + activityMean: mean(activityArray), + rolesMean: mean(roleArray), + moderationMean: mean(moderationArray), + cloudServicesMean: mean(cloudServicesArray), + otherMean: mean(otherArray), + miscMean: mean(miscArray), + }; + const splitHist = this.client.util.splitFields(histArray); + const cmdPages: RichEmbed[] = []; + splitHist.forEach((split) => { + const embed = new RichEmbed(); + embed.setTitle('Historical Community Report'); + let totalMean = '0'; + let totalMedian = '0'; + let totalMode = '0'; + let activityMean = '0'; + let moderationMean = '0'; + let roleMean = '0'; + let cloudServicesMean = '0'; + let otherMean = '0'; + let miscMean = '0'; + + if (stat.totalMean < 200) totalMean = '---'; + else if (stat.totalMean > 800) totalMean = '800'; + else totalMean = `${stat.totalMean}`; + + if (stat.totalMedian < 200) totalMedian = '---'; + else if (stat.totalMedian > 800) totalMedian = '800'; + else totalMedian = `${stat.totalMedian}`; + + if (stat.totalMode < 200) totalMode = '---'; + else if (stat.totalMode > 800) totalMode = '800'; + else totalMode = `${stat.totalMode}`; + + if (stat.activityMean < 10) activityMean = '---'; + else if (stat.activityMean > Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))) activityMean = String(Math.floor((Math.log1p(3000 + 300 + 200 + 100) * 12))); + else activityMean = `${stat.activityMean}`; + + if (stat.rolesMean <= 0) roleMean = '---'; + else if (stat.rolesMean > 54) roleMean = '54'; + else roleMean = `${stat.rolesMean}`; + + moderationMean = `${stat.moderationMean}`; + + if (stat.otherMean === 0) otherMean = '---'; + else otherMean = `${stat.otherMean}`; + + if (stat.miscMean <= 0) miscMean = '---'; + else miscMean = `${stat.miscMean}`; + + if (stat.cloudServicesMean === 0) cloudServicesMean = '---'; + else if (stat.cloudServicesMean > 10) cloudServicesMean = '10'; + else cloudServicesMean = `${stat.cloudServicesMean}`; + + embed.setDescription(`__**Statistical Averages**__\n**CommScore™ Mean:** ${totalMean} | **CommScore™ Mode:** ${totalMode} | **CommScore™ Median:** ${totalMedian}\n\n**Activity Mean:** ${activityMean}\n**Roles Mean:** ${roleMean}\n**Moderation Mean:** ${moderationMean}\n**Cloud Services Mean:** ${cloudServicesMean}\n**Other Mean:** ${otherMean}\n**Misc Mean:** ${miscMean}`); + embed.setAuthor(user.username, user.avatarURL); + embed.setThumbnail(user.avatarURL); + embed.setTimestamp(); + embed.setFooter(this.client.user.username, this.client.user.avatarURL); + split.forEach((c) => embed.addField(c.name, c.value)); + return cmdPages.push(embed); + }); + + let name = ''; + for (const role of this.client.util.resolveMember(message.author.id, this.mainGuild).roles.map((r) => this.mainGuild.roles.get(r)).sort((a, b) => b.position - a.position)) { + name = `Library of Code sp-us | ${role.name} - [HISTORICAL]`; + break; + } + await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name, date: new Date() } } }); + const embed2 = new RichEmbed(); + embed2.setTitle('Inquiry Notification'); + embed2.setColor('#00FFFF'); + const mem = this.client.util.resolveMember(user.id, this.client.guilds.get(this.client.config.guildID)); + embed2.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${user.id}>`, true); + embed2.addField('Type', 'SOFT', true); + embed2.addField('Department/Service', name.toUpperCase(), true); + embed2.setTimestamp(); + embed2.setFooter(this.client.user.username, this.client.user.avatarURL); + const log = this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849'); + log.createMessage({ embed: embed2 }).catch(() => {}); + + + if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] }); + return createPaginationEmbed(message, cmdPages); + } + return null; + } catch (err) { + return this.client.util.handleError(err, message, this); + } + } +} diff --git a/src/commands/score_notify.ts b/src/commands/score_notify.ts new file mode 100644 index 0000000..d6dfc08 --- /dev/null +++ b/src/commands/score_notify.ts @@ -0,0 +1,38 @@ +import { Message } from 'eris'; +import { Client, Command } from '../class'; +import Score_Hist from './score_hist'; + +export default class Score_Notify extends Command { + constructor(client: Client) { + super(client); + this.name = 'notify'; + this.description = 'Edits your notification preferences for Hard Inquiries.'; + this.usage = `${this.client.config.prefix}score notify `; + this.subcmds = [Score_Hist]; + this.permissions = 0; + this.guildOnly = false; + this.enabled = true; + } + + public async run(message: Message, args: string[]) { + try { + const user = message.author; + if (!user) return this.error(message.channel, 'Member not found.'); + const score = await this.client.db.Score.findOne({ userID: message.author.id }); + if (!score) return this.error(message.channel, 'Score not calculated yet.'); + if (!score.notify) await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { notify: false } }); + switch (args[0]) { + case 'on': + await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { notify: true } }); + return this.success(message.channel, 'You will now be sent notifications whenever your score is hard-pulled.'); + case 'off': + await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { notify: false } }); + return this.success(message.channel, 'You will no longer be sent notifications when your score is hard-pulled.'); + default: + return this.error(message.channel, 'Invalid option. Valid options are `yes` and `no`.'); + } + } catch (err) { + return this.client.util.handleError(err, message, this); + } + } +} diff --git a/src/commands/score_pref.ts b/src/commands/score_pref.ts new file mode 100644 index 0000000..fa6c257 --- /dev/null +++ b/src/commands/score_pref.ts @@ -0,0 +1,44 @@ +/* eslint-disable no-continue */ +/* eslint-disable default-case */ +import moment from 'moment'; +import { median, mode, mean } from 'mathjs'; +import { v4 as uuid } from 'uuid'; +import { createPaginationEmbed } from 'eris-pagination'; +import { Message, User, TextChannel } from 'eris'; +import { Client, Command, RichEmbed } from '../class'; +import Score_Hist from './score_hist'; +import Score_Notify from './score_notify'; + +export default class Score_Pref extends Command { + constructor(client: Client) { + super(client); + this.name = 'pref'; + this.description = 'Locks or unlocks your Community Report.'; + this.usage = `${this.client.config.prefix}score pref `; + this.subcmds = [Score_Hist, Score_Notify]; + this.permissions = 0; + this.guildOnly = false; + this.enabled = true; + } + + public async run(message: Message, args: string[]) { + try { + if (!message.author) return this.error(message.channel, 'Member not found.'); + const score = await this.client.db.Score.findOne({ userID: message.author.id }); + if (!score) return this.error(message.channel, 'Score not calculated yet.'); + if (!score.locked) await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { locked: false } }); + switch (args[0]) { + case 'lock': + await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { locked: true } }); + return this.success(message.channel, 'Your report is now locked.'); + case 'unlock': + await this.client.db.Score.updateOne({ userID: message.author.id }, { $set: { locked: false } }); + return this.success(message.channel, 'Your report is now unlocked.'); + default: + return this.error(message.channel, 'Invalid input'); + } + } catch (err) { + return this.client.util.handleError(err, message, this); + } + } +}