merge conflict fix

merge-requests/23/merge
Matthew 2021-03-06 19:39:19 -05:00
commit 986477fd96
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
14 changed files with 5890 additions and 3 deletions

4889
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
"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", "tslib": "^2.1.0",
"typescript": "^3.9.2" "typescript": "^3.9.8"
}, },
"dependencies": { "dependencies": {
"@google-cloud/text-to-speech": "^3.1.2", "@google-cloud/text-to-speech": "^3.1.2",

View File

@ -0,0 +1,3 @@
import { Server, ServerManagement } from '../../class';
export default (management: ServerManagement) => new Server(management, 3892, `${__dirname}/routes`);

View File

@ -0,0 +1 @@
export { default as Root } from './root';

View File

@ -0,0 +1,777 @@
import { TextChannel } from 'eris';
import { v4 as genUUID } from 'uuid';
import { Request, Response } from 'express';
import { RichEmbed, Route, Server } from '../../../class';
export default class Root extends Route {
constructor(server: Server) {
super(server);
this.conf = {
path: '/',
};
}
public bind() {
this.router.post('/eo', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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 eoID = 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('Executive Order');
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.addField('Director', directorDiscord.mention);
embed.setDescription(eoID);
embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const msg = await channel.createMessage({ embed });
const executiveOrder = await this.server.client.db.ExecutiveOrder.create({
issuer: director.userID,
subject: req.body.subject,
body: req.body.body,
at: new Date(),
oID: eoID,
msg: msg.id,
});
res.status(200).json({
code: this.constants.codes.SUCCESS,
message: `Created new Executive Order with ID ${executiveOrder.oID} by ${directorDiscord.username}#${directorDiscord.discriminator}, ${directorInformation.pn.join(', ')}.`,
});
});
this.router.post('/proc', async (req: Request, res: Response) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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(401).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 proclamationID = 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('Proclamation');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorInformation.pn.join(', ')}`, directorDiscord.avatarURL);
embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject);
embed.addField('Body', req.body.body);
embed.addField('ID', proclamationID);
embed.addField('Director', directorDiscord.mention);
embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const procMessage = await channel.createMessage({ embed });
await procMessage.addReaction(this.server.client.util.emojis.SUCCESS);
await procMessage.addReaction(this.server.client.util.emojis.ERROR);
await procMessage.getReaction('🙋');
const proclamation = await this.server.client.db.Proclamation.create({
issuer: director.userID,
subject: req.body.subject,
body: req.body.body,
at: new Date(),
oID: proclamationID,
processed: false,
msg: procMessage.id,
});
res.status(200).json({
code: this.constants.codes.SUCCESS,
message: `Created new Proclamation with ID ${proclamation.oID} by ${directorDiscord.username}#${directorDiscord.discriminator}, ${directorInformation.pn.join(', ')}.`,
});
});
this.router.delete('/eo/:id', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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 (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.ExecutiveOrder.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const executiveOrder = await this.server.client.db.ExecutiveOrder.findOne({ oID: req.params.id });
if (!['278620217221971968', executiveOrder.issuer].includes(director.userID)) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
await this.server.client.db.ExecutiveOrder.deleteOne({ oID: req.params.id });
res.status(200).json({ message: `Executive Order with ID ${req.params.id} deleted.` });
});
this.router.delete('/motion/:id', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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 (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Motion.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const motion = await this.server.client.db.Motion.findOne({ oID: req.params.id });
if (!['278620217221971968', motion.issuer].includes(director.userID)) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
await this.server.client.db.Motion.deleteOne({ oID: req.params.id });
res.status(200).json({ message: `Motion with ID ${req.params.id} deleted.` });
});
this.router.delete('/proc/:id', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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 (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Proclamation.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const proclamation = await this.server.client.db.Proclamation.findOne({ oID: req.params.id });
if (!['278620217221971968', proclamation.issuer].includes(director.userID)) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
await this.server.client.db.Proclamation.deleteOne({ oID: req.params.id });
res.status(200).json({ message: `Proclamation with ID ${req.params.id} deleted.` });
});
this.router.get('/eo/:id', async (req, res) => {
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.ExecutiveOrder.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const executiveOrder = await this.server.client.db.ExecutiveOrder.findOne({ oID: req.params.id }).lean();
res.status(200).json(executiveOrder);
});
this.router.get('/motion/:id', async (req, res) => {
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Motion.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const motion = await this.server.client.db.Motion.findOne({ oID: req.params.id }).lean();
res.status(200).json(motion);
});
this.router.get('/proc/:id', async (req: Request, res: Response) => {
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Proclamation.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const proclamation = await this.server.client.db.Proclamation.findOne({ oID: req.params.id }).lean();
res.status(200).json(proclamation);
});
this.router.get('/resolution/:id', async (req, res) => {
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Resolution.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const resolution = await this.server.client.db.Resolution.findOne({ oID: req.params.id }).lean();
res.status(200).json(resolution);
});
this.router.patch('/eo/:id', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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);
if (!director || !directorDiscord?.roles?.includes('662163685439045632')) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.ExecutiveOrder.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
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 executiveOrder = await this.server.client.db.ExecutiveOrder.findOne({ oID: req.params.id });
if (!['278620217221971968', executiveOrder.issuer].includes(director.userID)) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
await executiveOrder.updateOne({
subject: req.body.subject || executiveOrder.subject,
body: req.body.body || executiveOrder.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 embed = new RichEmbed();
embed.setTitle('Executive Order');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL);
embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject || executiveOrder.subject);
embed.addField('Body', req.body.body || executiveOrder.body);
embed.addField('Director', `<@!${executiveOrder.issuer}>`);
embed.setDescription(req.params.id);
embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const eoMessage = await channel.getMessage(executiveOrder.msg);
await eoMessage.edit({ embed });
}
res.status(200).json({ message: `Updated Executive Order with ID ${executiveOrder.oID}.` });
});
this.router.patch('/motion/:id', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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);
if (!director || !directorDiscord?.roles?.includes('662163685439045632')) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Motion.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
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 motion = await this.server.client.db.Motion.findOne({ oID: req.params.id });
if (!['278620217221971968', motion.issuer].includes(director.userID)) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
await motion.updateOne({
subject: req.body.subject || motion.subject,
body: req.body.body || motion.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 embed = new RichEmbed();
embed.setTitle('Motion');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL);
embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject || motion.subject);
embed.addField('Body', req.body.body || motion.body);
embed.addField('Director', `<@!${motion.issuer}>`);
embed.setDescription(req.params.id);
embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const motionMessage = await channel.getMessage(motion.msg);
await motionMessage.edit({ embed });
}
res.status(200).json({ message: `Updated Motion with ID ${motion.oID}.` });
});
this.router.patch('/proc/:id', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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);
if (!director || !directorDiscord?.roles?.includes('662163685439045632')) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Proclamation.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
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 proclamation = await this.server.client.db.Proclamation.findOne({ oID: req.params.id });
if (!['278620217221971968', proclamation.issuer].includes(director.userID)) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
await proclamation.updateOne({
subject: req.body.subject || proclamation.subject,
body: req.body.body || proclamation.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 embed = new RichEmbed();
embed.setTitle('Proclamation');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL);
embed.setColor('#66e1ff');
embed.addField('Subject', req.body.subject || proclamation.subject);
embed.addField('Body', req.body.body || proclamation.body);
embed.addField('Director', `<@!${proclamation.issuer}>`);
embed.setDescription(req.params.id);
embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const procMessage = await channel.getMessage(proclamation.msg);
await procMessage.edit({ embed });
}
res.status(200).json({ message: `Updated Proclamation with ID ${proclamation.oID}.` });
});
this.router.patch('/resolution/:id', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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);
if (!director || !directorDiscord?.roles?.includes('662163685439045632')) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Resolution.exists({ oID: req.params.id }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
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 resolution = await this.server.client.db.Resolution.findOne({ oID: req.params.id });
if (!['278620217221971968', resolution.issuer].includes(director.userID)) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
await resolution.updateOne({
subject: req.body.subject || resolution.subject,
body: req.body.body || resolution.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 motion = await this.server.client.db.Motion.findOne({ oID: resolution.oID });
const embed = new RichEmbed();
embed.setTitle('Resolution');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL);
embed.setColor('#75b0ff');
embed.addField('Subject', req.body.subject || resolution.subject);
embed.addField('Body', req.body.body || resolution.body);
embed.addField('Director', `<@!${motion.issuer}>`);
embed.setDescription(req.params.id);
embed.setTimestamp(new Date());
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const resMessage = await channel.getMessage(resolution.msg);
await resMessage.edit({
content: `<@!${resolution.issuer}>`,
embed,
});
}
res.status(200).json({ message: `Updated Resolution with ID ${resolution.oID}.` });
});
this.router.get('/eo', async (_req, res) => {
const executiveOrders = await this.server.client.db.ExecutiveOrder.find().lean();
res.status(200).json(executiveOrders);
});
this.router.get('/motion', async (_req, res) => {
const motions = await this.server.client.db.Motion.find().lean();
res.status(200).json(motions);
});
this.router.get('/proc', async (_req: Request, res: Response) => {
const proclamations = await this.server.client.db.Proclamation.find().lean();
res.status(200).send({ proclamations });
});
this.router.get('/resolution', async (_req, res) => {
const resolutions = await this.server.client.db.Resolution.find().lean();
res.status(200).json(resolutions);
});
this.router.patch('/motion/confirm', async (req, res) => {
if (!req.body.pin) {
return res.status(401).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
const director = await this.server.client.db.Score.findOne({ pin: req.body.pin });
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);
if (!director || !directorDiscord?.roles?.includes('662163685439045632')) {
return res.status(403).json({
code: this.constants.codes.UNAUTHORIZED,
message: this.constants.messages.UNAUTHORIZED,
});
}
if (!req.params.id) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
if (!(await this.server.client.db.Motion.exists({ oID: req.params.id, processed: false }))) {
return res.status(404).json({
code: this.constants.codes.NOT_FOUND,
message: this.constants.messages.NOT_FOUND,
});
}
const yea = Number(req.body.yea);
const nay = Number(req.body.nay);
const present = Number(req.body.present);
const absent = Number(req.body.absent);
if (Number.isNaN(yea) || Number.isNaN(nay) || Number.isNaN(present) || Number.isNaN(absent)) {
return res.status(400).json({
code: this.constants.codes.CLIENT_ERROR,
message: this.constants.messages.CLIENT_ERROR,
});
}
const motion = await this.server.client.db.Motion.findOne({ oID: req.params.id });
await motion.updateOne({
processed: true,
results: {
yea,
nay,
present,
absent,
},
});
const directorStaffProfile = await this.server.client.db.Staff.findOne({ userID: directorDiscord.id });
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
const embed = new RichEmbed();
embed.setTitle('Motion Confirmed');
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL);
embed.setColor('#27b17a');
embed.addField('Subject', motion.subject);
embed.addField('Body', motion.body);
embed.addField('Director', `<@!${motion.issuer}>`);
embed.setDescription(motion.oID);
embed.setFooter(motion.oID, directorDiscord.avatarURL);
embed.setTimestamp(new Date());
await channel.createMessage({ embed });
const excludingYea = nay + present + absent;
if (yea > excludingYea) {
const resolutionEmbed = new RichEmbed();
resolutionEmbed.setTitle('Resolution');
resolutionEmbed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorStaffProfile.pn.join(', ')}`, directorDiscord.avatarURL);
resolutionEmbed.setColor('#75b0ff');
resolutionEmbed.addField('Subject', motion.subject);
resolutionEmbed.addField('Body', motion.body);
resolutionEmbed.addField('Director', `<@!${motion.issuer}>`);
resolutionEmbed.setDescription(motion.oID);
resolutionEmbed.setTimestamp(new Date());
const resMsg = await channel.createMessage({
content: `<@!${motion.issuer}>`,
embed: resolutionEmbed,
});
await this.server.client.db.Resolution.create({
issuer: motion.issuer,
subject: motion.subject,
body: motion.body,
at: Date.now(),
oID: motion.oID,
results: {
yea,
nay,
present,
absent,
},
msg: resMsg.id,
});
}
res.status(200).json({ message: `Confirmed results of motion with ID ${motion.oID}.` });
});
}
}

View File

@ -1,8 +1,10 @@
import locsh from './loc.sh/main'; import locsh from './loc.sh/main';
import crins from './cr.ins/main'; import crins from './cr.ins/main';
import commlibraryofcodeorg from './comm.libraryofcode.org/main'; import commlibraryofcodeorg from './comm.libraryofcode.org/main';
import boardins from './board.ins/main';
export default { export default {
'board.ins': boardins,
'loc.sh': locsh, 'loc.sh': locsh,
'cr.ins': crins, 'cr.ins': crins,
'comm.libraryofcode.org': commlibraryofcodeorg, 'comm.libraryofcode.org': commlibraryofcodeorg,

View File

@ -7,17 +7,21 @@ import { Collection, Command, LocalStorage, Queue, Util, ServerManagement, Event
import { import {
Customer, CustomerInterface, Customer, CustomerInterface,
CustomerPortal, CustomerPortalInterface, CustomerPortal, CustomerPortalInterface,
ExecutiveOrder, ExecutiveOrderInterface,
File, FileInterface, File, FileInterface,
Inquiry, InquiryInterface, Inquiry, InquiryInterface,
Member, MemberInterface, Member, MemberInterface,
Merchant, MerchantInterface, Merchant, MerchantInterface,
Moderation, ModerationInterface, Moderation, ModerationInterface,
Motion, MotionInterface,
NNTrainingData, NNTrainingDataInterface, NNTrainingData, NNTrainingDataInterface,
Note, NoteInterface, Note, NoteInterface,
PagerNumber, PagerNumberInterface, PagerNumber, PagerNumberInterface,
Proclamation, ProclamationInterface,
Promo, PromoInterface, Promo, PromoInterface,
Rank, RankInterface, Rank, RankInterface,
Redirect, RedirectInterface, Redirect, RedirectInterface,
Resolution, ResolutionInterface,
Score, ScoreInterface, Score, ScoreInterface,
ScoreHistorical, ScoreHistoricalInterface, ScoreHistorical, ScoreHistoricalInterface,
Staff, StaffInterface, Staff, StaffInterface,
@ -44,7 +48,30 @@ 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>, 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 } }; public db: {
Customer: mongoose.Model<CustomerInterface>,
CustomerPortal: mongoose.Model<CustomerPortalInterface>,
ExecutiveOrder: mongoose.Model<ExecutiveOrderInterface>,
File: mongoose.Model<FileInterface>,
Inquiry: mongoose.Model<InquiryInterface>,
Member: mongoose.Model<MemberInterface>,
Merchant: mongoose.Model<MerchantInterface>,
Moderation: mongoose.Model<ModerationInterface>,
Motion: mongoose.Model<MotionInterface>,
NNTrainingData: mongoose.Model<NNTrainingDataInterface>,
Note: mongoose.Model<NoteInterface>,
PagerNumber: mongoose.Model<PagerNumberInterface>,
Proclamation: mongoose.Model<ProclamationInterface>,
Promo: mongoose.Model<PromoInterface>,
Rank: mongoose.Model<RankInterface>,
Redirect: mongoose.Model<RedirectInterface>,
Resolution: mongoose.Model<ResolutionInterface>,
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);
@ -52,7 +79,7 @@ export default class Client extends eris.Client {
this.events = new Collection<Event>(); this.events = new Collection<Event>();
this.intervals = new Collection<NodeJS.Timeout>(); this.intervals = new Collection<NodeJS.Timeout>();
this.queue = new Queue(this); this.queue = new Queue(this);
this.db = { Customer, CustomerPortal, File, Inquiry, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Promo, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } }; this.db = { Customer, CustomerPortal, ExecutiveOrder, File, Inquiry, Member, Merchant, Moderation, Motion, NNTrainingData, Note, PagerNumber, Proclamation, Promo, Rank, Redirect, Resolution, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } };
} }
get report() { get report() {

View File

@ -1,5 +1,6 @@
export { default as CallBackHandler } from './CallBackHandler'; export { default as CallBackHandler } from './CallBackHandler';
export { default as CommandHandler } from './CommandHandler'; export { default as CommandHandler } from './CommandHandler';
export { default as guildMemberAdd } from './guildMemberAdd'; export { default as guildMemberAdd } from './guildMemberAdd';
export { default as messageReactionAdd } from './messageReactionAdd';
export { default as ready } from './ready'; export { default as ready } from './ready';
export { default as Training } from './Training'; export { default as Training } from './Training';

View File

@ -0,0 +1,57 @@
import { Emoji, GuildTextableChannel, Member, Message } from 'eris';
import { Client, Event } from '../class';
export default class MessageReactionAdd extends Event {
public client: Client;
constructor(client: Client) {
super(client);
this.event = 'messageReactionAdd';
}
public async run(message: Message<GuildTextableChannel>, _emoji: Emoji, reactor: Member) {
if (message.channel.id !== '807444198969835550') return;
if (message.author.id !== this.client.user.id) return;
if (!reactor.roles[0]) {
reactor = await message.channel.guild.getRESTMember(reactor.id);
}
if (!reactor.roles.includes('662163685439045632')) return;
if ((await this.client.db.Proclamation.exists({ msg: message.id, processed: false }))) {
const yea = await message.getReaction(this.client.util.emojis.SUCCESS);
const nay = await message.getReaction(this.client.util.emojis.ERROR);
const present = await message.getReaction('🙋');
const totalDirectors = 6;
const proclamation = await this.client.db.Proclamation.findOne({ msg: message.id });
const processed = totalDirectors === (yea.length + nay.length + present.length) || Date.now() - proclamation.at > 604800000;
const absent = totalDirectors - (yea.length + nay.length + present.length);
await this.client.db.Proclamation.updateOne({ msg: message.id }, {
results: {
yea: yea.length,
nay: nay.length,
present: present.length,
absent,
},
processed,
});
const inTheMajority = yea.length > nay.length + present.length;
if (processed) {
const author = this.client.users.get(proclamation.issuer) || await this.client.getRESTUser(proclamation.issuer);
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 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}`);
} 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 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 reactor.user.createMessage(`__**Vote Recorded**\nYour vote on the proclamation with ID \`${proclamation.id}\` at Library of Code sp-us was successfully recorded.`);
}
}
}

