diff --git a/commands/admin/lockchannel.js b/commands/admin/lockchannel.js index 472052f..2102112 100644 --- a/commands/admin/lockchannel.js +++ b/commands/admin/lockchannel.js @@ -8,24 +8,26 @@ module.exports = { const arg = interaction.options.data[0]; const guild = bot.guilds.cache.get(interaction.guildId); - if (!checkRole(bot, guild, interaction.user.id)) { return interaction.reply('Insufficient Permissions!'); } + checkRole(bot, guild, interaction.user.id).then((isAllowed) => { + if (isAllowed) { return interaction.reply('Insufficient Permissions!'); } - var channel; - if (arg) { - channel = arg.channel; - } else { - channel = interaction.channel; - } + var channel; + if (arg) { + channel = arg.channel; + } else { + channel = interaction.channel; + } - let role = interaction.guild.roles.cache.find(r => r.name === "@everyone"); - channel.permissionOverwrites.edit(role.id, { - VIEW_CHANNEL: true, - SEND_MESSAGES: false, - READ_MESSAGE_HISTORY: true, - ATTACH_FILES: false + let role = interaction.guild.roles.cache.find(r => r.name === "@everyone"); + channel.permissionOverwrites.edit(role.id, { + VIEW_CHANNEL: true, + SEND_MESSAGES: false, + READ_MESSAGE_HISTORY: true, + ATTACH_FILES: false + }); + + interaction.reply(`${channel} has been locked!`); }); - - interaction.reply(`${channel} has been locked!`); }, options: [{name: 'channel', description: 'The channel to lock (defaults to current channel)', type: Constants.ApplicationCommandOptionTypes.CHANNEL, required: false}] } \ No newline at end of file diff --git a/commands/admin/moderation.js b/commands/admin/moderation.js index 2dfad25..a0f4f3e 100644 --- a/commands/admin/moderation.js +++ b/commands/admin/moderation.js @@ -99,51 +99,53 @@ function moderation_handler(bot, interaction, command) { const guild = interaction.guild; //Verify - if (!checkRole(bot, guild, interaction.user.id)) { return interaction.reply('Insufficient Permission!'); } + checkRole(bot, guild, interaction.user.id).then((isAllowed) => { + if (!isAllowed) { return interaction.reply('Insufficient Permission!'); } - const mentioned = interaction.options.data.filter((arg) => { return (arg.name == 'user'); })[0].user; - if (mentioned && mentioned.id == interaction.user.id) { return interaction.reply(`You can't ${command} yourself!`); } + const mentioned = interaction.options.data.filter((arg) => { return (arg.name == 'user'); })[0].user; + if (mentioned && mentioned.id == interaction.user.id) { return interaction.reply(`You can't ${command} yourself!`); } - const reasonInit = interaction.options.data.filter((arg) => { return (arg.name == 'reason'); })[0]; - const reason = (reasonInit) ? reasonInit.value : "None"; + const reasonInit = interaction.options.data.filter((arg) => { return (arg.name == 'reason'); })[0]; + const reason = (reasonInit) ? reasonInit.value : "None"; - const user = guild.members.resolve(mentioned.id); + const user = guild.members.resolve(mentioned.id); - if (user && (user.roles.highest.position > guild.members.resolve(bot.user).roles.highest.position)) { - return interaction.reply("I'm not high enough in the role hierarchy to do that!\n_To raise my place, go to **Server Settings -> Roles** then drag me up!_"); - } + if (user && (user.roles.highest.position > guild.members.resolve(bot.user).roles.highest.position)) { + return interaction.reply("I'm not high enough in the role hierarchy to do that!\n_To raise my place, go to **Server Settings -> Roles** then drag me up!_"); + } - - // if (command != 'unban' && !mentioned || !reason) { return message.channel.send(`Please use the following format: _! `); } - // if (command == 'unban' && !args[0] && !reason) { return message.channel.send("Please use the following format: _!unban # \nExample: _!unban John#1122_"); } - // if (command == 'ban' && guild.members.cache.get(mentioned.id).bannable) { message.reply("This user is not bannable!"); } //Broken - // if (command == 'ban' && !message.guild.members.cache.get(mentioned.id)) { message.reply("This user is not in the server"); } - - switch (command) { - case 'kick': kick(guild, mentioned); - log(bot, interaction, command, mentioned, reason, SEVCODES.medium); - break; - - case 'ban': toggle_ban(guild, interaction, mentioned, true, reason); - log(bot, interaction, command, mentioned, reason, SEVCODES.high); - break; - - //Leave the then() catch() thing, it needs to be async - case 'unban': toggle_ban(guild, interaction, false, reason).then((user) => { log(bot, interaction, command, user, reason, SEVCODES.none)}).catch((note) => { interaction.reply(note); }); - break; - - case 'mute': toggle_mute(bot, guild, command, interaction, mentioned, reason, true); - break; - case 'unmute': toggle_mute(bot, guild, command, interaction, mentioned, reason, true); - break; + // if (command != 'unban' && !mentioned || !reason) { return message.channel.send(`Please use the following format: _! `); } + // if (command == 'unban' && !args[0] && !reason) { return message.channel.send("Please use the following format: _!unban # \nExample: _!unban John#1122_"); } + // if (command == 'ban' && guild.members.cache.get(mentioned.id).bannable) { message.reply("This user is not bannable!"); } //Broken + // if (command == 'ban' && !message.guild.members.cache.get(mentioned.id)) { message.reply("This user is not in the server"); } - // case 'timeout': timeOut(bot, mentioned, message, args, command, reason); - // shouldIlog = false; - // break; - - default: console.log(`ERROR! Moderation Command "${command}" has somehow been used!`); - } + switch (command) { + case 'kick': kick(guild, mentioned); + log(bot, interaction, command, mentioned, reason, SEVCODES.medium); + break; + + case 'ban': toggle_ban(guild, interaction, mentioned, true, reason); + log(bot, interaction, command, mentioned, reason, SEVCODES.high); + break; + + //Leave the then() catch() thing, it needs to be async + case 'unban': toggle_ban(guild, interaction, false, reason).then((user) => { log(bot, interaction, command, user, reason, SEVCODES.none)}).catch((note) => { interaction.reply(note); }); + break; + + case 'mute': toggle_mute(bot, guild, command, interaction, mentioned, reason, true); + break; + + case 'unmute': toggle_mute(bot, guild, command, interaction, mentioned, reason, true); + break; + + // case 'timeout': timeOut(bot, mentioned, message, args, command, reason); + // shouldIlog = false; + // break; + + default: console.log(`ERROR! Moderation Command "${command}" has somehow been used!`); + } + }); } module.exports = { diff --git a/commands/admin/setup.js b/commands/admin/setup.js index db174d2..029a182 100644 --- a/commands/admin/setup.js +++ b/commands/admin/setup.js @@ -86,6 +86,19 @@ async function execute(interaction, Discord, Client, bot) { if (!channel) { return interaction.reply({content: 'The specified channel does not exist!', ephemeral: true}); } dbo.updateOne({_id: 'announcement'}, { $set: { 'channel': channel.id } }); + } else if (command == "add_mod_role") { + dbo.findOne({_id: "roles"}).then((doc) => { + const role = args[i].value; + if (!doc.commands.includes(role)) { + dbo.updateOne({_id: "roles"}, { $push: { commands: role } }); + interaction.reply({ content: "Role added!", ephemeral: true }); + } else { + interaction.reply({ content: "This role is already a command role!", ephemeral: true }); + } + }); + } else if (command == "remove_mod_role") { + dbo.updateOne({_id: "roles"}, { $pull: { commands: { $in: [ args[i].value ] }} }); + interaction.reply({ content: "Role removed!", ephemeral: true }); } else { interaction.reply({content: "Please chose a valid option", ephemeral: true}); } @@ -128,7 +141,9 @@ module.exports = { {name: 'log_channel', description: 'Sets the logging channel', type: Constants.ApplicationCommandOptionTypes.CHANNEL }, {name: 'log_severity', description: 'Sets the logging Severity (logs this/lower tiers)', type: Constants.ApplicationCommandOptionTypes.STRING, choices: [{name: 'none', value: 'none'}, {name: 'low', value: 'low'}, {name: 'medium', value: 'medium'}, {name: 'high', value: 'high'}] }, {name: 'announcement_role', description: 'Sets the role to be pinged for reminders', type: Constants.ApplicationCommandOptionTypes.ROLE}, - {name: 'announcement_channel', description: 'Sets the channel for reminders', type: Constants.ApplicationCommandOptionTypes.CHANNEL} + {name: 'announcement_channel', description: 'Sets the channel for reminders', type: Constants.ApplicationCommandOptionTypes.CHANNEL}, + {name: 'add_mod_role', description: 'Make a role into an admin role for Selmer Bot, able to execute ALL Selmer Bot commands', type: Constants.ApplicationCommandOptionTypes.ROLE}, + {name: 'remove_mod_role', description: 'Remove a Selmer Bot moderation role', type: Constants.ApplicationCommandOptionTypes.ROLE} // {name: 'help', description: 'gets help with setup commands', type: Constants.ApplicationCommandOptionTypes.STRING, choices: [{name: 'welcome', value: 'welcome'}, {name: 'logs', value: 'logs'}, {name: 'announcement', value: 'announcement'}]} ] } \ No newline at end of file diff --git a/commands/admin/unlockchannel.js b/commands/admin/unlockchannel.js new file mode 100644 index 0000000..6d0865e --- /dev/null +++ b/commands/admin/unlockchannel.js @@ -0,0 +1,35 @@ +const { checkRole } = require('./verify.js'); +const { Constants } = require('discord.js'); + + +module.exports = { + name: 'unlock', + description: 'Unlock a channel', + execute(interaction, Discord, Client, bot) { + const arg = interaction.options.data[0]; + const guild = bot.guilds.cache.get(interaction.guildId); + + checkRole(bot, guild, interaction.user.id).then((isAllowed) => { + if (!isAllowed) { return message.reply('Insufficient Permissions!'); } + + var channel; + if (arg) { + channel = arg.channel; + } else { + channel = interaction.channel; + } + + let role = interaction.guild.roles.cache.find(r => r.name === "@everyone"); + + channel.permissionOverwrites.edit(role.id, { + VIEW_CHANNEL: true, + SEND_MESSAGES: true, + READ_MESSAGE_HISTORY: true, + ATTACH_FILES: true + }); + + interaction.reply(`${channel} has been unlocked!`); + }); + }, + options: [{name: 'channel', description: 'The channel to unlock (defaults to current channel)', type: Constants.ApplicationCommandOptionTypes.CHANNEL, required: false}] +} \ No newline at end of file diff --git a/commands/admin/verify.js b/commands/admin/verify.js index a94ed2b..e5c7bbd 100644 --- a/commands/admin/verify.js +++ b/commands/admin/verify.js @@ -1,32 +1,39 @@ -function checkRole(bot, guild, userId, cal = false) { - var roleName; - - if (cal) { - roleName = "Selmer Bot Calendar"; - } else { - roleName = "Selmer Bot Commands"; - } +const Discord = require('discord.js'); - const role = guild.roles.cache.find((role) => { return (role.name == roleName); }) - const user = guild.members.cache.get(userId); +/** + * @param {Discord.Guild} guild + * @returns {Promise} + */ +function checkRole(bot, guild, userId) { + return new Promise((resolve, reject) => { + const user = guild.members.cache.get(userId); - return (role != undefined && user.roles.cache.has(role.id)); // || user.id == guild.ownerId || bot.inDebugMode + // return (role != undefined && user.roles.cache.has(role.id)); // || user.id == guild.ownerId || bot.inDebugMode + // Maybe implement this later, useless for now + bot.mongoconnection.then((client) => { + // const role = client.db(message.guild.id).collection("admin-roles"); + const a = new Array(); + client.db(guild.id).collection("SETUP").findOne({_id: "roles"}).then((doc) => { + const comRoles = doc.commands; + const role = guild.roles.cache.find((role) => { return (role.name == "Selmer Bot Commands"); }); + const hasPreAdminRole = (role != undefined && user.roles.cache.has(role.id) || user.id == guild.ownerId); - /*Maybe implement this later, useless for now - const client = new MongoClient(mongouri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 }); - client.connect(err => { - - - const role = client.db(message.guild.id).collection("admin-roles"); - shop.find().toArray(function(err, itemstemp) { - if (err) throw err; - - items = [...itemstemp]; - - client.close(); + if (!comRoles) { + resolve(hasPreAdminRole); + } else { + const hasRoles = []; + Promise.all(comRoles.map((val) => { + if (user.roles.cache.has(val)) { + hasRoles.push(true); + } + })).then(() => { + resolve(hasRoles.length > 0 || hasPreAdminRole); + }); + } + }); }); - });*/ + }); } diff --git a/commands/misc/giveaway.js b/commands/misc/giveaway.js new file mode 100644 index 0000000..ecb04e2 --- /dev/null +++ b/commands/misc/giveaway.js @@ -0,0 +1,182 @@ +const { Interaction, MessageActionRow, MessageButton, MessageEmbed, Modal, TextInputComponent } = require('discord.js'); +const { checkRole } = require('../admin/verify.js'); + + +async function postForm(interaction) { + // Create the modal + const modal = new Modal(); + + modal.setTitle('Creating a new giveaway') + .setCustomId('giveawayModal'); + + // Add components to modal + // Create the text input components + // The label is the prompt the user sees for this input + // Short means only a single line of text + // Paragraph means multiple lines of text + + const durationInp = new TextInputComponent() + .setCustomId('duration') + .setLabel("How long should the givaway last?") + .setPlaceholder('10S or 10M or 10H or 10D between 1 minute and 30 days') + .setStyle('SHORT'); + + const titleInp = new TextInputComponent() + .setCustomId('title') + .setLabel("What should the giveaway be called?") + .setStyle('SHORT'); + + const descriptionInp = new TextInputComponent() + .setCustomId('description') + .setLabel("Describe the giveaway") + .setPlaceholder('A fun giveaway!') + .setStyle('PARAGRAPH'); + + const prizeInp = new TextInputComponent() + .setCustomId('prize') + .setLabel("What does the winner....win?") + .setPlaceholder('Discord Nitro') + .setStyle('SHORT'); + + const winnersInp = new TextInputComponent() + .setCustomId('winners') + .setLabel("Number of winners") + .setPlaceholder('Between 1 and 99 winners') + .setMinLength(1) + .setMaxLength(2) + .setStyle('SHORT'); + + // An action row only holds one text input, + // so you need one action row per text input. + const title = new MessageActionRow().addComponents(titleInp); + const desc = new MessageActionRow().addComponents(descriptionInp); + const dur = new MessageActionRow().addComponents(durationInp); + const prize = new MessageActionRow().addComponents(prizeInp); + const winners = new MessageActionRow().addComponents(winnersInp); + + // Add inputs to the modal + modal.addComponents(title, desc, dur, prize, winners); + + // Show the modal to the user + interaction.showModal(modal); +} + + +/** + * @param {Interaction} interaction + */ +function processForm(interaction, bot) { + const title = interaction.fields.getTextInputValue('title'); + const desc = interaction.fields.getTextInputValue('description'); + const dur = interaction.fields.getTextInputValue('duration'); + const prize = interaction.fields.getTextInputValue('prize'); + const winners = interaction.fields.getTextInputValue('winners'); + + postGiveawayMessage(bot, interaction, title, desc, dur, prize, winners); +} + +/** +* @param {Interaction} interaction +*/ +function postGiveawayMessage(bot, interaction, title, desc, dur, prize, winners) { + + const author = { + name: "Selmer Bot", + url: "", + iconURL: bot.user.displayAvatarURL() + }; + + var timeAdjuster = 1; + var time; + + if (dur.indexOf('M') != -1) { + timeAdjuster = 60; + time = dur.replace("M", ""); + } else if (dur.indexOf('H') != -1) { + timeAdjuster = 3600; + time = dur.replace("H", ""); + } else if (dur.indexOf('D') != -1) { + timeAdjuster = 86400; + time = dur.replace("D", ""); + } + + if (!Number.isInteger(Number(time))) { + return interaction.reply("Please enter a valid time in the following format: 10[S, M, H, D]"); + } else if (!Number.isInteger(Number(winners))) { + return interaction.reply("Please enter a valid NUMBER of winners"); + } + + const embd = new MessageEmbed() + .setTitle(title) + .setAuthor(author) + .setDescription(desc) + .addFields([ + {name: 'Prize', value: prize}, + {name: 'Ends in', value: ``}, + {name: 'Host', value: `${interaction.user}`}, + {name: 'Number of Contestants', value: '0'}, + {name: 'Number of Winners', value: winners} + ]); + + const msgPromise = interaction.channel.send({ embeds: [embd] }); + msgPromise.then((msg) => { + msg.react('🎉'); + + var nonbots = []; + const filter = (reaction, user) => { + if (!user.bot) { + nonbots.push(user); + } + + return (reaction.emoji.name === '🎉'); + }; + + const collector = msg.createReactionCollector({ filter, time: 5000 }); + + // collector.on('collect', (reaction, user) => { + // console.log(`Collected ${reaction.emoji.name} from ${user.tag}`); + // }); + + collector.on('end', collected => { + const finalists = []; + if (winners >= nonbots.length) { + for (let i = 0; i < nonbots.length; i++) { + finalists.push(`<@${nonbots[i].id}>`); + } + } else { + for (let i = 0; i < winners; i++) { + const ind = Math.floor(nonbots.length * Math.random()); + finalists.push(`<@${nonbots[ind].id}>`); + delete nonbots[ind]; + nonbots = nonbots.filter((val) => { return (val != null); }); + } + } + + let embd = msg.embeds[0]; + + if (winners > 1) { + msg.reply(`And the winners are:\n${finalists.join("\n")}`); + embd.fields.push({name: 'winners:', value: `${finalists.join("\n")}`, inline: true}); + } else { + msg.reply(`And the winner is:\n${finalists.join("\n")}`); + embd.fields.push({name: 'winner:', value: `${finalists.join("\n")}`, inline: true}); + } + + msg.edit({ embeds: [embd] }); + }); + + interaction.reply({ content: 'Giveaway posted!', ephemeral: true }); + }); +} + + +module.exports = { + name: 'giveaway', + description: 'Create a giveaway', + execute(interaction, Discord, Client, bot) { + + postForm(interaction); + }, + processForm, + options: [] +} \ No newline at end of file diff --git a/commands/misc/rectionrole.js b/commands/misc/rectionrole.js deleted file mode 100644 index 92a4794..0000000 --- a/commands/misc/rectionrole.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - name: 'reactionrole', - description: 'Creates an embed that will give a role when reacted to', - async execute(message, args, Discord, bot) { - if (bot.commands.get('verify').checkRole(message, args)) { - console.log("IS ADMNIN"); - } - } -} \ No newline at end of file diff --git a/commands/premium/reminders.js b/commands/premium/reminders.js index 84403fb..c5318b0 100644 --- a/commands/premium/reminders.js +++ b/commands/premium/reminders.js @@ -1,5 +1,4 @@ const { Modal, TextInputComponent, MessageActionRow, MessageButton, MessageEmbed, Interaction } = require('discord.js'); -const { checkRole } = require('../admin/verify'); /**