add historical data to score reports

pull/29/head
Matthew 2020-11-01 19:46:28 -05:00
parent 3a974ce603
commit 03ae4d8e61
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
7 changed files with 90 additions and 7 deletions

View File

@ -12,6 +12,7 @@
"private": false, "private": false,
"devDependencies": { "devDependencies": {
"@types/bull": "^3.14.4", "@types/bull": "^3.14.4",
"@types/cron": "^1.7.2",
"@types/express": "^4.17.6", "@types/express": "^4.17.6",
"@types/helmet": "^0.0.47", "@types/helmet": "^0.0.47",
"@types/jsonwebtoken": "^8.5.0", "@types/jsonwebtoken": "^8.5.0",
@ -32,6 +33,7 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"brain.js": "^2.0.0-beta.2", "brain.js": "^2.0.0-beta.2",
"bull": "^3.18.1", "bull": "^3.18.1",
"cron": "^1.8.2",
"eris": "^0.13.3", "eris": "^0.13.3",
"eris-pagination": "bsian03/eris-pagination", "eris-pagination": "bsian03/eris-pagination",
"express": "^4.17.1", "express": "^4.17.1",

View File

@ -4,6 +4,7 @@ import jwt from 'jsonwebtoken';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { TextChannel } from 'eris'; import { TextChannel } from 'eris';
import { LocalStorage, Route, Server, RichEmbed } from '../../../class'; import { LocalStorage, Route, Server, RichEmbed } from '../../../class';
import { ScoreHistoricalRaw } from '../../../models/ScoreHistorical';
export default class Report extends Route { export default class Report extends Route {
public timeout: Set<string>; public timeout: Set<string>;
@ -43,7 +44,7 @@ export default class Report extends Route {
if (!mem) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.codes.NOT_FOUND }); if (!mem) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.codes.NOT_FOUND });
if (member.locked) return res.status(403).json({ code: this.constants.codes.PERMISSION_DENIED, message: this.constants.messages.PERMISSION_DENIED }); if (member.locked) return res.status(403).json({ code: this.constants.codes.PERMISSION_DENIED, message: this.constants.messages.PERMISSION_DENIED });
if (merchant.type !== 1) return res.status(403).json({ code: this.constants.codes.PERMISSION_DENIED, message: this.constants.messages.PERMISSION_DENIED }); if (merchant?.type !== 1) return res.status(403).json({ code: this.constants.codes.PERMISSION_DENIED, message: this.constants.messages.PERMISSION_DENIED });
const flags = []; const flags = [];
@ -105,6 +106,13 @@ export default class Report extends Route {
} }
} }
const historicalData = await this.server.client.db.ScoreHistorical.find({ userID: member.userID }).lean().exec();
const array: ScoreHistoricalRaw[] = [];
for (const data of historicalData) {
delete data.report?.softInquiries;
array.push(data);
}
if (member.notify) { if (member.notify) {
const chan = await this.server.client.getDMChannel(member.userID); const chan = await this.server.client.getDMChannel(member.userID);
try { try {
@ -152,6 +160,7 @@ export default class Report extends Route {
miscScore, miscScore,
otherScore, otherScore,
inquiries, inquiries,
historical: array ?? [],
}, },
}); });
} catch (err) { } catch (err) {
@ -246,6 +255,14 @@ export default class Report extends Route {
else if (member.cloudServices > 10) cloudServicesScore = 10; else if (member.cloudServices > 10) cloudServicesScore = 10;
else cloudServicesScore = Math.round(member.cloudServices); else cloudServicesScore = Math.round(member.cloudServices);
const historicalData = await this.server.client.db.ScoreHistorical.find({ userID: member.userID }).lean().exec();
const array: ScoreHistoricalRaw[] = [];
for (const data of historicalData) {
delete data.report?.softInquiries;
delete data.report?.inquiries;
array.push(data);
}
return res.status(200).json({ return res.status(200).json({
code: this.constants.codes.SUCCESS, code: this.constants.codes.SUCCESS,
@ -268,6 +285,7 @@ export default class Report extends Route {
cloudServicesScore, cloudServicesScore,
otherScore, otherScore,
miscScore, miscScore,
historical: array ?? [],
}, },
}); });
} catch (err) { } catch (err) {

View File

@ -3,7 +3,7 @@ import pluris from 'pluris';
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import { Collection, Command, LocalStorage, Queue, Util, ServerManagement, Event } from '.'; import { Collection, Command, LocalStorage, Queue, Util, ServerManagement, Event } from '.';
import { File, FileInterface, Member, MemberInterface, Merchant, MerchantInterface, Moderation, ModerationInterface, NNTrainingData, NNTrainingDataInterface, Note, NoteInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface, Score, ScoreInterface, Staff, StaffInterface, Stat, StatInterface } from '../models'; import { File, FileInterface, Member, MemberInterface, Merchant, MerchantInterface, Moderation, ModerationInterface, NNTrainingData, NNTrainingDataInterface, Note, NoteInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface, Score, ScoreInterface, ScoreHistorical, ScoreHistoricalInterface, Staff, StaffInterface, Stat, StatInterface } from '../models';
import { Config } from '../../types'; // eslint-disable-line import { Config } from '../../types'; // eslint-disable-line
pluris(eris); pluris(eris);
@ -23,7 +23,7 @@ export default class Client extends eris.Client {
public queue: Queue; public queue: Queue;
public db: { File: mongoose.Model<FileInterface>, Member: mongoose.Model<MemberInterface>, Merchant: mongoose.Model<MerchantInterface>, Moderation: mongoose.Model<ModerationInterface>, NNTrainingData: mongoose.Model<NNTrainingDataInterface>, Note: mongoose.Model<NoteInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Rank: mongoose.Model<RankInterface>, Redirect: mongoose.Model<RedirectInterface>, Score: mongoose.Model<ScoreInterface>, Staff: mongoose.Model<StaffInterface>, Stat: mongoose.Model<StatInterface>, local: { muted: LocalStorage } }; public db: { File: mongoose.Model<FileInterface>, Member: mongoose.Model<MemberInterface>, Merchant: mongoose.Model<MerchantInterface>, Moderation: mongoose.Model<ModerationInterface>, NNTrainingData: mongoose.Model<NNTrainingDataInterface>, Note: mongoose.Model<NoteInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Rank: mongoose.Model<RankInterface>, Redirect: mongoose.Model<RedirectInterface>, Score: mongoose.Model<ScoreInterface>, ScoreHistorical: mongoose.Model<ScoreHistoricalInterface>, Staff: mongoose.Model<StaffInterface>, Stat: mongoose.Model<StatInterface>, local: { muted: LocalStorage } };
constructor(token: string, options?: eris.ClientOptions) { constructor(token: string, options?: eris.ClientOptions) {
super(token, options); super(token, options);
@ -31,7 +31,7 @@ export default class Client extends eris.Client {
this.events = new Collection<Event>(); this.events = new Collection<Event>();
this.intervals = new Collection<NodeJS.Timeout>(); this.intervals = new Collection<NodeJS.Timeout>();
this.queue = new Queue(this); this.queue = new Queue(this);
this.db = { File, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Rank, Redirect, Score, Staff, Stat, local: { muted: new LocalStorage('muted') } }; this.db = { File, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } };
} }

View File

@ -1,5 +1,6 @@
/* eslint-disable no-eval */ /* eslint-disable no-eval */
import Bull from 'bull'; import Bull from 'bull';
import cron from 'cron';
import { TextableChannel } from 'eris'; import { TextableChannel } from 'eris';
import { Client, RichEmbed } from '.'; import { Client, RichEmbed } from '.';
import { ScoreInterface } from '../models'; import { ScoreInterface } from '../models';
@ -17,6 +18,30 @@ export default class Queue {
score: new Bull('score', { prefix: 'queue::score', limiter: { max: 80, duration: 1000 } }), score: new Bull('score', { prefix: 'queue::score', limiter: { max: 80, duration: 1000 } }),
}; };
this.setProcessors(); this.setProcessors();
// this.setCronJobs();
}
protected setCronJobs() {
const historialCommunityReportJob = new cron.CronJob('0 20 * * *', async () => {
try {
const reports = await this.client.db.Score.find().lean().exec();
const startDate = new Date();
for (const report of reports) {
const data = new this.client.db.ScoreHistorical({
userID: report.userID,
report,
date: startDate,
});
// eslint-disable-next-line no-await-in-loop
await data.save();
}
} catch (err) {
this.client.util.handleError(err);
}
});
historialCommunityReportJob.start();
} }
public async jobCounts() { public async jobCounts() {

View File

@ -0,0 +1,22 @@
import { Document, Schema, model } from 'mongoose';
import { ScoreInterfaceRaw } from '.';
export interface ScoreHistoricalRaw {
userID: string,
report: ScoreInterfaceRaw,
date: Date,
}
export interface ScoreHistoricalInterface extends Document {
userID: string,
report: ScoreInterfaceRaw,
date: Date
}
const ScoreHistorical: Schema = new Schema({
userID: String,
report: Object,
date: Date,
});
export default model<ScoreHistoricalInterface>('ScoreHistorical', ScoreHistorical);

View File

@ -7,6 +7,7 @@ export { default as Note, NoteInterface } from './Note';
export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber'; export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber';
export { default as Rank, RankInterface } from './Rank'; export { default as Rank, RankInterface } from './Rank';
export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect'; export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect';
export { default as Score, ScoreInterface } from './Score'; export { default as Score, ScoreInterface, ScoreInterfaceRaw } from './Score';
export { default as ScoreHistorical, ScoreHistoricalInterface } from './ScoreHistorical';
export { default as Staff, StaffInterface } from './Staff'; export { default as Staff, StaffInterface } from './Staff';
export { default as Stat, StatInterface } from './Stat'; export { default as Stat, StatInterface } from './Stat';

View File

@ -64,6 +64,14 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/cron@^1.7.2":
version "1.7.2"
resolved "https://registry.yarnpkg.com/@types/cron/-/cron-1.7.2.tgz#e9fb420da616920dae82d13adfca53282ffaab6e"
integrity sha512-AEpNLRcsVSc5AdseJKNHpz0d4e8+ow+abTaC0fKDbAU86rF1evoFF0oC2fV9FdqtfVXkG2LKshpLTJCFOpyvTg==
dependencies:
"@types/node" "*"
moment ">=2.14.0"
"@types/eslint-visitor-keys@^1.0.0": "@types/eslint-visitor-keys@^1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
@ -694,6 +702,13 @@ cron-parser@^2.13.0:
is-nan "^1.3.0" is-nan "^1.3.0"
moment-timezone "^0.5.31" moment-timezone "^0.5.31"
cron@^1.8.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/cron/-/cron-1.8.2.tgz#4ac5e3c55ba8c163d84f3407bde94632da8370ce"
integrity sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==
dependencies:
moment-timezone "^0.5.x"
cross-spawn@^7.0.2: cross-spawn@^7.0.2:
version "7.0.2" version "7.0.2"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.2.tgz#d0d7dcfa74e89115c7619f4f721a94e1fdb716d6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.2.tgz#d0d7dcfa74e89115c7619f4f721a94e1fdb716d6"
@ -2056,14 +2071,14 @@ mkdirp@^1.0.3:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
moment-timezone@^0.5.31: moment-timezone@^0.5.31, moment-timezone@^0.5.x:
version "0.5.31" version "0.5.31"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05"
integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA== integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==
dependencies: dependencies:
moment ">= 2.9.0" moment ">= 2.9.0"
"moment@>= 2.9.0": "moment@>= 2.9.0", moment@>=2.14.0:
version "2.29.1" version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==