add ability to req temporary t3 thru eds

master
Matthew 2021-12-09 21:07:39 -05:00
parent 8ce7f51f8d
commit 95468f3cf1
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
8 changed files with 5529 additions and 343 deletions

57
.gitignore vendored
View File

@ -1,28 +1,29 @@
# Package Management & Libraries # Package Management & Libraries
node_modules node_modules
.yarn .yarn
#.yarn/* #.yarn/*
#!.yarn/cache #!.yarn/cache
#!.yarn/patches #!.yarn/patches
#!.yarn/plugins #!.yarn/plugins
#!.yarn/releases #!.yarn/releases
#!.yarn/sdks #!.yarn/sdks
#!.yarn/versions #!.yarn/versions
# Configuration Files # Configuration Files
config.yaml config.yaml
configs/config.yaml configs/config.yaml
src/config.yaml src/config.yaml
build/config.yaml build/config.yaml
.vscode .vscode
yarn-error.log .idea
google.json yarn-error.log
src/google.json google.json
build/google.json src/google.json
build/google.json
# Build/Distribution Files
build # Build/Distribution Files
dist build
dist
# Storage/DB Files
localstorage # Storage/DB Files
localstorage

5129
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +1,67 @@
{ {
"name": "loccr", "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",
"scripts": { "scripts": {
"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, AD, FSEN <matthew@staff.libraryofcode.org>", "author": "Matthew R, AD, FSEN <matthew@staff.libraryofcode.org>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"devDependencies": { "devDependencies": {
"@types/ari-client": "^2.2.2", "@types/ari-client": "^2.2.7",
"@types/auth0": "^2.33.3", "@types/auth0": "^2.34.7",
"@types/bull": "^3.14.4", "@types/bull": "^3.15.7",
"@types/cron": "^1.7.2", "@types/cron": "^1.7.3",
"@types/express": "^4.17.6", "@types/express": "^4.17.13",
"@types/helmet": "^0.0.47", "@types/helmet": "^0.0.48",
"@types/jsonwebtoken": "^8.5.0", "@types/jsonwebtoken": "^8.5.6",
"@types/mathjs": "^6.0.7", "@types/mathjs": "^9.4.1",
"@types/mongoose": "^5.7.19", "@types/mongoose": "^5.11.96",
"@types/node": "^14.14.25", "@types/node": "^16.11.12",
"@types/nodemailer": "^6.4.0", "@types/nodemailer": "^6.4.4",
"@types/puppeteer": "^5.4.3", "@types/puppeteer": "^5.4.4",
"@types/signale": "^1.4.1", "@types/signale": "^1.4.2",
"@types/uuid": "^7.0.3", "@types/uuid": "^8.3.3",
"@typescript-eslint/eslint-plugin": "^2.33.0", "@typescript-eslint/eslint-plugin": "^5.6.0",
"@typescript-eslint/parser": "^2.33.0", "@typescript-eslint/parser": "^5.6.0",
"eslint": "^7.19.0", "eslint": "^8.4.1",
"eslint-config-airbnb-base": "^14.1.0", "eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.20.2", "eslint-plugin-import": "^2.25.3",
"tslib": "^2.1.0", "tslib": "^2.3.1",
"typescript": "^3.9.2" "typescript": "^4.5.3"
}, },
"dependencies": { "dependencies": {
"@google-cloud/text-to-speech": "^3.1.2", "@google-cloud/text-to-speech": "^3.4.0",
"ari-client": "^2.2.0", "ari-client": "^2.2.0",
"asterisk-manager": "^0.1.16", "asterisk-manager": "^0.2.0",
"auth0": "^2.35.0", "auth0": "^2.37.0",
"awesome-phonenumber": "^2.45.0", "awesome-phonenumber": "^2.65.0",
"axios": "^0.19.2", "axios": "^0.24.0",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"brain.js": "^2.0.0-beta.2", "brain.js": "^2.0.0-beta.4",
"bull": "^3.20.1", "bull": "^4.1.1",
"cheerio": "^1.0.0-rc.5", "cheerio": "^1.0.0-rc.10",
"cron": "^1.8.2", "cron": "^1.8.2",
"eris": "^0.15.0", "eris": "^0.16.1",
"eris-pagination": "github:bsian03/eris-pagination", "eris-pagination": "github:libraryofcode/eris-pagination",
"express": "^4.17.1", "express": "^4.17.1",
"helmet": "^3.22.0", "helmet": "^4.6.0",
"ioredis": "^4.26.0", "ioredis": "^4.28.2",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"mathjs": "^7.6.0", "mathjs": "^10.0.0",
"moment": "^2.25.3", "moment": "^2.29.1",
"mongoose": "^5.11.15", "mongoose": "^6.1.1",
"nanoid": "^3.1.22", "nanoid": "^3.1.30",
"nodemailer": "^6.4.8", "nodemailer": "^6.7.2",
"pluris": "^0.2.5", "pluris": "^0.3.7",
"puppeteer": "^5.5.0", "puppeteer": "^12.0.1",
"sd-notify": "^2.8.0", "sd-notify": "^2.8.0",
"signale": "^1.4.0", "signale": "^1.4.0",
"stock-info": "^1.2.0", "stock-info": "^1.5.1",
"stripe": "^8.120.0", "stripe": "^8.193.0",
"uuid": "^8.0.0", "uuid": "^8.3.2",
"yaml": "^1.9.2" "yaml": "^1.10.2"
} }
} }

