quality of life updates

merge-requests/15/merge
Matthew 2021-02-02 01:45:03 -05:00
parent 743970730b
commit d0dfe0e730
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
30 changed files with 373 additions and 434 deletions

View File

@ -2,7 +2,7 @@
We accept contributions from the community, however there's a few steps you need to do first before you're able to fork the project. We accept contributions from the community, however there's a few steps you need to do first before you're able to fork the project.
1. Join the [Discord Server](https://discord.gg/F4ztpQh). 1. Join the [Discord Server](https://loc.sh/discord).
2. Send a DM to @Ramirez in the server, provide your GitLab username. 2. Send a DM to @Ramirez in the server, provide your GitLab username.
3. We'll let you know when you'll be able to fork the project. 3. We'll let you know when you'll be able to fork the project.

View File

@ -1,5 +1,5 @@
{ {
"name": "loccommunityrelations", "name": "loccr",
"version": "1.0.0", "version": "1.0.0",
"description": "The official system for handling Community Relations in the LOC Discord server.", "description": "The official system for handling Community Relations in the LOC Discord server.",
"main": "build/main.js", "main": "build/main.js",
@ -7,7 +7,7 @@
"lint": "eslint -c ./.eslintrc.json src --ext ts" "lint": "eslint -c ./.eslintrc.json src --ext ts"
}, },
"repository": "https://gitlab.libraryofcode.org/engineering/communityrelations.git", "repository": "https://gitlab.libraryofcode.org/engineering/communityrelations.git",
"author": "Matthew R <matthew@staff.libraryofcode.org>", "author": "Matthew R, AD, FSEN <matthew@staff.libraryofcode.org>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"private": false, "private": false,
"devDependencies": { "devDependencies": {
@ -29,6 +29,7 @@
"eslint": "^7.0.0", "eslint": "^7.0.0",
"eslint-config-airbnb-base": "^14.1.0", "eslint-config-airbnb-base": "^14.1.0",
"eslint-plugin-import": "^2.20.2", "eslint-plugin-import": "^2.20.2",
"tslib": "^2.1.0",
"typescript": "^3.9.2" "typescript": "^3.9.2"
}, },
"dependencies": { "dependencies": {
@ -55,6 +56,7 @@
"puppeteer": "^5.5.0", "puppeteer": "^5.5.0",
"sd-notify": "^2.8.0", "sd-notify": "^2.8.0",
"signale": "^1.4.0", "signale": "^1.4.0",
"stock-info": "^1.2.0",
"stripe": "^8.120.0", "stripe": "^8.120.0",
"uuid": "^8.0.0", "uuid": "^8.0.0",
"yaml": "^1.9.2" "yaml": "^1.9.2"

View File

@ -1,9 +1,8 @@
/* eslint-disable no-bitwise */ /* eslint-disable no-bitwise */
/* eslint-disable no-continue */ /* eslint-disable no-continue */
import jwt from 'jsonwebtoken'; import jwt from 'jsonwebtoken';
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 } from '../../../class';
import { ScoreHistoricalRaw } from '../../../models/ScoreHistorical'; import { ScoreHistoricalRaw } from '../../../models/ScoreHistorical';
import { getTotalMessageCount } from '../../../intervals/score'; import { getTotalMessageCount } from '../../../intervals/score';
@ -129,11 +128,12 @@ 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 inqs = await this.server.client.db.Inquiry.find({ userID: member.userID }).lean().exec();
const inquiries: [{ id?: string, name: string, date: Date }?] = []; const inquiries: [{ id?: string, name: string, date: Date }?] = [];
if (member.inquiries?.length > 0) { if (inqs?.length > 0) {
for (const inq of member.inquiries) { for (const inq of inqs) {
const testDate = (new Date(new Date(inq.date).setHours(1460))); const testDate = (new Date(new Date(inq.date).setHours(1460)));
if (testDate > new Date()) inquiries.push({ id: inq.id, name: inq.name, date: inq.date }); if (testDate > new Date()) inquiries.push({ id: inq.iid, name: inq.name, date: inq.date });
} }
} }
@ -174,35 +174,14 @@ export default class Report extends Route {
array.push(data); array.push(data);
} }
if (member.notify) { const inq = await this.server.client.report.createInquiry(member.userID, merchant.name, 0, req.body.reason);
const chan = await this.server.client.getDMChannel(member.userID);
try {
chan.createMessage(`__**Community Score - Hard Pull Notification**__\n*You have signed up to be notified whenever your hard score has been pulled. See \`?score\` for more information.*\n\n**Department/Service:** ${merchant.name.toUpperCase()}`);
} catch (err) {
this.server.client.util.signale.error(`Unable to DM user: ${member.userID} | ${err}`);
}
}
await this.server.client.db.Merchant.updateOne({ key: req.headers.authorization }, { $addToSet: { pulls: { type: 0, reason: req.body.reason, date: new Date() } } }); await this.server.client.db.Merchant.updateOne({ key: req.headers.authorization }, { $addToSet: { pulls: { type: 0, reason: req.body.reason, date: new Date() } } });
const reportID = uuid();
await this.server.client.db.Score.updateOne({ userID: member.userID }, { $addToSet: { inquiries: { id: reportID, name: merchant.name, reason: req.body.reason, date: new Date(), report: member } } });
const embed = new RichEmbed();
embed.setTitle('Inquiry Notification');
embed.setDescription(reportID);
embed.setColor('#800080');
embed.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${member.userID}>`, true);
embed.addField('Type', 'HARD', true);
embed.addField('Department/Service', merchant.name.toUpperCase(), true);
embed.addField('Reason', req.body.reason ?? 'N/A', true);
embed.setTimestamp();
embed.setFooter(this.server.client.user.username, this.server.client.user.avatarURL);
const chan = <TextChannel> this.server.client.guilds.get(this.server.client.config.guildID).channels.get('611584771356622849');
chan.createMessage({ embed }).catch(() => {});
return res.status(200).json({ return res.status(200).json({
code: this.constants.codes.SUCCESS, code: this.constants.codes.SUCCESS,
message: { message: {
id: reportID, id: inq.id,
userID: member.userID, userID: member.userID,
memberInformation: { memberInformation: {
username: mem.user.username, username: mem.user.username,
@ -238,35 +217,24 @@ export default class Report extends Route {
const merchant = await this.server.client.db.Merchant.findOne({ key: req.headers.authorization }).lean().exec(); const merchant = await this.server.client.db.Merchant.findOne({ key: req.headers.authorization }).lean().exec();
if (!merchant) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); if (!merchant) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED });
const member = await this.server.client.db.Score.findOne({ userID: req.body.userID }).lean().exec(); const report = await this.server.client.db.Score.findOne({ userID: req.body.userID }).lean().exec();
if (!member) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); if (!report) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED });
let totalScore: number; let totalScore: number;
if (member.total < 200) totalScore = 0; if (report.total < 200) totalScore = 0;
else if (member.total > 800) totalScore = 800; else if (report.total > 800) totalScore = 800;
else totalScore = Math.round(member.total); else totalScore = Math.round(report.total);
await this.server.client.db.Merchant.updateOne({ key: req.headers.authorization }, { $addToSet: { pulls: { type: 1, reason: 'N/A', date: new Date() } } }); await this.server.client.db.Merchant.updateOne({ key: req.headers.authorization }, { $addToSet: { pulls: { type: 1, reason: 'N/A', date: new Date() } } });
await this.server.client.db.Score.updateOne({ userID: member.userID }, { $addToSet: { softInquiries: { name: merchant.name, date: new Date() } } }); const mem = this.server.client.util.resolveMember(report.userID, this.server.client.guilds.get(this.server.client.config.guildID));
const embed = new RichEmbed(); await this.server.client.report.createInquiry(report.userID, merchant.name.toUpperCase(), 1);
embed.setTitle('Inquiry Notification');
embed.setColor('#00FFFF');
const mem = this.server.client.util.resolveMember(member.userID, this.server.client.guilds.get(this.server.client.config.guildID));
if (!mem) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.codes.NOT_FOUND });
embed.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${member.userID}>`, true);
embed.addField('Type', 'SOFT', true);
embed.addField('Department/Service', merchant.name.toUpperCase(), true);
embed.setTimestamp();
embed.setFooter(this.server.client.user.username, this.server.client.user.avatarURL);
const chan = <TextChannel> this.server.client.guilds.get(this.server.client.config.guildID).channels.get('611584771356622849');
chan.createMessage({ embed }).catch(() => {});
if (!merchant.privileged) { if (!merchant.privileged) {
return res.status(200).json({ return res.status(200).json({
code: this.constants.codes.SUCCESS, code: this.constants.codes.SUCCESS,
message: { message: {
userID: member.userID, userID: report.userID,
totalScore, totalScore,
}, },
}); });
@ -288,36 +256,38 @@ export default class Report extends Route {
if ((mem.user.publicFlags & (1 << 17)) === 1 << 17) flags.push('EARLY_VERIFIED_BOT_DEVELOPER'); if ((mem.user.publicFlags & (1 << 17)) === 1 << 17) flags.push('EARLY_VERIFIED_BOT_DEVELOPER');
} }
const set = []; const set = [];
const accounts = await this.server.client.db.Score.find().lean().exec(); if (req.query.p?.toString() === 'true') {
for (const sc of accounts) { const accounts = await this.server.client.db.Score.find().lean().exec();
if (sc.total < 200) { continue; } for (const sc of accounts) {
if (sc.total > 800) { set.push(800); continue; } if (sc.total < 200) { continue; }
set.push(sc.total); if (sc.total > 800) { set.push(800); continue; }
set.push(sc.total);
}
} }
let activityScore: number; let activityScore: number;
const moderationScore = Math.round(member.moderation); const moderationScore = Math.round(report.moderation);
let roleScore: number; let roleScore: number;
let cloudServicesScore: number; let cloudServicesScore: number;
const otherScore = Math.round(member.other); const otherScore = Math.round(report.other);
let miscScore: number; let miscScore: number;
if (member.activity < 10) activityScore = 0; if (report.activity < 10) activityScore = 0;
else if (member.activity > Math.floor((Math.log1p(getTotalMessageCount(this.server.client)) * 12))) activityScore = Math.floor((Math.log1p(getTotalMessageCount(this.server.client)) * 12)); else if (report.activity > Math.floor((Math.log1p(getTotalMessageCount(this.server.client)) * 12))) activityScore = Math.floor((Math.log1p(getTotalMessageCount(this.server.client)) * 12));
else activityScore = Math.round(member.activity); else activityScore = Math.round(report.activity);
if (member.roles <= 0) roleScore = 0; if (report.roles <= 0) roleScore = 0;
else if (member.roles > 54) roleScore = 54; else if (report.roles > 54) roleScore = 54;
else roleScore = Math.round(member.roles); else roleScore = Math.round(report.roles);
if (member.staff <= 0) miscScore = 0; if (report.staff <= 0) miscScore = 0;
else miscScore = Math.round(member.staff); else miscScore = Math.round(report.staff);
if (member.cloudServices === 0) cloudServicesScore = 0; if (report.cloudServices === 0) cloudServicesScore = 0;
else if (member.cloudServices > 10) cloudServicesScore = 10; else if (report.cloudServices > 10) cloudServicesScore = 10;
else cloudServicesScore = Math.round(member.cloudServices); else cloudServicesScore = Math.round(report.cloudServices);
const historicalData = await this.server.client.db.ScoreHistorical.find({ userID: member.userID }).lean().exec(); const historicalData = await this.server.client.db.ScoreHistorical.find({ userID: report.userID }).lean().exec();
const array: ScoreHistoricalRaw[] = []; const array: ScoreHistoricalRaw[] = [];
for (const data of historicalData) { for (const data of historicalData) {
delete data.report?.softInquiries; delete data.report?.softInquiries;
@ -359,7 +329,7 @@ export default class Report extends Route {
return res.status(200).json({ return res.status(200).json({
code: this.constants.codes.SUCCESS, code: this.constants.codes.SUCCESS,
message: { message: {
userID: member.userID, userID: report.userID,
memberInformation: { memberInformation: {
username: mem.user.username, username: mem.user.username,
discriminator: mem.user.discriminator, discriminator: mem.user.discriminator,
@ -370,7 +340,7 @@ export default class Report extends Route {
nitroBoost: mem.premiumSince === null, nitroBoost: mem.premiumSince === null,
}, },
totalScore, totalScore,
percentile: Math.round(this.server.client.util.percentile(set, member.total)), percentile: Math.round(this.server.client.util.percentile(set, report.total)),
activityScore, activityScore,
moderationScore, moderationScore,
roleScore, roleScore,
@ -405,17 +375,7 @@ export default class Report extends Route {
else totalScore = Math.round(member.total); else totalScore = Math.round(member.total);
await this.server.client.db.Merchant.updateOne({ key: req.headers.authorization }, { $addToSet: { pulls: { type: 1, reason: 'N/A', date: new Date() } } }); await this.server.client.db.Merchant.updateOne({ key: req.headers.authorization }, { $addToSet: { pulls: { type: 1, reason: 'N/A', date: new Date() } } });
await this.server.client.db.Score.updateOne({ userID: member.userID }, { $addToSet: { softInquiries: { name: merchant.name, date: new Date() } } }); await this.server.client.report.createInquiry(member.userID, merchant.name.toUpperCase(), 1);
const embed = new RichEmbed();
embed.setTitle('Inquiry Notification');
embed.setColor('#00FFFF');
embed.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${member.userID}>`, true);
embed.addField('Type', 'SOFT', true);
embed.addField('Department/Service', merchant.name.toUpperCase(), true);
embed.setTimestamp();
embed.setFooter(this.server.client.user.username, this.server.client.user.avatarURL);
const chan = <TextChannel> this.server.client.guilds.get(this.server.client.config.guildID).channels.get('611584771356622849');
chan.createMessage({ embed }).catch(() => {});
if (!merchant.privileged) { if (!merchant.privileged) {
return res.status(200).json({ return res.status(200).json({
@ -489,42 +449,12 @@ export default class Report extends Route {
this.timeout.delete(req.ip); this.timeout.delete(req.ip);
if (staffScore.userID === score.userID) { if (staffScore.userID === score.userID) {
updated = true; updated = true;
await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: `${member.username} via report.libraryofcode.org @ IP ${req.ip}`, date: new Date() } } }); await this.server.client.report.createInquiry(member.user.id, `${member.username} via report.libraryofcode.org @ IP ${req.ip}`, 1);
const embed = new RichEmbed();
embed.setTitle('Inquiry Notification');
embed.setColor('#00FFFF');
embed.addField('Member', `${member.user.username}#${member.user.discriminator} | <@${member.user.id}>`, true);
embed.addField('Type', 'SOFT', true);
embed.addField('Department/Service', `${member.username} via report.libraryofcode.org @ IP ${req.ip}`.toUpperCase(), true);
embed.setTimestamp();
embed.setFooter(this.server.client.user.username, this.server.client.user.avatarURL);
const chan = <TextChannel> this.server.client.guilds.get(this.server.client.config.guildID).channels.get('611584771356622849');
chan.createMessage({ embed }).catch(() => {});
} else { } else {
await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: 'Library of Code sp-us | Staff Team via report.libraryofcode.org', date: new Date() } } }); await this.server.client.report.createInquiry(member.user.id, 'Library of Code sp-us | Staff Team via report.libraryofcode.org', 1);
const embed = new RichEmbed();
embed.setTitle('Inquiry Notification');
embed.setColor('#00FFFF');
embed.addField('Member', `${member.user.username}#${member.user.discriminator} | <@${member.user.id}>`, true);
embed.addField('Type', 'SOFT', true);
embed.addField('Department/Service', 'Library of Code sp-us | Staff Team via report.libraryofcode.org'.toUpperCase(), true);
embed.setTimestamp();
embed.setFooter(this.server.client.user.username, this.server.client.user.avatarURL);
const chan = <TextChannel> this.server.client.guilds.get(this.server.client.config.guildID).channels.get('611584771356622849');
chan.createMessage({ embed }).catch(() => {});
} }
} else if (!updated) { } else if (!updated) {
await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: `${member.username} via report.libraryofcode.org @ IP ${req.ip}`, date: new Date() } } }); await this.server.client.report.createInquiry(member.user.id, `${member.username} via report.libraryofcode.org @ IP ${req.ip}`, 1);
const embed = new RichEmbed();
embed.setTitle('Inquiry Notification');
embed.setColor('#00FFFF');
embed.addField('Member', `${member.user.username}#${member.user.discriminator} | <@${member.user.id}>`, true);
embed.addField('Type', 'SOFT', true);
embed.addField('Department/Service', `${member.username} via report.libraryofcode.org @ IP ${req.ip}`.toUpperCase(), true);
embed.setTimestamp();
embed.setFooter(this.server.client.user.username, this.server.client.user.avatarURL);
const chan = <TextChannel> this.server.client.guilds.get(this.server.client.config.guildID).channels.get('611584771356622849');
chan.createMessage({ embed }).catch(() => {});
} }
score = await this.server.client.db.Score.findOne({ pin: [Number(args.split('-')[0]), Number(args.split('-')[1]), Number(args.split('-')[2])] }).lean().exec(); score = await this.server.client.db.Score.findOne({ pin: [Number(args.split('-')[0]), Number(args.split('-')[1]), Number(args.split('-')[2])] }).lean().exec();
@ -560,7 +490,7 @@ export default class Report extends Route {
else if (score.cloudServices > 10) cloudServicesScore = '10'; else if (score.cloudServices > 10) cloudServicesScore = '10';
else cloudServicesScore = `${score.cloudServices}`; else cloudServicesScore = `${score.cloudServices}`;
const moderations = await this.server.client.db.Moderation.find({ userID: score.userID }); const moderations = await this.server.client.db.Moderation.find({ userID: score.userID }).lean().exec();
const historical = await this.server.client.db.ScoreHistorical.find({ userID: score.userID }).lean().exec(); const historical = await this.server.client.db.ScoreHistorical.find({ userID: score.userID }).lean().exec();
@ -595,6 +525,17 @@ export default class Report extends Route {
data.report.total = total; data.report.activity = activity; data.report.moderation = moderation; data.report.roles = role; data.report.cloudServices = cloud; data.report.other = other; data.report.staff = misc; data.report.total = total; data.report.activity = activity; data.report.moderation = moderation; data.report.roles = role; data.report.cloudServices = cloud; data.report.other = other; data.report.staff = misc;
} }
const inqs = await this.server.client.db.Inquiry.find({ userID: score.userID }).lean().exec();
const hardInquiries: [{ id?: string, name: string, reason: string, date: Date }?] = [];
const softInquiries: [{ id?: string, name: string, date: Date }?] = [];
for (const inq of inqs) {
if (inq.type === 0) {
hardInquiries.push({ id: inq.iid, name: inq.name, reason: inq.reason, date: inq.date });
} else if (inq.type === 1) {
softInquiries.push({ name: inq.name, date: inq.date });
}
}
return res.status(200).json({ return res.status(200).json({
name: `${member.username}#${member.discriminator}`, name: `${member.username}#${member.discriminator}`,
avatarURL: member.avatarURL, avatarURL: member.avatarURL,
@ -610,8 +551,8 @@ export default class Report extends Route {
notify: score.notify, notify: score.notify,
locked: !!score.locked, locked: !!score.locked,
totalModerations: moderations?.length > 0 ? moderations.length : 0, totalModerations: moderations?.length > 0 ? moderations.length : 0,
inquiries: score.inquiries?.length > 0 ? score.inquiries : [], inquiries: hardInquiries?.length > 0 ? hardInquiries : [],
softInquiries: score.softInquiries?.length > 0 ? score.softInquiries : [], softInquiries: softInquiries?.length > 0 ? softInquiries : [],
historical: historical ?? [], historical: historical ?? [],
lastUpdated: score.lastUpdate, lastUpdated: score.lastUpdate,
}); });

View File

@ -8,6 +8,7 @@ import {
Customer, CustomerInterface, Customer, CustomerInterface,
CustomerPortal, CustomerPortalInterface, CustomerPortal, CustomerPortalInterface,
File, FileInterface, File, FileInterface,
Inquiry, InquiryInterface,
Member, MemberInterface, Member, MemberInterface,
Merchant, MerchantInterface, Merchant, MerchantInterface,
Moderation, ModerationInterface, Moderation, ModerationInterface,
@ -43,7 +44,7 @@ export default class Client extends eris.Client {
public stripe: Stripe; public stripe: Stripe;
public db: { Customer: mongoose.Model<CustomerInterface>, CustomerPortal: mongoose.Model<CustomerPortalInterface>, 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>, Promo: mongoose.Model<PromoInterface>, 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 } }; public db: { Customer: mongoose.Model<CustomerInterface>, CustomerPortal: mongoose.Model<CustomerPortalInterface>, File: mongoose.Model<FileInterface>, Inquiry: mongoose.Model<InquiryInterface>, Member: mongoose.Model<MemberInterface>, Merchant: mongoose.Model<MerchantInterface>, Moderation: mongoose.Model<ModerationInterface>, NNTrainingData: mongoose.Model<NNTrainingDataInterface>, Note: mongoose.Model<NoteInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Promo: mongoose.Model<PromoInterface>, 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);
@ -51,7 +52,15 @@ 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 = { Customer, CustomerPortal, File, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Promo, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } }; this.db = { Customer, CustomerPortal, File, Inquiry, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Promo, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } };
}
get report() {
return this.util.report;
}
get pbx() {
return this.util.pbx;
} }