View File

@ -0,0 +1,21 @@
import { Document, model, Schema } from 'mongoose';
export interface ExecutiveOrderInterface extends Document {
issuer: string;
subject: string;
body: string;
at: Date;
oID: string;
msg: string;
}
const ExecutiveOrder = new Schema({
issuer: { type: String, required: true },
subject: { type: String, required: true },
body: { type: String, required: true },
at: { type: Date, required: true },
oID: { type: String, required: true, unique: true },
msg: { type: String, required: true, unique: true },
});
export default model<ExecutiveOrderInterface>('ExecutiveOrders', ExecutiveOrder);

35
src/models/Motion.ts Normal file
View File

@ -0,0 +1,35 @@
import { Document, model, Schema } from 'mongoose';
export interface MotionInterface extends Document {
issuer: string;
subject: string;
body: string;
at: Date;
oID: string;
results: {
yea: number;
nay: number;
present: number;
absent: number;
};
processed: boolean;
msg: string;
}
const Motion = new Schema({
issuer: { type: String, required: true },
subject: { type: String, required: true },
body: { type: String, required: true },
at: { type: Date, required: true },
oID: { type: String, required: true, unique: true },
results: {
yea: Number,
nay: Number,
present: Number,
absent: Number,
},
processed: Boolean,
msg: { required: true, unique: true, type: String },
});
export default model<MotionInterface>('Motions', Motion);

