mirror of
https://github.com/danbulant/Shasha
synced 2026-05-19 12:08:56 +00:00
531 lines
No EOL
21 KiB
JavaScript
531 lines
No EOL
21 KiB
JavaScript
'use strict';
|
|
|
|
const { Structures, Guild, GuildMember, BanOptions } = require("discord.js"),
|
|
{ database } = require("../database/mongo"),
|
|
{ errLog, defaultEventLogEmbed, defaultDateFormat, trySend } = require("./functions");
|
|
const { createSchedule } = require("../cmds/moderation/src/createSchedule");
|
|
const { TimedPunishment } = require("./classes");
|
|
const col = database.collection("Schedule");
|
|
|
|
Structures.extend("Guild", u => {
|
|
return class Guild extends u {
|
|
constructor(client, data) {
|
|
super(client, data);
|
|
}
|
|
|
|
async dbLoad() {
|
|
return database.collection("Guild").findOne({ document: this.id }).then((r, e) => {
|
|
if (e) return errLog(e, null, this.client);
|
|
if (!r) r = {};
|
|
if (!r.eventChannels) r.eventChannels = {};
|
|
if (!r.settings) r.settings = {};
|
|
if (!r.cached) r.cached = {};
|
|
let infractions = new Map(),
|
|
timedPunishments = new Map();
|
|
if (r.infractions)
|
|
for (const U in r.infractions) {
|
|
infractions.set(U, r.infractions[U]);
|
|
}
|
|
if (r.timedPunishments)
|
|
for (const U in r.timedPunishments) {
|
|
const tr = new TimedPunishment(r.timedPunishments[U]);
|
|
tr.setDataDuration(tr.duration.invoked, tr.duration.until);
|
|
timedPunishments.set(tr.userID + "/" + tr.type, tr);
|
|
}
|
|
r.infractions = infractions;
|
|
r.timedPunishments = timedPunishments;
|
|
// console.log("DB LOADED FOR GUILD:", this.name, this.id);
|
|
return this.DB = r;
|
|
});
|
|
}
|
|
|
|
async setDb(query, set) {
|
|
return database.collection("Guild").updateOne({ document: this.id }, { $set: { [query]: set }, $setOnInsert: { document: this.id } },
|
|
{ upsert: true }).then((r, e) => {
|
|
if (e) return errLog(e, null, this.client);
|
|
return this.DB[query] = set;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get user infractions
|
|
* @param {string} userID - User ID
|
|
* @returns {object[]} Array of infractions objects
|
|
*/
|
|
getInfractions(userID) {
|
|
let ret = []
|
|
for (const [k, v] of this.DB.infractions)
|
|
if (v.by.map(r => r.id).includes(userID)) ret.push(v);
|
|
return ret;
|
|
}
|
|
|
|
async addInfraction(add) {
|
|
try {
|
|
if (!this.DB) await this.dbLoad();
|
|
console.log("SETTING INF");
|
|
const ret = this.DB.infractions.set(add.moderator.id + "/" + add.infraction, add);
|
|
await this.setDb("infractions", this.DB.infractions);
|
|
return ret;
|
|
} catch (e) { }
|
|
}
|
|
|
|
async setQuoteOTD(set) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.quoteOTD = set;
|
|
return this.setDb("quoteOTD", this.DB.quoteOTD);
|
|
}
|
|
|
|
async setEventChannels(set) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.eventChannels = set;
|
|
return this.setDb("eventChannels", this.DB.eventChannels);
|
|
}
|
|
|
|
async setDefaultEmbed(set) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.defaultEmbed = set;
|
|
return this.setDb("defaultEmbed", this.DB.defaultEmbed);
|
|
}
|
|
|
|
async setModerationSettings(set) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.settings = set;
|
|
return this.setDb("settings", this.DB.settings);
|
|
}
|
|
|
|
/**
|
|
* @param {TimedPunishment} Punishment
|
|
* @returns {Map}
|
|
*/
|
|
async setTimedPunishment(Punishment) {
|
|
console.log("SET TIMED PUNISHMENT");
|
|
const ret = this.DB.timedPunishments.set(Punishment.userID + "/" + Punishment.type, Punishment);
|
|
await this.setDb("timedPunishments", this.DB.timedPunishments);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @param {string} userID
|
|
* @param {"mute"|"ban"} type
|
|
* @returns
|
|
*/
|
|
getTimedPunishment(userID, type) {
|
|
console.log("GET TIMEDPUNISHMENT");
|
|
return this.DB.timedPunishments.get(userID + "/" + type);
|
|
}
|
|
|
|
/**
|
|
* @param {string} userID
|
|
* @returns {object[]}
|
|
*/
|
|
searchTimedPunishment(userID) {
|
|
let ret = [];
|
|
for (const [k, v] of this.DB.timedPunishments) if (v.userID === userID) ret.push(v);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} userID
|
|
* @param {"mute"|"ban"} type
|
|
* @returns {boolean}
|
|
*/
|
|
async removeTimedPunishment(userID, type) {
|
|
const ret = this.DB.timedPunishments.delete(userID + "/" + type);
|
|
await this.setDb("timedPunishments", this.DB.timedPunishments);
|
|
await require("../cmds/moderation/src/createSchedule").jobManager?.stop([this.id, userID, type].join("/")).catch(() => { });
|
|
await require("../cmds/moderation/src/createSchedule").jobManager?.remove([this.id, userID, type].join("/")).catch(() => { });
|
|
console.log("REMOVED TIMEDPUNISHMENT");
|
|
return ret;
|
|
}
|
|
|
|
async setCached(key, value) {
|
|
this.DB.cached[key] = value;
|
|
await this.setDb("cached", this.DB.cached);
|
|
console.log("SET CACHED", key, value);
|
|
return this.DB.cached;
|
|
}
|
|
|
|
getCached(key) {
|
|
return this.DB.cached[key];
|
|
}
|
|
|
|
async updateCached(key, value) {
|
|
const cached = this.getCached(key);
|
|
if (cached === value) return false;
|
|
console.log("UPDATE CACHED", key, cached);
|
|
return this.setCached(key, value);
|
|
}
|
|
}
|
|
});
|
|
|
|
Structures.extend("User", u => {
|
|
return class User extends u {
|
|
constructor(client, data) {
|
|
super(client, data);
|
|
this.cutie = true;
|
|
}
|
|
|
|
async dbLoad() {
|
|
return database.collection("User").findOne({ document: this.id }).then((r, e) => {
|
|
if (e) return errLog(e, null, this.client);
|
|
if (!r) r = {};
|
|
if (!r.F) r.F = "<:pepewhysobLife:853237646666891274>";
|
|
if (!r.cachedAvatarURL) r.cachedAvatarURL = this.displayAvatarURL({ format: "png", size: 4096, dynamic: true });
|
|
if (!r.interactions) r.interactions = {};
|
|
// console.log("DB LOADED FOR USER:", this.tag, this.id);
|
|
return this.DB = r;
|
|
});
|
|
}
|
|
|
|
async setDb(query, set) {
|
|
return database.collection("User").updateOne({ document: this.id }, { $set: { [query]: set }, $setOnInsert: { document: this.id } },
|
|
{ upsert: true }).then((r, e) => {
|
|
if (e) return errLog(e, null, this.client);
|
|
return this.DB[query] = set;
|
|
});
|
|
}
|
|
|
|
async setF(string) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.F = string;
|
|
return this.setDb("F", this.DB.F);
|
|
}
|
|
|
|
async setInteractions(count) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.interactions = count;
|
|
return this.setDb("interactions", this.DB.interactions);
|
|
}
|
|
|
|
async setDescription(set) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.description = set;
|
|
return this.setDb("description", this.DB.description);
|
|
}
|
|
|
|
async setDefaultEmbed(set) {
|
|
if (!this.DB) await this.dbLoad();
|
|
this.DB.defaultEmbed = set;
|
|
return this.setDb("defaultEmbed", this.DB.defaultEmbed);
|
|
}
|
|
|
|
/**
|
|
* @param {Guild} guild
|
|
* @param {string} reason
|
|
* @param {{duration: object, saveTakenRoles: boolean, infraction: number, moderator: GuildMember}} data
|
|
*/
|
|
async mute(guild, data, reason) {
|
|
if (!guild || !(guild instanceof Guild)) throw new TypeError("Guild is: " + guild);
|
|
if (!data || !data.infraction) throw new Error("Missing infraction id");
|
|
|
|
const MEM = guild.member(this);
|
|
const CL = guild.member(this.client.user);
|
|
|
|
if (!(CL.isAdmin || CL.hasPermission("MANAGE_ROLES")) ||
|
|
!(data.moderator.isAdmin || data.moderator.hasPermission("MANAGE_ROLES"))) throw new Error("Missing Permissions");
|
|
|
|
if (MEM) {
|
|
if (data.moderator.roles.highest.position <= MEM.roles.highest.position ||
|
|
MEM.roles.highest.position >= guild.member(this.client.user).roles.highest.position)
|
|
throw new Error("You can't mute someone with higher position than you <:nekokekLife:852865942530949160>");
|
|
await MEM.mute(data, reason);
|
|
}
|
|
|
|
if (!guild.DB) await guild.dbLoad();
|
|
|
|
if (!this.bot) {
|
|
const emb = defaultEventLogEmbed(guild);
|
|
emb.setTitle("You have been muted")
|
|
.setDescription(reason || "No reason provided")
|
|
.addField("At", defaultDateFormat(data.duration.invoked), true)
|
|
.addField("Until", data.duration.until ? defaultDateFormat(data.duration.until) : "Never", true)
|
|
.addField("For", data.duration.duration?.strings.join(" ") || "Indefinite");
|
|
this.createDM().then(r => trySend(this.client, r, emb));
|
|
}
|
|
|
|
const MC = guild.getTimedPunishment(this.id, "mute"),
|
|
TP = new TimedPunishment({ userID: this.id, duration: data.duration, infraction: data.infraction, type: "mute" });
|
|
|
|
if (data.duration.until) await createSchedule(guild.client, { guildID: guild.id, userID: this.id, type: "mute", until: data.duration.until?.toJSDate() });
|
|
|
|
return { set: await guild.setTimedPunishment(TP), existing: MC }
|
|
}
|
|
|
|
/**
|
|
* @param {Guild} guild
|
|
* @param {GuildMember} moderator
|
|
* @param {string} reason
|
|
* @returns
|
|
*/
|
|
async unmute(guild, moderator, reason) {
|
|
if (!guild || !(guild instanceof Guild)) throw new TypeError("Guild is: " + guild);
|
|
const MEM = guild.member(this);
|
|
const CL = guild.member(this.client.user);
|
|
if (!(CL.isAdmin || CL.hasPermission("MANAGE_ROLES")) ||
|
|
!(moderator.isAdmin || moderator.hasPermission("MANAGE_ROLES"))) throw new Error("Missing Permissions");
|
|
if (!guild.DB) await guild.dbLoad();
|
|
|
|
if (!this.bot) {
|
|
const emb = defaultEventLogEmbed(guild);
|
|
|
|
emb.setTitle("You have been unmuted")
|
|
.setDescription(reason || "No reason provided");
|
|
|
|
this.createDM().then(r => trySend(this.client, r, emb));
|
|
}
|
|
|
|
const MC = guild.getTimedPunishment(this.id, "mute");
|
|
if (!MC) throw new Error(this.tag + " isn't muted in " + guild.name);
|
|
if (MEM) {
|
|
if (moderator.roles.highest.position < MEM.roles.highest.position ||
|
|
MEM.roles.highest.position > CL.roles.highest.position)
|
|
throw new Error("You can't mute someone with higher position than you <:nekokekLife:852865942530949160>");
|
|
await MEM.unmute(reason);
|
|
}
|
|
await col.deleteOne({ document: [guild.id, this.id, "mute"].join("/") }).then(() => console.log("SCHEDULE " + [guild.id, this.id, "mute"].join("/") + " DELETED")).catch(e => errLog(e, null, client));
|
|
return guild.removeTimedPunishment(this.id, "mute");
|
|
}
|
|
|
|
/**
|
|
* @param {Guild} guild
|
|
* @param {{duration: object, infraction: number, moderator: GuildMember}} data
|
|
* @param {BanOptions} option
|
|
*/
|
|
async ban(guild, data, option) {
|
|
if (!guild || !(guild instanceof Guild)) throw new TypeError("Guild is: " + guild);
|
|
if (!data || !data.infraction) throw new Error("Missing infraction id");
|
|
const MEM = guild.member(this);
|
|
const CL = guild.member(this.client.user);
|
|
if (!(CL.isAdmin || CL.hasPermission("BAN_MEMBERS")) ||
|
|
!(data.moderator.isAdmin || data.moderator.hasPermission("BAN_MEMBERS"))) throw new Error("Missing Permissions");
|
|
if (MEM) {
|
|
if (data.moderator.roles.highest.position <= MEM.roles.highest.position ||
|
|
MEM.roles.highest.position >= CL.roles.highest.position)
|
|
throw new Error("You can't ban someone with higher position than you <:nekokekLife:852865942530949160>");
|
|
}
|
|
if (!guild.DB) await guild.dbLoad();
|
|
|
|
if (!this.bot) {
|
|
const emb = defaultEventLogEmbed(guild);
|
|
emb.setTitle("You have been banned")
|
|
.setDescription(option.reason || "No reason provided")
|
|
.addField("At", defaultDateFormat(data.duration.invoked), true)
|
|
.addField("Until", data.duration.until ? defaultDateFormat(data.duration.until) : "Never", true)
|
|
.addField("For", data.duration.duration?.strings.join(" ") || "Indefinite");
|
|
await this.createDM().then(r => trySend(this.client, r, emb));
|
|
}
|
|
let already = false, cant = false;
|
|
if (option.days > 7) option.days = 7;
|
|
await guild.members.ban(this, option);
|
|
// .catch(e => {
|
|
|
|
// });
|
|
if (data.duration.until) await createSchedule(guild.client, { guildID: guild.id, userID: this.id, type: "ban", until: data.duration.until?.toJSDate() });
|
|
|
|
const MC = guild.getTimedPunishment(this.id, "ban"),
|
|
TP = new TimedPunishment({ userID: this.id, duration: data.duration, infraction: data.infraction, type: "ban" });
|
|
|
|
return { set: await guild.setTimedPunishment(TP), existing: MC, already: already, cant: cant }
|
|
}
|
|
|
|
async unban(guild, moderator, reason) {
|
|
if (!guild || !(guild instanceof Guild)) throw new TypeError("Guild is: " + guild);
|
|
const CL = guild.member(this.client.user);
|
|
if (!moderator.isAdmin || !CL.isAdmin) throw new Error("Missing permissions");
|
|
let already = false, cant = false;
|
|
await guild.members.unban(this, reason).catch(e => {
|
|
if (!/Unknown Ban/.test(e.message)) {
|
|
throw new Error(e.message);
|
|
};
|
|
});
|
|
// .catch(e => {
|
|
|
|
// });
|
|
if (!guild.DB) await guild.DB.dbLoad();
|
|
|
|
if (!this.bot) {
|
|
const emb = defaultEventLogEmbed(guild);
|
|
|
|
emb.setTitle("You have been unbanned")
|
|
.setDescription(reason || "No reason provided");
|
|
this.createDM().then(r => trySend(this.client, r, emb));
|
|
}
|
|
await col.deleteOne({ document: [guild.id, this.id, "ban"].join("/") }).then(() => console.log("SCHEDULE " + [guild.id, this.id, "ban"].join("/") + " DELETED")).catch(e => errLog(e, null, client));
|
|
return { set: await guild.removeTimedPunishment(this.id, "ban"), already: already, cant: cant };
|
|
}
|
|
}
|
|
});
|
|
|
|
Structures.extend("TextChannel", u => {
|
|
return class TextChannel extends u {
|
|
constructor(guild, data) {
|
|
super(guild, data);
|
|
this.lastMessagesID = [];
|
|
};
|
|
|
|
pushLastMessagesID() {
|
|
if (this.lastMessagesID.length === 3) {
|
|
this.lastMessagesID.shift();
|
|
};
|
|
return this.lastMessagesID.push(this.lastMessageID);
|
|
};
|
|
}
|
|
});
|
|
|
|
Structures.extend("DMChannel", u => {
|
|
return class DMChannel extends u {
|
|
constructor(client, data) {
|
|
super(client, data);
|
|
this.lastMessagesID = [];
|
|
};
|
|
|
|
pushLastMessagesID() {
|
|
if (this.lastMessagesID.length === 3) {
|
|
this.lastMessagesID.shift();
|
|
};
|
|
return this.lastMessagesID.push(this.lastMessageID);
|
|
};
|
|
}
|
|
});
|
|
|
|
Structures.extend("NewsChannel", u => {
|
|
return class NewsChannel extends u {
|
|
constructor(guild, data) {
|
|
super(guild, data);
|
|
this.lastMessagesID = [];
|
|
};
|
|
|
|
pushLastMessagesID() {
|
|
if (this.lastMessagesID.length === 3) {
|
|
this.lastMessagesID.shift();
|
|
};
|
|
return this.lastMessagesID.push(this.lastMessageID);
|
|
};
|
|
}
|
|
});
|
|
|
|
Structures.extend("StoreChannel", u => {
|
|
return class StoreChannel extends u {
|
|
constructor(guild, data) {
|
|
super(guild, data);
|
|
this.lastMessagesID = [];
|
|
};
|
|
|
|
pushLastMessagesID() {
|
|
if (this.lastMessagesID.length === 3) {
|
|
this.lastMessagesID.shift();
|
|
};
|
|
return this.lastMessagesID.push(this.lastMessageID);
|
|
};
|
|
}
|
|
});
|
|
|
|
Structures.extend("Message", e => {
|
|
return class Message extends e {
|
|
constructor(client, data, channel) {
|
|
super(client, data, channel);
|
|
this.previousMessageID = channel.lastMessageID;
|
|
};
|
|
|
|
setInvoker(user) {
|
|
return this.invoker = user;
|
|
};
|
|
};
|
|
});
|
|
|
|
Structures.extend("GuildMember", u => {
|
|
return class GuildMember extends u {
|
|
constructor(client, data, guild) {
|
|
super(client, data, guild);
|
|
}
|
|
|
|
async dbLoad() {
|
|
return database.collection("GuildMember").findOne({ document: this.guild.id + "/" + this.id }).then((r, e) => {
|
|
if (e) return errLog(e, null, this.client);
|
|
if (!r) r = {};
|
|
// console.log("DB LOADED FOR MEMBER:", this.user.tag, this.id, this.guild.name, this.guild.id);
|
|
return this.DB = r;
|
|
});
|
|
}
|
|
|
|
async setDb(query, set) {
|
|
return database.collection("GuildMember").updateOne({ document: this.guild.id + "/" + this.id }, { $set: { [query]: set }, $setOnInsert: { document: this.guild.id + "/" + this.id } },
|
|
{ upsert: true }).then((r, e) => {
|
|
if (e) return errLog(e, null, this.client);
|
|
return this.DB[query] = set;
|
|
});
|
|
}
|
|
|
|
get infractions() {
|
|
return this.guild.getInfractions(this.id);
|
|
}
|
|
|
|
/**
|
|
* @param {{duration: object, saveTakenRoles: boolean, infraction: number}} data
|
|
* @param {string} reason
|
|
* @returns
|
|
*/
|
|
async mute(data, reason) {
|
|
if (!this.DB) await this.dbLoad();
|
|
if (!data || !data.infraction) throw new Error("Missing infraction id");
|
|
if (!this.DB.muted) this.DB.muted = {};
|
|
if (data.saveTakenRoles === undefined) data.saveTakenRoles = !(this.DB.muted.takenRoles?.length);
|
|
|
|
const ROLES = this.roles.cache.filter((r) => !r.managed).map(r => r.id);
|
|
if (data.saveTakenRoles && ROLES?.length) {
|
|
console.log("POPULATING TAKEN ROLES BEFORE MUTE");
|
|
this.DB.muted.takenRoles = ROLES;
|
|
}
|
|
this.DB.muted.muteRole = this.guild.DB.settings.mute.role;
|
|
|
|
try {
|
|
if (ROLES?.length) await this.roles.remove(ROLES, reason);
|
|
await this.roles.add(this.DB.muted.muteRole, reason);
|
|
if (!this.DB.muted.takenRoles) this.DB.muted.takenRoles = [];
|
|
await this.setDb("muted", this.DB.muted);
|
|
return true;
|
|
} catch (e) {
|
|
if (this.DB.muted.takenRoles?.length) await this.roles.add(this.DB.muted.takenRoles, reason).catch(() => { });
|
|
if (this.DB.muted.muteRole) await this.roles.remove(this.DB.muted.muteRole, reason).catch(() => { });
|
|
console.log("CLEAR TAKEN ROLES MUTE ERROR");
|
|
this.DB.muted.takenRoles = [];
|
|
this.DB.muted.muteRole = undefined;
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
async unmute(reason) {
|
|
if (!this.DB) await this.dbLoad();
|
|
try {
|
|
if (this.DB.muted.takenRoles.length) await this.roles.add(this.DB.muted.takenRoles, reason);
|
|
if (this.DB.muted.muteRole) await this.roles.remove(this.DB.muted.muteRole, reason);
|
|
console.log("CLEAR TAKEN ROLES UNMUTE");
|
|
this.DB.muted.takenRoles = [];
|
|
this.DB.muted.muteRole = undefined;
|
|
await this.setDb("muted", this.DB.muted);
|
|
return true;
|
|
} catch (e) {
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string[]} roles
|
|
*/
|
|
async setLeaveRoles(roles = []) {
|
|
if (!this.DB) await this.dbLoad();
|
|
const kicked = (await this.guild.fetchAuditLogs({ "limit": 1, "type": "MEMBER_KICK" }).catch(() => { }))?.entries?.first();
|
|
if (kicked?.target.id === this.id) {
|
|
// console.log("KICKED:", true);
|
|
return;
|
|
}
|
|
const banned = await this.guild.fetchBan(this.user).catch(() => { });
|
|
// console.log("BANNED:", banned ? true : false);
|
|
if (banned) return;
|
|
return this.setDb("leaveRoles", roles);
|
|
}
|
|
|
|
get isAdmin() { if (!this.client.owners.includes(this.user)) return this.hasPermission("ADMINISTRATOR"); else return true }
|
|
}
|
|
}); |