View File

@ -1,9 +1,10 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-eval */ /* eslint-disable no-eval */
import Bull from 'bull'; import Bull from 'bull';
import cron from 'cron'; import cron from 'cron';
import { TextableChannel } from 'eris'; import { TextableChannel, TextChannel } from 'eris';
import { Client, RichEmbed } from '.'; import { Client, RichEmbed } from '.';
import { ScoreInterface } from '../models'; import { ScoreInterface, InqType as InquiryType } from '../models';
import { apply as Apply } from '../commands'; import { apply as Apply } from '../commands';
@ -28,12 +29,13 @@ export default class Queue {
const startDate = new Date(); const startDate = new Date();
for (const report of reports) { for (const report of reports) {
const inqs = await this.client.db.Inquiry.find({ userID: report.userID });
const data = new this.client.db.ScoreHistorical({ const data = new this.client.db.ScoreHistorical({
userID: report.userID, userID: report.userID,
report, report,
inquiries: inqs.map((inq) => inq._id),
date: startDate, date: startDate,
}); });
// eslint-disable-next-line no-await-in-loop
await data.save(); await data.save();
} }
} catch (err) { } catch (err) {
@ -77,6 +79,37 @@ export default class Queue {
} }
protected setProcessors() { protected setProcessors() {
this.queues.score.process('score::inquiry', async (job: Bull.Job<{ inqID: string, userID: string, name: string, type: InquiryType, reason?: string }>) => {
const member = this.client.util.resolveMember(job.data.userID, this.client.guilds.get(this.client.config.guildID));
const report = await this.client.db.Score.findOne({ userID: job.data.userID }).lean().exec();
const embed = new RichEmbed();
if (job.data.type === InquiryType.HARD) {
embed.setTitle('Inquiry Notification');
embed.setDescription(job.data.inqID);
embed.setColor('#800080');
embed.addField('Member', `${member.user.username}#${member.user.discriminator} | <@${job.data.userID}>`, true);
embed.addField('Type', 'HARD', true);
embed.addField('Department/Service', job.data.name.toUpperCase(), true);
embed.addField('Reason', job.data.reason ?? 'N/A', true);
embed.setTimestamp();
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
if (report.notify === true) {
await this.client.getDMChannel(job.data.userID).then((chan) => {
chan.createMessage(`__**Community Score - Hard Pull Notification**__\n*You have signed up to be notified whenever your hard score has been pulled. See \`?score\` for more information.*\n\n**Department/Service:** ${job.data.name.toUpperCase()}`);
}).catch(() => {});
}
} else {
embed.setTitle('Inquiry Notification');
embed.setColor('#00FFFF');
embed.addField('Member', `${member.user.username}#${member.user.discriminator} | <@${job.data.userID}>`, true);
embed.addField('Type', 'SOFT', true);
embed.addField('Department/Service', job.data.name.toUpperCase(), true);
embed.setTimestamp();
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
}
const log = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
log.createMessage({ embed }).catch(() => {});
});
this.queues.score.process('score::update', async (job: Bull.Job<{ score: ScoreInterface, total: number, activity: number, roles: number, moderation: number, cloudServices: number, other: number, staff: number }>) => { this.queues.score.process('score::update', async (job: Bull.Job<{ score: ScoreInterface, total: number, activity: number, roles: number, moderation: number, cloudServices: number, other: number, staff: number }>) => {
await this.client.db.Score.updateOne({ userID: job.data.score.userID }, { $set: { total: job.data.total, activity: job.data.activity, roles: job.data.roles, moderation: job.data.moderation, cloudServices: job.data.cloudServices, other: job.data.other, staff: job.data.staff, lastUpdate: new Date() } }); await this.client.db.Score.updateOne({ userID: job.data.score.userID }, { $set: { total: job.data.total, activity: job.data.activity, roles: job.data.roles, moderation: job.data.moderation, cloudServices: job.data.cloudServices, other: job.data.other, staff: job.data.staff, lastUpdate: new Date() } });
if (!job.data.score.pin || job.data.score.pin?.length < 1) { if (!job.data.score.pin || job.data.score.pin?.length < 1) {
@ -123,8 +156,12 @@ export default class Queue {
}); });
} }
public addInquiry(inqID: string, userID: string, name: string, type: InquiryType, reason?: string) {
return this.queues.score.add('score::inquiry', { inqID, userID, name, type, reason });
}
public updateScore(score: ScoreInterface, total: number, activity: number, roles: number, moderation: number, cloudServices: number, other: number, staff: number) { public updateScore(score: ScoreInterface, total: number, activity: number, roles: number, moderation: number, cloudServices: number, other: number, staff: number) {
this.queues.score.add('score::update', { score, total, activity, roles, moderation, cloudServices, other, staff }); return this.queues.score.add('score::update', { score, total, activity, roles, moderation, cloudServices, other, staff });
} }
public processApplication(channelInformation: { messageID: string, guildID: string, channelID: string }, url: string, userID: string, func?: string) { public processApplication(channelInformation: { messageID: string, guildID: string, channelID: string }, url: string, userID: string, func?: string) {

View File

@ -1,6 +1,6 @@
import { EventEmitter } from 'events'; import { v4 as uuid } from 'uuid';
import { Client, RichEmbed } from '.'; import { Client } from '.';
import { ScoreHistoricalRaw } from '../models/ScoreHistorical'; import { InqType } from '../models';
export default class Report { export default class Report {
public client: Client; public client: Client;
@ -9,7 +9,27 @@ export default class Report {
this.client = client; this.client = client;
} }
public async soft(userID: string) { public async createInquiry(userID: string, name: string, type: InqType, reason?: string) {
const report = await this.client.db.Score.findOne({ userID }).lean().exec();
const member = this.client.util.resolveMember(userID, this.client.guilds.get(this.client.config.guildID));
if (!report || !member) return null;
if (type === InqType.HARD && report.locked) return null;
const mod = await (new this.client.db.Inquiry({
iid: uuid(),
userID,
name,
type,
reason,
date: new Date(),
report,
}).save());
this.client.queue.addInquiry(mod.iid, userID, name, type, reason);
return mod;
}
/* public async soft(userID: string) {
const report = await this.client.db.Score.findOne({ userID }); const report = await this.client.db.Score.findOne({ userID });
if (!report) return null; if (!report) return null;
let totalScore: number; let totalScore: number;
@ -73,5 +93,5 @@ export default class Report {
array.push(data); array.push(data);
} }
} } */
} }

View File

@ -4,7 +4,7 @@ import childProcess from 'child_process';
import { promisify } from 'util'; import { promisify } from 'util';
import signale from 'signale'; import signale from 'signale';
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel, WebhookPayload } from 'eris'; import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel, WebhookPayload } from 'eris';
import { Client, Command, Moderation, PBX, RichEmbed } from '.'; import { Client, Command, Moderation, PBX, Report, RichEmbed } from '.';
import { statusMessages as emotes } from '../configs/emotes.json'; import { statusMessages as emotes } from '../configs/emotes.json';
export default class Util { export default class Util {
@ -18,6 +18,8 @@ export default class Util {
public pbx: PBX; public pbx: PBX;
public report: Report;
constructor(client: Client) { constructor(client: Client) {
this.client = client; this.client = client;
this.moderation = new Moderation(this.client); this.moderation = new Moderation(this.client);
@ -33,6 +35,7 @@ export default class Util {
auth: { user: 'internal', pass: this.client.config.emailPass }, auth: { user: 'internal', pass: this.client.config.emailPass },
}); });
this.pbx = new PBX(this.client); this.pbx = new PBX(this.client);
this.report = new Report(this.client);
} }
get emojis() { get emojis() {
@ -43,6 +46,46 @@ export default class Util {
}; };
} }
public hrn(number: any, fixed: number, formatter: any | any[]) {
const builtInFormatters = {
en: ['KMGTPEZY'.split(''), 1e3],
zh_CN: ['百千万亿兆京垓秭'.split(''), [100, 10, 10, 1e4, 1e4, 1e4, 1e4, 1e4]],
};
number = Math.abs(number);
if (!fixed && fixed !== 0) fixed = 1;
if (typeof formatter === 'object') {
const name = `${new Date().getTime()}`;
builtInFormatters[name] = formatter;
formatter = name;
}
if (!builtInFormatters[formatter]) formatter = 'en';
formatter = builtInFormatters[formatter];
let power = 1;
const texts = formatter[0];
const powers = formatter[1];
let loop = 0;
let is_array = false;
if (typeof powers === 'object') is_array = true;
// eslint-disable-next-line no-constant-condition
while (1) {
if (is_array) power = powers[loop];
else power = powers;
if (number >= power && loop < texts.length) number /= power;
else {
number = number.toFixed(fixed);
return loop === 0 ? number : `${number} ${texts[loop - 1]}`;
}
// eslint-disable-next-line no-plusplus
++loop;
}
}
/** /**
* Resolves a command * Resolves a command
* @param query Command input * @param query Command input

View File

@ -7,6 +7,7 @@ export { default as LocalStorage } from './LocalStorage';
export { default as Moderation } from './Moderation'; export { default as Moderation } from './Moderation';
export { default as PBX } from './PBX'; export { default as PBX } from './PBX';
export { default as Queue } from './Queue'; export { default as Queue } from './Queue';
export { default as Report } from './Report';
export { default as RichEmbed } from './RichEmbed'; export { default as RichEmbed } from './RichEmbed';
export { default as Route } from './Route'; export { default as Route } from './Route';
export { default as Server } from './Server'; export { default as Server } from './Server';

View File

@ -7,7 +7,7 @@ export default class Callback extends Command {
constructor(client: Client) { constructor(client: Client) {
super(client); super(client);
this.name = 'callback'; this.name = 'callback';
this.description = 'Requests a Callback from a Technican.\nPlease use `-` to separate the number if needed. E.x. 202-750-2585.\nDo note, we are unable to dial international numbers outside of the US and Canada.'; this.description = 'Requests a Callback from a Technican.\nPlease use `-` to separate the number if needed. E.x. 202-750-2585.\nDo note, we are unable to dial international numbers outside of the US and Canada.\n\n*We recommend you run this command in your DMs for privacy.*';
this.usage = 'callback <the number you want us to call>'; this.usage = 'callback <the number you want us to call>';
this.aliases = ['cb']; this.aliases = ['cb'];
this.permissions = 0; this.permissions = 0;
@ -31,17 +31,7 @@ export default class Callback extends Command {
embed.addField('Phone Number Type', phone.getType(), true); embed.addField('Phone Number Type', phone.getType(), true);
const communityReport = await this.client.db.Score.findOne({ userID: message.author.id }).lean().exec(); const communityReport = await this.client.db.Score.findOne({ userID: message.author.id }).lean().exec();
if (communityReport) { if (communityReport) {
await this.client.db.Score.updateOne({ userID: message.author.id }, { $addToSet: { softInquiries: { name: 'LIBRARY OF CODE SP-US | VOIP/PBX MEMBER SUPPORT SVCS', date: new Date() } } }); await this.client.report.createInquiry(member.user.id, 'Library of Code sp-us | VOIP/PBX Member Support SVCS', 1);
const embed2 = new RichEmbed();
embed2.setTitle('Inquiry Notification');
embed2.setColor('#00FFFF');
embed2.addField('Member', `${member.user.username}#${member.user.discriminator} | <@${member.user.id}>`, true);
embed2.addField('Type', 'SOFT', true);
embed2.addField('Department/Service', 'Library of Code sp-us | VOIP/PBX Member Support SVCS'.toUpperCase(), true);
embed2.setTimestamp();
embed2.setFooter(this.client.user.username, this.client.user.avatarURL);
const log = <TextChannel> this.mainGuild.channels.get('611584771356622849');
log.createMessage({ embed: embed2 }).catch(() => {});
embed.addField('PIN', `${communityReport.pin[0]}-${communityReport.pin[1]}-${communityReport.pin[2]}`, true); embed.addField('PIN', `${communityReport.pin[0]}-${communityReport.pin[1]}-${communityReport.pin[2]}`, true);
} }
try { try {

View File

@ -1,5 +1,4 @@
import { Message } from 'eris'; import { Message } from 'eris';
import { randomBytes } from 'crypto';
import { Client, Command } from '../class'; import { Client, Command } from '../class';
export default class DelMerchant extends Command { export default class DelMerchant extends Command {

View File

@ -21,6 +21,7 @@ export { default as info } from './info';
export { default as intercom } from './intercom'; export { default as intercom } from './intercom';
export { default as kick } from './kick'; export { default as kick } from './kick';
export { default as listredirects } from './listredirects'; export { default as listredirects } from './listredirects';
export { default as market } from './market';
export { default as members } from './members'; export { default as members } from './members';
export { default as mute } from './mute'; export { default as mute } from './mute';
export { default as notes } from './notes'; export { default as notes } from './notes';

View File

@ -1,4 +1,4 @@
import { Message, User, Member } from 'eris'; import { Member, Message } from 'eris';
import { Client, Command } from '../class'; import { Client, Command } from '../class';
export default class Kick extends Command { export default class Kick extends Command {

59
src/commands/market.ts Normal file
View File

@ -0,0 +1,59 @@
import { Message } from 'eris';
import stockInfo from 'stock-info';
import { Client, Command, RichEmbed } from '../class';
export default class Market extends Command {
constructor(client: Client) {
super(client);
this.name = 'market';
this.description = 'Fetches information from a ticker for a stock or fund.';
this.usage = `${this.client.config.prefix}market <ticker>`;
this.permissions = 0;
this.guildOnly = true;
this.enabled = true;
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let stock: stockInfo.Stock;
try {
stock = await stockInfo.getSingleStockInfo(args[0]);
} catch (err) {
return this.error(message.channel, `Unable to fetch information for that ticker. | ${err}`);
}
const embed = new RichEmbed();
embed.setTitle(stock.longName ?? stock.symbol);
let type: string;
switch (stock.quoteType) {
case 'EQUITY':
type = 'Common/Preferred Stock';
break;
case 'ETF':
type = 'Exchange Traded Fund (ETF)';
break;
case 'MUTUALFUND':
type = 'Mutual Fund';
break;
default:
type = 'N/A or Unknown';
break;
}
embed.addField('Type', type, true);
embed.addField('Market Cap', `${stock.marketCap ? this.client.util.hrn(stock.marketCap, undefined, undefined) : 'N/A'}`, true);
embed.addField('Day Quote Price', stock.regularMarketPrice ? `$${Number(stock.regularMarketPrice).toFixed(2)}` : 'N/A', true);
embed.addField('Day G/L', stock.regularMarketChange ? `$${Number(stock.regularMarketChange.toFixed(2))}` : 'N/A', true);
embed.addField('Day Range', stock.regularMarketDayRange ?? 'N/A', true);
embed.addField('Bid/Ask', `Bid: $${stock.bid?.toFixed(2) ?? 'N/A'} | Ask: $${stock.ask?.toFixed(2) ?? 'N/A'}`, true);
embed.addField('Forward P/E (Price/Earnings)', `${stock.forwardPE?.toFixed(2) ?? 'N/A'}`, true);
embed.addField('Forward EPS (Earnings Per Share)', `${stock.epsForward?.toFixed(2) ?? 'N/A'}`, true);
embed.addField('Exchange', `${stock.fullExchangeName?.toUpperCase() ?? 'N/A'}`, 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, false);
}
}
}

View File

@ -27,18 +27,7 @@ export default class Score extends Command {
const report = score.inquiries.find((inq) => inq.id === args[1]); const report = score.inquiries.find((inq) => inq.id === args[1]);
if (!report) return this.error(message.channel, 'Could not find inquiry information.'); if (!report) return this.error(message.channel, 'Could not find inquiry information.');
await this.client.db.Score.updateOne({ userID: member.id }, { $addToSet: { softInquiries: { name: 'Library of Code sp-us | Bureau of Community Reports', date: new Date() } } }); await this.client.report.createInquiry(member.id, 'Library of Code sp-us | Bureau of Community Reports', 1);
const embed2 = new RichEmbed();
embed2.setTitle('Inquiry Notification');
embed2.setColor('#00FFFF');
const mem = this.client.util.resolveMember(score.userID, this.client.guilds.get(this.client.config.guildID));
embed2.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${score.userID}>`, true);
embed2.addField('Type', 'SOFT', true);
embed2.addField('Department/Service', 'Library of Code sp-us | Bureau of Community Reports'.toUpperCase(), true);
embed2.setTimestamp();
embed2.setFooter(this.client.user.username, this.client.user.avatarURL);
const log = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
log.createMessage({ embed: embed2 }).catch(() => {});
const embed = new RichEmbed(); const embed = new RichEmbed();
embed.setTitle(`Hard Inquiry Information - ${report.id}`); embed.setTitle(`Hard Inquiry Information - ${report.id}`);

View File

@ -1,3 +1,4 @@
/* eslint-disable no-plusplus */
/* eslint-disable no-continue */ /* eslint-disable no-continue */
/* eslint-disable default-case */ /* eslint-disable default-case */
import moment from 'moment'; import moment from 'moment';
@ -13,8 +14,9 @@ export default class Score extends Command {
constructor(client: Client) { constructor(client: Client) {
super(client); super(client);
this.name = 'score'; this.name = 'score';
this.description = 'Retreives your Community Report'; this.description = 'Retrieves your Community Report';
this.usage = `${this.client.config.prefix}score\n${this.client.config.prefix}score <member> <type: 'hard' | 'soft'> <reporting department: ex. Library of Code sp-us | Cloud Account Services>:<reason>`; this.usage = `${this.client.config.prefix}score\n${this.client.config.prefix}score <member> <type: 'hard' | 'soft'> <reporting department: ex. Library of Code sp-us | Cloud Account Services>:<reason>`;
this.aliases = ['report'];
this.subcmds = [Score_Hist, Score_Notify, Score_Pref]; this.subcmds = [Score_Hist, Score_Notify, Score_Pref];
this.permissions = 0; this.permissions = 0;
this.guildOnly = false; this.guildOnly = false;
@ -28,18 +30,7 @@ export default class Score extends Command {
if (!args[0] || !this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) { if (!args[0] || !this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) {
user = message.author; user = message.author;
if (!user) return this.error(message.channel, 'Member not found.'); if (!user) return this.error(message.channel, 'Member not found.');
await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name: `${user.username} via Discord`, date: new Date() } } }); await this.client.report.createInquiry(user.id, `${user.username} via Discord`, 1);
const embed = new RichEmbed();
embed.setTitle('Inquiry Notification');
embed.setColor('#00FFFF');
const mem = this.client.util.resolveMember(user.id, this.client.guilds.get(this.client.config.guildID));
embed.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${user.id}>`, true);
embed.addField('Type', 'SOFT', true);
embed.addField('Department/Service', `${user.username} via Discord`.toUpperCase(), true);
embed.setTimestamp();
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
const log = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
log.createMessage({ embed }).catch(() => {});
check = true; check = true;
} else { } else {
user = this.client.util.resolveMember(args[0], this.mainGuild)?.user; user = this.client.util.resolveMember(args[0], this.mainGuild)?.user;
@ -57,30 +48,12 @@ export default class Score extends Command {
const score = await this.client.db.Score.findOne({ userID: user.id }); const score = await this.client.db.Score.findOne({ userID: user.id });
if (!score) return this.error(message.channel, 'Score not calculated yet.'); if (!score) return this.error(message.channel, 'Score not calculated yet.');
if (score.locked) return this.error(message.channel, 'The score report you have requested has been locked.'); if (score.locked) return this.error(message.channel, 'The score report you have requested has been locked.');
const reportID = uuid(); await this.client.report.createInquiry(score.userID, name, 0, reason);
await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { inquiries: { id: reportID, name, reason, date: new Date(), report: score.toObject() } } });
const embed = new RichEmbed();
embed.setTitle('Inquiry Notification');
embed.setDescription(reportID);
embed.setColor('#800080');
const mem = this.client.util.resolveMember(score.userID, this.client.guilds.get(this.client.config.guildID));
embed.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${score.userID}>`, true);
embed.addField('Type', 'HARD', true);
embed.addField('Department/Service', name.toUpperCase(), true);
embed.addField('Reason', reason ?? 'N/A', true);
embed.setTimestamp();
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
const log = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
log.createMessage({ embed }).catch(() => {});
if (score.notify === true) {
await this.client.getDMChannel(user.id).then((chan) => {
chan.createMessage(`__**Community Score - Hard Pull Notification**__\n*You have signed up to be notified whenever your hard score has been pulled. See \`?score\` for more information.*\n\n**Department/Service:** ${name.toUpperCase()}`);
}).catch(() => {});
}
} }
} }
if (!user) return this.error(message.channel, 'Member not found.'); if (!user) return this.error(message.channel, 'Member not found.');
const score = await this.client.db.Score.findOne({ userID: user.id }); const score = await this.client.db.Score.findOne({ userID: user.id });
const inqs = await this.client.db.Inquiry.find({ userID: user.id, type: 0 });
if (!score) return this.error(message.channel, 'Community Report has not been generated yet.'); if (!score) return this.error(message.channel, 'Community Report has not been generated yet.');
let totalScore = '0'; let totalScore = '0';
let activityScore = '0'; let activityScore = '0';
@ -134,13 +107,16 @@ export default class Score extends Command {
break; break;
} }
} */ } */
if (score?.inquiries?.length > 0) { let inqAdded = 0;
if (inqs?.length > 0) {
let desc = '__**Hard Inquiries**__\n*These inquiries will fall off your report within 2 months, try to keep your hard inquiries to a minimum. If you want to file a dispute, please DM Ramirez.*\n\n'; let desc = '__**Hard Inquiries**__\n*These inquiries will fall off your report within 2 months, try to keep your hard inquiries to a minimum. If you want to file a dispute, please DM Ramirez.*\n\n';
score.inquiries.forEach((inq) => { inqs.forEach((inq) => {
const testDate = (new Date(new Date(inq.date).setHours(1460))); const testDate = (new Date(new Date(inq.date).setHours(1460)));
// eslint-disable-next-line no-useless-escape // eslint-disable-next-line no-useless-escape
if (testDate > new Date()) desc += `${inq.id ? `__[${inq.id}]__\n` : ''}**Department/Service:** ${inq.name.replace(/\*/gmi, '')}\n**Reason:** ${inq.reason}\n**Date:** ${inq.date.toLocaleString('en-us')} ET\n**Expires:** ${moment(testDate).calendar()}\n\n`; if (testDate > new Date()) desc += `${inq.iid ? `__[${inq.iid}]__\n` : ''}**Department/Service:** ${inq.name.replace(/\*/gmi, '')}\n**Reason:** ${inq.reason}\n**Date:** ${inq.date.toLocaleString('en-us')} ET\n**Expires:** ${moment(testDate).calendar()}\n\n`;
inqAdded++;
}); });
if (inqAdded <= 0) desc = '';
if (desc.length >= 1900) { if (desc.length >= 1900) {
embed.setDescription('__***Too many Hard Inquiries to show, please see https://report.libraryofcode.org***__'); embed.setDescription('__***Too many Hard Inquiries to show, please see https://report.libraryofcode.org***__');
} else { } else {
@ -183,18 +159,7 @@ export default class Score extends Command {
name = `Library of Code sp-us | ${role.name}`; name = `Library of Code sp-us | ${role.name}`;
break; break;
} }
await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name, date: new Date() } } }); await this.client.report.createInquiry(user.id, name, 1);
const embed2 = new RichEmbed();
embed2.setTitle('Inquiry Notification');
embed2.setColor('#00FFFF');
const mem = this.client.util.resolveMember(score.userID, this.client.guilds.get(this.client.config.guildID));
embed2.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${score.userID}>`, 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 = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
log.createMessage({ embed: embed2 }).catch(() => {});
} }
} }
if (args[1] === 'hard' && this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 6)) { if (args[1] === 'hard' && this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 6)) {

View File

@ -1,3 +1,4 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-continue */ /* eslint-disable no-continue */
/* eslint-disable default-case */ /* eslint-disable default-case */
import moment from 'moment'; import moment from 'moment';
@ -6,6 +7,7 @@ import { createPaginationEmbed } from 'eris-pagination';
import { Message, User, TextChannel } from 'eris'; import { Message, User, TextChannel } from 'eris';
import { Client, Command, RichEmbed } from '../class'; import { Client, Command, RichEmbed } from '../class';
import { getTotalMessageCount } from '../intervals/score'; import { getTotalMessageCount } from '../intervals/score';
import { InquiryInterface } from '../models';
export default class Score_Hist extends Command { export default class Score_Hist extends Command {
constructor(client: Client) { constructor(client: Client) {
@ -78,8 +80,15 @@ export default class Score_Hist extends Command {
let data = ''; let data = '';
let hardInquiries = 0; let hardInquiries = 0;
if (hist.report?.inquiries?.length > 0) { const inquiries: InquiryInterface[] = [];
hist.report.inquiries.forEach((inq) => { if (hist.inquiries?.length > 0) {
for (const h of hist.inquiries) {
const inq = await this.client.db.Inquiry.findOne({ _id: h });
inquiries.push(inq);
}
}
if (inquiries?.length > 0) {
inquiries.forEach((inq) => {
const testDate = (new Date(new Date(inq.date).setHours(1460))); const testDate = (new Date(new Date(inq.date).setHours(1460)));
// eslint-disable-next-line no-plusplus // eslint-disable-next-line no-plusplus
if (testDate > new Date()) hardInquiries++; if (testDate > new Date()) hardInquiries++;
@ -156,17 +165,7 @@ export default class Score_Hist extends Command {
return cmdPages.push(embed); return cmdPages.push(embed);
}); });
const name = `${user.username} VIA DISCORD - [HISTORICAL]`; const name = `${user.username} VIA DISCORD - [HISTORICAL]`;
await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name: name.toUpperCase(), date: new Date() } } }); await this.client.report.createInquiry(user.id, name, 1);
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 = <TextChannel> 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] }); if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
@ -231,8 +230,15 @@ export default class Score_Hist extends Command {
let data = ''; let data = '';
let hardInquiries = 0; let hardInquiries = 0;
if (hist.report?.inquiries?.length > 0) { const inquiries: InquiryInterface[] = [];
hist.report.inquiries.forEach((inq) => { if (hist.inquiries?.length > 0) {
for (const h of hist.inquiries) {
const inq = await this.client.db.Inquiry.findOne({ _id: h });
inquiries.push(inq);
}
}
if (inquiries?.length > 0) {
inquiries.forEach((inq) => {
const testDate = (new Date(new Date(inq.date).setHours(1460))); const testDate = (new Date(new Date(inq.date).setHours(1460)));
// eslint-disable-next-line no-plusplus // eslint-disable-next-line no-plusplus
if (testDate > new Date()) hardInquiries++; if (testDate > new Date()) hardInquiries++;
@ -314,18 +320,7 @@ export default class Score_Hist extends Command {
name = `Library of Code sp-us | ${role.name} - [HISTORICAL]`; name = `Library of Code sp-us | ${role.name} - [HISTORICAL]`;
break; break;
} }
await this.client.db.Score.updateOne({ userID: user.id }, { $addToSet: { softInquiries: { name, date: new Date() } } }); await this.client.report.createInquiry(user.id, name, 1);
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 = <TextChannel> 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] }); if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });

View File

@ -62,7 +62,7 @@ export default class SiteInfo extends Command {
this.aliases = ['ssl', 'cert', 'certinfo', 'ci', 'tls', 'si', 'siteinfo']; this.aliases = ['ssl', 'cert', 'certinfo', 'ci', 'tls', 'si', 'siteinfo'];
this.permissions = 0; this.permissions = 0;
this.guildOnly = true; this.guildOnly = true;
this.enabled = true; this.enabled = false;
} }
public async run(message: Message, args: string[]) { public async run(message: Message, args: string[]) {
@ -157,6 +157,7 @@ export default class SiteInfo extends Command {
const page = await browser.newPage(); const page = await browser.newPage();
await page.goto(`https://${args[0]}`); await page.goto(`https://${args[0]}`);
screenshotData = await page.screenshot(); screenshotData = await page.screenshot();
browser.close();
} catch (e) { } catch (e) {
this.client.util.signale.error(e); this.client.util.signale.error(e);
} }