View File

@ -0,0 +1,37 @@
import { Document, model, Schema } from 'mongoose';
export interface ProclamationInterface extends Document {
issuer: string;
subject: string;
body: string;
at: number;
oID: string;
results: {
yea: number;
nay: number;
present: number;
absent: number;
};
acceptedAt: number;
msg: string;
processed: boolean;
}
const Proclamation = new Schema({
issuer: { type: String, required: true },
subject: { type: String, required: true },
body: { type: String, required: true },
at: { type: Number, required: true },
oID: { type: String, required: true, unique: true },
results: {
yea: Number,
nay: Number,
present: Number,
absent: Number,
},
acceptedAt: Number,
msg: { type: String, required: true, unique: true },
processed: Boolean,
});
export default model<ProclamationInterface>('Proclamations', Proclamation);

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

@ -0,0 +1,33 @@
import { Document, model, Schema } from 'mongoose';
export interface ResolutionInterface extends Document {
issuer: string;
subject: string;
body: string;
at: number;
oID: string;
results: {
yea: number;
nay: number;
present: number;
absent: number;
};
msg: string;
}
const Resolution = new Schema({
issuer: { type: String, required: true },
subject: { type: String, required: true },
body: { type: String, required: true },
at: { type: Number, required: true },
oID: { type: String, required: true, unique: true },
results: {
yea: Number,
Nay: Number,
present: Number,
absent: Number,
},
msg: { type: String, required: true, unique: true },
});
export default model<ResolutionInterface>('Resolutions', Resolution);

