diff --git a/commands/eval.js b/commands/eval.js index a9fde3e..10ba1ee 100644 --- a/commands/eval.js +++ b/commands/eval.js @@ -15,7 +15,7 @@ exports.help = { usage: 'eval [code]' } -exports.run = async (client, message, args, level, settings) => { +exports.run = async (client, message, args, level, data) => { const hastebin = require('hastebin-gen') const code = args.join(' ') try { diff --git a/commands/help.js b/commands/help.js new file mode 100644 index 0000000..279bdfa --- /dev/null +++ b/commands/help.js @@ -0,0 +1,21 @@ +exports.conf = { + enabled: true, + guildOnly: false, + aliases: ['commands', 'cmds', 'h'], + permLevel: 'User', + requiredPerms: ['EMBED_LINKS'], + cooldown: 2000 +} + +exports.help = { + name: 'help', + category: 'General', + description: 'Returns your permission level.', + usage: 'help ' +} + +const Discord = require('discord.js') +exports.run = (client, message, args, level, data) => { + const embed = new Discord.MessageEmbed() + embed.setColor(client.embedColour(message.guild)) +} diff --git a/commands/level.js b/commands/level.js index 4e09980..8295366 100644 --- a/commands/level.js +++ b/commands/level.js @@ -14,7 +14,7 @@ exports.help = { usage: 'level' } -exports.run = async (client, message, args, level, settings) => { +exports.run = async (client, message, args, level, data) => { try { const friendly = client.config.permLevels.find(l => l.level === level).name message.reply(`your permission level is ${level} (${friendly}).`) diff --git a/commands/ping.js b/commands/ping.js index 6384847..07d3552 100644 --- a/commands/ping.js +++ b/commands/ping.js @@ -14,7 +14,7 @@ exports.help = { usage: 'ping' } -exports.run = async (client, message, args, level, settings) => { +exports.run = async (client, message, args, level, data) => { const msg = await message.channel.send('Pinging...') msg.edit( `Pong! \`${msg.createdTimestamp - message.createdTimestamp}ms\` (💗 \`${Math.round(client.ws.ping)}ms\`)` diff --git a/events/message.js b/events/message.js index 85099be..2792ae8 100644 --- a/events/message.js +++ b/events/message.js @@ -1,33 +1,31 @@ module.exports = async (client, message) => { if (message.author.bot) return - try { - await client.getGuild(message.guild) - } catch (err) { - try { - const newGuild = { - guildID: message.guild.id - } - await client.createGuild(newGuild) - } catch (err) { - client.logger.error('Failed to create DB entry for existing guild: ' + err) + const data = {} + + data.userData = await client.findOrCreateUser(message.author) + + if (message.guild) { + if (!message.channel.permissionsFor(client.user).has('SEND_MESSAGES')) { + try { + return message.author.send(`I don't have permission to speak in **#${message.channel.name}**, Please ask a moderator to give me the send messages permission!`) + } catch (err) {} } + data.guildData = await client.findOrCreateGuild(message.guild) } - const settings = await client.getGuild(message.guild) + const prefixes = [data.userData.prefix, data.guildData.prefix] - let prefix = settings.prefix + let prefix - const myMention = `<@&${client.user.id}>` - const myMention2 = `<@!${client.user.id}>` + const prefixMention = new RegExp(`^<@!?${client.user.id}> `) + if (message.content.match(prefixMention) ? message.content.match(prefixMention)[0] : '!') { + prefix = message.content.match(prefixMention) ? message.content.match(prefixMention)[0] : '!' + } - if (message.content.startsWith(myMention) || message.content.startsWith(myMention2)) { - if (message.content.length > myMention.length + 1 && (message.content.substr(0, myMention.length + 1) === myMention + ' ' || message.content.substr(0, myMention2.length + 1) === myMention2 + ' ')) { - prefix = message.content.substr(0, myMention.length) + ' ' - } else { - return message.channel.send(`Current prefix: \`${prefix}\``) - }; - }; + for (const thisPrefix of prefixes) { + if (message.content.startsWith(thisPrefix)) prefix = thisPrefix + } if (message.content.indexOf(prefix) !== 0) return @@ -36,19 +34,35 @@ module.exports = async (client, message) => { if (message.guild && !message.member) await message.guild.fetchMember(message.author) - const level = client.permlevel(message, settings) + const level = client.permlevel(message, data.guildSettings) const cmd = client.commands.get(command) || client.commands.get(client.aliases.get(command)) if (!cmd) return + if (!cmd.conf.enabled) { + if (data.guildData.systemNotice.enabled === true) { + return message.channel.send('This command has been disabled by my developers.') + } else { + return + } + } + if (cmd && !message.guild && cmd.conf.guildOnly) { return message.channel.send('This command is unavailable via private message. Please run this command in a guild.') } + if (message.guild) { + var missing = cmd.conf.requiredPerms.filter(p => !message.channel.permissionsFor(client.user).has(p)) + if (missing.length > 0) { + missing = '`' + (missing.join('`, `')) + '`' + return message.channel.send(`Missing permissions: ${missing}`) + } + } + // Dev perm level is separate so dev's don't get owner perms where they shouldn't have them if (cmd.conf.permLevel === 'Developer') { if (!client.config.devs.includes(message.author.id)) { - if (settings.systemNotice === true) { + if (data.guildData.systemNotice.enabled === true) { return message.channel.send('You don\'t have permission to run this command!') } else { return @@ -57,7 +71,7 @@ module.exports = async (client, message) => { } if (level < client.levelCache[cmd.conf.permLevel]) { - if (settings.systemNotice === true) { + if (data.guildData.systemNotice.enabled === true) { return message.channel.send('You don\'t have permission to run this command!') } else { return @@ -88,5 +102,5 @@ module.exports = async (client, message) => { } client.logger.log(`Command ran: ${cmd.help.name}`) - cmd.run(client, message, args, level, settings) + cmd.run(client, message, args, level, data) } diff --git a/events/ready.js b/events/ready.js index 2f581a2..12b6365 100644 --- a/events/ready.js +++ b/events/ready.js @@ -2,12 +2,12 @@ module.exports = (client) => { const activities = client.commands.keyArray() let activity = activities.random() - client.user.setActivity(`${client.config.defaultGuildSettings.prefix + activity} | v${client.version.number}`, { type: 'PLAYING' }) + client.user.setActivity(`${client.config.defaultPrefix + activity} | v${client.version.number}`, { type: 'PLAYING' }) setInterval(() => { activity = activities.random() if (client.lockActivity === false) { - client.user.setActivity(`${client.config.defaultGuildSettings.prefix + activity} | v${client.version.number}`, { type: 'PLAYING' }) + client.user.setActivity(`${client.config.defaultPrefix + activity} | v${client.version.number}`, { type: 'PLAYING' }) }; }, 30000) diff --git a/index.js b/index.js index 39d58a3..353a155 100644 --- a/index.js +++ b/index.js @@ -8,12 +8,20 @@ if (Number(process.version.slice(1).split('.')[0]) < 12) { } // Libraries +const Discord = require('discord.js') +const client = new Discord.Client({ disabledEvents: ['TYPING_START'] }) const fs = require('fs') const colors = require('colors') const isDocker = require('is-docker') -const Discord = require('discord.js') -const client = new Discord.Client({ disabledEvents: ['TYPING_START'] }) +// Helpers +client.config = require('./config') +client.version = require('./version.json') +client.db = require('./helpers/mongoose') +require('./helpers/_functions')(client) +require('./helpers/music')(client) + +// Initialise logger client.logger = require('tracer').colorConsole({ transport: function (data) { console.log(data.output) @@ -39,24 +47,13 @@ client.logger = require('tracer').colorConsole({ filters: [colors.white] }) -// Check to make sure config exists -if (fs.existsSync('./config.js') === false) { - client.logger.fatal('The config.js file is missing! Please create a config.js file.') - process.exit() -} - +// Create caches for permissions, commands, cooldowns and aliases client.levelCache = {} client.commands = new Discord.Collection() client.cooldown = new Discord.Collection() client.aliases = new Discord.Collection() -client.config = require('./config') -client.version = require('./version.json') -client.db = require('./util/mongoose') -require('./util/functions')(client) -require('./util/music')(client) - -// Initialization function +// Main initialisation function const init = async () => { // Command handler fs.readdir('./commands', (err, files) => { @@ -98,6 +95,7 @@ const init = async () => { client.levelCache[thisLevel.name] = thisLevel.level } + // Check if Woomy is running inside a Docker container if (isDocker() === true) { client.devmode = true client.logger.warn('Running in development mode.') diff --git a/models/guild.js b/models/guild.js index 6b7001a..23ccbb8 100644 --- a/models/guild.js +++ b/models/guild.js @@ -1,35 +1,90 @@ -const mongoose = require('mongoose') -const Schema = mongoose.Schema -const { defaultGuildSettings: defaults } = require('../config') +const { Schema, model } = require('mongoose') +const { defaultPrefix } = require('../config') -module.exports = mongoose.model('Guild', new Schema({ - _id: mongoose.Schema.Types.ObjectId, +module.exports = model('Guild', new Schema({ + _id: Schema.Types.ObjectId, guildID: String, - guildName: String, prefix: { type: String, - default: defaults.prefix - }, - - systemNotice: { - type: Boolean, - default: defaults.systemNotice + default: defaultPrefix }, modRole: { type: String, - default: defaults.modRole + default: null }, adminRole: { type: String, - default: defaults.adminRole + default: null }, mutedRole: { type: String, - default: defaults.mutedRole + default: null + }, + + autoRole: { + type: String, + default: null + }, + + systemNotice: { + type: Object, + default: { + enabled: true, + autoDelete: 0 + } + }, + + plugins: { + type: Object, + default: { + welcome: { + enabled: false, + channel: null, + message: null + }, + goodbye: { + enabled: false, + channel: null, + message: null + }, + chatLogs: { + enabled: false, + channel: null + }, + modLogs: { + enabled: false, + channel: null + } + } + }, + + botChannels: { + type: Array, + default: [] + }, + + blacklisted: { + type: Array, + default: [] + }, + + customCommands: { + type: Array, + default: [] + }, + + disabledCommands: { + type: Array, + default: [] + }, + + disabledCategories: { + type: Array, + default: [] } })) diff --git a/models/member.js b/models/member.js index e69de29..9a367c8 100644 --- a/models/member.js +++ b/models/member.js @@ -0,0 +1,8 @@ +const { Schema, model } = require('mongoose') + +module.exports = model('Member', new Schema({ + _id: Schema.Types.ObjectId, + userID: String + + // Will chuck in some stuff like timed mutes, warning system, levelling, etc +})) diff --git a/models/user.js b/models/user.js index e69de29..5400bd7 100644 --- a/models/user.js +++ b/models/user.js @@ -0,0 +1,28 @@ +const { Schema, model } = require('mongoose') +const { defaultPrefix } = require('../config') + +module.exports = model('User', new Schema({ + _id: Schema.Types.ObjectId, + userID: String, + + prefix: { + type: String, + default: defaultPrefix + }, + + profile: { + type: Object, + default: { + bio: 'I should run ~setbio :P', + birthdate: null, + pronouns: null, + favColour: null + } + }, + + // polyamory uwu + marriages: { + type: Array, + default: [] + } +}))