'use strict'; const coreClass = require("../core"); const async = require('async'); const mongoose = require('mongoose'); module.exports = class extends coreClass { constructor(name, moduleManager) { super(name, moduleManager); this.dependsOn = ["cache", "db", "utils"]; } initialize() { return new Promise((resolve, reject) => { this.setStage(1); this.cache = this.moduleManager.modules['cache']; this.db = this.moduleManager.modules['db']; this.io = this.moduleManager.modules['io']; this.utils = this.moduleManager.modules['utils']; async.waterfall([ (next) => { this.setStage(2); this.cache.hgetall('punishments', next); }, (punishments, next) => { this.setStage(3); if (!punishments) return next(); let punishmentIds = Object.keys(punishments); async.each(punishmentIds, (punishmentId, next) => { this.db.models.punishment.findOne({_id: punishmentId}, (err, punishment) => { if (err) next(err); else if (!punishment) this.cache.hdel('punishments', punishmentId, next); else next(); }); }, next); }, (next) => { this.setStage(4); this.db.models.punishment.find({}, next); }, (punishments, next) => { this.setStage(5); async.each(punishments, (punishment, next) => { if (punishment.active === false || punishment.expiresAt < Date.now()) return next(); this.cache.hset('punishments', punishment._id, this.cache.schemas.punishment(punishment, punishment._id), next); }, next); } ], async (err) => { if (err) { err = await utils.getError(err); reject(err); } else { resolve(); } }); }); } /** * Gets all punishments in the cache that are active, and removes those that have expired * * @param {Function} cb - gets called once we're done initializing */ async getPunishments(cb) { try { await this._validateHook(); } catch { return; } let punishmentsToRemove = []; async.waterfall([ (next) => { this.cache.hgetall('punishments', next); }, (punishmentsObj, next) => { let punishments = []; for (let id in punishmentsObj) { let obj = punishmentsObj[id]; obj.punishmentId = id; punishments.push(obj); } punishments = punishments.filter(punishment => { if (punishment.expiresAt < Date.now()) punishmentsToRemove.push(punishment); return punishment.expiresAt > Date.now(); }); next(null, punishments); }, (punishments, next) => { async.each( punishmentsToRemove, (punishment, next2) => { this.cache.hdel('punishments', punishment.punishmentId, () => { next2(); }); }, () => { next(null, punishments); } ); } ], (err, punishments) => { if (err && err !== true) return cb(err); cb(null, punishments); }); } /** * Gets a punishment by id * * @param {String} id - the id of the punishment we are trying to get * @param {Function} cb - gets called once we're done initializing */ async getPunishment(id, cb) { try { await this._validateHook(); } catch { return; } async.waterfall([ (next) => { if (!mongoose.Types.ObjectId.isValid(id)) return next('Id is not a valid ObjectId.'); this.cache.hget('punishments', id, next); }, (punishment, next) => { if (punishment) return next(true, punishment); this.db.models.punishment.findOne({_id: id}, next); }, (punishment, next) => { if (punishment) { this.cache.hset('punishments', id, punishment, next); } else next('Punishment not found.'); }, ], (err, punishment) => { if (err && err !== true) return cb(err); cb(null, punishment); }); } /** * Gets all punishments from a userId * * @param {String} userId - the userId of the punishment(s) we are trying to get * @param {Function} cb - gets called once we're done initializing */ async getPunishmentsFromUserId(userId, cb) { try { await this._validateHook(); } catch { return; } async.waterfall([ (next) => { this.getPunishments(next); }, (punishments, next) => { punishments = punishments.filter((punishment) => { return punishment.type === 'banUserId' && punishment.value === userId; }); next(null, punishments); } ], (err, punishments) => { if (err && err !== true) return cb(err); cb(null, punishments); }); } async addPunishment(type, value, reason, expiresAt, punishedBy, cb) { try { await this._validateHook(); } catch { return; } async.waterfall([ (next) => { const punishment = new this.db.models.punishment({ type, value, reason, active: true, expiresAt, punishedAt: Date.now(), punishedBy }); punishment.save((err, punishment) => { if (err) return next(err); next(null, punishment); }); }, (punishment, next) => { this.cache.hset('punishments', punishment._id, this.cache.schemas.punishment(punishment, punishment._id), (err) => { next(err, punishment); }); }, (punishment, next) => { // DISCORD MESSAGE next(null, punishment); } ], (err, punishment) => { cb(err, punishment); }); } async removePunishmentFromCache(punishmentId, cb) { try { await this._validateHook(); } catch { return; } async.waterfall([ (next) => { const punishment = new this.db.models.punishment({ type, value, reason, active: true, expiresAt, punishedAt: Date.now(), punishedBy }); punishment.save((err, punishment) => { console.log(err); if (err) return next(err); next(null, punishment); }); }, (punishment, next) => { this.cache.hset('punishments', punishment._id, punishment, next); }, (punishment, next) => { // DISCORD MESSAGE next(); } ], (err) => { cb(err); }); } }