diff --git a/bot.js b/bot.js index 0f583f7..7eb6ae9 100644 --- a/bot.js +++ b/bot.js @@ -15,6 +15,15 @@ class MainClient extends AkairoClient { constructor () { super({ ownerID: ['200616508328509442', '223217915673968641'] + }, { + fetchAllMembers: true, + presence: { + status: 'online', + activity: { + name: `Arduino | ${version}`, + type: 'WATCHING' + } + } }) this.commandHandler = new CommandHandler(this, { directory: './commands/', @@ -31,11 +40,3 @@ class MainClient extends AkairoClient { } const client = new MainClient() client.login(process.env.BOT_TOKEN) -client.options.fetchAllMembers = true -client.options.presence = { - status: 'online', - activity: { - name: `Arduino | v${version}`, - type: 'WATCHING' - } -} diff --git a/commands/about.js b/commands/about.js index 446231a..fd7d9ab 100644 --- a/commands/about.js +++ b/commands/about.js @@ -3,6 +3,13 @@ const { MessageEmbed } = require('discord.js') const { embed } = require('../bot') const { version } = require('../package.json') +var packLock +try { + packLock = require('../package-lock.json') +} catch (err) { + packLock = undefined +} + class AboutCommand extends Command { constructor() { super('about', { @@ -12,12 +19,16 @@ class AboutCommand extends Command { } exec(message) { - message.channel.send( - new MessageEmbed(embed) - .setTimestamp(new Date()) - .setTitle('About Arduino Bot') - .addField('Version', version) - ) + const about = new MessageEmbed(embed) + .setTimestamp(new Date()) + .setTitle('About Arduino Bot') + .addField('Bot Version', version) + .addField('Node Version', process.version) + + if (packLock) { + about.addField('DiscordJS Version', 'v' + packLock.dependencies['discord.js'].version) + } + message.channel.send(about) } } module.exports = AboutCommand \ No newline at end of file diff --git a/commands/codeblock.js b/commands/codeblock.js index fa99ddb..b4804ce 100644 --- a/commands/codeblock.js +++ b/commands/codeblock.js @@ -6,7 +6,7 @@ const { embed } = require('../bot') class CodeBlockCommand extends Command { constructor() { super('codeblock', { - aliases: ['codeblock'], + aliases: ['codeblock', 'codeblocks', 'code', 'block'], description: 'Explains how to post a code block in discord.' }) } diff --git a/commands/gist.js b/commands/gist.js index afe9229..ddad9ed 100644 --- a/commands/gist.js +++ b/commands/gist.js @@ -11,7 +11,7 @@ const gists = new Gists({ class GistCommand extends Command { constructor() { super('gist', { - aliases: ['gist'], + aliases: ['gist', 'paste'], channel: 'guild', description: 'Command for helpers to paste any message to a gist.', args: [ diff --git a/commands/say.js b/commands/say.js new file mode 100644 index 0000000..5bdb7c7 --- /dev/null +++ b/commands/say.js @@ -0,0 +1,147 @@ +const { Command } = require('discord-akairo') +const { MessageEmbed } = require('discord.js') +const { embed } = require('../bot') + +class SayCommand extends Command { + constructor() { + super('say', { + aliases: ['say'], + description: '(For admins) Have the bot say something as an embed.', + channel: 'guild', + userPermissions: 'ADMINISTRATOR', + argumentDefaults: { + prompt: { + time: 1200000 + } + }, + args: [ + { + id: 'channel', + type: 'channel', + prompt: { + start: m => { + return new MessageEmbed(embed) + .setTitle('What channel would you like the message sent in?') + .setTimestamp(new Date()) + } + } + }, + { + id: 'title', + type: 'string', + prompt: { + start: m => { + return new MessageEmbed(embed) + .setTitle('What would you like the primary embed title to be?') + } + } + }, + { + id: 'description', + type: 'string', + prompt: { + start: m => { + return new MessageEmbed(embed) + .setTitle('What would you like the primary embed description to be?') + } + } + }, + { + id: 'fields', + type: 'string', + prompt: { + infinite: true, + stopWord: 'done', + start: m => { + return new MessageEmbed(embed) + .setTitle('What fields would you like to send? **Read below!!**') + .setDescription('Please send **separate** messages alternating between the new field title and the new field value. Add as many fields as you want, and when you are ready to go to the next step, send the message "`done`". You have 20 minutes to complete this step.') + .setTimestamp(new Date()) + } + } + } + ] + }) + } + + exec(message, args) { + if ((args.fields.length % 2) !== 0) { + return message.channel.send( + new MessageEmbed(embed) + .setTitle('No value was supplied for your final field. Every field must have a name and a value. Canceling command.') + .setTimestamp(new Date()) + ) + } + message.channel.send( + new MessageEmbed(embed) + .setTitle('If you would like to add a thumbnail (small in top right), react with ✅. Otherwise react with ❌') + .setTimestamp(new Date()) + ).then(m => { + m.react('✅').then(() => { + m.react('❌').then(() => { + m.awaitReactions((reaction, user) => user === message.author, { max: 1, time: 300000 }).then(reactionCollection => { + let reaction = reactionCollection.first() + if (reaction.emoji.toString() === '✅') { + message.channel.send( + new MessageEmbed(embed) + .setTitle('What thumbnail would you like to add? Please provide a direct URL.') + .setTimestamp(new Date()) + ).then(() => { + message.channel.awaitMessages(msg => msg.author === message.author, { max: 1, time: 300000}).then(msgCollector => { + let msg = msgCollector.first() + try { + var url = new URL(msg.content) + } catch (err) { + return message.channel.send( + new MessageEmbed(embed) + .setTitle('URL provided was invalid. Canceling command.') + .setTimestamp(new Date()) + ) + } + args.thumbnail = url.toString() + sendIt(true) + }) + }) + } else if (reaction.emoji.toString() === '❌') { + sendIt(false) + } + }) + }) + }) + }) + + function sendIt(thumbnail) { + const say = new MessageEmbed(embed) + .setTimestamp(new Date()) + .setTitle(args.title).setDescription(args.description) + + // And that's on spending an hour realizing you can't iterate over an array you're modifying + const iterableLength = args.fields.length + + for (let i = 0; i < iterableLength / 2; i++) { + let name = args.fields.shift() + let value = args.fields.shift() + say.addField(name, value) + } + if (thumbnail) { + say.setThumbnail(args.thumbnail) + } + message.guild.channels.resolve(args.channel).send(say).then(() => { + message.channel.send( + new MessageEmbed(embed) + .setTimestamp(new Date()) + .setTitle('Great success!') + .setDescription('Embed sent.') + ) + }).catch(err => { + message.channel.send( + new MessageEmbed(embed) + .setTimestamp(new Date()) + .setTitle('An error occured whilst trying to send.') + .setDescription('Error: ' + err) + ) + }) + } + } +} +module.exports = SayCommand \ No newline at end of file diff --git a/commands/setavatar.js b/commands/setavatar.js new file mode 100644 index 0000000..cbe853d --- /dev/null +++ b/commands/setavatar.js @@ -0,0 +1,29 @@ +const { Command } = require('discord-akairo') +const { MessageEmbed } = require('discord.js') +const { embed } = require('../bot') + +class SetAvatarCommand extends Command { + constructor() { + super('setavatar', { + aliases: ['setavatar', 'setpicture'], + description: "(For admins) Sets the bot's profile picture.", + userPermissions: 'ADMINISTRATOR', + args: [ + { + id: 'url', + type: 'url' + } + ] + }) + } + + exec(message, args) { + this.client.user.setAvatar(args.url).then(() => { + message.channel.send(new MessageEmbed(embed) + .setTitle('Success') + .setTimestamp(new Date()) + ) + }) + } +} +module.exports = SetAvatarCommand \ No newline at end of file diff --git a/listeners/message.js b/listeners/message.js index 077e60e..29589e5 100644 --- a/listeners/message.js +++ b/listeners/message.js @@ -12,10 +12,11 @@ class MessageListener extends Listener { } exec(message) { + // File filter if (message.attachments.find(attachment => { const allowedExtensions = ['png', 'jpg', 'gif', 'webp', 'tiff', 'heif', 'jpeg', 'svg', 'webm', 'mpg', 'mpeg', 'ogg', 'mp4', 'm4v', 'avi', 'mov', 'm4a', 'mp3', 'wav'] const extension = attachment.name.split('.').pop().toLowerCase() - return !allowedExtensions.includes(extension) + return (!allowedExtensions.includes(extension)) && (!message.member.roles.cache.find(role => role.id === '451152561735467018')) })) { message.delete().then(() => { message.channel.send( @@ -27,9 +28,33 @@ class MessageListener extends Listener { ) }).catch(err => console.error(err)) } + + // Initial reaction for code block pastes if (message.content.includes('```') && message.content.match(/```/g).length >= 2) { message.react(config.pasteEmoji) } + + // Message link flattening + const messageLinkMatchArray = message.content.match(/https?:\/\/(canary.)?discord\.com\/channels\/\d{18}\/\d{18}\/\d{18}/gm) + if (messageLinkMatchArray) { + messageLinkMatchArray.forEach(link => { + let linkArray = link.split('/') + linkArray.splice(0, 4) + if (linkArray[0] === message.guild.id) { + message.guild.channels.resolve(linkArray[1]).messages.fetch(linkArray[2]).then(msg => { + message.channel.send( + new MessageEmbed(embed) + .setTitle(msg.content) + .setAuthor(msg.author.tag + ' said:', msg.author.avatarURL({ dynamic: true })) + .setFooter(`Message link sent by ${message.author.tag}, click original for context.`) + ) + }).catch(err => { + console.error(err) + }) + } + }) + } + } } module.exports = MessageListener diff --git a/listeners/messageReactionAdd.js b/listeners/messageReactionAdd.js index 8e4e8df..e830001 100644 --- a/listeners/messageReactionAdd.js +++ b/listeners/messageReactionAdd.js @@ -32,7 +32,7 @@ class MessageReactionAddListener extends Listener { let files = { "ArduinoDiscordBot.md": { "content": `## This gist was pasted by the Arduino discord server bot. - \n[![](https://img.shields.io/github/issues/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot/issues) [![](https://img.shields.io/github/forks/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot) [![](https://img.shields.io/github/stars/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot) [![](https://img.shields.io/github/license/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot/blob/master/LICENSE) [![](https://user-images.githubusercontent.com/7288322/34429152-141689f8-ecb9-11e7-8003-b5a10a5fcb29.png)](http://arduino.cc/discord) + \n[![](https://img.shields.io/github/issues/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot/issues) [![](https://img.shields.io/github/forks/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot) [![](https://img.shields.io/github/stars/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot) [![](https://img.shields.io/github/license/BluLightShow/arduino-bot)](https://github.com/BluLightShow/arduino-bot/blob/master/LICENSE) [![](https://img.shields.io/discord/420594746990526466?color=%237289DA&label=%20Discord%20&logo=discord&logoColor=%23FFFFFF)](https://arduino.cc/discord) \n> **This gist was automatically pasted at the request of the code author or one of the discord server helpers. If you have any suggestions or bugs to report, you can do so on our [GitHub](https://github.com/BluLightShow/arduino-bot/ "GitHub page") repository, or in our discord server. This project is run by volunteers so feel free to fork and commit your changes then open a pull request!** \n------------ \n# ⬇️ Pasted Code ⬇️` diff --git a/package.json b/package.json index 160b224..35dab3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "arduino-bot", - "version": "0.1.0", + "version": "v0.1.1", "description": "A bot to help the arduino community!", "main": "bot.js", "dependencies": {