Motions
parent
d83c35b256
commit
eebd5d1e4c
|
@ -1,47 +1,45 @@
|
|||
{
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"node": {
|
||||
"extensions": [".js", ".jsx", ".ts", ".tsx"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"airbnb-base"
|
||||
],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"linebreak-style": "off",
|
||||
"no-unused-vars": "off",
|
||||
"max-len": "off",
|
||||
"import/no-dynamic-require": "off",
|
||||
"global-require": "off",
|
||||
"class-methods-use-this":"off",
|
||||
"no-restricted-syntax": "off",
|
||||
"camelcase": "off",
|
||||
"indent": "warn",
|
||||
"object-curly-newline": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"no-useless-constructor": "off",
|
||||
"@typescript-eslint/no-useless-constructor": 2,
|
||||
"import/extensions": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-underscore-dangle": "off"
|
||||
},
|
||||
"ignorePatterns": "**/*.js"
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"node": {
|
||||
"extensions": [".js", ".jsx", ".ts", ".tsx"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["airbnb-base"],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"rules": {
|
||||
"linebreak-style": "off",
|
||||
"no-unused-vars": "off",
|
||||
"max-len": "off",
|
||||
"import/no-dynamic-require": "off",
|
||||
"global-require": "off",
|
||||
"class-methods-use-this": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
"camelcase": "off",
|
||||
"indent": "warn",
|
||||
"object-curly-newline": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"no-useless-constructor": "off",
|
||||
"@typescript-eslint/no-useless-constructor": 2,
|
||||
"import/extensions": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-underscore-dangle": "off",
|
||||
"keyword-spacing": "off",
|
||||
"no-multiple-empty-lines": "off"
|
||||
},
|
||||
"ignorePatterns": "**/*.js"
|
||||
}
|
||||
|
|
|
@ -68,7 +68,74 @@ export default class Root extends Route {
|
|||
|
||||
return res.status(200).json({
|
||||
code: this.constants.codes.SUCCESS,
|
||||
message: `Created new Executive Order with ID ${executiveOrder.oID} by the ${staffDiscord.username}#${staffDiscord.discriminator}, ${staffInformation.pn.join(', ')}.`,
|
||||
message: `Created new Executive Order with ID ${executiveOrder.oID} by ${staffDiscord.username}#${staffDiscord.discriminator}, ${staffInformation.pn.join(', ')}.`,
|
||||
});
|
||||
});
|
||||
|
||||
this.router.post('/motions/new', 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('446067825673633794') || await this.server.client.getRESTGuild('446067825673633794');
|
||||
|
||||
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 (!req.body.subject) {
|
||||
return res.status(400).json({
|
||||
code: this.constants.codes.CLIENT_ERROR,
|
||||
message: this.constants.messages.CLIENT_ERROR,
|
||||
});
|
||||
}
|
||||
|
||||
if (!req.body.body) {
|
||||
return res.status(400).json({
|
||||
code: this.constants.codes.CLIENT_ERROR,
|
||||
message: this.constants.messages.CLIENT_ERROR,
|
||||
});
|
||||
}
|
||||
|
||||
const motionID = genUUID();
|
||||
|
||||
const staffDiscord = this.server.client.users.get(director.userID) || await this.server.client.getRESTUser(director.userID);
|
||||
const staffInformation = await this.server.client.db.Staff.findOne({ userID: director.userID });
|
||||
|
||||
const embed = new RichEmbed();
|
||||
embed.setTitle('Motion');
|
||||
embed.setAuthor(`${staffDiscord.username}#${staffDiscord.discriminator}, ${staffInformation.pn.join(', ')}`, staffDiscord.avatarURL);
|
||||
embed.setColor('#66e1ff');
|
||||
embed.addField('Subject', req.body.subject);
|
||||
embed.addField('Body', req.body.body);
|
||||
embed.addField('ID', motionID);
|
||||
embed.setTimestamp(new Date());
|
||||
|
||||
const channel = <TextChannel>this.server.client.getChannel('807444198969835550');
|
||||
const motionMessage = await channel.createMessage({ embed });
|
||||
await motionMessage.addReaction(this.server.client.util.emojis.SUCCESS);
|
||||
await motionMessage.addReaction(this.server.client.util.emojis.ERROR);
|
||||
|
||||
const motion = await this.server.client.db.Motion.create({
|
||||
issuedBy: director.userID,
|
||||
subject: req.body.subject,
|
||||
body: req.body.body,
|
||||
at: new Date(),
|
||||
oID: motionID,
|
||||
motionMessage: motionMessage.id,
|
||||
processed: false,
|
||||
});
|
||||
|
||||
return res.status(200).json({
|
||||
code: this.constants.codes.SUCCESS,
|
||||
message: `Created new Motion with ID ${motion.oID} by ${staffDiscord.username}#${staffDiscord.discriminator}, ${staffInformation.pn.join(', ')}.`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
Member, MemberInterface,
|
||||
Merchant, MerchantInterface,
|
||||
Moderation, ModerationInterface,
|
||||
Motion, MotionInterface,
|
||||
NNTrainingData, NNTrainingDataInterface,
|
||||
Note, NoteInterface,
|
||||
PagerNumber, PagerNumberInterface,
|
||||
|
@ -44,7 +45,27 @@ export default class Client extends eris.Client {
|
|||
|
||||
public stripe: Stripe;
|
||||
|
||||
public db: { Customer: mongoose.Model<CustomerInterface>, CustomerPortal: mongoose.Model<CustomerPortalInterface>, ExecutiveOrder: mongoose.Model<ExecutiveOrderInterface>, File: mongoose.Model<FileInterface>, Member: mongoose.Model<MemberInterface>, Merchant: mongoose.Model<MerchantInterface>, Moderation: mongoose.Model<ModerationInterface>, NNTrainingData: mongoose.Model<NNTrainingDataInterface>, Note: mongoose.Model<NoteInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Promo: mongoose.Model<PromoInterface>, Rank: mongoose.Model<RankInterface>, Redirect: mongoose.Model<RedirectInterface>, Score: mongoose.Model<ScoreInterface>, ScoreHistorical: mongoose.Model<ScoreHistoricalInterface>, Staff: mongoose.Model<StaffInterface>, Stat: mongoose.Model<StatInterface>, local: { muted: LocalStorage } };
|
||||
public db: {
|
||||
Customer: mongoose.Model<CustomerInterface>,
|
||||
CustomerPortal: mongoose.Model<CustomerPortalInterface>,
|
||||
ExecutiveOrder: mongoose.Model<ExecutiveOrderInterface>,
|
||||
File: mongoose.Model<FileInterface>,
|
||||
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>,
|
||||
Promo: mongoose.Model<PromoInterface>,
|
||||
Rank: mongoose.Model<RankInterface>,
|
||||
Redirect: mongoose.Model<RedirectInterface>,
|
||||
Score: mongoose.Model<ScoreInterface>,
|
||||
ScoreHistorical: mongoose.Model<ScoreHistoricalInterface>,
|
||||
Staff: mongoose.Model<StaffInterface>,
|
||||
Stat: mongoose.Model<StatInterface>,
|
||||
local: { muted: LocalStorage }
|
||||
};
|
||||
|
||||
constructor(token: string, options?: eris.ClientOptions) {
|
||||
super(token, options);
|
||||
|
@ -52,10 +73,9 @@ export default class Client extends eris.Client {
|
|||
this.events = new Collection<Event>();
|
||||
this.intervals = new Collection<NodeJS.Timeout>();
|
||||
this.queue = new Queue(this);
|
||||
this.db = { Customer, CustomerPortal, ExecutiveOrder, File, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Promo, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } };
|
||||
this.db = { Customer, CustomerPortal, ExecutiveOrder, File, Member, Merchant, Moderation, Motion, NNTrainingData, Note, PagerNumber, Promo, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } };
|
||||
}
|
||||
|
||||
|
||||
public async loadDatabase() {
|
||||
await mongoose.connect(this.config.mongoDB, { useNewUrlParser: true, useUnifiedTopology: true, poolSize: 50 });
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@ export default class Util {
|
|||
}
|
||||
return `${(bytes / 1024 ** i).toFixed(2)} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
|
||||
public async exec(command: string, _options: childProcess.ExecOptions = {}): Promise<string> {
|
||||
const ex = promisify(childProcess.exec);
|
||||
|
@ -105,7 +104,7 @@ export default class Util {
|
|||
* @param query Command input
|
||||
* @param message Only used to check for errors
|
||||
*/
|
||||
public resolveCommand(query: string | string[], message?: Message): Promise<{cmd: Command, args: string[] }> {
|
||||
public resolveCommand(query: string | string[], message?: Message): Promise<{ cmd: Command, args: string[] }> {
|
||||
try {
|
||||
let resolvedCommand: Command;
|
||||
if (typeof query === 'string') query = query.split(' ');
|
||||
|
@ -195,7 +194,7 @@ export default class Util {
|
|||
|
||||
public splitFields(fields: { name: string, value: string, inline?: boolean }[]): { name: string, value: string, inline?: boolean }[][] {
|
||||
let index = 0;
|
||||
const array: {name: string, value: string, inline?: boolean}[][] = [[]];
|
||||
const array: { name: string, value: string, inline?: boolean }[][] = [[]];
|
||||
while (fields.length) {
|
||||
if (array[index].length >= 25) { index += 1; array[index] = []; }
|
||||
array[index].push(fields[0]); fields.shift();
|
||||
|
|
|
@ -38,7 +38,7 @@ export default class Apply extends Command {
|
|||
validation: (member: Member) => member.roles.includes('546457886440685578'),
|
||||
func: async (client: Client, ...data: any[]) => {
|
||||
const member = await client.guilds.get(client.config.guildID).getRESTMember(data[0]);
|
||||
const ax = <AxiosStatic> require('axios');
|
||||
const ax = <AxiosStatic>require('axios');
|
||||
await ax({
|
||||
method: 'get',
|
||||
url: `https://api.cloud.libraryofcode.org/wh/t2?userID=${member.id}&auth=${client.config.internalKey}`,
|
||||
|
|
|
@ -23,7 +23,7 @@ export default class Billing_T3 extends Command {
|
|||
emailAddress?: string,
|
||||
tier?: number,
|
||||
supportKey?: string,
|
||||
}> (await axios.get(`https://api.cloud.libraryofcode.org/wh/info?id=${message.author.id}&authorization=${this.client.config.internalKey}`)).data;
|
||||
}>(await axios.get(`https://api.cloud.libraryofcode.org/wh/info?id=${message.author.id}&authorization=${this.client.config.internalKey}`)).data;
|
||||
if (!response.found) return this.error(message.channel, 'CS Account not found.');
|
||||
|
||||
const customer = await this.client.db.Customer.findOne({ userID: message.author.id });
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* eslint-disable no-await-in-loop */
|
||||
import type { TextChannel } from 'eris';
|
||||
import { Client, RichEmbed } from '../class';
|
||||
|
||||
export default (client: Client) => {
|
||||
const interval = setInterval(async () => {
|
||||
const motions = await client.db.Motion.find({ processed: false });
|
||||
const directorLogs = <TextChannel>client.getChannel('807444198969835550');
|
||||
|
||||
for (const motion of motions) {
|
||||
const motionMessage = await directorLogs.getMessage(motion.motionMessage);
|
||||
|
||||
if ((Date.now() - motionMessage.createdAt) > 86400) {
|
||||
const yea = await motionMessage.getReaction(client.util.emojis.SUCCESS);
|
||||
const nay = await motionMessage.getReaction(client.util.emojis.ERROR);
|
||||
const present = yea.length + nay.length;
|
||||
const totalDirectors = 5;
|
||||
const absent = totalDirectors - present;
|
||||
|
||||
await client.db.Motion.updateOne({ oID: motion.oID }, {
|
||||
processed: true,
|
||||
voteResults: {
|
||||
yea: yea.length,
|
||||
nay: nay.length,
|
||||
present,
|
||||
absent,
|
||||
},
|
||||
});
|
||||
|
||||
const directorDiscord = client.users.get(motion.issuedBy);
|
||||
const directorProfile = await client.db.Staff.findOne({ userID: motion.issuedBy });
|
||||
|
||||
const embed = new RichEmbed();
|
||||
embed.setAuthor(`${directorDiscord.username}#${directorDiscord.discriminator}, ${directorProfile.pn.join(', ')}`, directorDiscord.avatarURL);
|
||||
embed.setFooter(`${directorProfile.position} | Library of Code sp-us | Board of Directors`, 'https://static.libraryofcode.org/loccommunityadmin.png');
|
||||
let colour;
|
||||
if (yea.length > nay.length) colour = '#27b17a';
|
||||
else if (yea.length === nay.length) colour = '#ffb34d';
|
||||
else colour = '#ff474a';
|
||||
embed.setColor(colour);
|
||||
embed.addField('Motion ID', motion.oID);
|
||||
embed.addField('Result', `- **Yea:** ${yea.length}\n**Nay:** ${nay.length}\n**Present:** ${present}\n**Absent:** ${absent}\n**Total:** ${present + absent}`);
|
||||
embed.setTimestamp();
|
||||
|
||||
await directorLogs.createMessage({ content: directorDiscord.mention, embed });
|
||||
}
|
||||
}
|
||||
}, 300000);
|
||||
|
||||
return interval;
|
||||
};
|
|
@ -13,7 +13,7 @@ const ExecutiveOrder = new Schema({
|
|||
subject: { type: String, required: true },
|
||||
body: { type: String, required: true },
|
||||
at: { type: Date, required: true },
|
||||
oID: { type: String, required: true, unique: true }
|
||||
oID: { type: String, required: true, unique: true },
|
||||
});
|
||||
|
||||
export default model<ExecutiveOrderInterface>('ExecutiveOrders', ExecutiveOrder);
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import { Document, model, Schema } from 'mongoose';
|
||||
|
||||
export interface MotionInterface extends Document {
|
||||
issuedBy: string;
|
||||
subject: string;
|
||||
body: string;
|
||||
at: Date;
|
||||
oID: string;
|
||||
voteResults: {
|
||||
yea: number;
|
||||
nay: number;
|
||||
present: number;
|
||||
absent: number;
|
||||
};
|
||||
motionMessage: string;
|
||||
}
|
||||
|
||||
const Motion = new Schema({
|
||||
issuedBy: { 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 },
|
||||
voteResults: {
|
||||
yea: Number,
|
||||
Nay: Number,
|
||||
present: Number,
|
||||
absent: Number,
|
||||
},
|
||||
motionMessage: { type: String, required: true, unique: true },
|
||||
processed: Boolean,
|
||||
});
|
||||
|
||||
export default model<MotionInterface>('Motions', Motion);
|
|
@ -5,6 +5,7 @@ export { default as File, FileInterface } from './File';
|
|||
export { default as Member, MemberInterface } from './Member';
|
||||
export { default as Merchant, MerchantInterface } from './Merchant';
|
||||
export { default as Moderation, ModerationInterface } from './Moderation';
|
||||
export { default as Motion, MotionInterface } from './Motion';
|
||||
export { default as NNTrainingData, NNTrainingDataInterface } from './NNTrainingData';
|
||||
export { default as Note, NoteInterface } from './Note';
|
||||
export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber';
|
||||
|
|
Loading…
Reference in New Issue