diff --git a/.gitignore b/.gitignore index 7182f91..d7885fb 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ build/Release # Dependency directories node_modules/ jspm_packages/ +exp/ # Snowpack dependency directory (https://snowpack.dev/) web_modules/ diff --git a/cmds/experiment/dropexp.js b/cmds/experiment/dropexp.js new file mode 100644 index 0000000..2e7adb9 --- /dev/null +++ b/cmds/experiment/dropexp.js @@ -0,0 +1,22 @@ +'use strict'; + +const { trySend } = require("../../resources/functions"); + +const commando = require("@iceprod/discord.js-commando"), +{ database } = require("../../database/mongo"), +col = database.collection("Experiment"); + +module.exports = class dropexp extends commando.Command { + constructor(client) { + super(client, { + name: "dropexp", + memberName: "dropexp", + group: "experiment", + description: "description", + ownerOnly:true + }); + } + run(msg, arg) { + col.drop().then(trySend(this.client, msg, "cleared")).catch(e => trySend(this.client, msg, `\`\`\`js\n${e.stack}\`\`\``)); + } +}; \ No newline at end of file diff --git a/cmds/experiment/mydatabase.js b/cmds/experiment/mydatabase.js index 9874bb7..dbf55bf 100644 --- a/cmds/experiment/mydatabase.js +++ b/cmds/experiment/mydatabase.js @@ -3,6 +3,7 @@ const commando = require("@iceprod/discord.js-commando"); const { errLog, trySend, ranLog } = require("../../resources/functions"); const { database } = require("../../database/mongo"); +const exp = database.collection("Experiment"); module.exports = class mydatabase extends commando.Command { constructor(client) { @@ -10,19 +11,24 @@ module.exports = class mydatabase extends commando.Command { name: "mydatabase", memberName: "mydatabase", group: "experiment", - description: "Show all document collection." + description: "Show all document collection.", + ownerOnly:true }); } - run(msg) { + async run(msg) { + if (!msg.guild?.member(msg.author).hasPermission("MANAGE_GUILD")) { + return trySend(this.client, msg, "No"); + } const data = msg.guild ? "Guild" : "User"; - const doc = msg.guild?.id ?? msg.author.id; + const doc = msg.guild?.id ?? msg.author.id, + dbExp = await exp.find({}).toArray(); database.collection(data).find({document: doc}).toArray(async (e, fetched) => { if (e) { return errLog(e, msg, this.client); } let mes = `Fetched documents for ${msg.guild ? `server **${msg.guild.name}**` : `**${msg.author.tag}**`}`; - mes = `${mes}\`\`\`js\n${JSON.stringify(fetched, null, 2)}\`\`\``; - trySend(this.client, msg, mes); + mes = `${mes}\`\`\`js\n${JSON.stringify(fetched, null, 2)}\`\`\`` + `\`\`\`js\n${JSON.stringify(dbExp, null, 2)}\`\`\``; + trySend(this.client, msg, {content:mes,split:{maxLength:2000,append:",```",prepend:"```js\n",char:","}}); return ranLog(msg, "mydatabase", fetched); }); } diff --git a/cmds/experiment/regive.js b/cmds/experiment/regive.js new file mode 100644 index 0000000..9ca6216 --- /dev/null +++ b/cmds/experiment/regive.js @@ -0,0 +1,32 @@ +'use strict'; + +const { trySend, cleanMentionID } = require("../../resources/functions"); + +const commando = require("@iceprod/discord.js-commando"), +{ database } = require("../../database/mongo"), +col = database.collection("Experiment"); + +module.exports = class regive extends commando.Command { + constructor(client) { + super(client, { + name: "regive", + memberName: "regive", + group: "experiment", + description: "description" + }); + } + /** + * + * @param {commando.CommandoMessage} msg + * @param {*} arg + */ + async run(msg, arg ) { + const args = arg.split(" "), + member = msg.guild.member(cleanMentionID(args[0])), + doc = await col.findOne({"rolesScreenshot.name":member.id}).catch(e => trySend(this.client, msg, "```js\n" + e.stack + "```")), + test = doc.rolesScreenshot.data; + await member.roles.add(test.map(r => r)).catch(e => trySend(this.client, msg, "```js\n" + e.stack + "```")); + await member.roles.remove("772114626720432128").catch(e => trySend(this.client, msg, "```js\n" + e.stack + "```")) + trySend(this.client, msg, "Success!"+"```js\n"+JSON.stringify(test, null, 2)+"```"); + } +}; \ No newline at end of file diff --git a/cmds/experiment/replace.js b/cmds/experiment/replace.js new file mode 100644 index 0000000..f59d0a5 --- /dev/null +++ b/cmds/experiment/replace.js @@ -0,0 +1,29 @@ +'use strict'; + +const commando = require("@iceprod/discord.js-commando"); +const { cleanMentionID, trySend } = require("../../resources/functions"); + +module.exports = class replace extends commando.Command { + constructor(client) { + super(client, { + name: "replace", + memberName: "replace", + group: "experiment", + description: "replace test" + }); + } + /** + * + * @param {commando.CommandoMessage} msg + * @param {*} arg + */ + async run(msg, arg) { + const args = arg.split(" "), + targetID = cleanMentionID(args[0]), + targetUser = msg.guild.member(targetID); + await targetUser.roles.remove(targetUser.roles.cache.array()).catch(e => trySend(this.client, msg, "```js\n" + e.stack + "```")); + await targetUser.roles.add("772114626720432128").catch(e => trySend(this.client, msg, "```js\n" + e.stack + "```")); + //trySend(this.client, msg, "```js\n"+JSON.stringify(mes, null, 2)+"```"); + trySend(this.client, msg, "Replaced!"); + } +}; \ No newline at end of file diff --git a/cmds/experiment/resetdatabase.js b/cmds/experiment/resetdatabase.js index d3df9fa..9954a17 100644 --- a/cmds/experiment/resetdatabase.js +++ b/cmds/experiment/resetdatabase.js @@ -10,10 +10,14 @@ module.exports = class resetdatabase extends commando.Command { name: "resetdatabase", memberName: "resetdatabase", group: "experiment", - description: "Reset your server/private database." + description: "Reset your server/private database.", + ownerOnly:true }); } async run(msg) { + if (!msg.guild?.member(msg.author).hasPermission("MANAGE_GUILD")) { + return trySend(this.client, msg, "No"); + } const doc = msg.guild?.id ?? msg.author.id; const col = database.collection(msg.guild ? "Guild" : "User"); trySend(this.client, msg, "Are you sure? You will lose every saved settings. This process can't be undone. Type `yes` in 30 seconds to confirm."); diff --git a/cmds/experiment/resetinfractions.js b/cmds/experiment/resetinfractions.js new file mode 100644 index 0000000..dfb0aed --- /dev/null +++ b/cmds/experiment/resetinfractions.js @@ -0,0 +1,28 @@ +'use strict'; + +const commando = require("@iceprod/discord.js-commando"), +{ database } = require("../../database/mongo"); +const { trySend } = require("../../resources/functions"), +col = database.collection("Guild"); + +module.exports = class resetinfractions extends commando.Command { + constructor(client) { + super(client, { + name: "resetinfractions", + memberName: "resetinfractions", + group: "experiment", + description: "description", + guildOnly:true, + ownerOnly:true + }); + } + run(msg) { + col.updateOne({document:msg.guild.id}, {$set:{"moderation.infractions":[]}}, {upsert:true}, (e, r) => { + if (e) { + return trySend(this.client, msg, "```js\n"+e.stack+"```"); + } + col.updateOne({document:msg.guild.id}, {$set:{"moderation.settings.mute": {}}}); + return trySend(this.client, msg, "Wiped!"); + }); + } +}; \ No newline at end of file diff --git a/cmds/experiment/screenshot.js b/cmds/experiment/screenshot.js new file mode 100644 index 0000000..73cc890 --- /dev/null +++ b/cmds/experiment/screenshot.js @@ -0,0 +1,32 @@ +'use strict'; + +const { cleanMentionID, trySend } = require("../../resources/functions"); + +const commando = require("@iceprod/discord.js-commando"), +{ database } = require("../../database/mongo"), +dbExp = database.collection("Experiment"); + +module.exports = class screenshot extends commando.Command { + constructor(client) { + super(client, { + name: "screenshot", + memberName: "screenshot", + group: "experiment", + description: "description" + }); + } + /** + * + * @param {commando.CommandoMessage} msg + * @param {*} arg + */ + async run(msg, arg) { + const args = arg.split(" "), + targetID = cleanMentionID(args[0]), + targetUser = msg.guild.member(targetID), + test = targetUser.roles.cache.map(r => r.id); + //trySend(this.client,msg,{content:`\`\`\`js\n${test}\`\`\``,split:true}) + await dbExp.insertOne({ rolesScreenshot: { name: targetUser.id, data: test }}).catch(e => trySend(this.client, msg, "```js\n" + e.stack + "```")); + trySend(this.client, msg, "Sceenshoted!") + } +}; \ No newline at end of file diff --git a/cmds/image/neko.js b/cmds/image/neko.js index 578cb76..44d8c05 100644 --- a/cmds/image/neko.js +++ b/cmds/image/neko.js @@ -16,7 +16,7 @@ module.exports = class neko extends commando.Command { const aut = msg.guild ? msg.guild.member(msg.author) : msg.author; const title = `${msg.guild ? aut.displayName : aut.username}! ~Nyann~ (UwU) <3`; const image = `https://nekos.best/nekos/${String(Math.floor(Math.random() * 314)).padStart(4, '0')}.png`; - const emb = await defaultImageEmbed(this.client, msg, image, aut, title); + const emb = await defaultImageEmbed(this.client, msg, aut, image, title); trySend(this.client, msg, emb); return ranLog(msg, "neko"); } diff --git a/cmds/moderation/mute.js b/cmds/moderation/mute.js index 6418c55..67233bb 100644 --- a/cmds/moderation/mute.js +++ b/cmds/moderation/mute.js @@ -1,10 +1,10 @@ 'use strict'; const commando = require("@iceprod/discord.js-commando"); -const { trySend, findMemberRegEx, cleanMentionID } = require("../../resources/functions"); +const { trySend, findMemberRegEx, cleanMentionID, findChannelRegEx, findRoleRegEx, defaultImageEmbed } = require("../../resources/functions"); const { database } = require("../../database/mongo"); const col = database.collection("Guild"); -const dbExp = database.collection("Experiment"); +const schedule = database.collection("Schedule"); const { scheduler } = require("../../resources/scheduler"); module.exports = class mute extends commando.Command { @@ -25,9 +25,11 @@ module.exports = class mute extends commando.Command { */ async run(msg, arg) { const doc = await col.findOne({document: msg.guild.id}), - moderationDoc = doc?.["moderation"], - infractionDoc = moderationDoc?.infractions, - args = arg.trim().split(/(? 0 && argument !== "--") { + if (!settingRole && !settingLogChannel && argument.length > 0 && argument !== "--") { reason = argument.trim(); + } else { + if (settingLogChannel && !settingLogChannelHasSet && argument.length > 0 && argument !== "--" && setArg !== "log") { + settingLogChannelHasSet = true; + const key = cleanMentionID(argument); + let logChannel; + if (/^\d{17,19}$/.test(key)) { + logChannel = msg.guild.channels.cache.get(argument); + } else { + const found = findChannelRegEx(msg, key); + logChannel = found[0]; + } + if (logChannel) { + theSettingUp.logChannel = logChannel.id; + resultMsg += `Log channel set to: **${logChannel.name}**\n`; + } else { + resultMsg += `No channel found for: **${argument}**\n`; + } + } + if (settingRole && !settingRoleHasSet && argument.length > 0 && argument !== "--" && setArg !== "role") { + settingRoleHasSet = true; + const key = cleanMentionID(argument); + let role; + if (/^\d{17,19}$/.test(key)) { + role = msg.guild.roles.cache.get(argument); + } else { + const found = findRoleRegEx(msg, key); + role = found[0].id; + } + if (role) { + theSettingUp.role = role; + resultMsg += `Mute role set to: **${role.name}**\n`; + } else { + resultMsg += `No role found for: **${argument}**\n`; + } + } } } } + const roleConfCheck = msg.guild.roles.cache.get(muteSettingsDoc?.role); + if (!roleConfCheck && !settingUp) { + return trySend(this.clientPermissions, msg, `No mute role configured! Run \`${this.client.commandPrefix}mute --settings <--role --> [--duration -- | --log --]\` to set it up.`); + } if (duration.year > 275500) { duration.year = 275500; } let untilDate = new Date(String(duration.year), String(duration.month), String(duration.date), String(duration.hour), String(duration.minute), String(duration.second)); - if (untilDate.toUTCString() === invokedAt.toUTCString()) { - untilDate = "Indefinite"; - } else { + if (untilDate.toUTCString() === invokedAt.toUTCString() && !settingDuration) { + if (defaultDurationDoc?.date?.valueOf() > 0) { + untilDate = new Date(invokedAt.valueOf() + defaultDurationDoc.date.valueOf() - 1000); + } else { + untilDate = "Indefinite"; + } + } + if (untilDate !== "Indefinite") { timeForMessage = []; const elapsedTime = new Date(untilDate.valueOf() - invokedAt.valueOf() + 1000), elapsed = [ @@ -110,19 +176,49 @@ module.exports = class mute extends commando.Command { "minute", "second" ]; + for (let index = 0; index < elapsed.length; index++) { if (elapsed[index] > 0) { - timeForMessage.push(`${elapsed[index]} ${elapsedName[index]}`); + let mes = `${elapsed[index]} ${elapsedName[index]}`; + if (elapsed[index] > 1) { + mes += "s"; + } else {} + timeForMessage.push(mes); } else {} } - for (let index = 0; index < timeForMessage.length; index++) { - if (parseInt(timeForMessage[index].split(" ")[0], 10) > 1) { - timeForMessage[index] += "s"; - } - } if (timeForMessage.length > 1) { timeForMessage[timeForMessage.length - 2] += " and"; } + if (settingDuration && !settingDurationHasSet && timeForMessage.length > 0) { + settingDurationHasSet = true; + theSettingUp.defaultDuration.date = elapsedTime, + theSettingUp.defaultDuration.string = timeForMessage.join(" "); + resultMsg += `Default Duration set to: **${theSettingUp.defaultDuration.string}**\n`; + } + } + if (settingUp) { + if(settingRoleHasSet) { + await col.updateOne({document:msg.guild.id}, {$set:{"moderation.settings.mute.role":theSettingUp.role}}, {upsert:true}).catch(e => {return trySend(this.client, msg, "```js\n"+e.stack+"```")}); + } + if (durationHasSet) { + await col.updateOne({document:msg.guild.id}, {$set:{"moderation.settings.mute.defaultDuration":theSettingUp.defaultDuration}}, {upsert:true}).catch(e => {return trySend(this.client, msg, "```js\n"+e.stack+"```")}); + } + if (settingLogChannelHasSet) { + await col.updateOne({document:msg.guild.id}, {$set:{"moderation.settings.mute.logChannel":theSettingUp.logChannel}}, {upsert:true}).catch(e => {return trySend(this.client, msg, "```js\n"+e.stack+"```")}); + } + const doc = await col.findOne({document: msg.guild.id}), + modDoc = doc?.["moderation"], + muteSettingsDoc = modDoc?.["settings"]?.mute, + defaultDurationDoc = muteSettingsDoc?.defaultDuration, + logChannelDoc = muteSettingsDoc?.logChannel, + roleDoc = muteSettingsDoc?.role; + let settings = await defaultImageEmbed(this.client, msg, msg.member); + settings + .setTitle("Mute Configuration") + .addField("Role", roleDoc ? "<@&"+roleDoc+">" : "Not set") + .addField("Duration", defaultDurationDoc?.string ?? "Not set") + .addField("Log", logChannelDoc ? "<#"+logChannelDoc+">" : "Not set"); + return trySend(this.client, msg, settings); } for (const usermention of mentions) { if (usermention.length > 0) { @@ -151,35 +247,62 @@ module.exports = class mute extends commando.Command { } else { resultMsg += `Can't find user: **${usermention.trim()}**\n`; } + } else { + if (!settingUp) { + return trySend(this.client, msg, "Who are you wanna mute? Provide as first argument `<[RegExp | user_[mention | ID]]>`"); + } else { + + } } } let infractionToDoc; if (targetUser.length > 0) { - const infractionCase = infractionDoc?.map(r => r.infraction)?.length; + let targetMember = [], + notInServer = []; + for (const user of targetUser) { + const member = msg.guild.member(user); + if (member) { + const pushIt = { + name:member.user.tag, + id:member.id, + roles:member.roles.cache.map(r => r.id) + } + targetMember.push(pushIt); + } else { + const pushIt = { + name: user.tag, + id:user.id + } + notInServer.push(pushIt); + } + } + const infractionCase = infractionsDoc?.map(r => r.infraction)?.length; infractionToDoc = { infraction: infractionCase ? infractionCase + 1 : 1, by: targetUser, moderator: `**${msg.author.tag}** <@${msg.author.id}> (${msg.author.id})`, - punishment: "**Mute**", + punishment: "mute", at: invokedAt, for: timeForMessage, until: untilDate, reason: reason, - scene: msg.url + scene: msg.url, + members: targetMember, + users: notInServer } + await col.updateOne({document: msg.guild.id}, { $push:{"moderation.infractions": infractionToDoc}}, {upsert:true}); const newUnmuteSchedule = { - name: "unmute schedule " + targetUser?.id, + name: "unmute", path: "./scheduler/unmute.js", worker: { - argv: { - - } - } + argv: [msg, infractionToDoc.infraction] + }, + date: untilDate } } - resultMsg += `Result:\`\`\`js\nUsers: ${targetUser.map(r => r?.tag).join(", ")}\nReason: ${reason}\nAt: ${invokedAt.toUTCString()}\nFor: ${timeForMessage.join(" ")}\nUntil: ${typeof untilDate !== "string" ? untilDate.toUTCString() : untilDate}\`\`\`\n`; - trySend(this.client, msg, "```js\n" + JSON.stringify(infractionToDoc, null, 2) + "```"); - return trySend(this.client, msg, resultMsg); + resultMsg += `Result:\`\`\`js\nUsers: ${targetUser.map(r => r?.tag).join(", ")}\nReason: ${reason}\nAt: ${invokedAt.toUTCString()}\nFor: ${timeForMessage.join(" ")}\nUntil: ${typeof untilDate !== "string" ? untilDate.toUTCString() : untilDate}\`\`\``; + trySend(this.client, msg, {content:resultMsg+"```js\n" + JSON.stringify(infractionToDoc, null, 2) + "```",split:{maxLength:2000,append:",```",prepend:"```js\n",char:","}}); + return } }; diff --git a/resources/functions.js b/resources/functions.js index 7d4135e..e254b1f 100644 --- a/resources/functions.js +++ b/resources/functions.js @@ -3,6 +3,7 @@ const { MessageEmbed, Message, GuildMember, User, Client, GuildChannel, Role, MessageOptions } = require('discord.js'); const { defaultErrorLogChannel } = require("../config.json"); const { database } = require("../database/mongo"); +const getColor = require('./getColor'); /** * Log an error. If second argument, third argument is required @@ -139,7 +140,6 @@ async function ranLog(msg, cmd, addition) { * @returns {String} */ function multipleMembersFound(client, msg, arr, key, max = 4, withID) { - arr = arr.slice(1); if (arr.length > 0) { try { let multipleFound = []; @@ -216,7 +216,8 @@ async function trySend(client, msg, content) { msgOf = client.channels.cache.get(msg); } const sentMes = await msgOf.send(content) - .catch(() => { + .catch((e) => { + console.error(e); if (msg?.channel) { noPerm(msg); } @@ -270,23 +271,20 @@ function sentAdCheck(sent) { * @param {String} footerText * @returns {Promise} */ -async function defaultImageEmbed(client, msg, image, author, title, footerText) { +async function defaultImageEmbed(client, msg, author, image, title, footerText) { const { randomColors } = require("../config.json"); let footerQuote = footerText; if (!footerQuote) { - const doc = await database.collection(msg.guild ? "Guild" : "User").findOne({document: msg.guild?.id ?? msg.author.id}); - footerQuote = doc?.["settings"]?.defaultEmbed?.footerQuote || ""; + const r = await database.collection(msg.guild ? "Guild" : "User").findOne({document: msg.guild?.id ?? msg.author.id}); + footerQuote = r?.["settings"]?.defaultEmbed?.footerQuote || ""; } let emb = new MessageEmbed(); try { emb .setTitle(title) .setImage(image) - .setColor(msg.guild ? author?.displayColor : randomColors[Math.floor(Math.random() * randomColors.length)]) + .setColor(msg.guild ? getColor(author?.displayColor) : randomColors[Math.floor(Math.random() * randomColors.length)]) .setFooter(footerQuote); - if (author?.displayColor === 16777215) { - emb.setColor(16777214); - } } catch (e) { return errLog(e, msg, client, false, "", false); } @@ -363,7 +361,6 @@ function findRoleRegEx(msg, name) { * @returns {String} */ function multipleChannelsFound(client, msg, arr, key, max = 4, withID) { - arr = arr.slice(1); if (arr.length > 0) { try { let multipleFound = []; @@ -404,7 +401,6 @@ function multipleChannelsFound(client, msg, arr, key, max = 4, withID) { * @returns {String} */ function multipleRolesFound(client, msg, arr, key, max = 4, withID) { - arr = arr.slice(1); if (arr.length > 0) { try { let multipleFound = []; diff --git a/resources/getColor.js b/resources/getColor.js index 8714a79..2518245 100644 --- a/resources/getColor.js +++ b/resources/getColor.js @@ -6,6 +6,9 @@ * @returns {String | Number} Color hex | Color number */ module.exports = function getColor(name) { + if (!name) { + return + } if (typeof name === "string") { name = name.toLowerCase(); } diff --git a/resources/shaChat.js b/resources/shaChat.js index f758997..daa61fd 100644 --- a/resources/shaChat.js +++ b/resources/shaChat.js @@ -2,7 +2,7 @@ const puppeteer = require('puppeteer'); -const { trySend, errLog, ranLog, noPerm } = require('./functions'); +const { trySend, ranLog, noPerm } = require('./functions'); const Commando = require("@iceprod/discord.js-commando"); require("discord.js");