View File

@ -1,8 +1,7 @@
/* eslint-disable no-bitwise */ /* eslint-disable no-bitwise */
import moment from 'moment'; import moment from 'moment';
import { Message, Member, TextChannel } from 'eris'; import { Message, Member } from 'eris';
import { Client, Command, RichEmbed } from '../class'; import { Client, Command, RichEmbed } from '../class';
// import acknowledgements from '../configs/acknowledgements.json';
import { whois as emotes } from '../configs/emotes.json'; import { whois as emotes } from '../configs/emotes.json';
export default class Whois extends Command { export default class Whois extends Command {
@ -34,7 +33,6 @@ export default class Whois extends Command {
} }
const embed = new RichEmbed(); const embed = new RichEmbed();
embed.setThumbnail(member.avatarURL); embed.setThumbnail(member.avatarURL);
// const ackResolve = this.resolveStaffInformation(member.id);
const ackResolve = await this.client.db.Staff.findOne({ userID: member.id }).lean().exec(); const ackResolve = await this.client.db.Staff.findOne({ userID: member.id }).lean().exec();
let title = `${member.user.username}#${member.user.discriminator}`; let title = `${member.user.username}#${member.user.discriminator}`;
if (ackResolve?.pn?.length > 0) title += `, ${ackResolve.pn.join(', ')}`; if (ackResolve?.pn?.length > 0) title += `, ${ackResolve.pn.join(', ')}`;
@ -53,7 +51,7 @@ export default class Whois extends Command {
} }
const pager = await this.client.db.PagerNumber.findOne({ individualAssignID: member.user.id }).lean().exec(); const pager = await this.client.db.PagerNumber.findOne({ individualAssignID: member.user.id }).lean().exec();
if (pager?.num) { if (pager?.num) {
description += `📡 ${pager.num}\n`; description += `📟 ${pager.num}\n`;
} }
if (ackResolve?.extension) { if (ackResolve?.extension) {
description += `☎️ ${ackResolve.extension}\n`; description += `☎️ ${ackResolve.extension}\n`;
@ -77,24 +75,11 @@ export default class Whois extends Command {
} }
} }
embed.addField('Status', member.status === 'dnd' ? 'Do Not Disturb' : this.capsFirstLetter(member.status) || 'Offline', true); embed.addField('Status', member.status === 'dnd' ? 'Do Not Disturb' : this.capsFirstLetter(member.status) || 'Offline', true);
// const platform = member.bot && member.status !== 'offline' ? 'API/WebSocket' : Object.entries(message.member.clientStatus).filter((a) => a[1] !== 'offline').map((a) => this.capsFirstLetter(a[0])).join(', ');
// 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('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); 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 }).lean().exec(); const score = await this.client.db.Score.findOne({ userID: member.id }).lean().exec();
if (score) { if (score) {
await this.client.db.Score.updateOne({ userID: member.id }, { $addToSet: { softInquiries: { name: 'Library of Code sp-us | Bureau of Community Reports', date: new Date() } } }); await this.client.report.createInquiry(member.id, 'Library of Code sp-us | Bureau of Community Reports', 1);
const embed2 = new RichEmbed();
embed2.setTitle('Inquiry Notification');
embed2.setColor('#00FFFF');
const mem = this.client.util.resolveMember(score.userID, this.client.guilds.get(this.client.config.guildID));
embed2.addField('Member', `${mem.user.username}#${mem.user.discriminator} | <@${score.userID}>`, true);
embed2.addField('Type', 'SOFT', true);
embed2.addField('Department/Service', 'Library of Code sp-us | Bureau of Community Reports'.toUpperCase(), true);
embed2.setTimestamp();
embed2.setFooter(this.client.user.username, this.client.user.avatarURL);
const log = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
log.createMessage({ embed: embed2 }).catch(() => {});
let totalScore = '0'; let totalScore = '0';
if (score.total < 200) totalScore = '---'; if (score.total < 200) totalScore = '---';
else if (score.total > 800) totalScore = '800'; else if (score.total > 800) totalScore = '800';
@ -228,7 +213,7 @@ export default class Whois extends Command {
if (serverAcknowledgements.length > 0) { if (serverAcknowledgements.length > 0) {
embed.addField('Acknowledgements', serverAcknowledgements[0]); embed.addField('Acknowledgements', serverAcknowledgements[0]);
} }
if (ackResolve?.acknowledgements) { if (ackResolve?.acknowledgements?.length > 0) {
embed.addField('Bot Acknowledgements', ackResolve.acknowledgements.join(', ')); embed.addField('Bot Acknowledgements', ackResolve.acknowledgements.join(', '));
} }
embed.setFooter(this.client.user.username, this.client.user.avatarURL); embed.setFooter(this.client.user.username, this.client.user.avatarURL);

View File

@ -1,149 +0,0 @@
[
{
"name": "Matthew",
"id": "278620217221971968",
"title": "Chief Director of Engineering",
"pn": ["AD", "FSEN", "FSO", "FSCR", "FSCE", "FSED"],
"dept": "Board of Directors",
"emailAddress": "matthew@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/matthew",
"github": "https://github.com/matthew119427",
"bio": "so baby come light me up, and maybe ill let you on it. a little bit dangerous, but baby thats how i want it. a little less conversation and a little more touch my body. cuz im so into you... ~ Ariana Grande, Into You - Dangerous Woman",
"acknowledgements": ["Maintainer & Lead Developer"]
},
{
"name": "Bsian",
"id": "253600545972027394",
"title": "Director of Engineering",
"pn": ["AD", "FSEN", "FSCR", "FSED"],
"dept": "Board of Directors",
"emailAddress": "bsian@staff.libraryofcode.org",
"bio": "I also like trains",
"acknowledgements": ["Maintainer & Assistant Lead Developer"]
},
{
"name": "NightRaven",
"id": "239261547959025665",
"title": "Director of Information Security",
"pn": ["AD", "FSEN", "FSO", "FSCR", "FSED"],
"dept": "Board of Directors",
"emailAddress": "nightraven@staff.libraryofcode.org",
"bio": "I like trains"
},
{
"name": "Unknown",
"id": "143414786913206272",
"title": "Director of Operations",
"pn": ["AD", "FSO", "FSM", "FSCR"],
"dept": "Board of Directors",
"emailAddress": "unknown@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/unknown",
"bio": "im not a proffesional developer or anything, i just enjoy it as a hobby."
},
{
"name": "TheSkele27",
"id": "213632190557192192",
"title": "Director of Community Engagement",
"pn": ["AD", "FSCE"],
"dept": "Board of Directors",
"emailAddress": "theskele27@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/TheSkele27",
"github": "https://github.com/TheSkele27",
"bio": "Is water wet?"
},
{
"name": "Catbirby",
"id": "131953641371205632",
"pn": ["SP", "FSO", "FSM"],
"dept": "Supervisor",
"emailAddress": "catbirby@staff.libraryofcode.org",
"github": "https://github.com/catbirby",
"bio": "Computer Tech/Networking Nerd/SysADin/Graphic Designer/Audiophile. I don't do much coding but know my way around most languages."
},
{
"name": "D3XTER",
"id": "468009964263178262",
"pn": ["ST", "CE-I"],
"dept": "Core Team",
"emailAddress": "dexter@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/D3XTER",
"bio": "Hi I'm D3XTER how are ya?"
},
{
"name": "DedShotTM",
"id": "402154763363418142",
"pn": ["ST", "FSCR"],
"dept": "Technician & Moderator",
"emailAddress": "dedshot@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/DedShotTM",
"github": "https://github.com/DedShotTM",
"bio": "Imagine having a bio",
"acknowledgements": ["Contributor"]
},
{
"name": "EdgyBoi2414",
"id": "397432516010835970",
"pn": ["ST"],
"dept": "Core Team",
"emailAddress": "edgyboi2414@gmail.com",
"gitlab": "https://gitlab.libraryofcode.org/EdgyBoi2414",
"github": "https://github.com/EdgyBoi2414",
"bio": "\"If teardrops could be bottled, there'd be swimming pools, built by model..\" - Some Philosopher"
},
{
"name": "Hector",
"id": "377781496292835339",
"pn": ["ST", "CRS-I"],
"dept": "Technician",
"emailAddress": "hector@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/Hector",
"github": "https://github.com/Hector6704",
"bio": "Hi there, I'm the developer of Delta, the Discord bot. I'm a free-time French JavASript developer. I hope you'll enjoy LOC!",
"acknowledgements": ["Contributor"]
},
{
"name": "KhaaZ",
"id": "179908288337412096",
"pn": ["ST", "FSEN"],
"dept": "Core Team",
"emailAddress": "khaaz@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/KhaaZ",
"github": "https://github.com/Khaazz",
"bio": "I baguette for a living and eat code for breakfast.",
"acknowledgements": ["Assistant Maintainer"]
},
{
"name": "PlayerVMachine",
"id": "273999507174195203",
"pn": ["ST", "ED-I"],
"dept": "Instructor & Core Team",
"emailAddress": "nicolas@staff.libraryofcode.org",
"bio": "I write C++ to pay off my student loans"
},
{
"name": "Sterben",
"id": "241361691730903040",
"pn": ["ST", "CRS-I", "ENG-I"],
"dept": "Core Team",
"emailAddress": "sterben@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/Sterben",
"github": "https://github.com/sterben6",
"bio": "im bored"
},
{
"name": "Raymond",
"id": "314564798992089090",
"pn": ["AS"],
"dept": "Associate",
"emailAddress": "smashjarchive@staff.libraryofcode.org",
"gitlab": "https://gitlab.libraryofcode.org/javaarchive",
"github": "https://github.com/javaarchive",
"bio": "I don't like reinventing the wheel and don't like coding on small screens like laptops as much"
},
{
"name": "Null",
"id": "323673862971588609",
"gitlab": "https://gitlab.libraryofcode.org/null",
"acknowledgements": ["Contributor"]
}
]

View File

@ -13,7 +13,7 @@ export default class GuildMemberAdd extends Event {
try { try {
const search = await this.client.db.local.muted.get<boolean>(`muted-${member.user.id}`); const search = await this.client.db.local.muted.get<boolean>(`muted-${member.user.id}`);
if (search === true) { if (search === true) {
member.addRole('478373942638149643'); member.addRole('478373942638149643', 'muted user left server and joined back');
} }
} catch (err) { } catch (err) {
this.client.util.handleError(err); this.client.util.handleError(err);

View File

@ -11,7 +11,7 @@ export default function checkLock(client: Client): NodeJS.Timeout {
if (moderation.expiration.processed) return; if (moderation.expiration.processed) return;
if (new Date() > moderation.expiration.date) { if (new Date() > moderation.expiration.date) {
await moderation.updateOne({ 'expiration.processed': true }); await moderation.updateOne({ 'expiration.processed': true });
// const moderator = client.guilds.get(client.config.guildID).members.get(moderation.moderatorID);
const system = client.guilds.get(client.config.guildID).members.get(client.user.id); const system = client.guilds.get(client.config.guildID).members.get(client.user.id);
switch (moderation.type) { switch (moderation.type) {
case 5: case 5:

View File

@ -63,8 +63,8 @@ export default async function calculateScore(client: Client): Promise<NodeJS.Tim
staff: boolean, staff: boolean,
locked: boolean, locked: boolean,
notify: boolean, notify: boolean,
inquiries: [{ name: string, reason: string, date: Date }?], // inquiries: [{ name: string, reason: string, date: Date }?],
softInquiries: [{name: string, date: Date }?] // softInquiries: [{name: string, date: Date }?]
lastUpdated: Date, lastUpdated: Date,
pin: number[], pin: number[],
/* generalMessagesRatio: number, /* generalMessagesRatio: number,
@ -82,8 +82,8 @@ export default async function calculateScore(client: Client): Promise<NodeJS.Tim
staff: false, staff: false,
locked: false, locked: false,
notify: false, notify: false,
inquiries: [], // inquiries: [],
softInquiries: [], // softInquiries: [],
lastUpdated: new Date(), lastUpdated: new Date(),
pin: [client.util.randomNumber(100, 999), client.util.randomNumber(10, 99), client.util.randomNumber(1000, 9999)], pin: [client.util.randomNumber(100, 999), client.util.randomNumber(10, 99), client.util.randomNumber(1000, 9999)],
}; };

33
src/models/Inquiry.ts Normal file
View File

@ -0,0 +1,33 @@
import { Document, Schema, model } from 'mongoose';
import { ScoreInterfaceRaw } from '.';
export enum InqType {
HARD,
SOFT,
}
export interface InquiryInterface extends Document {
iid?: string,
userID: string,
/**
* - 0: Hard
* - 1: Soft
*/
type: InqType,
name: string,
reason?: string,
date: Date,
report?: ScoreInterfaceRaw,
}
const Inquiry: Schema = new Schema({
iid: String,
userID: String,
type: Number,
name: String,
reason: String,
date: String,
report: Object,
});
export default model<InquiryInterface>('Inquiry', Inquiry);

View File

@ -1,11 +1,12 @@
import { Document, Schema, model } from 'mongoose'; import { Document, Schema, model } from 'mongoose';
export interface MemberInterface extends Document { export interface MemberInterface extends Document {
userID: string userID: string,
additional: { additional: {
langs: ['js', 'py', 'rb', 'ts', 'rs', 'go', 'cfam', 'csharp', 'swift', 'java', 'kt', 'asm'], langs: ['js', 'py', 'rb', 'ts', 'rs', 'go', 'cfam', 'csharp', 'swift', 'java', 'kt', 'asm'],
operatingSystems: ['arch', 'deb', 'cent', 'fedora', 'manjaro', 'mdarwin', 'redhat', 'ubuntu', 'win'], operatingSystems: ['arch', 'deb', 'cent', 'fedora', 'manjaro', 'mdarwin', 'redhat', 'ubuntu', 'win'],
}, },
bio: string,
} }
const Member: Schema = new Schema({ const Member: Schema = new Schema({
@ -14,6 +15,7 @@ const Member: Schema = new Schema({
langs: Array, langs: Array,
operatingSystems: Array, operatingSystems: Array,
}, },
bio: String,
}); });
export default model<MemberInterface>('Member', Member); export default model<MemberInterface>('Member', Member);

View File

@ -49,30 +49,11 @@ export interface ScoreInterfaceRaw {
export interface ScoreInterface extends Document { export interface ScoreInterface extends Document {
userID: string 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, total: number,
/**
* 10 - 55
*/
activity: number, activity: number,
/**
* 0 - 54
*/
roles: number, roles: number,
/**
* -50 - 2
* all users start out with 2 moderation points, the number of points decreases for each moderation.
*/
moderation: number, moderation: number,
/**
* -20 - 50
* processed by CSD
*/
cloudServices: number, cloudServices: number,
// 0 or 20, 20 points are added if the user is a staff member
staff: number, staff: number,
other: number, other: number,
notify: boolean, notify: boolean,

View File

@ -1,21 +1,24 @@
import { Document, Schema, model } from 'mongoose'; import { Document, Schema, model, Types } from 'mongoose';
import { ScoreInterfaceRaw } from '.'; import { ScoreInterfaceRaw } from '.';
export interface ScoreHistoricalRaw { export interface ScoreHistoricalRaw {
userID: string, userID: string,
report: ScoreInterfaceRaw, report: ScoreInterfaceRaw,
inquiries: [ Types.ObjectId ],
date: Date, date: Date,
} }
export interface ScoreHistoricalInterface extends Document { export interface ScoreHistoricalInterface extends Document {
userID: string, userID: string,
report: ScoreInterfaceRaw, report: ScoreInterfaceRaw,
inquiries: [ Types.ObjectId ],
date: Date date: Date
} }
const ScoreHistorical: Schema = new Schema({ const ScoreHistorical: Schema = new Schema({
userID: String, userID: String,
report: Object, report: Object,
inquiries: Array,
date: Date, date: Date,
}); });

View File

@ -1,6 +1,7 @@
export { default as Customer, CustomerInterface } from './Customer'; export { default as Customer, CustomerInterface } from './Customer';
export { default as CustomerPortal, CustomerPortalInterface } from './CustomerPortal'; export { default as CustomerPortal, CustomerPortalInterface } from './CustomerPortal';
export { default as File, FileInterface } from './File'; export { default as File, FileInterface } from './File';
export { default as Inquiry, InquiryInterface, InqType } from './Inquiry';
export { default as Member, MemberInterface } from './Member'; export { default as Member, MemberInterface } from './Member';
export { default as Merchant, MerchantInterface } from './Merchant'; export { default as Merchant, MerchantInterface } from './Merchant';
export { default as Moderation, ModerationInterface } from './Moderation'; export { default as Moderation, ModerationInterface } from './Moderation';

View File

@ -4,11 +4,17 @@ import { promises as fs } from 'fs';
import { PBX } from '../../class'; import { PBX } from '../../class';
export default class Misc { export default class Misc {
public static async accessDenied(channel: ARI.Channel) { public static accessDenied(channel: ARI.Channel) {
const playback = await channel.play({ return new Promise<void>((resolve, reject) => {
media: 'sound:access-denied', channel.play({
}, undefined); media: 'sound:access-denied',
playback.once('PlaybackFinished', () => channel.hangup()); }, undefined).then((playback) => {
playback.on('PlaybackFinished', () => {
channel.hangup().catch((err) => reject(err));
resolve();
});
}).catch((err) => reject(err));
});
} }
public static async TTS(pbx: PBX, text: string, gender: string | any): Promise<string> { public static async TTS(pbx: PBX, text: string, gender: string | any): Promise<string> {

View File

@ -18,7 +18,7 @@
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
"removeComments": true, /* Do not emit comments to output. */ "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */ // "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */ "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

View File

@ -596,6 +596,14 @@ ax@0.1.8:
resolved "https://registry.yarnpkg.com/ax/-/ax-0.1.8.tgz#27ca9a73fa4c78a478d62d827cad860a24fdd497" resolved "https://registry.yarnpkg.com/ax/-/ax-0.1.8.tgz#27ca9a73fa4c78a478d62d827cad860a24fdd497"
integrity sha1-J8qac/pMeKR41i2CfK2GCiT91Jc= integrity sha1-J8qac/pMeKR41i2CfK2GCiT91Jc=
axios@^0.18.1:
version "0.18.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3"
integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==
dependencies:
follow-redirects "1.5.10"
is-buffer "^2.0.2"
axios@^0.19.2: axios@^0.19.2:
version "0.19.2" version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
@ -2229,6 +2237,11 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-buffer@^2.0.2:
version "2.0.5"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
is-callable@^1.1.4, is-callable@^1.1.5: is-callable@^1.1.4, is-callable@^1.1.5:
version "1.1.5" version "1.1.5"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
@ -3773,6 +3786,13 @@ standard-as-callback@^2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
stock-info@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/stock-info/-/stock-info-1.2.0.tgz#a29f54c5416deec5a08a9f3c19736a91c913c20a"
integrity sha512-GxhFrCWlibRdS/9KC1aRMBD0p4IyGj/rKD5InK/ZUOFAapJ76QhVY/ShsNT0WRkOh12Bh6NfZkWU/Ipj90NstQ==
dependencies:
axios "^0.18.1"
stream-shift@^1.0.0: stream-shift@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
@ -4051,6 +4071,11 @@ tslib@^1.8.1, tslib@^1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.12.0.tgz#d1fc9cacd06a1456c62f2902b361573e83d66473" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.12.0.tgz#d1fc9cacd06a1456c62f2902b361573e83d66473"
integrity sha512-5rxCQkP0kytf4H1T4xz1imjxaUUPMvc5aWp0rJ/VMIN7ClRiH1FwFvBt8wOeMasp/epeUnmSW6CixSIePtiLqA== integrity sha512-5rxCQkP0kytf4H1T4xz1imjxaUUPMvc5aWp0rJ/VMIN7ClRiH1FwFvBt8wOeMasp/epeUnmSW6CixSIePtiLqA==
tslib@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
tsutils@^3.17.1: tsutils@^3.17.1:
version "3.17.1" version "3.17.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"