View File

@ -335,7 +335,7 @@ export default class Report extends Route {
createdAt: new Date(mem.createdAt), createdAt: new Date(mem.createdAt),
avatarURL: mem.avatarURL, avatarURL: mem.avatarURL,
flags, flags,
nitroBoost: mem.premiumSince === null, nitroBoost: mem.premiumSince ?? null,
}, },
totalScore, totalScore,
percentile: Math.round(this.server.client.util.percentile(set, report.total)), percentile: Math.round(this.server.client.util.percentile(set, report.total)),

View File

@ -1,181 +1,213 @@
/* eslint-disable no-continue */ /* eslint-disable no-continue */
import type { AxiosError, AxiosStatic } from 'axios'; import type { AxiosError, AxiosStatic } from 'axios';
import axios from 'axios'; import axios from 'axios';
import { Member, Message } from 'eris'; import { Member, Message } from 'eris';
import { Client, Command, RichEmbed } from '../class'; import { Client, Command, RichEmbed } from '../class';
import { CloudServicesUtil } from '../util';
export default class Apply extends Command {
public services: Map<string, { description: string, type: 'HARD' | 'SOFT', saaOnly?: boolean, url: string, validation: (...cond: any) => Promise<boolean> | boolean, func?: Function }>; export default class Apply extends Command {
public services: Map<string, { description: string, type: 'HARD' | 'SOFT', saaOnly?: boolean, url: string, validation: (...cond: any) => Promise<boolean> | boolean, func?: Function }>;
constructor(client: Client) {
super(client); constructor(client: Client) {
this.name = 'apply'; super(client);
this.description = 'Application frontend for EDS.'; this.name = 'apply';
this.usage = `${this.client.config.prefix}apply [serviceName]\n${this.client.config.prefix}apply full`; this.description = 'Application frontend for EDS.';
this.permissions = 0; this.usage = `${this.client.config.prefix}apply [serviceName]\n${this.client.config.prefix}apply full`;
this.guildOnly = true; this.permissions = 0;
this.enabled = true; this.guildOnly = true;
this.setServices(); this.enabled = true;
} this.setServices();
}
protected setServices() {
this.services = new Map(); protected setServices() {
this.services.set('role::proficient', { this.services = new Map();
description: 'Proficient role assignment.', this.services.set('role::proficient', {
type: 'HARD', description: 'Proficient role assignment.',
saaOnly: true, type: 'HARD',
url: 'https://eds.libraryofcode.org/roles/proficient', saaOnly: true,
validation: (member: Member) => !member.roles.includes('506943223680466955'), url: 'https://eds.libraryofcode.org/roles/proficient',
func: async (client: Client, ...data: any[]) => { validation: (member: Member) => !member.roles.includes('506943223680466955'),
const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]); func: async (client: Client, ...data: any[]) => {
await member.addRole('506943223680466955', 'Proficient Approval from EDS'); const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]);
}, await member.addRole('506943223680466955', 'Proficient Approval from EDS');
}); },
this.services.set('role::regulars', { });
description: 'Regulars role assignment.', this.services.set('role::regulars', {
type: 'HARD', description: 'Regulars role assignment.',
saaOnly: true, type: 'HARD',
url: 'https://eds.libraryofcode.org/roles/regulars', saaOnly: true,
validation: (member: Member) => !member.roles.includes('472524444083159050'), url: 'https://eds.libraryofcode.org/roles/regulars',
func: async (client: Client, ...data: any[]) => { validation: (member: Member) => !member.roles.includes('472524444083159050'),
const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]); func: async (client: Client, ...data: any[]) => {
await member.addRole('472524444083159050', 'Regulars Approval from EDS'); const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]);
}, await member.addRole('472524444083159050', 'Regulars Approval from EDS');
}); },
this.services.set('role::constants', { });
description: 'Constants role assignment.', this.services.set('role::constants', {
type: 'HARD', description: 'Constants role assignment.',
url: 'https://eds.libraryofcode.org/roles/constants', type: 'HARD',
validation: (member: Member) => !member.roles.includes('511771731891847168'), url: 'https://eds.libraryofcode.org/roles/constants',
func: async (client: Client, ...data: any[]) => { validation: (member: Member) => !member.roles.includes('511771731891847168'),
const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]); func: async (client: Client, ...data: any[]) => {
await member.addRole('511771731891847168', 'Constants Approval from EDS'); const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]);
}, await member.addRole('511771731891847168', 'Constants Approval from EDS');
}); },
});
this.services.set('cs::t2', {
description: 'Tier 2 upgrade for Cloud Services account.', this.services.set('cs::t2', {
type: 'HARD', description: 'Tier 2 upgrade for Cloud Services account.',
url: 'https://eds.libraryofcode.org/cs/t2', type: 'HARD',
validation: (member: Member) => member.roles.includes('546457886440685578'), url: 'https://eds.libraryofcode.org/cs/t2',
func: async (client: Client, ...data: any[]) => { validation: async (member: Member) => {
const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]); if (!member.roles.includes('546457886440685578')) return false;
const ax = <AxiosStatic>require('axios'); const csAccount = await CloudServicesUtil.fetchAccountStatus(member.id, this.client.config.internalKey);
await ax({ if (csAccount.tier > 2) return false;
method: 'get', return true;
url: `https://api.cloud.libraryofcode.org/wh/t2?userID=${member.id}&auth=${client.config.internalKey}`, },
}); func: async (client: Client, ...data: any[]) => {
}, const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]);
}); const ax = <AxiosStatic>require('axios');
await ax({
this.services.set('cs::promot3', { method: 'get',
description: 'Receive 25% off your first purchase of Tier 3.', url: `https://api.cloud.libraryofcode.org/wh/t2?userID=${member.id}&auth=${client.config.internalKey}`,
type: 'SOFT', });
url: 'https://eds.libraryofcode.org/cs/t3-promo', },
validation: async (member: Member) => { });
if (!member.roles.includes('546457886440685578')) return false;
const customer = await this.client.db.Customer.findOne({ userID: member.user.id }).lean().exec(); this.services.set('cs::temp-upgrade', {
if (!customer) return false; description: 'Temporary Tier 3 upgrade for your Cloud Services account to install dependencies or RAM-dependent operations.',
return true; type: 'SOFT',
}, url: 'https://eds.libraryofcode.org/cs/t3-temp',
func: async (client: Client, ...data: any[]) => { validation: async (member: Member) => {
const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]); const csAccount = await CloudServicesUtil.fetchAccountStatus(member.id, this.client.config.internalKey);
const customer = await client.db.Customer.findOne({ userID: member.user.id }).lean().exec(); // const memberCheck = await this.client.db.Member.findOne({ userID: member.id }).lean().exec();
const coupon = await client.stripe.coupons.create({ // if (new Date() > memberCheck?.misc?.t3TemporaryExpiration?.date) return false;
percent_off: 25, if (csAccount.tier === 3) return false;
duration: 'once', return true;
max_redemptions: 1, },
name: 'Tier 3 - EDS Discount', func: async (client: Client, ...data: any[]) => {
metadata: { const dmember = await client.guilds.get(client.config.guildID).getRESTMember(data[0]);
userID: member.user.id, const member = await this.client.db.Member.findOne({ userID: dmember.id }).lean().exec();
}, if (!member) {
}); const addMember = new this.client.db.Member({
const promo = await client.stripe.promotionCodes.create({ userID: dmember.id,
coupon: coupon.id, });
customer: customer.cusID, await addMember.save();
max_redemptions: 1, }
restrictions: { await this.client.db.Member.updateOne({ userID: dmember.id }, { $set: { misc: { t3TemporaryExpiration: { processed: false, date: new Date(Date.now() + 129600000) } } } });
first_time_transaction: true,
}, await CloudServicesUtil.upgradeT2(dmember.id, this.client.config.internalKey);
}); },
const doc = new client.db.Promo({ });
code: promo.code,
pID: promo.id, this.services.set('cs::promot3', {
}); description: 'Receive 25% off your first purchase of Tier 3.',
await doc.save(); type: 'SOFT',
const chan = await client.getDMChannel(customer.userID); url: 'https://eds.libraryofcode.org/cs/t3-promo',
chan.createMessage(`__**Tier 3 Coupon Code**__\n\`${promo.code}\`\n\n*Do not share this promotional code with anyone else. This promo code is good for your first purchase of Tier 2, 25% off applied. Will apply to your first invoice only, for more questions contact support.*`); validation: async (member: Member) => {
}, if (!member.roles.includes('546457886440685578')) return false;
}); const customer = await this.client.db.Customer.findOne({ userID: member.user.id }).lean().exec();
if (!customer) return false;
this.services.set('p::role::constants', { return true;
description: 'Pre-approval for Constants role assignment.', },
type: 'SOFT', func: async (client: Client, ...data: any[]) => {
url: 'https://eds.libraryofcode.org/roles/preconstants', const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]);
validation: (member: Member) => !member.roles.includes('511771731891847168'), const customer = await client.db.Customer.findOne({ userID: member.user.id }).lean().exec();
}); const coupon = await client.stripe.coupons.create({
percent_off: 25,
this.services.set('p::cs::t2', { duration: 'once',
description: 'Pre-approval for Tier 2.', max_redemptions: 1,
type: 'SOFT', name: 'Tier 3 - EDS Discount',
url: 'https://eds.libraryofcode.org/cs/t2pre', metadata: {
validation: (member: Member) => member.roles.includes('546457886440685578'), userID: member.user.id,
}); },
} });
const promo = await client.stripe.promotionCodes.create({
public async run(message: Message, args: string[]) { coupon: coupon.id,
try { customer: customer.cusID,
if (!args[0] || args[0] === 'full') { max_redemptions: 1,
const embed = new RichEmbed(); restrictions: {
embed.setTitle('Instant Application Service [IAS]'); first_time_transaction: true,
embed.setColor('#556cd6'); },
if (args[0] !== 'full') { });
embed.setDescription(`*These applications are specifically targeted to you based on validation conditions. Run \`${this.client.config.prefix}apply full\` for a full list of all applications.*`); const doc = new client.db.Promo({
embed.setThumbnail(message.member.avatarURL); code: promo.code,
embed.setAuthor(message.member.username, message.member.avatarURL); pID: promo.id,
} });
for (const service of this.services) { await doc.save();
// eslint-disable-next-line no-await-in-loop const chan = await client.getDMChannel(customer.userID);
const test = await service[1].validation(message.member); chan.createMessage(`__**Tier 3 Coupon Code**__\n\`${promo.code}\`\n\n*Do not share this promotional code with anyone else. This promo code is good for your first purchase of Tier 2, 25% off applied. Will apply to your first invoice only, for more questions contact support.*`);
if (!test && args[0] !== 'full') continue; },
embed.addField(service[0], `**Description**: ${service[1].description}\n**Inquiry Type:** ${service[1].type}\n\n${service[1].saaOnly ? '*This application can only be ran as a Staff-Assisted Application and cannot be ran automatically. Please DM <@457750238208327691> to apply.*' : `*Run \`${this.client.config.prefix}apply ${service[0]}\` to apply.*`}`); });
}
if (embed.fields?.length <= 0) embed.setDescription(`*We have no offers for you at this time. To see a full list of offers, please run \`${this.client.config.prefix}apply full\`.*`); this.services.set('p::role::constants', {
embed.setFooter(this.client.user.username, this.client.user.avatarURL); description: 'Pre-approval for Constants role assignment.',
embed.setTimestamp(); type: 'SOFT',
return message.channel.createMessage({ embed }); url: 'https://eds.libraryofcode.org/roles/preconstants',
} validation: (member: Member) => !member.roles.includes('511771731891847168'),
});
if (!this.services.has(args[0])) return this.error(message.channel, 'Invalid service/product name.');
const service = this.services.get(args[0]); this.services.set('p::cs::t2', {
const test = await this.services.get(args[0]).validation(message.member); description: 'Pre-approval for Tier 2.',
if (!test) return this.error(message.channel, 'A condition exists which prevents you from applying, please try again later.'); type: 'SOFT',
if (service.saaOnly) return this.error(message.channel, 'This application can only be ran as a Staff-Assisted Application and cannot be ran automatically. Please DM <@457750238208327691> to apply.'); url: 'https://eds.libraryofcode.org/cs/t2pre',
const msg = await this.loading(message.channel, 'Thank you for submitting an application. We are currently processing it, you will receive a DM with a decision.'); validation: (member: Member) => member.roles.includes('546457886440685578'),
return await this.client.queue.processApplication({ channelID: message.channel.id, guildID: this.mainGuild.id, messageID: msg.id }, service.url, message.author.id, service.func ? service.func.toString() : undefined); });
} catch (err) { }
return this.client.util.handleError(err, message, this);
} public async run(message: Message, args: string[]) {
} try {
if (!args[0] || args[0] === 'full') {
public static async apply(client: Client, url: string, userID: string) { const embed = new RichEmbed();
try { embed.setTitle('Instant Application Service [IAS]');
const { data } = await axios({ embed.setColor('#556cd6');
method: 'get', if (args[0] !== 'full') {
url: `${url}?userID=${userID}&auth=${client.config.internalKey}`, embed.setDescription(`*These applications are specifically targeted to you based on validation conditions. Run \`${this.client.config.prefix}apply full\` for a full list of all applications.*`);
}); embed.setThumbnail(message.member.avatarURL);
embed.setAuthor(message.member.username, message.member.avatarURL);
return { }
status: 'SUCCESS', for (const service of this.services) {
decision: data.decision, // eslint-disable-next-line no-await-in-loop
id: data.id, const test = await service[1].validation(message.member);
processedBy: data.processedBy, if (!test && args[0] !== 'full') continue;
token: data.token, embed.addField(service[0], `**Description**: ${service[1].description}\n**Inquiry Type:** ${service[1].type}\n\n${service[1].saaOnly ? '*This application can only be ran as a Staff-Assisted Application and cannot be ran automatically. Please DM <@457750238208327691> to apply.*' : `*Run \`${this.client.config.prefix}apply ${service[0]}\` to apply.*`}`);
}; }
} catch (err) { if (embed.fields?.length <= 0) embed.setDescription(`*We have no offers for you at this time. To see a full list of offers, please run \`${this.client.config.prefix}apply full\`.*`);
const error = <AxiosError>err; embed.setFooter(this.client.user.username, this.client.user.avatarURL);
if (error.response?.status === 404 || error.response.status === 400 || error.response.status === 401) return { id: 'N/A', processedBy: 'N/A', status: 'CLIENT_ERROR', decision: 'PRE-DECLINED' }; embed.setTimestamp();
return { id: 'N/A', processedBy: 'N/A', status: 'SERVER_ERROR', decision: 'PRE-DECLINED' }; return message.channel.createMessage({ embed });
} }
}
} if (!this.services.has(args[0])) return this.error(message.channel, 'Invalid service/product name.');
const service = this.services.get(args[0]);
const test = await this.services.get(args[0]).validation(message.member);
if (!test) return this.error(message.channel, 'A condition exists which prevents you from applying, please try again later.');
if (service.saaOnly) return this.error(message.channel, 'This application can only be ran as a Staff-Assisted Application and cannot be ran automatically. Please DM <@457750238208327691> to apply.');
const msg = await this.loading(message.channel, 'Thank you for submitting an application. We are currently processing it, you will receive a DM with a decision.');
return await this.client.queue.processApplication({ channelID: message.channel.id, guildID: this.mainGuild.id, messageID: msg.id }, service.url, message.author.id, service.func ? service.func.toString() : undefined);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
public static async apply(client: Client, url: string, userID: string) {
try {
const { data } = await axios({
method: 'get',
url: `${url}?userID=${userID}&auth=${client.config.internalKey}`,
});
return {
status: 'SUCCESS',
decision: data.decision,
id: data.id,
processedBy: data.processedBy,
token: data.token,
};
} catch (err) {
const error = <AxiosError>err;
if (error.response?.status === 404 || error.response.status === 400 || error.response.status === 401) return { id: 'N/A', processedBy: 'N/A', status: 'CLIENT_ERROR', decision: 'PRE-DECLINED' };
return { id: 'N/A', processedBy: 'N/A', status: 'SERVER_ERROR', decision: 'PRE-DECLINED' };
}
}
}

