Tested version of BRS

merge-requests/17/head
Hiroyuki 2021-03-05 20:55:54 -04:00
parent 0289632f50
commit 45e11803c7
No known key found for this signature in database
GPG Key ID: C15AC26538975A24
12 changed files with 895 additions and 6033 deletions

4889
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@
"bull": "^3.20.1", "bull": "^3.20.1",
"cheerio": "^1.0.0-rc.5", "cheerio": "^1.0.0-rc.5",
"cron": "^1.8.2", "cron": "^1.8.2",
"eris": "^0.13.3", "eris": "^0.14.0",
"eris-pagination": "github:bsian03/eris-pagination", "eris-pagination": "github:bsian03/eris-pagination",
"express": "^4.17.1", "express": "^4.17.1",
"helmet": "^3.22.0", "helmet": "^3.22.0",

View File

@ -13,14 +13,15 @@ export default class Root extends Route {
public bind() { public bind() {
this.router.post('/eo', async (req, res) => { this.router.post('/eo', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) { if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) {
@ -48,7 +49,6 @@ export default class Root extends Route {
embed.setColor('#dd3acd'); embed.setColor('#dd3acd');
embed.addField('Subject', req.body.subject); embed.addField('Subject', req.body.subject);
embed.addField('Body', req.body.body); embed.addField('Body', req.body.body);
embed.addField('Director', directorDiscord.mention);
embed.setDescription(eoID); embed.setDescription(eoID);
embed.setTimestamp(new Date()); embed.setTimestamp(new Date());
@ -59,7 +59,7 @@ export default class Root extends Route {
issuer: director.userID, issuer: director.userID,
subject: req.body.subject, subject: req.body.subject,
body: req.body.body, body: req.body.body,
at: new Date(), at: Date.now(),
oID: eoID, oID: eoID,
msg: msg.id, msg: msg.id,
}); });
@ -70,15 +70,75 @@ export default class Root extends Route {
}); });
}); });
this.router.post('/proc', async (req: Request, res: Response) => { this.router.post('/motion', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
if (typeof req.body.subject !== 'string' || typeof req.body.body !== 'string' || req.body.subject.length > 1024 || req.body.body.length > 1024) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
const motionID = genUUID();
const directorDiscord = this.server.client.users.get(director.userID) || await this.server.client.getRESTUser(director.userID);
const directorInformation = await this.server.client.db.Staff.findOne({ userID: director.userID });
const embed = new RichEmbed();
embed.setTitle('Motion');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorInformation.pn.join(', ')}`, directorDiscord.avatarURL);
embed.setColor('#dd3acd');
embed.addField('Subject', req.body.subject);
embed.addField('Body', req.body.body);
embed.setDescription(motionID);
embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const msg = await channel.createMessage({ embed });
const motion = await this.server.client.db.Motion.create({
issuer: director.userID,
subject: req.body.subject,
body: req.body.body,
at: Date.now(),
oID: motionID,
msg: msg.id,
processed: false,
});
res.status(200).json({
code: this.constants.codes.SUCCESS,
message: `Created new Motion with ID ${motion.oID} by ${directorDiscord.username}#${directorDiscord.discriminator}, ${directorInformation.pn.join(', ')}.`,
});
});
this.router.post('/proc', async (req: Request, res: Response) => {
if (!req.headers.authorization) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) { if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) {
@ -106,21 +166,20 @@ export default class Root extends Route {
embed.setColor('#66e1ff'); embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject); embed.addField('Subject', req.body.subject);
embed.addField('Body', req.body.body); embed.addField('Body', req.body.body);
embed.addField('ID', proclamationID); embed.setDescription(proclamationID);
embed.addField('Director', directorDiscord.mention);
embed.setTimestamp(new Date()); embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550'); const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const procMessage = await channel.createMessage({ embed }); const procMessage = await channel.createMessage({ embed });
await procMessage.addReaction(this.server.client.util.emojis.SUCCESS); await procMessage.addReaction('modSuccess:578750988907970567');
await procMessage.addReaction(this.server.client.util.emojis.ERROR); await procMessage.addReaction('modError:578750737920688128');
await procMessage.getReaction('🙋'); await procMessage.addReaction('🙋');
const proclamation = await this.server.client.db.Proclamation.create({ const proclamation = await this.server.client.db.Proclamation.create({
issuer: director.userID, issuer: director.userID,
subject: req.body.subject, subject: req.body.subject,
body: req.body.body, body: req.body.body,
at: new Date(), at: Date.now(),
oID: proclamationID, oID: proclamationID,
processed: false, processed: false,
msg: procMessage.id, msg: procMessage.id,
@ -133,14 +192,15 @@ export default class Root extends Route {
}); });
this.router.delete('/eo/:id', async (req, res) => { this.router.delete('/eo/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) { if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) {
@ -179,14 +239,15 @@ export default class Root extends Route {
}); });
this.router.delete('/motion/:id', async (req, res) => { this.router.delete('/motion/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) { if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) {
@ -225,14 +286,15 @@ export default class Root extends Route {
}); });
this.router.delete('/proc/:id', async (req, res) => { this.router.delete('/proc/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) { if (!director || !staffGuild.members.get(director.userID)?.roles?.includes('662163685439045632')) {
@ -346,14 +408,15 @@ export default class Root extends Route {
}); });
this.router.patch('/eo/:id', async (req, res) => { this.router.patch('/eo/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
const directorDiscord = staffGuild.members.get(director.userID); const directorDiscord = staffGuild.members.get(director.userID);
@ -398,20 +461,18 @@ export default class Root extends Route {
}); });
if (executiveOrder.subject !== req.body.subject || executiveOrder.body !== req.body.body) { if (executiveOrder.subject !== req.body.subject || executiveOrder.body !== req.body.body) {
const directorStaffProfile = await this.server.client.db.Staff.findOne({ userID: directorDiscord.id }); const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const eoMessage = await channel.getMessage(executiveOrder.msg);
const embed = new RichEmbed(); const embed = new RichEmbed();
embed.setTitle('Executive Order'); embed.setTitle('Executive Order');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL); embed.author = eoMessage.embeds[0].author;
embed.setColor('#66e1ff'); embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject || executiveOrder.subject); embed.addField('Subject', req.body.subject || executiveOrder.subject);
embed.addField('Body', req.body.body || executiveOrder.body); embed.addField('Body', req.body.body || executiveOrder.body);
embed.addField('Director', `<@!${executiveOrder.issuer}>`);
embed.setDescription(req.params.id); embed.setDescription(req.params.id);
embed.setTimestamp(new Date()); embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const eoMessage = await channel.getMessage(executiveOrder.msg);
await eoMessage.edit({ embed }); await eoMessage.edit({ embed });
} }
@ -419,14 +480,15 @@ export default class Root extends Route {
}); });
this.router.patch('/motion/:id', async (req, res) => { this.router.patch('/motion/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
const directorDiscord = staffGuild.members.get(director.userID); const directorDiscord = staffGuild.members.get(director.userID);
@ -471,20 +533,18 @@ export default class Root extends Route {
}); });
if (motion.subject !== req.body.subject || motion.body !== req.body.body) { if (motion.subject !== req.body.subject || motion.body !== req.body.body) {
const directorStaffProfile = await this.server.client.db.Staff.findOne({ userID: directorDiscord.id }); const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const motionMessage = await channel.getMessage(motion.msg);
const embed = new RichEmbed(); const embed = new RichEmbed();
embed.setTitle('Motion'); embed.setTitle('Motion');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL); embed.author = motionMessage.embeds[0].author;
embed.setColor('#66e1ff'); embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject || motion.subject); embed.addField('Subject', req.body.subject || motion.subject);
embed.addField('Body', req.body.body || motion.body); embed.addField('Body', req.body.body || motion.body);
embed.addField('Director', `<@!${motion.issuer}>`);
embed.setDescription(req.params.id); embed.setDescription(req.params.id);
embed.setTimestamp(new Date()); embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const motionMessage = await channel.getMessage(motion.msg);
await motionMessage.edit({ embed }); await motionMessage.edit({ embed });
} }
@ -492,14 +552,15 @@ export default class Root extends Route {
}); });
this.router.patch('/proc/:id', async (req, res) => { this.router.patch('/proc/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
const directorDiscord = staffGuild.members.get(director.userID); const directorDiscord = staffGuild.members.get(director.userID);
@ -544,20 +605,18 @@ export default class Root extends Route {
}); });
if (proclamation.subject !== req.body.subject || proclamation.body !== req.body.body) { if (proclamation.subject !== req.body.subject || proclamation.body !== req.body.body) {
const directorStaffProfile = await this.server.client.db.Staff.findOne({ userID: directorDiscord.id }); const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const procMessage = await channel.getMessage(proclamation.msg);
const embed = new RichEmbed(); const embed = new RichEmbed();
embed.setTitle('Proclamation'); embed.setTitle('Proclamation');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL); embed.author = procMessage.embeds[0].author;
embed.setColor('#66e1ff'); embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject || proclamation.subject); embed.addField('Subject', req.body.subject || proclamation.subject);
embed.addField('Body', req.body.body || proclamation.body); embed.addField('Body', req.body.body || proclamation.body);
embed.addField('Director', `<@!${proclamation.issuer}>`);
embed.setDescription(req.params.id); embed.setDescription(req.params.id);
embed.setTimestamp(new Date()); embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const procMessage = await channel.getMessage(proclamation.msg);
await procMessage.edit({ embed }); await procMessage.edit({ embed });
} }
@ -565,14 +624,15 @@ export default class Root extends Route {
}); });
this.router.patch('/resolution/:id', async (req, res) => { this.router.patch('/resolution/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
const directorDiscord = staffGuild.members.get(director.userID); const directorDiscord = staffGuild.members.get(director.userID);
@ -617,21 +677,18 @@ export default class Root extends Route {
}); });
if (resolution.subject !== req.body.subject || resolution.body !== req.body.body) { if (resolution.subject !== req.body.subject || resolution.body !== req.body.body) {
const directorStaffProfile = await this.server.client.db.Staff.findOne({ userID: directorDiscord.id }); const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const motion = await this.server.client.db.Motion.findOne({ oID: resolution.oID }); const resMessage = await channel.getMessage(resolution.msg);
const embed = new RichEmbed(); const embed = new RichEmbed();
embed.setTitle('Resolution'); embed.setTitle('Resolution');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL); embed.author = resMessage.embeds[0].author;
embed.setColor('#75b0ff'); embed.setColor('#75b0ff');
embed.addField('Subject', req.body.subject || resolution.subject); embed.addField('Subject', req.body.subject || resolution.subject);
embed.addField('Body', req.body.body || resolution.body); embed.addField('Body', req.body.body || resolution.body);
embed.addField('Director', `<@!${motion.issuer}>`);
embed.setDescription(req.params.id); embed.setDescription(req.params.id);
embed.setTimestamp(new Date()); embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const resMessage = await channel.getMessage(resolution.msg);
await resMessage.edit({ await resMessage.edit({
content: `<@!${resolution.issuer}>`, content: `<@!${resolution.issuer}>`,
embed, embed,
@ -666,15 +723,16 @@ export default class Root extends Route {
res.status(200).json(resolutions); res.status(200).json(resolutions);
}); });
this.router.patch('/motion/confirm', async (req, res) => { this.router.patch('/motion/confirm/:id', async (req, res) => {
if (!req.body.pin) { if (!req.headers.authorization) {
return res.status(401).json({ return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED, code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED,
}); });
} }
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin }); const users = await this.server.client.db.Score.find();
const director = users.filter((user) => user.pin.join('-') === req.headers.authorization)[0];
const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID); const staffGuild = this.server.client.guilds.get(this.server.client.config.guildID) || await this.server.client.getRESTGuild(this.server.client.config.guildID);
const directorDiscord = staffGuild.members.get(director.userID); const directorDiscord = staffGuild.members.get(director.userID);
@ -731,9 +789,8 @@ export default class Root extends Route {
embed.setColor('#27b17a'); embed.setColor('#27b17a');
embed.addField('Subject', motion.subject); embed.addField('Subject', motion.subject);
embed.addField('Body', motion.body); embed.addField('Body', motion.body);
embed.addField('Director', `<@!${motion.issuer}>`); embed.addField('Results', `Yea: ${yea}\nNay: ${nay}\nPresent: ${present}\nAbsent: ${absent}`);
embed.setDescription(motion.oID); embed.setDescription(motion.oID);
embed.setFooter(motion.oID, directorDiscord.avatarURL);
embed.setTimestamp(new Date()); embed.setTimestamp(new Date());
await channel.createMessage({ embed }); await channel.createMessage({ embed });

View File

@ -1,9 +1,10 @@
/* eslint-disable no-constant-condition */ /* eslint-disable no-constant-condition */
import { promises as fs, accessSync, constants, writeFileSync } from 'fs'; import { promises as fs, accessSync, constants, writeFileSync } from 'fs';
import { promisify } from 'util'; import { promisify } from 'util';
import { join } from 'path'
import { gzip, gzipSync, unzip } from 'zlib'; import { gzip, gzipSync, unzip } from 'zlib';
type JSONData = [{key: string, value: any}?]; type JSONData = [{ key: string, value: any }?];
/** /**
@ -18,7 +19,7 @@ export default class LocalStorage {
private locked: boolean = false; private locked: boolean = false;
constructor(dbName: string, dir = `${__dirname}/../../localstorage`) { constructor(dbName: string, dir = `${__dirname}/../../localstorage`) {
this.storagePath = `${dir}/${dbName}.json.gz`; this.storagePath = join(__dirname, '../../localstorage') || dir;
this.init(); this.init();
} }
@ -42,7 +43,7 @@ export default class LocalStorage {
*/ */
static async compress(data: string): Promise<Buffer> { static async compress(data: string): Promise<Buffer> {
const func = promisify(gzip); const func = promisify(gzip);
const comp = <Buffer> await func(data); const comp = <Buffer>await func(data);
return comp; return comp;
} }
@ -57,7 +58,7 @@ export default class LocalStorage {
*/ */
static async decompress(data: Buffer): Promise<string> { static async decompress(data: Buffer): Promise<string> {
const func = promisify(unzip); const func = promisify(unzip);
const uncomp = <Buffer> await func(data); const uncomp = <Buffer>await func(data);
return uncomp.toString(); return uncomp.toString();
} }
@ -91,7 +92,7 @@ export default class LocalStorage {
* await LocalStorage.get<type>('data-key'); * await LocalStorage.get<type>('data-key');
* @param key The key for the data entry. * @param key The key for the data entry.
*/ */
public async getMany<T>(key: string): Promise<{key: string, value: T}[]> { public async getMany<T>(key: string): Promise<{ key: string, value: T }[]> {
while (true) { while (true) {
if (!this.locked) break; if (!this.locked) break;
} }

View File

@ -56,6 +56,7 @@ export default class Server {
public init() { public init() {
if (this.parse) { if (this.parse) {
this.app.use(bodyParser.json()); this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded({ extended: true }));
} }
this.app.set('trust proxy', 'loopback'); this.app.set('trust proxy', 'loopback');
this.app.use(helmet({ this.app.use(helmet({

View File

@ -20,15 +20,19 @@ export default class MessageReactionAdd extends Event {
if (!reactor.roles.includes('662163685439045632')) return; if (!reactor.roles.includes('662163685439045632')) return;
if ((await this.client.db.Proclamation.exists({ msg: message.id, processed: false }))) { if ((await this.client.db.Proclamation.exists({ msg: message.id, processed: false }))) {
const yea = await message.getReaction(this.client.util.emojis.SUCCESS); let yea = await message.getReaction('modSuccess:578750988907970567');
const nay = await message.getReaction(this.client.util.emojis.ERROR); yea = yea.filter((val) => !val.bot);
const present = await message.getReaction('🙋'); let nay = await message.getReaction('modError:578750737920688128');
nay = nay.filter((val) => !val.bot);
let present = await message.getReaction('🙋');
present = present.filter((val) => !val.bot);
const totalDirectors = 6; const totalDirectors = 6;
const proclamation = await this.client.db.Proclamation.findOne({ msg: message.id }); const proc = await this.client.db.Proclamation.findOne({ msg: message.id });
const processed = totalDirectors === (yea.length + nay.length + present.length) || Date.now() - proclamation.at > 604800000; if (proc.votedDirectors?.includes(message.author.id)) return;
const processed = totalDirectors === (yea.length + nay.length + present.length) || Date.now() - proc.at > 604800000;
const absent = totalDirectors - (yea.length + nay.length + present.length); const absent = totalDirectors - (yea.length + nay.length + present.length);
await this.client.db.Proclamation.updateOne({ msg: message.id }, { await proc.updateOne({
results: { results: {
yea: yea.length, yea: yea.length,
nay: nay.length, nay: nay.length,
@ -36,22 +40,23 @@ export default class MessageReactionAdd extends Event {
absent, absent,
}, },
processed, processed,
votedDirectors: [...(proc.votedDirectors || []), message.author.id],
}); });
const inTheMajority = yea.length > nay.length + present.length; const inTheMajority = yea.length > nay.length + present.length;
if (processed) { if (processed) {
const author = this.client.users.get(proclamation.issuer) || await this.client.getRESTUser(proclamation.issuer); const author = this.client.users.get(proc.issuer) || await this.client.getRESTUser(proc.issuer);
if (inTheMajority) { if (inTheMajority) {
await author.createMessage(`__**Proclamation Majority Vote Received**__\nThe Proclamation you created at Library of Code sp-us, titled **${proclamation.subject}** (\`${proclamation.oID}\`) received the majority vote.`); await author.createMessage(`__**Proclamation Majority Vote Received**__\nThe Proclamation you created at Library of Code sp-us, titled **${proc.subject}** (\`${proc.oID}\`) received the majority vote.`);
await message.channel.createMessage(`__**Proclamation Results**__\nProclamation issued by ${author.mention} **received** the majority vote. Proclamation ID: ${proclamation.oID}\n\n__Results:__\n**Yea:** ${yea.length}\n**Nay:** ${nay.length}\n**Present:** ${present.length}\n**Absent:** ${absent}`); await message.channel.createMessage(`__**Proclamation Results**__\nProclamation issued by ${author.mention} **received** the majority vote. Proclamation ID: ${proc.oID}\n\n__Results:__\n**Yea:** ${yea.length}\n**Nay:** ${nay.length}\n**Present:** ${present.length}\n**Absent:** ${absent}`);
} else { } else {
await author.createMessage(`__**Proclamation Majority Vote Lost**__\nThe Proclamation you created at Library of Code sp-us, titled **${proclamation.subject}** (\`${proclamation.oID}\`) lost the majority vote.`); await author.createMessage(`__**Proclamation Majority Vote Lost**__\nThe Proclamation you created at Library of Code sp-us, titled **${proc.subject}** (\`${proc.oID}\`) lost the majority vote.`);
await message.channel.createMessage(`__**Proclamation Results**__\nProclamation issued by ${author.mention} **lost** the majority vote. Proclamation ID: ${proclamation.oID}\n\n__Results:__\n**Yea:** ${yea.length}\n**Nay:** ${nay.length}\n**Present:** ${present.length}\n**Absent:** ${absent}`); await message.channel.createMessage(`__**Proclamation Results**__\nProclamation issued by ${author.mention} **lost** the majority vote. Proclamation ID: ${proc.oID}\n\n__Results:__\n**Yea:** ${yea.length}\n**Nay:** ${nay.length}\n**Present:** ${present.length}\n**Absent:** ${absent}`);
} }
} }
await reactor.user.createMessage(`__**Vote Recorded**\nYour vote on the proclamation with ID \`${proclamation.id}\` at Library of Code sp-us was successfully recorded.`); await reactor.user.createMessage(`__**Vote Recorded**__\nYour vote on the proclamation with ID \`${proc.id}\` at Library of Code sp-us was successfully recorded.`);
} }
} }
} }

View File

@ -71,7 +71,7 @@ async function setupDepartmentCodes(client: Client): Promise<void> {
function logNewPager(client: Client, num: string, member: Member): void { function logNewPager(client: Client, num: string, member: Member): void {
client.util.signale.log(`Pager Number '${num}' created for '${member.user.username}#${member.user.discriminator}'.`); client.util.signale.log(`Pager Number '${num}' created for '${member.user.username}#${member.user.discriminator}'.`);
const channel = <TextableChannel> client.guilds.get(client.config.guildID).channels.get('722636436716781619'); const channel = <TextableChannel>client.guilds.get(client.config.guildID).channels.get('722636436716781619');
channel.createMessage(`__**'${member.user.username}#${member.user.discriminator}' assigned to pager number '${num}'.**__`); channel.createMessage(`__**'${member.user.username}#${member.user.discriminator}' assigned to pager number '${num}'.**__`);
} }

View File

@ -4,6 +4,7 @@
import sdNotify from 'sd-notify'; import sdNotify from 'sd-notify';
import { parse } from 'yaml'; import { parse } from 'yaml';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import { join } from 'path';
import { Client } from './class'; import { Client } from './class';
import * as eventFiles from './events'; import * as eventFiles from './events';
import * as commandFiles from './commands'; import * as commandFiles from './commands';
@ -14,7 +15,7 @@ async function main(): Promise<void> {
sdNotify.ready(); sdNotify.ready();
sdNotify.startWatchdogMode(2500); sdNotify.startWatchdogMode(2500);
} }
const read = await fs.readFile('../config.yaml', 'utf8'); const read = await fs.readFile(join(__dirname, '../config.yaml'), 'utf8');
const config: Config = parse(read); const config: Config = parse(read);
const client = new Client(config.token, { defaultImageFormat: 'png', restMode: true, intents: ['guildBans', 'guildEmojis', 'guildInvites', 'guildMembers', 'guildMessageReactions', 'guildMessages', 'guildPresences', 'guildWebhooks', 'guilds', 'directMessages'] }); const client = new Client(config.token, { defaultImageFormat: 'png', restMode: true, intents: ['guildBans', 'guildEmojis', 'guildInvites', 'guildMembers', 'guildMessageReactions', 'guildMessages', 'guildPresences', 'guildWebhooks', 'guilds', 'directMessages'] });
client.config = config; client.config = config;

View File

@ -4,7 +4,7 @@ export interface ExecutiveOrderInterface extends Document {
issuer: string; issuer: string;
subject: string; subject: string;
body: string; body: string;
at: Date; at: number;
oID: string; oID: string;
msg: string; msg: string;
} }
@ -13,7 +13,7 @@ const ExecutiveOrder = new Schema({
issuer: { type: String, required: true }, issuer: { type: String, required: true },
subject: { type: String, required: true }, subject: { type: String, required: true },
body: { type: String, required: true }, body: { type: String, required: true },
at: { type: Date, required: true }, at: { type: Number, required: true },
oID: { type: String, required: true, unique: true }, oID: { type: String, required: true, unique: true },
msg: { type: String, required: true, unique: true }, msg: { type: String, required: true, unique: true },
}); });

View File

@ -4,7 +4,7 @@ export interface MotionInterface extends Document {
issuer: string; issuer: string;
subject: string; subject: string;
body: string; body: string;
at: Date; at: number;
oID: string; oID: string;
results: { results: {
yea: number; yea: number;
@ -20,7 +20,7 @@ const Motion = new Schema({
issuer: { type: String, required: true }, issuer: { type: String, required: true },
subject: { type: String, required: true }, subject: { type: String, required: true },
body: { type: String, required: true }, body: { type: String, required: true },
at: { type: Date, required: true }, at: { type: Number, required: true },
oID: { type: String, required: true, unique: true }, oID: { type: String, required: true, unique: true },
results: { results: {
yea: Number, yea: Number,

View File

@ -15,6 +15,7 @@ export interface ProclamationInterface extends Document {
acceptedAt: number; acceptedAt: number;
msg: string; msg: string;
processed: boolean; processed: boolean;
votedDirectors: string[];
} }
const Proclamation = new Schema({ const Proclamation = new Schema({
@ -32,6 +33,7 @@ const Proclamation = new Schema({
acceptedAt: Number, acceptedAt: Number,
msg: { type: String, required: true, unique: true }, msg: { type: String, required: true, unique: true },
processed: Boolean, processed: Boolean,
votedDirectors: Array,
}); });
export default model<ProclamationInterface>('Proclamations', Proclamation); export default model<ProclamationInterface>('Proclamations', Proclamation);

1818
yarn.lock

File diff suppressed because it is too large Load Diff