mirror of
https://github.com/danbulant/Shasha
synced 2026-06-18 05:41:19 +00:00
Plan: Move user punishments to guild
This commit is contained in:
parent
bf43f30da9
commit
2bd1774e4f
13 changed files with 135 additions and 66 deletions
63
cmds/moderation/ban.js
Normal file
63
cmds/moderation/ban.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
'use strict';
|
||||
|
||||
const commando = require("@iceprod/discord.js-commando");
|
||||
const { Message } = require("discord.js");
|
||||
const { DateTime } = require("luxon");
|
||||
const { parseDoubleDash, trySend } = require("../../resources/functions");
|
||||
const { duration, CHECK_FOR_DURATION_REGEXP } = require("./src/duration");
|
||||
const targetUser = require("./src/targetUser");
|
||||
|
||||
module.exports = class ban extends commando.Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: "ban",
|
||||
memberName: "ban",
|
||||
group: "moderation",
|
||||
description: "Ban pesky troll and toxic members",
|
||||
guildOnly: true,
|
||||
userPermissions: ["BAN_MEMBERS"],
|
||||
clientPermissions: ["BAN_MEMBERS"],
|
||||
details: "Args: `user_[name|mention|ID] -- [reason] -- [duration] [--d [number of days to delete messages of the user to ban]]`",
|
||||
examples: ["some user name, some user tag -- 10d76y8m99mo6h70w -- sending unsolicited cakes in DM --d 5"]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Message} msg
|
||||
* @param {*} arg
|
||||
* @returns
|
||||
*/
|
||||
async run(msg, arg) {
|
||||
const args = parseDoubleDash(arg),
|
||||
target = args?.shift();
|
||||
let reason = "No reason provided", pDuration = {}, execTarget = [], resultMsg = "", daysToDeleteMessage = 0;
|
||||
|
||||
if (!target || target.length < 1) return trySend(msg.client, msg, this.description); else {
|
||||
const ET = await targetUser(msg, target);
|
||||
execTarget = ET.targetUser;
|
||||
resultMsg = ET.resultMsg;
|
||||
}
|
||||
|
||||
if (args?.[1]) {
|
||||
for (const ARG of args) {
|
||||
if (ARG === "--" || ARG.trim().length < 1) continue;
|
||||
if (ARG.startsWith("d ")) {
|
||||
const U = ARG.slice(2).trim();
|
||||
if (U.length > 0 && !/\D/.test(U)) daysToDeleteMessage = parseInt(U, 10); else return trySend(msg.client, msg, "Invalid number of days to delete messages!");
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_FOR_DURATION_REGEXP.test(ARG.trim()))
|
||||
pDuration = duration(msg.editedAt || msg.createdAt, ARG.trim()); else reason = ARG.trim();
|
||||
}
|
||||
}
|
||||
|
||||
if (!pDuration.invoked) pDuration.invoked = DateTime.fromJSDate(msg.editedAt || msg.createdAt);
|
||||
|
||||
if (execTarget.length > 0) {
|
||||
for (const U of execTarget) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ const durationFn = fn.duration;
|
|||
const targetUser = require("./src/targetUser");
|
||||
const configureMuteRole = require("./src/configureMuteRole");
|
||||
const { makeJSONMessage } = require("../../resources/debug");
|
||||
const createInfraction = require("./src/createInfraction");
|
||||
Settings.defaultZone = "utc";
|
||||
|
||||
/*{
|
||||
|
|
@ -82,12 +83,13 @@ module.exports = class mute extends commando.Command {
|
|||
|
||||
if (args?.[1]) {
|
||||
for (const ARG of args) {
|
||||
if (ARG === "--" || ARG.trim().length < 1) continue;
|
||||
const U = ARG.slice(2).trim();
|
||||
if (/^cmr(\s|$)/.test(ARG)) return configureMuteRole(msg, ARG.slice(3).trim());
|
||||
if (/^s(\s|$)/.test(ARG)) return muteSetting(msg, U);
|
||||
if (/^[\-\+]?\d{1,16}(?![^ymwdhs])[ymwdhs]?o?/i.test(ARG.trim())) {
|
||||
if (fn.CHECK_FOR_DURATION_REGEXP.test(ARG.trim())) {
|
||||
duration = durationFn(msg.editedAt || msg.createdAt, ARG.trim());
|
||||
} else if (!ARG || ARG === "--" || ARG.trim().length === 0) continue; else reason = ARG.trim();
|
||||
} else reason = ARG.trim();
|
||||
}
|
||||
} else if (!MUTE.role || !msg.guild.roles.cache.get(MUTE.role)) {
|
||||
return trySend(this.client, msg, `No mute role configured!\n\n**[ADMINISTRATOR]**\nRun \`${msg.guild.commandPrefix + this.name} --s -r role_[name|ID|mention] -d [duration]\` to set it up.\n` +
|
||||
|
|
@ -110,19 +112,8 @@ module.exports = class mute extends commando.Command {
|
|||
resultMsg = FR.resultMsg;
|
||||
} else return trySend(this.client, msg, "Args: `<[user_[mention|ID|name]]> -- [reason] -- [duration]`. Use `,` to provide multiple user. `--s` to view settings.\nExample:```js\n" + `${msg.guild.commandPrefix + this.name} 580703409934696449, @Shasha#1234, ur mom,#6969,^yuck\\s(ur)?\\s.{5}#\\d+69$--69y69mo69w420d420h420m420s -- Saying "joe"\`\`\``);
|
||||
|
||||
let infractionToDoc;
|
||||
if (targetUsers.length > 0) {
|
||||
let infractionCase = msg.guild.DB.moderation.infractions?.length,
|
||||
muted = [], cant = [], already = [], infractionN = [];
|
||||
|
||||
infractionToDoc = {
|
||||
infraction: infractionCase ? infractionCase++ : 1,
|
||||
by: targetUsers,
|
||||
moderator: msg.author,
|
||||
punishment: "mute",
|
||||
reason: reason,
|
||||
msg: msg.toJSON()
|
||||
}
|
||||
let muted = [], cant = [], already = [], infractionN = [];
|
||||
|
||||
for (const EXEC of targetUsers) {
|
||||
try {
|
||||
|
|
@ -142,12 +133,13 @@ module.exports = class mute extends commando.Command {
|
|||
EXEC.createDM().then(r => trySend(msg.client, r, emb));
|
||||
}
|
||||
|
||||
if (muted.length > 0) {
|
||||
infractionToDoc.executed = muted;
|
||||
infractionToDoc.aborted = already;
|
||||
infractionToDoc.failed = cant;
|
||||
msg.guild.addInfraction(infractionToDoc);
|
||||
}
|
||||
let infractionToDoc = createInfraction(msg, targetUsers, "mute", reason);
|
||||
|
||||
infractionToDoc.executed = muted;
|
||||
infractionToDoc.aborted = already;
|
||||
infractionToDoc.failed = cant;
|
||||
|
||||
if (muted.length > 0) msg.guild.addInfraction(infractionToDoc);
|
||||
|
||||
const NAME = msg.guild.id + "/" + infractionToDoc.infraction,
|
||||
newUnmuteSchedule = {
|
||||
|
|
|
|||
21
cmds/moderation/src/createInfraction.js
Normal file
21
cmds/moderation/src/createInfraction.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
const { Message, User } = require("discord.js");
|
||||
|
||||
/**
|
||||
* @param {Message} msg
|
||||
* @param {User[]} targetUsers
|
||||
* @param {["ban"|"mute"|"kick"|"strike"]} punishment
|
||||
* @param {string} reason
|
||||
*/
|
||||
module.exports = (msg, targetUsers, punishment, reason) => {
|
||||
let infractionCase = msg.guild.DB.moderation.infractions?.length;
|
||||
return {
|
||||
infraction: infractionCase ? infractionCase++ : 1,
|
||||
by: targetUsers,
|
||||
moderator: msg.author,
|
||||
punishment: punishment,
|
||||
reason: reason,
|
||||
msg: msg.toJSON()
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
const { DateTime, Settings, Interval } = require("luxon"),
|
||||
DURATION_REGEXP = /[\-]?\d+(?![^ymwdhs])[ymwdhs]?o?/gi,
|
||||
DT_PRINT_FORMAT = "DDD'\n'cccc',' tt";
|
||||
DT_PRINT_FORMAT = "DDD'\n'cccc',' tt",
|
||||
CHECK_FOR_DURATION_REGEXP = /^[\-\+]?\d{1,16}(?![^ymwdhs])[ymwdhs]?o?/i;
|
||||
|
||||
Settings.defaultZone = "utc";
|
||||
/**
|
||||
|
|
@ -90,4 +91,4 @@ function duration(base, string) {
|
|||
return { invoked: DT_INVOKED, until: DT_END, interval: DT_INTERVAL, duration: intervalToDuration(DT_INTERVAL) }
|
||||
}
|
||||
|
||||
module.exports = { duration, DT_PRINT_FORMAT, intervalToDuration }
|
||||
module.exports = { duration, DT_PRINT_FORMAT, intervalToDuration, DURATION_REGEXP, CHECK_FOR_DURATION_REGEXP }
|
||||
|
|
@ -10,7 +10,7 @@ const { cleanMentionID, findMemberRegEx } = require("../../../resources/function
|
|||
* @param {string} resultMsg
|
||||
* @returns {Promise<{ targetUser: User[], resultMsg: string }>}
|
||||
*/
|
||||
module.exports = async (msg, mentions = [], targetUser = [], resultMsg) => {
|
||||
module.exports = async (msg, mentions = [], targetUser = [], resultMsg = "") => {
|
||||
if (mentions.length === 0) throw new TypeError("Mentions has no length");
|
||||
for (const usermention of mentions) {
|
||||
if (usermention.length > 0) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module.exports = class UnknownCommandCommand extends Command {
|
|||
// eslint-disable-next-line
|
||||
async run(msg) {
|
||||
if (msg.guild && !msg.member.hasPermission("MANAGE_MESSAGES")) return;
|
||||
if (new RegExp("^<@\!?" + msg.client.user.id + ">\s").test(msg.content)) {
|
||||
if (new RegExp("^<@\!?" + msg.client.user.id + ">.").test(msg.content)) {
|
||||
msg.channel.startTyping();
|
||||
const s = msg.cleanContent.slice((msg.guild ? msg.guild.member(msg.client.user).displayName.length : msg.client.user.username.length) + 2).trim();
|
||||
return trySend(msg.client, msg, await chatAnswer(s));
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ module.exports = class avatar extends commando.Command {
|
|||
});
|
||||
}
|
||||
async run(msg, arg) {
|
||||
const doc = msg.guild ?? msg.author;
|
||||
const doc = msg.guild.DB.settings || msg.author.DB;
|
||||
const footerQuote = doc.defaultEmbed?.footerQuote;
|
||||
const option = "";// || arg.match(/(?<!\\)--s +\d+/)?.[0];
|
||||
let user, avatar, member, show, notFound = "";
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
const commando = require("@iceprod/discord.js-commando");
|
||||
const { MessageEmbed, User, Message } = require("discord.js");
|
||||
const { DateTime } = require("luxon");
|
||||
const { DateTime, Interval } = require("luxon");
|
||||
const { errLog, trySend, getUser, defaultImageEmbed, splitOnLength } = require("../../resources/functions");
|
||||
const getColor = require("../../resources/getColor");
|
||||
const { DT_PRINT_FORMAT } = require("../moderation/src/duration");
|
||||
const { DT_PRINT_FORMAT, intervalToDuration } = require("../moderation/src/duration");
|
||||
|
||||
module.exports = class profile extends commando.Command {
|
||||
constructor(client) {
|
||||
|
|
@ -31,13 +31,13 @@ module.exports = class profile extends commando.Command {
|
|||
emb = defaultImageEmbed(msg, null, `\`${TM.tag}\`'s Profile`);
|
||||
emb
|
||||
.setThumbnail(TM.displayAvatarURL({ format: "png", size: 4096, dynamic: true }))
|
||||
.addField("Registered", DateTime.fromJSDate(TM.createdAt).toFormat(DT_PRINT_FORMAT), true)
|
||||
.addField("ID", TM.id, true);
|
||||
.addField("ID", TM.id)
|
||||
.addField("Registered", "<t:" + (Math.floor(TM.createdAt.valueOf() / 1000)) + ":F>");
|
||||
if (TM.description) emb.setDescription(TM.description);
|
||||
if (MEM) {
|
||||
const RI = MEM.roles.cache.sort((a, b) => b.position - a.position).map(r => r.id).slice(0, -1),
|
||||
RFS = splitOnLength(RI, 1010, ">, <@&");
|
||||
emb.addField("Joined", DateTime.fromJSDate(MEM.joinedAt).toFormat(DT_PRINT_FORMAT))
|
||||
RFS = splitOnLength(RI, 1010, ">, <@&"), INT = Interval.fromDateTimes(DateTime.fromJSDate(MEM.joinedAt), DateTime.now());
|
||||
emb.addField("Joined", "<t:" + (Math.floor(MEM.joinedAt.valueOf() / 1000)) + `:F>\n(${intervalToDuration(INT).strings.join(" ")} ago)`)
|
||||
.addField("Nick", `\`${MEM.displayName}\``);
|
||||
if (RFS[0]?.length > 0) {
|
||||
for (const p of RFS) {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ const getColor = require("../../resources/getColor");
|
|||
module.exports = class servav extends commando.Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: "serv-av",
|
||||
memberName: "serv-av",
|
||||
name: "servav",
|
||||
memberName: "servav",
|
||||
aliases: ["server-avatar", "serv-avatar", "server-av"],
|
||||
group: "profile",
|
||||
description: "Show server avatar."
|
||||
|
|
@ -20,7 +20,7 @@ module.exports = class servav extends commando.Command {
|
|||
const server_ID = arg.split(/ +/)[0];
|
||||
const doc = msg.guild?.id ?? msg.author.id;
|
||||
const col = database.collection(msg.guild ? "Guild" : "User");
|
||||
col.findOne({document: doc}, (err, res) => {
|
||||
col.findOne({ document: doc }, (err, res) => {
|
||||
if (err) {
|
||||
errLog(err, msg, this.client);
|
||||
}
|
||||
|
|
@ -36,15 +36,15 @@ module.exports = class servav extends commando.Command {
|
|||
target = msg.guild;
|
||||
}
|
||||
if (target) {
|
||||
icon = target.iconURL({size:4096, dynamic:true});
|
||||
icon = target.iconURL({ size: 4096, dynamic: true });
|
||||
} else {
|
||||
return trySend(this.client, msg, "I'm not in that server...");
|
||||
}
|
||||
if (icon) {
|
||||
let embed = new MessageEmbed()
|
||||
.setImage(icon)
|
||||
.setTitle(target.name)
|
||||
.setFooter(footerQuote ?? "");
|
||||
.setImage(icon)
|
||||
.setTitle(target.name)
|
||||
.setFooter(footerQuote ?? "");
|
||||
if (target.owner.displayColor) {
|
||||
const color = getColor(target.owner.displayColor)
|
||||
embed.setColor(color);
|
||||
|
|
|
|||
|
|
@ -8,22 +8,17 @@ module.exports = class setfootq extends commando.Command {
|
|||
constructor(client) {
|
||||
super(client, {
|
||||
name: "setfootq",
|
||||
aliases:["setfooterquote"],
|
||||
aliases: ["setfooterquote"],
|
||||
memberName: "setfootq",
|
||||
group: "utility",
|
||||
description: "Set server embed footer text.",
|
||||
userPermissions: ["ADMINISTRATOR"]
|
||||
userPermissions: ["MANAGE_GUILD"]
|
||||
});
|
||||
}
|
||||
async run(msg, args) {
|
||||
try {
|
||||
if (msg.guild ? !msg.guild.member(msg.author).hasPermission("MANAGE_GUILD") : false && !this.client.owners.includes(msg.author)) {
|
||||
return trySend(this.client, msg, 'No lol');
|
||||
}
|
||||
let oldQ = msg.guild?.defaultEmbed ?? msg.author.defaultEmbed;
|
||||
if (!oldQ) {
|
||||
oldQ = {};
|
||||
}
|
||||
let oldQ = msg.guild ? msg.guild.DB.settings.defaultEmbed : msg.author.DB.defaultEmbed;
|
||||
if (!oldQ) oldQ = {};
|
||||
const newQ = oldQ?.footerQuote;
|
||||
oldQ.footerQuote = args.trim();
|
||||
const r = msg.guild ? msg.guild.setDefaultEmbed(oldQ) : msg.author.setDefaultEmbed(oldQ);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module.exports = (member) => {
|
|||
.setTitle("`" + member.user.tag + "` joined")
|
||||
.setThumbnail(member.user.displayAvatarURL({ format: "png", size: 4096, dynamic: true }))
|
||||
.setColor(getColor("cyan"))
|
||||
.addField("Registered", DateTime.fromJSDate(member.user.createdAt).toFormat(DT_PRINT_FORMAT), true)
|
||||
.addField("Registered", "<t:" + (Math.floor(member.user.createdAt.valueOf() / 1000)) + ":F>", true)
|
||||
.setDescription(`<@!${member.id}> (${member.id}) just joined.\nWe have ${member.guild.memberCount} total members now.`);
|
||||
return trySend(member.client, log, emb);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,15 +18,14 @@ module.exports = (member) => {
|
|||
const emb = defaultEventLogEmbed(member.guild),
|
||||
RO = member.roles.cache.sort((a, b) => b.position - a.position).map(r => r.id).slice(0, -1),
|
||||
RU = splitOnLength(RO, 1010, ">, <@&"),
|
||||
JO = DateTime.fromJSDate(member.user.createdAt),
|
||||
LE = DateTime.fromJSDate(member.joinedAt),
|
||||
INT = Interval.fromDateTimes(LE, DateTime.now());
|
||||
emb
|
||||
.setTitle("`" + member.user.tag + "` left")
|
||||
.setThumbnail(member.user.displayAvatarURL({ format: "png", size: 4096, dynamic: true }))
|
||||
.setColor(getColor("yellow"))
|
||||
.addField("Registered", JO.toFormat(DT_PRINT_FORMAT), true)
|
||||
.addField("Joined", LE.toFormat(DT_PRINT_FORMAT) + `\n(${intervalToDuration(INT).strings.join(" ")} ago)`, true)
|
||||
.addField("Registered", "<t:" + (Math.floor(member.user.createdAt.valueOf() / 1000)) + ":F>", true)
|
||||
.addField("Joined", "<t:" + (Math.floor(member.joinedAt.valueOf() / 1000)) + `:F>\n(${intervalToDuration(INT).strings.join(" ")} ago)`, true)
|
||||
.addField("Nick", "`" + member.displayName + "`")
|
||||
.setDescription(`<@!${member.id}> (${member.id}) just left.\nWe have ${member.guild.memberCount} total members now.`);
|
||||
for (const U of RU) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const { Structures, Guild, GuildMember } = require("discord.js"),
|
||||
const { Structures, Guild, GuildMember, BanOptions } = require("discord.js"),
|
||||
{ database } = require("../database/mongo"),
|
||||
{ errLog } = require("./functions");
|
||||
const { DateTime, Duration } = require("luxon");
|
||||
|
|
@ -20,7 +20,8 @@ Structures.extend("Guild", u => {
|
|||
if (!r.moderation) r.moderation = {};
|
||||
if (!r.settings.eventChannels) r.settings.eventChannels = {};
|
||||
if (!r.moderation.settings) r.moderation.settings = {};
|
||||
if (!r.moderation.infractions) r.moderation.infractions = [];
|
||||
if (!r.moderation.infractions) r.moderation.infractions = new Map();
|
||||
if (!r.moderation.timedPunishments) r.moderation.timedPunishments = new Map();
|
||||
return this.DB = r;
|
||||
});
|
||||
}
|
||||
|
|
@ -48,23 +49,12 @@ Structures.extend("Guild", u => {
|
|||
/**
|
||||
* Get user infractions
|
||||
* @param {String} get - User ID
|
||||
* @returns {Promise<Object[]>} Array of infractions objects
|
||||
* @returns {Promise<Map>} Array of infractions objects
|
||||
*/
|
||||
async getInfractions(get) {
|
||||
try {
|
||||
if (!this.DB) await this.dbLoad();
|
||||
let found = [];
|
||||
if (this.DB.moderation.infractions.length > 0) {
|
||||
for (const inf of this.DB.moderation.infractions) {
|
||||
for (const user of inf.by) {
|
||||
if (user.id === get) {
|
||||
found.push(inf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
return this.DB.moderation.infractions.filter(r => r.map(u => u.id).includes(get));
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +255,14 @@ Structures.extend("User", u => {
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Guild} guild
|
||||
* @param {BanOptions} option
|
||||
*/
|
||||
async ban(guild, option) {
|
||||
guild.members.ban(this, option);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue