From 5e8a6c8837f3206cd15916fafae813b557823e50 Mon Sep 17 00:00:00 2001 From: Matthew R Date: Sat, 9 Oct 2021 20:18:27 -0400 Subject: [PATCH 1/2] refactor score calculations for performance --- src/class/Queue.ts | 3 + src/intervals/score.ts | 411 ++++++++++++++++++++--------------------- 2 files changed, 206 insertions(+), 208 deletions(-) diff --git a/src/class/Queue.ts b/src/class/Queue.ts index 70b4d1d..4d022bb 100644 --- a/src/class/Queue.ts +++ b/src/class/Queue.ts @@ -183,6 +183,9 @@ export default class Queue { return this.queues.score.add('score::inquiry', { inqID, userID, name, type, reason }); } + /** + * @deprecated + */ public updateScore(score: ScoreInterface, total: number, activity: number, roles: number, moderation: number, cloudServices: number, other: number, staff: number) { return this.queues.score.add('score::update', { score, total, activity, roles, moderation, cloudServices, other, staff }); } diff --git a/src/intervals/score.ts b/src/intervals/score.ts index fa726fc..0949920 100644 --- a/src/intervals/score.ts +++ b/src/intervals/score.ts @@ -1,208 +1,203 @@ -/* eslint-disable no-plusplus */ -/* eslint-disable no-continue */ -/* eslint-disable one-var-declaration-per-line */ -/* eslint-disable no-await-in-loop */ -import axios from 'axios'; -import { Message, TextChannel } from 'eris'; -import { Client } from '../class'; - -interface CSResponse { - found: boolean, - tier: number, - totalReferrals?: number, - createdAt?: Date, - warns?: Date[], - locks?: Date[], - deletes?: Date[], -} - -let interval: NodeJS.Timeout; - -export function getTotalMessageCount(client: Client): number { - const projectChannels: TextChannel[] = []; - for (const c of client.guilds.get(client.config.guildID).channels.filter((ch) => ch.type === 0)) { - const chan = c; - if (chan.parentID !== '701591772186411108') continue; - projectChannels.push(chan); - } - return (projectChannels.length * 200) + 2200 + 300 + 100 + 200; -} - -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(2200); - const programmingSupport = await ( client.guilds.get(client.config.guildID).channels.get('506970598631538708')).getMessages(300); - const programmingSupport2 = await ( client.guilds.get(client.config.guildID).channels.get('554892820553531422')).getMessages(100); - const cloudSupport = await ( client.guilds.get(client.config.guildID).channels.get('546457788184789013')).getMessages(200); - - const projectChannels: TextChannel[] = []; - for (const c of client.guilds.get(client.config.guildID).channels.filter((ch) => ch.type === 0)) { - const chan = c; - if (chan.parentID !== '701591772186411108') continue; - projectChannels.push(chan); - } - const projectMessages: Message[] = []; - for (const chan of projectChannels) { - const msg = await chan.getMessages(200); - projectMessages.push(...msg); - } - 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, - other: number, - staff: boolean, - locked: boolean, - notify: boolean, - lastUpdated: Date, - pin: number[], - } = { - userID: member.user.id, - total: 0, - activity: 0, - roles: 0, - moderation: 0, - cloudServices: 0, - other: 0, - staff: false, - locked: false, - notify: false, - lastUpdated: new Date(), - pin: [client.util.randomNumber(100, 999), client.util.randomNumber(10, 99), client.util.randomNumber(1000, 9999)], - }; - 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, other = 0, staff = 0; - cloudServices = 0; - - roles = Math.floor(member.roles.length * 0.50); - if (roles > 54) roles = 54; - - const moderations = await client.db.Moderation.find({ userID: member.user.id }); - let activeMods = 0; - for (const mod of moderations) { - if (mod.type === 1 || mod.type === 4) continue; - const testDate = (new Date(new Date(mod.date).setHours(2190))); - if (testDate > new Date()) { moderation -= 15; activeMods++; } - } - if (activeMods <= 0) moderation = 2; - - let messageCountTotal = 0; - const allMessagesArray = [...general, ...programmingSupport, ...programmingSupport2, ...cloudSupport, ...projectMessages]; - - for (const msg of allMessagesArray.filter((m) => m.member?.id === member.id)) { - if (!msg.content) continue; - if (msg.content.length <= 5) continue; - // eslint-disable-next-line no-plusplus - messageCountTotal++; - } - - const activityTotal = messageCountTotal; - activity = Math.floor(Math.log1p(activityTotal) * 12); - if (activity > (Math.log1p(getTotalMessageCount(client)) * 12)) activity = Math.floor((Math.log1p(getTotalMessageCount(client)) * 12)); - if (member.roles.includes('446104438969466890') || member.roles.includes('701481967149121627')) staff = 20; - - const response = (await axios.get(`https://api.cloud.libraryofcode.org/wh/score?id=${member.user.id}&authorization=${client.config.internalKey}`)).data; - if (response.found === true) { - let negatives = 0; - let positives = 0; - if (response.createdAt) { - const csCreatedTestDate = (new Date(new Date(response.createdAt).setHours(730))); - if (csCreatedTestDate > new Date()) { - negatives -= 10; - } - } - let warns = 0; - for (const warn of response.warns) { - const date = (new Date(new Date(warn).setHours(730))); - if (date > new Date()) { negatives -= 2; warns++; } - } - if (warns <= 0) positives += 2; - if (response.warns.length === 0) positives += 3; - - let locks = 0; - for (const lock of response.locks) { - const date = (new Date(new Date(lock).setHours(1460))); - if (date > new Date()) { negatives -= 5; locks++; } - } - if (locks <= 0) positives += 3; - if (response.locks.length === 0) positives += 7; - - if (response.deletes.length > 0) { - for (const del of response.deletes) { - const date = (new Date(new Date(del).setHours(3650))); - if (date > new Date()) negatives -= 20; - } - } - positives += Math.floor(response.totalReferrals * 1.17); - if (response.tier === 2) positives += 2; - else if (response.tier === 3) positives += 3; - - if (negatives < 0) cloudServices = Math.floor((negatives * 1.2) + (positives * 0.06)); - else cloudServices = Math.floor(positives * 0.61); - } - - const inquiries = await client.db.Inquiry.find({ userID: member.user.id, type: 0 }).lean().exec(); - const judgements = await client.db.Judgement.find({ userID: member.user.id }).lean().exec(); - - if (inquiries?.length > 0) { - for (const inq of inquiries) { - const testDate = (new Date(new Date(inq.date).setHours(1460))); - if (testDate > new Date()) other -= 1.65; - } - other = Math.floor(other * 1.15); - } - - if (judgements?.length > 0) { - for (const judgement of judgements) { - switch (judgement.severity) { - default: - break; - case 0: - other -= 5; - break; - case 1: - other -= 10; - break; - case 2: - other -= 20; - break; - } - } - } - - const discordAccountCreatedAtTestDate = (new Date(new Date(new Date(member.user.createdAt)).setHours(730))); - if (discordAccountCreatedAtTestDate > new Date()) { - other -= 10; - } - - const joinedAtTestDate = (new Date(new Date(new Date(member.joinedAt)).setHours(420))); - if (joinedAtTestDate > new Date()) { - other -= 30; - } - - total = Math.floor(((total + activity + roles + moderation + cloudServices + staff + other) * 5.13) * 1.87); - - client.queue.updateScore(score, total, activity, roles, moderation, cloudServices, other, staff); - } - }; - await start(); - interval = setInterval(async () => { - await start(); - }, 1800000); - return interval; -} +/* eslint-disable no-plusplus */ +/* eslint-disable no-continue */ +/* eslint-disable one-var-declaration-per-line */ +/* eslint-disable no-await-in-loop */ +import { Message, TextChannel } from 'eris'; +import { Client } from '../class'; +import { CloudServicesUtil } from '../util'; + +let interval: NodeJS.Timeout; + +export function getTotalMessageCount(client: Client): number { + const projectChannels: TextChannel[] = []; + for (const c of client.guilds.get(client.config.guildID).channels.filter((ch) => ch.type === 0)) { + const chan = c; + if (chan.parentID !== '701591772186411108') continue; + projectChannels.push(chan); + } + return (projectChannels.length * 200) + 2200 + 300 + 100 + 200; +} + +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(2200); + const programmingSupport = await ( client.guilds.get(client.config.guildID).channels.get('506970598631538708')).getMessages(300); + const programmingSupport2 = await ( client.guilds.get(client.config.guildID).channels.get('554892820553531422')).getMessages(100); + const cloudSupport = await ( client.guilds.get(client.config.guildID).channels.get('546457788184789013')).getMessages(200); + + const projectChannels: TextChannel[] = []; + for (const c of client.guilds.get(client.config.guildID).channels.filter((ch) => ch.type === 0)) { + const chan = c; + if (chan.parentID !== '701591772186411108') continue; + projectChannels.push(chan); + } + const projectMessages: Message[] = []; + for (const chan of projectChannels) { + const msg = await chan.getMessages(200); + projectMessages.push(...msg); + } + 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, + other: number, + staff: boolean, + locked: boolean, + notify: boolean, + lastUpdated: Date, + pin: number[], + } = { + userID: member.user.id, + total: 0, + activity: 0, + roles: 0, + moderation: 0, + cloudServices: 0, + other: 0, + staff: false, + locked: false, + notify: false, + lastUpdated: new Date(), + pin: [client.util.randomNumber(100, 999), client.util.randomNumber(10, 99), client.util.randomNumber(1000, 9999)], + }; + 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, other = 0, staff = 0; + cloudServices = 0; + + roles = Math.floor(member.roles.length * 0.50); + if (roles > 54) roles = 54; + + const moderations = await client.db.Moderation.find({ userID: member.user.id }); + let activeMods = 0; + for (const mod of moderations) { + if (mod.type === 1 || mod.type === 4) continue; + const testDate = (new Date(new Date(mod.date).setHours(2190))); + if (testDate > new Date()) { moderation -= 15; activeMods++; } + } + if (activeMods <= 0) moderation = 2; + + let messageCountTotal = 0; + const allMessagesArray = [...general, ...programmingSupport, ...programmingSupport2, ...cloudSupport, ...projectMessages]; + + for (const msg of allMessagesArray.filter((m) => m.member?.id === member.id)) { + if (!msg.content) continue; + if (msg.content.length <= 5) continue; + // eslint-disable-next-line no-plusplus + messageCountTotal++; + } + + const activityTotal = messageCountTotal; + activity = Math.floor(Math.log1p(activityTotal) * 12); + if (activity > (Math.log1p(getTotalMessageCount(client)) * 12)) activity = Math.floor((Math.log1p(getTotalMessageCount(client)) * 12)); + if (member.roles.includes('446104438969466890') || member.roles.includes('701481967149121627')) staff = 20; + + const response = await CloudServicesUtil.fetchAccountStatus(member.user.id, client.config.internalKey); + if (response || response.found === true) { + let negatives = 0; + let positives = 0; + if (response.createdAt) { + const csCreatedTestDate = (new Date(new Date(response.createdAt).setHours(730))); + if (csCreatedTestDate > new Date()) { + negatives -= 10; + } + } + let warns = 0; + for (const warn of response.warns) { + const date = (new Date(new Date(warn).setHours(730))); + if (date > new Date()) { negatives -= 2; warns++; } + } + if (warns <= 0) positives += 2; + if (response.warns.length === 0) positives += 3; + + let locks = 0; + for (const lock of response.locks) { + const date = (new Date(new Date(lock).setHours(1460))); + if (date > new Date()) { negatives -= 5; locks++; } + } + if (locks <= 0) positives += 3; + if (response.locks.length === 0) positives += 7; + + if (response.deletes.length > 0) { + for (const del of response.deletes) { + const date = (new Date(new Date(del).setHours(3650))); + if (date > new Date()) negatives -= 20; + } + } + positives += Math.floor(response.totalReferrals * 1.17); + if (response.tier === 2) positives += 2; + else if (response.tier === 3) positives += 3; + + if (negatives < 0) cloudServices = Math.floor((negatives * 1.2) + (positives * 0.06)); + else cloudServices = Math.floor(positives * 0.61); + } + + const inquiries = await client.db.Inquiry.find({ userID: member.user.id, type: 0 }).lean().exec(); + const judgements = await client.db.Judgement.find({ userID: member.user.id }).lean().exec(); + + if (inquiries?.length > 0) { + for (const inq of inquiries) { + const testDate = (new Date(new Date(inq.date).setHours(1460))); + if (testDate > new Date()) other -= 1.65; + } + other = Math.floor(other * 1.15); + } + + if (judgements?.length > 0) { + for (const judgement of judgements) { + switch (judgement.severity) { + default: + break; + case 0: + other -= 5; + break; + case 1: + other -= 10; + break; + case 2: + other -= 20; + break; + } + } + } + + const discordAccountCreatedAtTestDate = (new Date(new Date(new Date(member.user.createdAt)).setHours(730))); + if (discordAccountCreatedAtTestDate > new Date()) { + other -= 10; + } + + const joinedAtTestDate = (new Date(new Date(new Date(member.joinedAt)).setHours(420))); + if (joinedAtTestDate > new Date()) { + other -= 30; + } + + total = Math.floor(((total + activity + roles + moderation + cloudServices + staff + other) * 5.13) * 1.87); + + // client.queue.updateScore(score, total, activity, roles, moderation, cloudServices, other, staff); + + client.db.Score.updateOne({ userID: score.userID }, { $set: { total, activity, roles, moderation, cloudServices, other, staff, lastUpdate: new Date() } }).exec(); + if (!score.pin || score.pin?.length < 1) { + client.db.Score.updateOne({ userID: score.userID }, { $set: { pin: [this.client.util.randomNumber(100, 999), this.client.util.randomNumber(10, 99), this.client.util.randomNumber(1000, 9999)] } }).exec(); + } + } + }; + await start(); + interval = setInterval(async () => { + await start(); + }, 3600000); + return interval; +} From 1422cdfc9ae431c08917f8c23e6c7f109b4d7b65 Mon Sep 17 00:00:00 2001 From: Matthew R Date: Sat, 9 Oct 2021 20:19:33 -0400 Subject: [PATCH 2/2] add message util class --- src/util/MessageUtil.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/util/MessageUtil.ts diff --git a/src/util/MessageUtil.ts b/src/util/MessageUtil.ts new file mode 100644 index 0000000..e5785f9 --- /dev/null +++ b/src/util/MessageUtil.ts @@ -0,0 +1,10 @@ +import type { MessageContent } from 'eris'; +import type { Client } from '../class'; + +export default class MessageUtil { + static async sendDirectMessage(content: MessageContent, userID: string, client: Client) { + const dmChannel = await client.getDMChannel(userID); + if (!dmChannel) throw new Error(`DM Channel for user ${userID} doesn't exist.`); + return dmChannel.createMessage(content); + } +}