View File

@ -1,16 +1,20 @@
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 ExecutiveOrder, ExecutiveOrderInterface } from './ExecutiveOrder';
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 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';
export { default as Motion, MotionInterface } from './Motion';
export { default as NNTrainingData, NNTrainingDataInterface } from './NNTrainingData'; export { default as NNTrainingData, NNTrainingDataInterface } from './NNTrainingData';
export { default as Note, NoteInterface } from './Note'; export { default as Note, NoteInterface } from './Note';
export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber'; export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber';
export { default as Proclamation, ProclamationInterface } from './Proclamation'
export { default as Promo, PromoInterface } from './Promo'; export { default as Promo, PromoInterface } from './Promo';
export { default as Rank, RankInterface } from './Rank'; export { default as Rank, RankInterface } from './Rank';
export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect'; export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect';
export { default as Resolution, ResolutionInterface } from './Resolution';
export { default as Score, ScoreInterface, ScoreInterfaceRaw } from './Score'; export { default as Score, ScoreInterface, ScoreInterfaceRaw } from './Score';
export { default as ScoreHistorical, ScoreHistoricalInterface } from './ScoreHistorical'; export { default as ScoreHistorical, ScoreHistoricalInterface } from './ScoreHistorical';
export { default as Staff, StaffInterface } from './Staff'; export { default as Staff, StaffInterface } from './Staff';