diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..b10b294 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +guild.js \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..cd711a0 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index f304111..1a6fcaf 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -3,6 +3,12 @@ +<<<<<<< HEAD +======= + + + +>>>>>>> 36ede9d7de87f20d905c506a6f9eb8a6f9d2816d diff --git a/bot.js b/bot.js index 095b749..47ef014 100644 --- a/bot.js +++ b/bot.js @@ -1,6 +1,10 @@ const Discord = require('discord.js'); const client = new Discord.Client(); +const chalk = require('chalk'); +const ora = require('ora'); +const mongoose = require('mongoose'); + client.misc = { savers: ['497598953206841375'], activeDMs: new Discord.Collection(), @@ -15,21 +19,48 @@ const auth = require('./auth.json'); //client.config = config; async function init() { + let cloginsp = ora(chalk.magentaBright('Connecting Discord client...')).start(); + let pclc = new Date().getTime(); await client.login(auth.token); + cloginsp.stop(); cloginsp.clear(); + console.log(`${chalk.green('[BOOT]')} >> ${chalk.greenBright(`Connected to Discord in `)}${chalk.white(`${new Date().getTime() - pclc}ms`)}`); + client.misc.startupNoConnect = new Date(); client.config = auth; + let mloginsp = ora(chalk.magentaBright('Connecting to Mongo client...')).start(); + let pmcc = new Date().getTime(); + const config = client.config; + try { + await mongoose.connect(`mongodb+srv://${config.database.user}:${config.database.password}@${config.database.cluster}.3jpp4.mongodb.net/test`, { + useFindAndModify: false, useNewUrlParser: true, dbName: 'Natsuki-Main', useUnifiedTopology: true, useCreateIndex: true + }).catch(e => { + let date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6); + console.error(`\n${chalk.red('[ERROR]')} >> ${chalk.yellow(`At [${date}] | Occurred while trying to connect to Mongo Cluster`)}`, e); + mloginsp.stop(); mloginsp.clear(); + }); + mloginsp.stop(); mloginsp.clear(); + console.log(`${chalk.green('[BOOT]')} >> ${chalk.greenBright(`Connected to Mongo Database in `)}${chalk.white(`${new Date().getTime() - pmcc}ms`)}`); + } catch (e) { + let date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6); + console.error(`\n${chalk.red('[ERROR]')} >> ${chalk.yellow(`At [${date}] | Occurred while trying to connect to Mongo Cluster`)}`, e); + mloginsp.stop(); mloginsp.clear(); + } + ['commands', 'aliases'].forEach(x => client[x] = new Discord.Collection()); client.responses = {triggers: [], commands: new Discord.Collection()}; + ['command', 'event', 'response'].forEach(x => require(`./handle/${x}`)(client)); client.developers = ["330547934951112705", "673477059904929802"]; - client.utils = {}; - client.utils.logch = async () => {return client.guilds.cache.get('762707532417335296').channels.cache.get('762732961753595915');}; + client.utils.logch = async () => {return client.guilds.cache.get('762707532417335296').channels.cache.get('762732961753595915');}; client.guildconfig = {}; client.guildconfig.prefixes = new Map(); + client.guildconfig.logs = new Map(); + + await require('./events/ready')(client); } -init(); \ No newline at end of file +init().then(() => {}); \ No newline at end of file diff --git a/commands/8ball.js b/commands/8ball.js index 4e45f48..8a6920c 100644 --- a/commands/8ball.js +++ b/commands/8ball.js @@ -7,6 +7,12 @@ module.exports = { .setTitle("Help -> 8ball") .setDescription("Gives you moral support, decides if you really do want that third taco, or helps you decide on your existential crisis. Answers come with an accuracy guarantee of 0%!") .addField("Syntax", "`8ball `"), + meta: { + category: 'Fun', + description: "Gives you moral support, decides if you really do want that third taco, or helps you decide on your existential crisis. Answers come with an accuracy guarantee of 0%!", + syntax: '`8ball `', + extra: null + }, execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) {return message.channel.send(`Syntax: \`${prefix}8ball \``);} let question = args.join(" "); diff --git a/commands/admin.js b/commands/admin.js index d82f594..6934843 100644 --- a/commands/admin.js +++ b/commands/admin.js @@ -8,6 +8,12 @@ module.exports = { .setDescription("Make a user a Natsuki admin") .addField("Syntax", "`admin <@user|userID>`") .addField("Notice", "This command is only available to Natsuki developers."), + meta: { + category: 'Developer', + description: "Add or remove users as Natsuki admins", + syntax: '`admin <@user|userID>`', + extra: "You can check if a user is an admin without being a developer." + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This is a guild-only command.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}\``);} diff --git a/commands/afk.js b/commands/afk.js index d73f251..9a9e795 100644 --- a/commands/afk.js +++ b/commands/afk.js @@ -10,6 +10,12 @@ module.exports = { .setDescription("Set your status within the bot as AFK and specify a reason. Then, when other people ping you, I can let them know that you're not available!") .addField("Syntax", "`afk [clearMode] `") .addField("Notice","Your status clear mode can be set to either 'auto' or 'manual'. If not specified, it will clear next time you send a message (auto)."), + meta: { + category: 'Social', + description: "Tell others that you're AFK so that they'll be notified when you ping them.", + syntax: '`afk [clearMode] `', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) {return message.channel.send(`Syntax: \`${prefix}afk [clearMode] \``);} let tu = await UserData.findOne({uid: message.author.id}) diff --git a/commands/ar.js b/commands/ar.js index f324b05..4127619 100644 --- a/commands/ar.js +++ b/commands/ar.js @@ -9,15 +9,11 @@ module.exports = { name: "ar", aliases: ['autoresponse', 'autoresponses'], meta: { - category: "", - perms: "", - staff: false, - vip: "", - serverPerms: [], - writtenBy: "", - serverOnly: true + category: 'Misc', + description: "Create and edit automatic responses, which lets the bot say stuff when you say something in your server!", + syntax: '`ar `', + extra: null }, - tags: [], help: new Discord.MessageEmbed() .setTitle("Help -> Auto Responses") .setDescription("Create and edit automatic responses, which lets the bot say stuff when you say something in your server!") @@ -27,7 +23,15 @@ module.exports = { if (!message.guild) {return message.channel.send("You must be in a server in order to use this command.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}\``);} const tg = await GuildData.findOne({gid: message.guild.id}); - if (['a', 'add', 'e', 'edit', 'delete', 'd'].includes(args[0].toLowerCase()) && (!tg || !tg.staffrole || !tg.staffrole.length || (message.member.roles.cache.has(tg.staffrole) && message.member.permissions.has("ADMINISTRATOR")))) {return message.channel.send("You must have the staff role or be an administrator in this server in order to edit AR settings.");} + if (['a', 'add', 'e', 'edit', 'delete', 'd'].includes(args[0].toLowerCase()) && ((!tg || !tg.staffrole || !tg.staffrole.length || !message.member.roles.cache.has(tg.staffrole)) && !message.member.permissions.has("ADMINISTRATOR"))) {return message.channel.send("You must have the staff role or be an administrator in this server in order to edit AR settings.");} + + function viewARs(tar) { + let t = tar.triggers; + let ar = tar.ars; + let s = ''; + + for (let i=0;i 300) {return message.channel.send("Your response needs to be less than 300 characters, please!");} let tar = await AR.findOne({gid: message.guild.id}) || new AR({gid: message.guild.id}); + if (tar.triggers.length === 20) {return message.channel.send("Because of data storage concerns, your ARs are capped at 20 per server. You can join the official support server and talk to the devs if you have a legitimate reason for raising this limit and they can see about raising it for you!");} let h = false; let ar; for (ar of tar.triggers) {if (ar.toLowerCase() === `${trigger}`.toLowerCase()) {h = true;}} if (!h) {tar.triggers.push(trigger);} + tar.ars[`${trigger}`.trim().toLowerCase()] = `${response}`.trim(); + tar.markModified('tar.ars'); + tar.save(); + return message.channel.send("AR added!"); + } + + if (['e', 'edit'].includes(args[0].toLowerCase())) { + } + + if (['d', 'delete'].includes(args[0].toLowerCase())) { + let tar = await AR.findOne({gid: message.guild.id}); + if (!tar || !tar.triggers.length) {return message.channel.send("It's not like this server has any ARs for me to delete in the first place!");} + + + } + + return message.channel.send(`That's not a valid argument! Try \`${prefix}help ar\``); } }; \ No newline at end of file diff --git a/commands/autorole.js b/commands/autorole.js index d8ee895..05b757d 100644 --- a/commands/autorole.js +++ b/commands/autorole.js @@ -9,6 +9,12 @@ module.exports = { .setDescription("Set a role to be automatically added to users when they join the server.") .addField("Syntax", "`autorole `") .addField('Notice', "This command can only be used by server staff members and admins."), + meta: { + category: 'Moderation', + description: "Set a role to be automatically added when a member joins the server.", + syntax: '`autorole `', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This command is only available in servers.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}autorole \``);} diff --git a/commands/avatar.js b/commands/avatar.js index 8f474cc..e920a6e 100644 --- a/commands/avatar.js +++ b/commands/avatar.js @@ -6,6 +6,12 @@ module.exports = { name: "avatar", aliases: ['av', 'a', 'pfp'], help: "Use `{{p}}avatar` to get your own profile picture, or mention someone to get theirs!", + meta: { + category: 'Misc', + description: "Flare your avatar or peek at others'", + syntax: '`avatar [@mention]`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let member = !args.length ? message.author : mention ? mention : client.users.cache.has(args[0]) ? client.users.cache.get(args[0]) : message.author; let name = !args.length ? message.member ? message.member.displayName : message.author.username : mention ? mention.username : client.users.cache.has(args[0]) ? client.users.cache.get(args[0]).username : message.author.username; @@ -16,7 +22,7 @@ module.exports = { try { let avem = new Discord.MessageEmbed() .setTitle(`${name.endsWith('s') ? `${name}'` : `${name}'s`} Avatar`) - .setImage(member.avatarURL({size: options.vsmall ? 128 : options.small ? 256 : 2048})) + .setImage(member.avatarURL({size: options.vsmall ? 128 : options.small ? 256 : 2048, dynamic: true})) .setColor('c375f0') .setFooter("Natsuki", client.user.avatarURL()) if (!options.vsmall) {avem.setTimestamp();} diff --git a/commands/ban.js b/commands/ban.js new file mode 100644 index 0000000..a53bb47 --- /dev/null +++ b/commands/ban.js @@ -0,0 +1,73 @@ +const Discord = require('discord.js'); + +const Mod = require('../models/mod'); + +const {Tag} = require('../util/tag'); +const {TagFilter} = require('../util/tagfilter'); + +module.exports = { + name: "ban", + aliases: [], + meta: { + category: 'Moderation', + description: "Bans a member from the server!", + syntax: '`ban <@member|memberID> [reason]`', + extra: null, + guildOnly: true + }, + help: new Discord.MessageEmbed() + .setTitle("Help -> Member Banning") + .setDescription("This command bans a member from the server permanently, making it so they cannot rejoin. *Yikes*") + .addField("Syntax", "`ban <@member|memberID> [reason]`") + .addField("Permissions", "You'll want to have the `ban members` permission in your server or be an administrator to do this!"), + async execute(message, msg, args, cmd, prefix, mention, client) { + if (!args.length) {return message.channel.send(`Syntax: \`${prefix}ban <@member|memberID> [reason]\``);} + + if (!message.member.permissions.has("BAN_MEMBERS")) {return message.channel.send("You don't have permissions to do that!");} + if (!message.guild.me.permissions.has("BAN_MEMBERS")) {return message.channel.send("I don't have permissions to ban members in your server.");} + let user = message.guild.members.cache.get(args[0]) || message.mentions.members.first(); + + if (!user) {return message.channel.send("You must mention a user to ban, or provide their ID.");} + if (user.roles.highest.position >= message.member.roles.highest.position) {return message.channel.send("You don't have permissions to ban that member as they are above you in the roles list.");} + if (user.roles.highest.position >= message.guild.me.roles.highest.position) {return message.channel.send("I can't ban that member as their highest role is above mine! (Or the same as mine, too)");} + if (!user.bannable) {return message.channel.send("Hmm, it seems like I can't ban that member. This is probably a permissions issue. Or maybe they were already banned?");} + + let options = new TagFilter([ + new Tag(['r', 'reason'], 'reason', 'append'), + new Tag(['n', 'notes'], 'notes', 'append'), + new Tag(['d', 'days', 'm', 'messages'], 'days', 'append') + ]).test(args.join(" ")); + let reason; let days; + if (options.reason && options.reason.length) {reason = options.reason;} + if (options.days && options.days.length) { + if (isNaN(Number(options.days)) || Number(options.days) < 0 || Number(options.days) > 7 || options.days.includes('.')) {return message.channel.send("The `days` option must be a whole number between 0 and 7.");} + days = Number(options.days); + } + if (options.notes && options.notes.length > 250) {return message.channel.send("I mean I get it, they pissed you off, but do you really need to give me that much info on why you're banning them? I can't keep track of all that!");} + else {if (args[1] && !options.days /*&& (!options.notes || !options.notes.length)*/ && (!options.reason || !options.reason.length)) {args.shift(); reason = args.join(" ");}} + if (reason && reason.length > 250) {return message.channel.send("I mean I get it, they pissed you off, but do you really need to give me that much info on why you're banning them? I can't keep track of all that!");} + + return user.ban({reason: reason}) + .then(async () => { + /*let mh = await Mod.findOne({gid: message.guild.id}) || new Mod({gid: message.guild.id}); + let mhcases = mh.cases; + + mhcases.push({ + members: [user.id], + punishment: "Banned", + reason: reason ? reason : "", + status: "Closed", + moderators: [message.author.id], + notes: options.notes, + history: [`${new Date().toISOString()} - ${message.author.username} - Created case`, `${new Date().toISOString()} - ${message.author.username} - Banned ${client.users.cache.get(user.id).username}`], + issued: new Date().toUTCString() + }); + + mh.cases = mhcases; + mh.save();*/ + + return message.channel.send(`The hammer of justice has spoken!${reason ? ` Reason for banning: ${reason}` : ''}`); + }) + .catch(() => {return message.channel.send("Something went wrong while trying to ban that user! If the problem persists, contact my devs.");}); + } +}; \ No newline at end of file diff --git a/commands/bio.js b/commands/bio.js index fc8486d..ea81b0d 100644 --- a/commands/bio.js +++ b/commands/bio.js @@ -7,6 +7,12 @@ module.exports = { .setTitle("Help -> Bio") .setDescription("Set and view user bios, which are fun ways to express yourself!") .addField("Syntax", "`bio `"), + meta: { + category: 'Social', + description: "Set your own user bio, which can be seen by everyone!", + syntax: '`bio `', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) {return message.channel.send(`Syntax: \`${prefix}bio \``);} let tu = await UserData.findOne({uid: message.author.id}) ? await UserData.findOne({uid: message.author.id}) : new UserData({uid: message.author.id}); diff --git a/commands/clearstatus.js b/commands/clearstatus.js index 4692d56..0c46737 100644 --- a/commands/clearstatus.js +++ b/commands/clearstatus.js @@ -7,16 +7,20 @@ module.exports = { name: "clearstatus", aliases: ['statusclear', 'cs'], help: "Clears your status, if you have one set. Does not take any arguments.", + meta: { + category: 'Social', + description: "Clear your status, if you have one set.", + syntax: '`clearstatus`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let tu = await UserData.findOne({uid: message.author.id}); - if (!tu && !tu.statusmsg.length) { - return message.reply("you have no status for me to clear"); - } + if (!tu && !tu.statusmsg.length) {return message.reply("you have no status for me to clear");} if (tu.statusclearmode === "auto") {return;} tu.statusmsg = ''; tu.statustype = ''; tu.save(); - require('../util/siftstatuses')(client, message.author.id); - return message.reply("welcome back! I cleared your status."); + require('../util/siftstatuses')(client, message.author.id, true); + return message.reply("welcome back! I cleared your status.").then(m => {m.delete({timeout: 5000}).then(() => {message.delete().catch(() => {});})}); } }; \ No newline at end of file diff --git a/commands/clearwarnings.js b/commands/clearwarnings.js index d50dbb0..a9fd5da 100644 --- a/commands/clearwarnings.js +++ b/commands/clearwarnings.js @@ -6,18 +6,14 @@ module.exports = { name: "clearwarnings", aliases: ['clearwarn', 'cw', 'warnclear', 'wc', 'clearwarning'], meta: { - category: "", - perms: "", - staff: false, - vip: "", - serverPerms: [], - writtenBy: "", - serverOnly: false + category: 'Moderation', + description: "Clear a user's warnings in your server.", + syntax: '`clearwarnings <@user|userID>`', + extra: null }, - tags: [], help: new Discord.MessageEmbed() .setTitle("Help -> Warn Clearing") - .setDescription("Clears the warnigns of a user") + .setDescription("Clears the warnings of a user") .addField("Syntax", "`clearwarnings <@user|userID>`") .addField("Notice", "You must be a server administrator in order to use this command."), async execute(message, msg, args, cmd, prefix, mention, client) { diff --git a/commands/cry.js b/commands/cry.js index d16a876..1ed3b9d 100644 --- a/commands/cry.js +++ b/commands/cry.js @@ -7,6 +7,12 @@ module.exports = { name: "cry", aliases: ['sob'], help: "Tell others that you're crying with `{{p}}cry`. We're here for you!", + meta: { + category: 'Social', + description: "Tell others that you're not feeling so well using this command.", + syntax: '`cry`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let savess = await Saves.findOne({name: 'cry'}) ? await Saves.findOne({name: 'cry'}) : new Saves({name: 'cry'}); let saves = savess.saves; diff --git a/commands/deathnote.js b/commands/deathnote.js index f2a51e0..80af634 100644 --- a/commands/deathnote.js +++ b/commands/deathnote.js @@ -56,6 +56,12 @@ module.exports = { .setTitle("Help -> Death Note") .setDescription("Congratulations! You've picked up a death note. Write someone's name in it, and see for yourself if it's the real deal...") .addField("Syntax", "\`deathnote <@member> [method of death]\`"), + meta: { + category: 'Fun', + description: "Write someone's name in your deathnote. I'm not legally responsible for anything that happens after that.", + syntax: '`deathnote <@member> [method of death]`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("Unfortunately, this is a **guild-only** command!");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}deathnote <@member> [method of death]\``);} diff --git a/commands/developer.js b/commands/developer.js index f04a2a2..61d85fb 100644 --- a/commands/developer.js +++ b/commands/developer.js @@ -10,6 +10,12 @@ module.exports = { .setDescription("Add or remove users as Natsuki developers.") .addField("Syntax", "`developer <@user|userID>`") .addField("Notice", "You must already be a developer of Natsuki in order to use this command."), + meta: { + category: 'Developer', + description: "Add or remove users as Natsuki developers", + syntax: '`developer <@user|userID>`', + extra: "You can check if a user is a developer without being a developer." + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This is a guild-only command!");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}developer <@user|userID>\``);} diff --git a/commands/dnd.js b/commands/dnd.js index b19057f..96633ee 100644 --- a/commands/dnd.js +++ b/commands/dnd.js @@ -10,6 +10,12 @@ module.exports = { .setDescription("Set your status within the bot as DnD and specify a reason. Then, when other people ping you, I can let them know that you don't want to be disturbed!") .addField("Syntax", "`dnd [clearMode] `") .addField("Notice","Your status clear mode can be set to either 'auto' or 'manual'. If not specified, it will clear when you use `n?clearstatus`."), + meta: { + category: 'Social', + description: "Tell others not to disturb you so that they'll know not to ping you.", + syntax: '`dnd [clearMode] `', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) {return message.channel.send(`Syntax: \`${prefix}dnd [clearMode] \``);} let tu = await UserData.findOne({uid: message.author.id}) diff --git a/commands/eval.js b/commands/eval.js index 0e3c8af..03ab1c5 100644 --- a/commands/eval.js +++ b/commands/eval.js @@ -8,6 +8,12 @@ module.exports = { name: 'eval', aliases: ['ev', ':', 'e'], help: "Evaluates raw JavaScript code. *This is a __developer-only__ command.* Usage: `{{p}}eval `", + meta: { + category: 'Developer', + description: "Evaluates raw JavaScript code. Nerd access only.", + syntax: '`eval `', + extra: null + }, execute(message, msg, args, cmd, prefix, mention, client) { try { if (!client.developers.includes(message.author.id)) {return message.channel.send("Sorry, but I've got trust issues, so only me devs can go commanding me around like that.");}; diff --git a/commands/help.js b/commands/help.js index 454d7c2..2a7db91 100644 --- a/commands/help.js +++ b/commands/help.js @@ -1,6 +1,7 @@ const Discord = require("discord.js"); const {Pagination} = require('../util/pagination'); +const ask = require('../util/ask'); module.exports = { name: "help", @@ -8,7 +9,52 @@ module.exports = { help: 'you silly! What did you expect me to respond with?', async execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) { - return message.channel.send("Heya! My help command is currently under construction since my devs are hard at work on my commands and they haven't released me to the full public yet! Consider yourself lucky..."); + let sorted = {}; + await Array.from(client.commands.values()).forEach(command => {if (command.name !== "help" && command.meta) { + sorted[command.meta.category] = sorted[command.meta.category] ? sorted[command.meta.category] : {}; + sorted[command.meta.category][command.name] = command; + }}); + let helpSorted = {}; + let category; for (category of Object.keys(sorted)) { + let categorySorted = []; + let current = 1; + let currentEmbed = new Discord.MessageEmbed().setAuthor("Help Menu", message.author.avatarURL()).setTitle(category).setDescription("React to control the menu! You can also specify a command name when doing the help command to get more info about it.").setColor("c375f0"); + let commands = Object.keys(sorted[category]); + let command; for (command of commands) { + let aliases = ''; + let a; if (sorted[category][command].aliases) {for (a of sorted[category][command].aliases) {aliases += `\`${a}\`, `}} + aliases = aliases.length ? aliases.slice(0, aliases.length - 2) : 'None'; + currentEmbed.addField(`${command.slice(0,1).toUpperCase()}${command.slice(1)}`, `${sorted[category][command].meta.description}\n\nAliases: ${aliases}\nSyntax: ${sorted[category][command].meta.syntax}${sorted[category][command].meta.extra ? '\n\n' + sorted[category][command].meta.extra : ''}`); + current += 1; + if (current === 5) { + categorySorted.push(currentEmbed); + current = 1; + currentEmbed = new Discord.MessageEmbed().setAuthor("Help Menu", message.author.avatarURL()).setTitle(category).setDescription("React to control the menu! You can also specify a command name when doing the help command to get more info about it.").setColor("c375f0"); + } + } + if (current > 1) {categorySorted.push(currentEmbed);} + helpSorted[category] = categorySorted; + } + + let cat = await ask(message, "What would you like help with? (`Fun`|`Roleplay`|`Utility`|`Misc`|`Moderation`|`Social`) or `all` if you'd like to browse all commands", 60000); if (!cat) {return;} + if (!['f', 'fun', 'rp', 'roleplay', 'dnd', 'role play', 'rpg', 'dice', 'u', 'util', 'utility', 'utilities', 'm', 'misc', 'miscellaneous', 'mod', 'moderation', 's', 'social', 'a', 'all'].includes(`${cat}`.trim().toLowerCase())) {return message.channel.send("That wasn't a valid response! Try again?");} + + let pages; + if (['f', 'fun'].includes(`${cat}`.trim().toLowerCase())) {pages = helpSorted['Fun'];} + if (['roleplay', 'dnd', 'role play', 'rpg', 'dice'].includes(`${cat}`.trim().toLowerCase())) {pages = helpSorted['RP'];} + if (['u', 'util', 'utility', 'utilities'].includes(`${cat}`.trim().toLowerCase())) {pages = helpSorted['Utility'];} + if (['m', 'misc', 'miscellaneous'].includes(`${cat}`.trim().toLowerCase())) {pages = helpSorted['Misc'];} + if (['d', 'dev', 'developer'].includes(`${cat}`.trim().toLowerCase())) {pages = helpSorted['Developer'];} + if (['mod', 'moderation'].includes(`${cat}`.trim().toLowerCase())) {pages = helpSorted['Moderation'];} + if (['s', 'social'].includes(`${cat}`.trim().toLowerCase())) {pages = helpSorted['Social'];} + if (['a', 'all'].includes(`${cat}`.trim().toLowerCase())) {pages = []; let c; for (c of Object.values(helpSorted)) {let h; for (h of c) {pages.push(h)}}} + + await require('../util/wait')(500); + + if (pages.length > 1) { + let help = new Pagination(message.channel, pages, message, client, true); + return await help.start({endTime: 120000, user: message.author.id}); + } else {return message.channel.send(pages[0].setFooter("Natsuki", client.user.avatarURL()).setTimestamp());} } else { let command; if (client.commands.has(args[0])) {command = client.commands.get(args[0]);} diff --git a/commands/hug.js b/commands/hug.js index 41dae4b..340fe5b 100644 --- a/commands/hug.js +++ b/commands/hug.js @@ -6,6 +6,12 @@ const makeId = require('../util/makeid'); module.exports = { name: "hug", help: "Tell others that you need a hug with `{{p}}hug`, or give one by mentioning someone to hug!", + meta: { + category: 'Social', + description: "Give someone a hug, or tell others that you need one! We've got your back :p", + syntax: '`hug <@user>`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let savess = await Saves.findOne({name: 'hug'}) ? await Saves.findOne({name: 'hug'}) : new Saves({name: 'hug'}); let saves = savess.saves; diff --git a/commands/info.js b/commands/info.js index c76710a..56b0935 100644 --- a/commands/info.js +++ b/commands/info.js @@ -5,6 +5,12 @@ module.exports = { name: "info", aliases: ["i", "botinfo", "bot"], help: "There's not really anything to help with here! Just use `{{p}}info` to learn more about me!", + meta: { + category: 'Misc', + description: "Get info about me, my creators, and my status.", + syntax: '`info`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let botData = await require('../models/bot').findOne({finder: 'lel'}); diff --git a/commands/kick.js b/commands/kick.js new file mode 100644 index 0000000..456a28d --- /dev/null +++ b/commands/kick.js @@ -0,0 +1,68 @@ +const Discord = require('discord.js'); + +const Mod = require('../models/mod'); + +const {Tag} = require('../util/tag'); +const {TagFilter} = require('../util/tagfilter'); + +module.exports = { + name: "kick", + aliases: ['kicc', 'k'], + meta: { + category: 'Moderation', + description: "Kicks a user from the server!", + syntax: '`kick <@user|userID> [reason]`', + extra: null, + guildOnly: true + }, + help: new Discord.MessageEmbed() + .setTitle("Help -> Kick") + .setDescription("Kicks a user from the server!") + .addField("Syntax", "`kick <@user|userID> [reason]`") + .addField("Notice", "This command requires you to have `kick` permissions in the server."), + async execute(message, msg, args, cmd, prefix, mention, client) { + if (!args.length) {return message.channel.send(`Syntax: \`${prefix}kick <@user|userID> [reason]\``);} + + if (!message.member.permissions.has("KICK_MEMBERS")) {return message.channel.send("You don't have permissions to do that!");} + if (!message.guild.me.permissions.has("KICK_MEMBERS")) {return message.channel.send("I don't have permissions to kick members in your server.");} + let user = message.guild.members.cache.get(args[0]) || message.mentions.members.first(); + if (!user) {return message.channel.send("You must mention a user to kick, or provide their ID.");} + + if (user.roles.highest.position >= message.member.roles.highest.position) {return message.channel.send("You don't have permissions to kick that member as they are above you in the roles list.");} + if (user.roles.highest.position >= message.guild.me.roles.highest.position) {return message.channel.send("I can't kick that member as their highest role is above mine! (Or the same as mine, too)");} + if (!user.kickable) {return message.channel.send("For some reason, I can't kick that user!");} + + let options = new TagFilter([ + new Tag(['r', 'reason'], 'reason', 'append')/*, + new Tag(['n', 'notes'], 'notes', 'append')*/ + ]).test(args.join(" ")); + let reason; + if (options.reason && options.reason.length) {reason = options.reason;} + //if (options.notes && options.notes.length > 250) {return message.channel.send("Hey, listen, let's not write an essay on why you're kicking that member!");} + else {if (args[1]) {args.shift(); reason = args.join(" ");}} + if (reason && reason.length > 250) {return message.channel.send("Hey, listen, let's not write an essay on why you're kicking that member!");} + + return user.kick(reason) + .then(async () => { + /*let mh = await Mod.findOne({gid: message.guild.id}) || new Mod({gid: message.guild.id}); + let mhcases = mh.cases; + + mhcases.push({ + members: [user.id], + punishment: "Kicked", + reason: reason ? reason : "", + status: "Closed", + moderators: [message.author.id], + notes: options.notes, + history: [`${new Date().toISOString()} - ${message.author.username} - Created case`, `${new Date().toISOString()} - ${message.author.username} - Kicked ${client.users.cache.get(user.id).username}`], + issued: new Date().toUTCString() + }); + + mh.cases = mhcases; + mh.save();*/ + + return message.channel.send(`I got em outta here!${reason ? ` Reason for kicking: ${reason}` : ''}`); + }) + .catch(() => {return message.channel.send("Something went wrong while trying to kick that user! If the problem persists, contact my devs.");}); + } +}; \ No newline at end of file diff --git a/commands/kiss.js b/commands/kiss.js index 97b3339..c8c31bf 100644 --- a/commands/kiss.js +++ b/commands/kiss.js @@ -6,6 +6,12 @@ const makeId = require('../util/makeid'); module.exports = { name: "kiss", help: "Ask for a kiss with `{{p}}kiss`, or give one by mentioning someone!", + meta: { + category: 'Fun', + description: "Give someone a kiss, or show that you're looking for one. Best of luck pal!", + syntax: '`kiss <@user>`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let savess = await Saves.findOne({name: 'kiss'}) ? await Saves.findOne({name: 'kiss'}) : new Saves({name: 'kiss'}); let saves = savess.saves; diff --git a/commands/leave.js b/commands/leave.js index c5a919e..c73aae0 100644 --- a/commands/leave.js +++ b/commands/leave.js @@ -12,6 +12,12 @@ module.exports = { .addField("Syntax", "`leave `") .addField("Notice", "You must be a staff or admin in your server to edit these settings.") .addField("Responses", "Your leave message should be generated through a response using my `response` command, and then bound to the leave message by providing your response's name."), + meta: { + category: 'Moderation', + description: "Set the channel and message to be sent when a user leaves the server.", + syntax: '`leave `', + extra: "You must use the `response` command to create a response. The response's name is what will be given in this command." + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This command is server-only.");} let tg = await GuildData.findOne({gid: message.guild.id}) ? await GuildData.findOne({gid: message.guild.id}) : new GuildData({gid: message.guild.id}); diff --git a/commands/logs.js b/commands/logs.js index 1d558ca..8cda3bf 100644 --- a/commands/logs.js +++ b/commands/logs.js @@ -38,10 +38,16 @@ module.exports = { name: "logs", aliases: ["log", "l", "modlog", "modlogs"], help: new Discord.MessageEmbed() - .setTitle("Help -> Server Logs") - .setDescription("Configure your server's log settings.\n\nLogs will update you on events in your server that have the potential to require moderator intervention, like someone deleting a hateful message before you can see it or a misbehaving moderator kicking/banning a member when they aren't supposed to.") - .addField("Syntax", "`log [logType] [#channel]`") - .addField("Notice", "You must be an admin or have the specified staff role in order to use this command."), + .setTitle("Help -> Server Logs") + .setDescription("Configure your server's log settings.\n\nLogs will update you on events in your server that have the potential to require moderator intervention, like someone deleting a hateful message before you can see it or a misbehaving moderator kicking/banning a member when they aren't supposed to.") + .addField("Syntax", "`log [logType] [#channel]`") + .addField("Notice", "You must be an admin or have the specified staff role in order to use this command."), + meta: { + category: 'Moderation', + description: "Configure your server's log settings, which allow mods to see potentially suspicious activity in the server.", + syntax: '`log [logType] [#channel]`', + extra: "**Please note** that this command is still in the works, and that not all log types are available. The currently existing ones have been thoroughly tested, though." + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This command is server-only!");} let tg = await GuildData.findOne({gid: message.guild.id}); diff --git a/commands/prefix.js b/commands/prefix.js index e8d115f..78f9bb5 100644 --- a/commands/prefix.js +++ b/commands/prefix.js @@ -10,6 +10,12 @@ module.exports = { .addField("Syntax", "`prefix `") .addField("Staff Command", "This command requires you to either be admin, or to have the designated staff role.") .addField("Notice", "Prefixes are cached, and may take up to a minute to update."), + meta: { + category: 'Misc', + description: "Change my prefix in your server.", + syntax: '`prefix `', + extra: "You can always mention me and then type your command in place of a prefix in case you forget it." + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This is a guild-only command!");} let tguild = await GuildSettings.findOne({gid: message.guild.id}) diff --git a/commands/pull.js b/commands/pull.js index 7daab80..401b22b 100644 --- a/commands/pull.js +++ b/commands/pull.js @@ -9,8 +9,14 @@ module.exports = { help: new Discord.MessageEmbed() .setTitle("Help -> VCS Pull") .setDescription("Pulls new commits from VCS") - .addField("Syntax", "`refresh`") + .addField("Syntax", "`pull`") .addField("Notice", "This command is only available to Natsuki developers."), + meta: { + category: 'Developer', + description: "Pull new commits from VSC and update the bot. Otaku zone, non-otakus not allowed.", + syntax: '`pull`', + extra: "You'll still need to use `reload` afterwards" + }, async execute(message, msg, args, cmd, prefix, mention, client) { const tu = await UserData.findOne({uid: message.author.id}); if (!tu || !tu.developer) {return message.channel.send("You must be a Natsuki developer in order to do this!");} diff --git a/commands/randnum.js b/commands/randnum.js index 24197ce..8f17250 100644 --- a/commands/randnum.js +++ b/commands/randnum.js @@ -17,6 +17,12 @@ module.exports = { .setTitle("Help -> Random Numbers") .setDescription("Generates a Random Number in the specified range.") .addField("Syntax", "`randnum [count]`"), + meta: { + category: 'Utility', + description: "Generate a random number... or a lot of them. It's up to you, really.", + syntax: '`randnum [count]`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) {return message.channel.send(`Syntax: \`${prefix}randnum [count]\``);} if (args.length < 2) {return message.channel.send("You have to specify two numbers");} diff --git a/commands/reload.js b/commands/reload.js index a76eb8e..bb0f3a5 100644 --- a/commands/reload.js +++ b/commands/reload.js @@ -1,6 +1,8 @@ const Discord = require('discord.js'); const fs = require('fs'); const chalk = require('chalk'); +const ora = require('ora'); + const UserData = require("../models/user"); module.exports = { @@ -11,24 +13,33 @@ module.exports = { .setDescription("Reloads the system extensions by refreshing all command and event files into client without terminating the node process. *Hi I'm Wubzy and this makes no sense to anyone but discord.js devs because we're nerds*") .addField("Syntax", "`refresh [log]`. Adding 'log' will log to the console as though the bot were in startup.") .addField("Notice", "This command is only available to Natsuki developers."), + meta: { + category: 'Developer', + description: "Refresh all client commands and events and clear most of the require cache. Only two people can use this command and they're probably not you.", + syntax: '`reload`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) { const tu = await UserData.findOne({uid: message.author.id}); if (!tu || !tu.developer) {return message.channel.send("You must be a Natsuki developer in order to do this!");} - var commands = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); + let commands = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); console.log(`\n${chalk.yellow('[WARN]')} >> ${chalk.gray('Reload:')} ${chalk.white('All commands and events are being reloaded!')}`); console.log(`${chalk.gray('[INFO]')} >> ${chalk.hex('ff4fd0')(`Developer ${message.author.username} initiated the system refresh`)}\n`); + let cmdspinner = ora(chalk.blue('Loading Commands')).start(); ['commands', 'aliases'].forEach(x => client[x] = new Discord.Collection()); for (let commandf of commands) { if (Object.keys(require.cache).includes(require.resolve(`./${commandf}`))) {delete require.cache[require.resolve(`./${commandf}`)];} - var command = require(`./${commandf}`); + let command = require(`./${commandf}`); client.commands.set(command.name, command); if (command.aliases) {command.aliases.forEach(a => client.aliases.set(a, command.name));} } + cmdspinner.stop(); cmdspinner.clear(); console.log(`${chalk.gray('[LOG]')} >> ${chalk.blue('Loaded all Commands')}`); + let eventspinner = ora(chalk.blue('Loading Events')).start(); let eventFilter = fs.readdirSync('./events/').filter(x => x.endsWith('.js')); for (let file of eventFilter) { let evtName = file.split('.')[0]; @@ -37,16 +48,19 @@ module.exports = { client.removeAllListeners(evtName); client.on(evtName, evt.bind(null, client)); } + eventspinner.stop(); eventspinner.clear(); console.log(`${chalk.gray('[LOG]')} >> ${chalk.blue('Loaded all Events')}`); - var responses = fs.readdirSync('./responses').filter(file => file.endsWith('.js')); + let rspspinner = ora(chalk.blue('Loading Commands')).start(); + let responses = fs.readdirSync('./responses').filter(file => file.endsWith('.js')); client.responses.triggers = []; for (let responsef of responses) { if (Object.keys(require.cache).includes(require.resolve(`../responses/${responsef}`))) {delete require.cache[require.resolve(`../responses/${responsef}`)];} - var response = require(`../responses/${responsef}`); + let response = require(`../responses/${responsef}`); client.responses.triggers.push([response.name, response.condition]); client.responses.commands.set(response.name, response); } + rspspinner.stop(); rspspinner.clear(); console.log(`${chalk.gray('[LOG]')} >> ${chalk.blue('Loaded all Responses')}`); console.log(`\n${chalk.gray('[INFO]')} >> ${chalk.hex('ff4fd0')(`Client refresh successful`)}\n`); diff --git a/commands/response.js b/commands/response.js index e285dd9..c6df9b2 100644 --- a/commands/response.js +++ b/commands/response.js @@ -1,4 +1,5 @@ const Discord = require('discord.js'); + const GuildData = require('../models/guild'); const Responses = require('../models/responses'); @@ -15,10 +16,16 @@ module.exports = { .setDescription("Configure your server's saved responses. These are reusable and editable, and can be placed in things like welcome messages and used for announcements.") .addField("Syntax", "`response `") .addField("Notice", "You must have your server's staff role or be an admin to use this command."), + meta: { + category: 'Moderation', + description: "Set responses that can be used for various purposes in your server, namely welcome and leave messages.", + syntax: '`response `', + extra: "Response editing is currently not available and will be Soon:tm:" + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("You must be in a server to use this command.");} let tg = await GuildData.findOne({gid: message.guild.id}); - if (!tg && !['q', 'quick'].includes(args[0].toLowerCase()) && (tg.staffrole.length && !message.member.roles.cache.has(tg.staffrole)) && message.member.permissions.has("ADMINISTRATOR")) {return message.reply("you need to be staff or admin in this server in order to edit those settings.");} + if (!['q', 'quick'].includes(args[0].toLowerCase()) && ((tg && tg.staffrole.length && !message.member.roles.cache.has(tg.staffrole))) && !message.member.permissions.has("ADMINISTRATOR")) {return message.reply("you need to be staff or admin in this server in order to edit those settings.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}response \``);} if (args.length < 1) {return message.reply("You have to tell me what I'm supposed to find or save!");} diff --git a/commands/secretsanta.js b/commands/secretsanta.js index aeb5147..a97e61e 100644 --- a/commands/secretsanta.js +++ b/commands/secretsanta.js @@ -9,9 +9,15 @@ module.exports = { help: new Discord.MessageEmbed() .setTitle("Help -> Secret Santa") .setDescription("Create a secret santa for all of your friends or for your server! Whether you celebrate the holidays or not, this can still be loads of fun!") - .addField("Syntax", "``"), + .addField("Syntax", "`secretsanta `"), + meta: { + category: 'Fun', + description: "Create and join fully-functioning secret santas. I even randomize the assignments for you, how neat!", + syntax: '`secretsanta `', + extra: "It's not Christmas anymore, but you know what, who cares. Some features of this command, such as `end` and `kick` are not available/not working." + }, async execute(message, msg, args, cmd, prefix, mention, client) { - if (!args.length) {return message.channel.send(`Syntax: \`${prefix}\``);} + if (!args.length) {return message.channel.send(`Syntax: \`${prefix}secretsanta \``);} if (['create', 'new', 'c', 'n', 's'].includes(args[0].toLowerCase())) { function clearDM() {client.misc.activeDMs.delete(message.author.id);} if (client.misc.activeDMs.has(message.author.id)) {return message.reply("I'm already asking you questions in DM for a separate command! Finish that command before using this one.");} diff --git a/commands/setstatus.js b/commands/setstatus.js index 6c100f7..d143653 100644 --- a/commands/setstatus.js +++ b/commands/setstatus.js @@ -9,22 +9,19 @@ module.exports = { name: "setstatus", aliases: ['sst'], meta: { - category: "", - perms: "", - staff: false, - vip: "", - serverPerms: [], - writtenBy: "", - serverOnly: false + category: 'Developer', + description: "Set my public status. Don't make me say something weird! (Also only available to devs, of course.)", + syntax: '`setstatus <-s status> <-t type>`', + extra: "You can check if a user is an admin without being a developer." }, tags: [], help: new Discord.MessageEmbed() .setTitle("Help -> Status-Setting") .setDescription("Sets the bot's status") - .addField("Syntax", "`setstatus [type]`") + .addField("Syntax", "`setstatus <-s status> <-t type>`") .addField('Notice', "This command is **developer-only**"), async execute(message, msg, args, cmd, prefix, mention, client) { - if (!args.length) {return message.channel.send(`Syntax: \`${prefix}setstatus [type]\``);} + if (!args.length) {return message.channel.send(`Syntax: \`${prefix}setstatus <-s status> <-t type>\``);} let tu = await UserData.findOne({uid: message.author.id}); if (!tu || !tu.developer) {return message.channel.send("You must be a Natsuki developer in order to do that!");} diff --git a/commands/sip.js b/commands/sip.js index e5dd740..4ddd0c0 100644 --- a/commands/sip.js +++ b/commands/sip.js @@ -6,6 +6,12 @@ const makeId = require('../util/makeid'); module.exports = { name: "sip", help: "Take a sip and watch the shenanigans unfold using `{{p}}sip`.", + meta: { + category: 'Social', + description: "Take a sip and watch the shenanigans unfold. Slurp if you're feeling... risqué.", + syntax: '`sip`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let savess = await Saves.findOne({name: 'sip'}) ? await Saves.findOne({name: 'sip'}) : new Saves({name: 'sip'}); let saves = savess.saves; diff --git a/commands/slap.js b/commands/slap.js index a94a622..6700f24 100644 --- a/commands/slap.js +++ b/commands/slap.js @@ -5,7 +5,14 @@ const makeId = require('../util/makeid'); module.exports = { name: "slap", + aliases: ['hit'], help: "Use `{{p}}slap @person` to have me personally deliver your anger to them with a nice s l a p.", + meta: { + category: 'Fun', + description: "Slap another user! Virtually, of course.", + syntax: '`slap <@user>`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let savess = await Saves.findOne({name: 'slap'}) ? await Saves.findOne({name: 'slap'}) : new Saves({name: 'slap'}); let saves = savess.saves; diff --git a/commands/staff.js b/commands/staff.js index 48b3477..e14c06e 100644 --- a/commands/staff.js +++ b/commands/staff.js @@ -8,6 +8,12 @@ module.exports = { .setDescription("Make a user a Natsuki staff member") .addField("Syntax", "`staff <@user|userID>`") .addField("Notice", "This command is only available to Natsuki developers."), + meta: { + category: 'Developer', + description: "Add or remove users as Natsuki staff", + syntax: '`staff <@user|userID>`', + extra: "You can check if a user is staff without being a developer." + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This is a guild-only command.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}\``);} diff --git a/commands/staffrole.js b/commands/staffrole.js index 4b2e494..05235d6 100644 --- a/commands/staffrole.js +++ b/commands/staffrole.js @@ -6,6 +6,12 @@ module.exports = { name: "staffrole", aliases: ['sr', 'setstaffrole'], help: "Set your server's staff role, which allows users with that role to modify my settings in this server. You must be an admin in the server to change this setting.", + meta: { + category: 'Moderation', + description: "Set the role that can edit my settings for the server", + syntax: '`staffrole <@role|roleID|clear|view>`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This is a guild-only command!");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}staffrole <@role|roleID|clear|view>\``);} diff --git a/commands/starboard.js b/commands/starboard.js index 217154d..2846603 100644 --- a/commands/starboard.js +++ b/commands/starboard.js @@ -10,6 +10,12 @@ module.exports = { .setDescription("Setup and view information on this server's starboard! This allows messages to be sent to a dedicated channel when they receive a set number of star messages.") .addField("Syntax", "`starboard `") .addField("Notice", "You must have the staff-role or be an admin in order to set up or toggle the starboard"), + meta: { + category: 'Social', + description: "Set up a star board to feature users' messages in", + syntax: '`starboard `', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("You must be in a server in order to use this command.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}starboard \``);} diff --git a/commands/support.js b/commands/support.js index 490bbc1..16b7863 100644 --- a/commands/support.js +++ b/commands/support.js @@ -8,6 +8,12 @@ module.exports = { .setDescription("Make a user a Natsuki Support Team member") .addField("Syntax", "`support <@user|userID>`") .addField("Notice", "This command is only available to Natsuki admin."), + meta: { + category: 'Developer', + description: "Add or remove users as Natsuki support", + syntax: '`support <@user|userID>`', + extra: "You can check if a user is a support member without being a developer." + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This is a guild-only command.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}\``);} diff --git a/commands/testpage.js b/commands/testpage.js deleted file mode 100644 index b2562dd..0000000 --- a/commands/testpage.js +++ /dev/null @@ -1,44 +0,0 @@ -const Discord = require('discord.js'); -const {Pagination} = require('../util/pagination'); - -module.exports = { - name: "testpage", - aliases: ['tp'], - meta: { - category: "", - perms: "", - staff: false, - vip: "", - serverPerms: [], - writtenBy: "", - serverOnly: false - }, - tags: [], - help: new Discord.MessageEmbed() - .setTitle("Help -> ") - .setDescription("") - .addField("Syntax", "``"), - async execute(message, msg, args, cmd, prefix, mention, client) { - let p = await new Pagination(message.channel, [ - new Discord.MessageEmbed() - .setTitle("bonk") - .setDescription("bonk horny jail") - .addField("bonk", "you have been bonked") - .setColor('c375f0'), - new Discord.MessageEmbed() - .setTitle("stonks") - .setDescription("yeet") - .setColor('c375f0'), - new Discord.MessageEmbed() - .setTitle("honks") - .setDescription("such wow many honks") - .addField("aye", "lul text") - .setColor('c375f0'), - new Discord.MessageEmbed() - .setTitle("yoink") - .setDescription("give me the vibes") - .addField("vibecheck", "your vibe will now be checked.") - .setColor('c375f0'), - ], message, client).start({endTime: 60000, user: message.author.id}); - } -}; \ No newline at end of file diff --git a/commands/togglestatuses.js b/commands/togglestatuses.js index f2284be..74fc4e6 100644 --- a/commands/togglestatuses.js +++ b/commands/togglestatuses.js @@ -8,6 +8,12 @@ module.exports = { .setTitle("Help -> Server Status-Toggling") .setDescription("Disables or enables the warning that appears when you ping someone that has a status set.") .addField("Syntax", "`togglestatuses [c]` (add `c` to the end of the message if you want to check if they're enabled or not.)"), + meta: { + category: 'Moderation', + description: "Toggle the warning I give members when they ping someone with a status. Some people find it annoying, but here's my mute button!", + syntax: '`togglestatuses [-c]`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply('You must be in a server to use this command.');} let tg = await GuildSettings.findOne({gid: message.guild.id}); diff --git a/commands/userinfo.js b/commands/userinfo.js index 9ce5d9b..fc8f627 100644 --- a/commands/userinfo.js +++ b/commands/userinfo.js @@ -7,6 +7,12 @@ module.exports = { name: "userinfo", aliases: ['ui', 'memberinfo', 'user'], help: "Shows your info, or shows the info of a user you ping.", + meta: { + category: 'Misc', + description: "See some info about a user", + syntax: '`userinfo [@user]`', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { let person = message.guild ? mention ? message.guild.members.cache.get(mention.id) : args[0] ? message.guild.members.cache.has(args[0]) ? message.guild.members.cache.get(args[0]) : message.member : message.member : message.author; let name = message.guild ? person.displayName : person.username; diff --git a/commands/vip.js b/commands/vip.js index 55cc1a8..b594d78 100644 --- a/commands/vip.js +++ b/commands/vip.js @@ -8,6 +8,12 @@ module.exports = { .setDescription("Toggle a server as VIP. This grants a few small bonuses to your server that you can't get anywhere else!\n\nWant to become a VIP? Support the bot by [joining the support server](), donating to the bot's creators, or promoting/spreading the bot to other servers.") .addField("Syntax", "`vip `") .addField("Notice", "This command is **developer-only**."), + meta: { + category: 'Developer', + description: "Set server VIP status", + syntax: '`vip `', + extra: "This command is mostly cosmetic as there are no real perks *yet*" + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This command is server-only!");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}vip \``);} diff --git a/commands/warn.js b/commands/warn.js index 3b76ece..f1b8122 100644 --- a/commands/warn.js +++ b/commands/warn.js @@ -9,9 +9,15 @@ module.exports = { name: "warn", help: new Discord.MessageEmbed() .setTitle("Help -> Warnings") - .setDescription("") + .setDescription("Warn misbehaving members that what they are doing is wrong, and have it stored in a database in order to see a list of all their past warnings") .addField("Syntax", "`warn <@member> `") .addField("Notice", "You must be a server administrator in order to use this command."), + meta: { + category: 'Moderation', + description: "Warn misbehaving members that what they are doing is wrong, and have it stored in a database in order to see a list of all their past warnings", + syntax: '`warn <@member> `', + extra: null + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.channel.send("This is a server-only command.");} if (!args.length) {return message.channel.send(`Syntax: \`${prefix}warn <@member> \``);} diff --git a/commands/welcome.js b/commands/welcome.js index 3ddade7..fe0d511 100644 --- a/commands/welcome.js +++ b/commands/welcome.js @@ -12,12 +12,18 @@ module.exports = { .addField("Syntax", "`welcome `") .addField("Notice", "You must be a staff or admin in your server to edit these settings.") .addField("Responses", "Your welcome message should be generated through a response using my `response` command, and then bound to the welcome message by providing your response's name."), + meta: { + category: 'Moderation', + description: "Set the channel and message to be sent when a user joins the server.", + syntax: '`welcome `', + extra: "You'll need to use `response` to configure the message that you want sent with this command. The name you give the response is what you'll give to this command" + }, async execute(message, msg, args, cmd, prefix, mention, client) { if (!message.guild) {return message.reply("This command is server-only.");} let tg = await GuildData.findOne({gid: message.guild.id}) ? await GuildData.findOne({gid: message.guild.id}) : new GuildData({gid: message.guild.id}); if (!args.length) {return message.channel.send(`Syntax: \`${prefix}welcome \``);} if (['v', 'view', 'c', 'check'].includes(args[0].toLowerCase())) {} - if ((!tg.staffrole.length || !message.member.roles.cache.has(tg.staffrole)) && !message.member.permissions.has("ADMINISTRATOR")) {return message.reply("You can't do that without staff or admin permissions, silly!");} + if ((!tg || !tg.staffrole.length || !message.member.roles.cache.has(tg.staffrole)) && !message.member.permissions.has("ADMINISTRATOR")) {return message.reply("You can't do that without staff or admin permissions, silly!");} if (['s', 'set'].includes(args[0].toLowerCase())) { if (!args[1]) {return message.reply("You need to specify a channel for your welcome messages to be sent in!");} diff --git a/events/message.js b/events/message.js index a0220fa..a6a5de8 100644 --- a/events/message.js +++ b/events/message.js @@ -14,16 +14,16 @@ module.exports = async (client, message) => { if (message.guild && !message.member.permissions.has("SEND_MESSAGES")) {return undefined;} - var prefix = message.guild ? client.guildconfig.prefixes.has(message.guild.id) ? client.guildconfig.prefixes.get(message.guild.id) !== null ? client.guildconfig.prefixes.get(message.guild.id) : 'n?' : 'n?' : 'n?'; + let prefix = message.guild ? client.guildconfig.prefixes.has(message.guild.id) ? client.guildconfig.prefixes.get(message.guild.id) !== null ? client.guildconfig.prefixes.get(message.guild.id) : 'n?' : 'n?' : 'n?'; - var msg = message.content.toLowerCase(); - var mention = message.mentions.users.first(); - var args = msg.startsWith(prefix) + let msg = message.content.toLowerCase(); + let mention = message.mentions.users.first(); + let args = msg.startsWith(prefix) ? message.content.slice(prefix.length).trim().split(/\s+/g) : msg.startsWith('<@!') ? message.content.slice(4 + client.user.id.length).trim().split(/\s+/g) : message.content.slice(3 + client.user.id.length).trim().split(/\s+/g); - var cmd = args.shift().toLowerCase().trim(); + let cmd = args.shift().toLowerCase().trim(); if ([`<@${client.user.id}>`, `<@!${client.user.id}>`].includes(msg)) { return message.channel.send(new Discord.MessageEmbed() @@ -33,18 +33,14 @@ module.exports = async (client, message) => { } if (mention && message.guild) {require('../util/mention')(message, msg, args, cmd, prefix, mention, client);} - let tu = await UserData.findOne({uid: message.author.id}); + UserData.findOne({uid: message.author.id}).then(async (tu) => { if (tu && tu.statusmsg.length && tu.statusclearmode === 'auto') { tu.statusmsg = ''; tu.statustype = ''; tu.save(); - const statuses = await StatusCache.findOne({f: 'lol'}); - let status; for (status of statuses.statuses) { - if (status.id === message.author.id) {delete statuses.statuses.indexOf(status);} - } - statuses.save(); - message.reply('Hey there! You asked me to clear your status when you send a message next, so I went ahead and did that for you.'); - } + require('../util/siftstatuses')(client, message.author.id, true); + message.reply('Hey there! You asked me to clear your status when you send a message next, so I went ahead and did that for you.').then(m => {m.delete({timeout: 5000});}); + }}); try { if (msg.startsWith(prefix) || msg.startsWith(`<@${client.user.id}>`) || msg.startsWith(`<@!${client.user.id}>`)) { @@ -53,12 +49,13 @@ module.exports = async (client, message) => { message.channel.startTyping(); await wait(800); message.channel.stopTyping(); + if (command.meta && command.meta.guildOnly && !message.guild) {return message.channel.send("You must be in a server to use this command!");} require('../util/oncommand')(message, msg, args, cmd, prefix, mention, client); return command.execute(message, msg, args, cmd, prefix, mention, client); } let trigger; for (trigger of client.responses.triggers) {if (await trigger[1](message, msg, args, cmd, prefix, mention, client)) {await client.responses.commands.get(trigger[0]).execute(message, msg, args, cmd, prefix, mention, client); break;}} } catch (e) { - var date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6); + let date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6); console.error(`\n${chalk.red('[ERROR]')} >> ${chalk.yellow(`At [${date}] | In ${message.guild.name}\n`)}`, e); } }; \ No newline at end of file diff --git a/events/ready.js b/events/ready.js index 7c33d8f..52ae3b8 100644 --- a/events/ready.js +++ b/events/ready.js @@ -13,14 +13,6 @@ var prefix = 'n?'; module.exports = async client => { const config = client.config; - try { - await mongoose.connect(`mongodb+srv://${config.database.user}:${config.database.password}@${config.database.cluster}.3jpp4.mongodb.net/test`, { - useFindAndModify: false, useNewUrlParser: true, dbName: 'Natsuki-Main', useUnifiedTopology: true, useCreateIndex: true - }); - } catch (e) { - let date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6); - console.error(`\n${chalk.red('[ERROR]')} >> ${chalk.yellow(`At [${date}] | Occurred while trying to connect to Mongo Cluster`)}`, e); - } /*let db = mongoose.connection; await db.guild.update({}, {"$set": {'prefix': ''}}, false, true);*/ diff --git a/handle/command.js b/handle/command.js index 2f88f53..e1f39af 100644 --- a/handle/command.js +++ b/handle/command.js @@ -1,16 +1,28 @@ const Discord = require('discord.js'); const fs = require('fs'); const chalk = require('chalk'); +//const ora = require('ora'); module.exports = client => { var commands = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); + + //console.log(''); + //let cora = ora(`${chalk.white("Loading commands into client.")} ${chalk.blue("[")}${chalk.blueBright("0")}${chalk.blue("/")}${chalk.blueBright(`${commands.length}`)}${chalk.blue("]")}`).start(); + //let num = 0; console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Commands...')}\n`); for (let commandf of commands) { + //num++; + //cora.text = `${chalk.white("Loading commands into client.")} ${chalk.blue("[")}${chalk.blueBright(`${num}`)}${chalk.blue("/")}${chalk.blueBright(`${commands.length}`)}${chalk.blue("]")}`; if (Object.keys(require.cache).includes(require.resolve(`../commands/${commandf}`))) {delete require.cache[require.resolve(`../commands/${commandf}`)];} var command = require(`../commands/${commandf}`); client.commands.set(command.name, command); if (command.aliases) {command.aliases.forEach(a => client.aliases.set(a, command.name));} console.log(`${chalk.gray('[LOG] ')} >> ${chalk.blueBright('Loaded Command')} ${chalk.white(command.name)} ${chalk.blueBright('with')} ${chalk.white(command.aliases && command.aliases.length ? command.aliases.length : 0)} ${chalk.blueBright('aliases')}`); } + /*cora.stop(); cora.clear(); + console.log(`${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Commands...')}\n`); + Array.from(client.commands.values()).forEach(command => { + console.log(`${chalk.gray('[LOG] ')} >> ${chalk.blueBright('Loaded Command')} ${chalk.white(command.name)} ${chalk.blueBright('with')} ${chalk.white(command.aliases && command.aliases.length ? command.aliases.length : 0)} ${chalk.blueBright('aliases')}`); + });*/ console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Commands')}`); }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c2c83aa..2bf4609 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1388,11 +1388,9 @@ "integrity": "sha512-2N7AmszH/WPPpl5Z3XMw1HAP+8d+xugnKQAeKvxFZ/04dbT/CAznqwbl+7eSr3HkwdepNwtb2yx3CAMQWvG01Q==", "requires": { "clone-response": "^1.0.2", - "get-stream": "^4.0.0", "http-cache-semantics": "^4.0.0", "keyv": "^3.0.0", "lowercase-keys": "^1.0.1", - "normalize-url": "^3.1.0", "responselike": "^1.0.2" } }, @@ -1440,14 +1438,6 @@ "ms": "2.1.2" } }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "requires": { - "mimic-response": "^1.0.0" - } - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1569,14 +1559,6 @@ "write": "1.0.3" } }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, "globals": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", @@ -1590,11 +1572,8 @@ "@sindresorhus/is": "^0.14.0", "@szmarczak/http-timer": "^1.1.2", "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", "p-cancelable": "^1.0.0", "to-readable-stream": "^1.0.0", "url-parse-lax": "^3.0.0" @@ -1722,11 +1701,6 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -1753,11 +1727,6 @@ } } }, - "normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==" - }, "onetime": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", @@ -5503,6 +5472,15 @@ "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", @@ -5744,6 +5722,11 @@ } } }, + "cli-spinners": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz", + "integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==" + }, "cli-ux": { "version": "4.9.3", "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-4.9.3.tgz", @@ -5846,6 +5829,11 @@ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -6067,6 +6055,14 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -7010,6 +7006,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", @@ -7208,6 +7209,11 @@ "is-extglob": "^2.1.1" } }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -7433,6 +7439,14 @@ "byline": "5.x" } }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "requires": { + "chalk": "^4.0.0" + } + }, "logform": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", @@ -7922,6 +7936,56 @@ "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" }, + "ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "requires": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -9113,6 +9177,14 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index 61ed0bf..bbf9ac2 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "moment": "^2.28.0", "mongoose": "^5.10.3", "node-fetch": "^2.6.1", + "ora": "^5.3.0", "sequelize": "^5.22.3", "sqlite3": "^4.2.0", "swwrap": "^1.0.0", diff --git a/template.js b/template.js index 74475a2..8cbfcff 100644 --- a/template.js +++ b/template.js @@ -4,15 +4,11 @@ module.exports = { name: "", aliases: [], meta: { - category: "", - perms: "", - staff: false, - vip: "", - serverPerms: [], - writtenBy: "", - serverOnly: false + category: '', + description: "", + syntax: '` <>`', + extra: null }, - tags: [], help: new Discord.MessageEmbed() .setTitle("Help -> ") .setDescription("") @@ -30,15 +26,11 @@ module.exports = { name: "", aliases: [], meta: { - category: "", - perms: "", - staff: false, - vip: "", - serverPerms: [], - writtenBy: "", - serverOnly: false + category: '', + description: "", + syntax: '` <>`', + extra: null }, - tags: [], help: "", async execute(message, msg, args, cmd, prefix, mention, client) { if (!args.length) {return message.channel.send(`Syntax: \`${prefix}\``);} diff --git a/util/mention.js b/util/mention.js index 14ead11..6809bb0 100644 --- a/util/mention.js +++ b/util/mention.js @@ -12,6 +12,9 @@ module.exports = async(message, msg, args, cmd, prefix, mention, client) => { if (tu && tu.statusmsg.length) { if (!client.misc.statusPings.has(message.guild.id)) {client.misc.statusPings.set(message.guild.id, new Discord.Collection());} client.misc.statusPings.get(message.guild.id).set(mention.id, new Date()); - return message.reply(`That user ${tu.statustype === 'dnd' ? 'wishes not to be disturbed' : 'is AFK'}. Reason: \`${tu.statusmsg}\`. (This status was set ${moment(tu.statussetat.getTime()).fromNow()})`); + let m = await message.channel.send(`That user ${tu.statustype === 'dnd' ? 'wishes not to be disturbed' : 'is AFK'}. Reason: ${tu.statusmsg}.${tu.statssetat ? ` \`(This status was set ${moment(tu.statussetat.getTime()).fromNow()})\`` : ''}`); + await require('../util/wait')(10000); + m.delete().catch((e) => {console.log(e);}); + console.log(m); } }; \ No newline at end of file diff --git a/util/pagination.js b/util/pagination.js index 154cc21..9123e5f 100644 --- a/util/pagination.js +++ b/util/pagination.js @@ -88,7 +88,6 @@ class Pagination { : (r) => { return emoji.includes(r.emoji.name); }; this.controllers.collector = this.message.createReactionCollector(filter, { time: 450000 }); this.controllers.collector.on('collect', async (r) => { - console.log(r); let functions = { '⬅': () => { return this.prevPage(); }, '➡': () => { return this.nextPage(); }, diff --git a/util/siftstatuses.js b/util/siftstatuses.js index 7cfe378..320526e 100644 --- a/util/siftstatuses.js +++ b/util/siftstatuses.js @@ -1,14 +1,16 @@ const UserData = require('../models/user'); const StatusCache = require('../models/statuses'); -module.exports = async function (client, lookFor) { +module.exports = async function (client, lookFor, forceClear) { let statusesm = await StatusCache.findOne({f: 'lol'}) || new StatusCache({f: 'lol', statuses: []}); let statuses = statusesm.statuses; let date = new Date(); let ns = []; if (!client) {return 'no client found or given';} + let forcePass; let status; for (status of statuses) { - if (date.getTime() > status.clear.getTime()) { + forcePass = lookFor && status.id === lookFor && forceClear; + if (date.getTime() > status.clear.getTime() || forcePass) { if (lookFor && status.id !== lookFor) {continue;} let tu = await UserData.findOne({uid: status.id}); if (tu) { diff --git a/util/ts/pagination.ts b/util/ts/pagination.ts index ae786f6..d27561a 100644 --- a/util/ts/pagination.ts +++ b/util/ts/pagination.ts @@ -31,7 +31,7 @@ export class Pagination { if (!this.message) { let tempm = await this.channel.send("One moment...") - .catch(() => {this.originalMessage.reply("There seemed to be a problem doing that..."); return this;}); + .catch(() => {this.originalMessage.reply("There seemed to be a problem doing that..."); return this;}); if (tempm instanceof Pagination) {return this;} else {this.message = tempm;} } @@ -98,7 +98,6 @@ export class Pagination { this.controllers.collector = this.message.createReactionCollector(filter, {time: 450000}); this.controllers.collector.on('collect', async (r: MessageReaction) => { - console.log(r); let functions = { '⬅': () => {return this.prevPage();}, '➡': () => {return this.nextPage();},