View File

@ -1,5 +1,7 @@
/* eslint-disable no-undef */
import { TextChannel } from 'eris'; import { TextChannel } from 'eris';
import { Client, RichEmbed } from '../class'; import { Client, RichEmbed } from '../class';
import { CloudServicesUtil } from '../util';
let interval: NodeJS.Timeout; let interval: NodeJS.Timeout;
@ -8,6 +10,16 @@ export default function checkLock(client: Client): NodeJS.Timeout {
try { try {
const moderations = await client.db.Moderation.find(); const moderations = await client.db.Moderation.find();
const judgements = await client.db.Judgement.find().lean().exec(); const judgements = await client.db.Judgement.find().lean().exec();
const members = await client.db.Member.find();
members.forEach(async (member) => {
if (member.misc?.t3TemporaryExpiration?.processed === false) {
if (new Date() > member.misc?.t3TemporaryExpiration?.date) {
await member.updateOne({ 'misc.t3TemporaryExpiration.processed': true });
await CloudServicesUtil.downgradeT2(member.id, client.config.internalKey);
}
}
});
judgements.forEach(async (judgement) => { judgements.forEach(async (judgement) => {
if (!judgement.expires) return; if (!judgement.expires) return;
if (new Date() > judgement.expires) { if (new Date() > judgement.expires) {

View File

@ -1,29 +1,41 @@
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'],
github: string, github: string,
gitlab: string, gitlab: string,
bio: string, bio: string,
}, },
x509?: string, misc?: {
pgp?: string t3TemporaryExpiration?: {
} date: Date,
processed: boolean
const Member: Schema = new Schema({ }
userID: String, }
additional: { x509?: string,
langs: Array, pgp?: string,
operatingSystems: Array, }
github: String,
gitlab: String, const Member: Schema = new Schema({
bio: String, userID: String,
}, additional: {
x509: String, langs: Array,
pgp: String, operatingSystems: Array,
}); github: String,
gitlab: String,
export default model<MemberInterface>('Member', Member); bio: String,
},
misc: {
t3TemporaryExpiration: {
date: Date,
processed: Boolean,
},
},
x509: String,
pgp: String,
});
export default model<MemberInterface>('Member', Member);

View File

@ -1,37 +1,37 @@
import { Document, Schema, model } from 'mongoose'; import { Document, Schema, model } from 'mongoose';
export interface ModerationInterface extends Document { export interface ModerationInterface extends Document {
userID: string, userID: string,
logID: string, logID: string,
moderatorID: string, moderatorID: string,
reason: string, reason: string,
/** /**
* @field 0 - Warn * @field 0 - Warn
* @field 1 - Unmute * @field 1 - Unmute
* @field 2 - Mute * @field 2 - Mute
* @field 3 - Kick * @field 3 - Kick
* @field 4 - Unban * @field 4 - Unban
* @field 5 - Ban * @field 5 - Ban
*/ */
type: 0 | 1 | 2 | 3 | 4 | 5 type: 0 | 1 | 2 | 3 | 4 | 5
date: Date, date: Date,
expiration?: { expiration?: {
date: Date, date: Date,
processed: boolean processed: boolean
} }
} }
const Moderation: Schema = new Schema({ const Moderation: Schema = new Schema({
userID: String, userID: String,
logID: String, logID: String,
moderatorID: String, moderatorID: String,
reason: String, reason: String,
type: Number, type: Number,
date: Date, date: Date,
expiration: { expiration: {
date: Date, date: Date,
processed: Boolean, processed: Boolean,
}, },
}); });
export default model<ModerationInterface>('Moderation', Moderation); export default model<ModerationInterface>('Moderation', Moderation);