From 475a0b93b2ad47c8bc19af224ea8ff9b069b5994 Mon Sep 17 00:00:00 2001 From: Matthew R Date: Thu, 3 Sep 2020 03:47:24 -0400 Subject: [PATCH] add community score --- src/class/Client.ts | 6 ++-- src/commands/index.ts | 1 + src/commands/score.ts | 63 ++++++++++++++++++++++++++++++++++++ src/commands/whois.ts | 8 +++++ src/intervals/score.ts | 72 ++++++++++++++++++++++++++++++++++++++++++ src/models/Score.ts | 47 +++++++++++++++++++++++++++ src/models/index.ts | 1 + 7 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 src/commands/score.ts create mode 100644 src/intervals/score.ts create mode 100644 src/models/Score.ts diff --git a/src/class/Client.ts b/src/class/Client.ts index a8117cd..a89d964 100644 --- a/src/class/Client.ts +++ b/src/class/Client.ts @@ -3,7 +3,7 @@ import pluris from 'pluris'; import mongoose from 'mongoose'; import { promises as fs } from 'fs'; import { Collection, Command, LocalStorage, Util, ServerManagement, Event } from '.'; -import { File, FileInterface, Member, MemberInterface, Moderation, ModerationInterface, Note, NoteInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface, Staff, StaffInterface, Stat, StatInterface } from '../models'; +import { File, FileInterface, Member, MemberInterface, Moderation, ModerationInterface, Note, NoteInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface, Score, ScoreInterface, Staff, StaffInterface, Stat, StatInterface } from '../models'; import { Config } from '../../types'; // eslint-disable-line pluris(eris); @@ -21,14 +21,14 @@ export default class Client extends eris.Client { public serverManagement: ServerManagement; - public db: { File: mongoose.Model, Member: mongoose.Model, Moderation: mongoose.Model, Note: mongoose.Model, PagerNumber: mongoose.Model, Rank: mongoose.Model, Redirect: mongoose.Model, Staff: mongoose.Model, Stat: mongoose.Model, local: { muted: LocalStorage } }; + public db: { File: mongoose.Model, Member: mongoose.Model, Moderation: mongoose.Model, Note: mongoose.Model, PagerNumber: mongoose.Model, Rank: mongoose.Model, Redirect: mongoose.Model, Score: mongoose.Model, Staff: mongoose.Model, Stat: mongoose.Model, local: { muted: LocalStorage } }; constructor(token: string, options?: eris.ClientOptions) { super(token, options); this.commands = new Collection(); this.events = new Collection(); this.intervals = new Collection(); - this.db = { File, Member, Moderation, Note, PagerNumber, Rank, Redirect, Staff, Stat, local: { muted: new LocalStorage('muted') } }; + this.db = { File, Member, Moderation, Note, PagerNumber, Rank, Redirect, Score, Staff, Stat, local: { muted: new LocalStorage('muted') } }; } public async loadDatabase() { diff --git a/src/commands/index.ts b/src/commands/index.ts index 0f3d8d9..e9ab990 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -23,6 +23,7 @@ export { default as page } from './page'; export { default as ping } from './ping'; export { default as rank } from './rank'; export { default as roleinfo } from './roleinfo'; +export { default as score } from './score'; export { default as stats } from './stats'; export { default as storemessages } from './storemessages'; export { default as unban } from './unban'; diff --git a/src/commands/score.ts b/src/commands/score.ts new file mode 100644 index 0000000..9bd1978 --- /dev/null +++ b/src/commands/score.ts @@ -0,0 +1,63 @@ +import { Message } from 'eris'; +import { Client, Command, RichEmbed } from '../class'; + +export default class Score extends Command { + constructor(client: Client) { + super(client); + this.name = 'score'; + this.description = 'Gets your Community Score.'; + this.usage = 'score'; + this.permissions = 0; + this.guildOnly = true; + this.enabled = true; + } + + public async run(message: Message) { + try { + const score = await this.client.db.Score.findOne({ userID: message.author.id }); + let totalScore = '0'; + let activityScore = '0'; + let moderationScore = '0'; + let roleScore = '0'; + let cloudServicesScore = '0'; + let miscScore = '0'; + + if (score) { + if (score.total < 200) totalScore = '---'; + else if (score.total > 800) totalScore = '800'; + else totalScore = `${score.total}`; + + if (score.activity <= 0) activityScore = '---'; + else if (score.activity > 55) activityScore = '55'; + else activityScore = `${score.activity}`; + + if (score.roles <= 0) roleScore = '---'; + else if (score.roles > 54) roleScore = '54'; + else roleScore = `${score.roles}`; + + moderationScore = `${score.moderation}`; + + if (score.staff <= 0) miscScore = '---'; + else miscScore = `${score.staff}`; + + if (score.cloudServices === 0) cloudServicesScore = '---'; + else if (score.cloudServices > 50) cloudServicesScore = '50'; + else cloudServicesScore = `${score.cloudServices}`; + } else return this.error(message.channel, 'Your Community Score has not been calculated yet.'); + + const embed = new RichEmbed(); + embed.setTitle('Community Score'); + embed.addField('Total | 200 - 800', totalScore, true); + embed.addField('Activity | 10 - 55', activityScore, true); + embed.addField('Roles | 1 - 54', roleScore, true); + embed.addField('Moderation | -50 - 2', moderationScore, true); + embed.addField('Cloud Services | -20 - 50', cloudServicesScore, true); + embed.addField('Misc', miscScore, true); + embed.setFooter(this.client.user.username, this.client.user.avatarURL); + embed.setTimestamp(); + return message.channel.createMessage({ embed }); + } catch (err) { + return this.client.util.handleError(err, message, this); + } + } +} diff --git a/src/commands/whois.ts b/src/commands/whois.ts index 245ef69..d661592 100644 --- a/src/commands/whois.ts +++ b/src/commands/whois.ts @@ -72,6 +72,14 @@ export default class Whois extends Command { // if (platform) embed.addField('Platform', platform, true); embed.addField('Joined At', `${moment(new Date(member.joinedAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true); embed.addField('Created At', `${moment(new Date(member.user.createdAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true); + const score = await this.client.db.Score.findOne({ userID: member.id }); + if (score) { + let totalScore = '0'; + if (score.total < 200) totalScore = '---'; + else if (score.total > 800) totalScore = '800'; + else totalScore = `${score.total}`; + embed.addField('Community Score', totalScore, true); + } else embed.addField('Community Score', 'N/C', true); if (member.roles.length > 0) { embed.addField(`Roles [${member.roles.length}]`, member.roles.map((r) => this.mainGuild.roles.get(r)).sort((a, b) => b.position - a.position).map((r) => `<@&${r.id}>`).join(', ')); } diff --git a/src/intervals/score.ts b/src/intervals/score.ts new file mode 100644 index 0000000..b368b93 --- /dev/null +++ b/src/intervals/score.ts @@ -0,0 +1,72 @@ +/* eslint-disable no-continue */ +/* eslint-disable one-var-declaration-per-line */ +/* eslint-disable no-await-in-loop */ +import { TextChannel } from 'eris'; +import { Client } from '../class'; + +let interval: NodeJS.Timeout; + +export default async function calculateScore(client: Client): Promise { + const start = async () => { + const { members } = client.guilds.get(client.config.guildID); + + const general = await ( client.guilds.get(client.config.guildID).channels.get('485680288123584525')).getMessages(1000); + const programmingSupport = await ( client.guilds.get(client.config.guildID).channels.get('506970598631538708')).getMessages(300); + const cloudSupport = await ( client.guilds.get(client.config.guildID).channels.get('546457788184789013')).getMessages(200); + for (const member of members.values()) { + if (member.bot) continue; + let score = await client.db.Score.findOne({ userID: member.user.id }); + if (!score) { + const data: { + userID: string, + total: number, + activity: number, + roles: number, + moderation: number, + cloudServices: number, + staff: boolean, + inquiries: [{ name: string, reason: string}?], + } = { + userID: member.user.id, + total: 0, + activity: 0, + roles: 0, + moderation: 0, + cloudServices: 0, + staff: false, + inquiries: [], + }; + score = await (new client.db.Score(data)).save(); + client.util.signale.debug(`SCORE INIT - ${member.username}`); + } + + // eslint-disable-next-line prefer-const + // eslint-disable-next-line one-var-declaration-per-line + // eslint-disable-next-line one-var + let total = 0, activity = 0, roles = 0, moderation = 0, cloudServices = 0, staff = 0; + cloudServices = 0; + + roles = Math.floor(member.roles.length * 0.87); + if (roles > 54) roles = 54; + + const moderations = await client.db.Moderation.find({ userID: member.user.id }); + if (moderations?.length > 0) moderation = -moderations.length * 8; + else moderation = 2; + + const activityTotal = (general.filter((m) => m.member?.id === member.id).length + programmingSupport.filter((m) => m.member?.id === member.id).length + cloudSupport.filter((m) => m.member?.id === member.id).length) * 0.485; + activity = Math.floor(activityTotal); + if (activity > 55) activity = 55; + if (member.roles.includes('446104438969466890') || member.roles.includes('701481967149121627')) staff = 20; + + total = Math.floor(((total + activity + roles + moderation + cloudServices + staff) * 5.13) * 1.87); + + await score.updateOne({ $set: { total, activity, roles, moderation, cloudServices, staff } }); + client.util.signale.debug(`SCORE SET - ${member.username}\nTotal: ${total}\nActivity: ${activity}\nRoles: ${roles}\nModeration: ${moderation}\nCloud Services: ${cloudServices}\nStaff: ${staff}`); + } + }; + await start(); + interval = setInterval(async () => { + await start(); + }, 1800000); + return interval; +} diff --git a/src/models/Score.ts b/src/models/Score.ts new file mode 100644 index 0000000..9a898be --- /dev/null +++ b/src/models/Score.ts @@ -0,0 +1,47 @@ +// Community Score + +import { Document, Schema, model } from 'mongoose'; + + +export interface ScoreInterface extends Document { + userID: string + /** + * total will be between 800-200 - 0 signfies "No Score", too little information is available or other variable are too low + * - CALCULATION: `(COMBINED SUBSCORES x 5) * 5.13; Math.floor()` + */ + total: number, + /** + * 10 - 55 + */ + activity: number, + /** + * 0 - 54 + */ + roles: number, + /** + * -50 - 2 + * all users start out with 2 moderation points, the number of points decreases for each moderation. + */ + moderation: number, + /** + * -20 - 50 + * processed by CSD + */ + cloudServices: number, + // 0 or 20, 20 points are added if the user is a staff member + staff: number, + inquiries: [{ name: string, reason: string}], +} + +const Score: Schema = new Schema({ + userID: String, + total: Number, + activity: Number, + roles: Number, + moderation: Number, + cloudServices: Number, + staff: Number, + inquiries: Array, +}); + +export default model('Score', Score); diff --git a/src/models/index.ts b/src/models/index.ts index 09e88fe..4c64936 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -5,5 +5,6 @@ export { default as Note, NoteInterface } from './Note'; export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber'; export { default as Rank, RankInterface } from './Rank'; export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect'; +export { default as Score, ScoreInterface } from './Score'; export { default as Staff, StaffInterface } from './Staff'; export { default as Stat, StatInterface } from './Stat';