From 652b03136e70d74387817755758d26ac7f2d1a19 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Mon, 16 Mar 2020 12:14:33 +1100 Subject: [PATCH 01/27] synced changes --- package.json | 4 +- resources/other/coolpeople.json | 19 ++++++++++ src/commands/catfact.js | 16 ++++---- src/commands/colourify.js | 53 +++++++++++++++++++++++++++ src/commands/ship.js | 41 +++++++++++++++++++-- src/commands/ship1.js | 65 +++++++++++++++++++++++++++++++++ src/commands/userinfo.js | 14 ++++++- src/commands/yoda.js | 28 +++++++------- src/modules/functions.js | 2 +- 9 files changed, 215 insertions(+), 27 deletions(-) create mode 100644 resources/other/coolpeople.json create mode 100644 src/commands/colourify.js create mode 100644 src/commands/ship1.js diff --git a/package.json b/package.json index 7210610..1c03415 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Woomy is a all-purpose discord bot built off the guidebot base and coded in node.js using discord.js.", "main": "index.js", "dependencies": { + "@discordjs/opus": "^0.1.0", "better-sqlite3": "^5.4.1", "chalk": "^3.0.0", "dblapi.js": "^2.3.1", @@ -12,12 +13,13 @@ "garfield": "^1.1.2", "get-youtube-id": "^1.0.1", "hastebin-gen": "^2.0.5", + "is-url": "^1.2.4", "moment": "^2.24.0", "moment-duration-format": "^2.3.2", "prism-media": "^1.2.1", "randomcolor": "^0.5.4", - "request": "^2.88.2", "relevant-urban": "^2.0.0", + "request": "^2.88.2", "urban": "^0.3.2", "url-unshort": "^5.0.0", "url-unshorten": "^1.0.6", diff --git a/resources/other/coolpeople.json b/resources/other/coolpeople.json new file mode 100644 index 0000000..f0de195 --- /dev/null +++ b/resources/other/coolpeople.json @@ -0,0 +1,19 @@ +{ + "coolPeople": [ + "448354605617643520", + "433790467830972417", + "231777839576252417", + "285992938314661899", + "231704701433937931", + "324937993972350976", + "336492042299637771", + "273867501006225419", + "331870539897372672", + "304000458144481280", + "239787232666451980", + "264970229514371072", + "254310746450690048", + "358390849807319040", + "211011138656272386" + ] +} \ No newline at end of file diff --git a/src/commands/catfact.js b/src/commands/catfact.js index 8beb770..9fef875 100644 --- a/src/commands/catfact.js +++ b/src/commands/catfact.js @@ -3,14 +3,14 @@ const request = require("request"); exports.run = async (bot, message, args) => { message.channel.startTyping(); try{ - request({ uri: "https://catfact.ninja/facts", json: true }, (error, response, body) => { - message.channel.send(`**Did you know?**\n ${body.data[0].fact}`); - message.channel.startTyping(); - }); -} catch(err) { - message.channel.send(`<:error:466995152976871434> API error: ${err}`); - message.channel.stopTyping(); -}; + request({ uri: "https://catfact.ninja/facts", json: true }, (error, response, body) => { + message.channel.send(`**Did you know?**\n ${body.data[0].fact}`); + message.channel.stopTyping(); + }); + } catch(err) { + message.channel.send(`<:error:466995152976871434> API error: ${err}`); + message.channel.stopTyping(); + }; }; exports.conf = { diff --git a/src/commands/colourify.js b/src/commands/colourify.js new file mode 100644 index 0000000..f13720d --- /dev/null +++ b/src/commands/colourify.js @@ -0,0 +1,53 @@ +const isURL = require("is-url") +exports.run = async (client, message, args) => { + var img; + if(!args[0]) { + if(!message.attachments.first()) { + return message.channel.send("No attachment") + }; + img = message.attachments.first().attachment; + } else { + if(isURL(args[0]) == true ) { + img = args[0]; + } else { + user = message.mentions.members.first(); + + if (!user) { + let users; + users = client.searchForMembers(message.guild, args[0]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0]; + }; + + if(user) { + img = user.user.avatarURL({format: "png", dynamic: true}) + } + } + }; + + var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/filter/magik?image=${img}`) + message.channel.send(attachment) +}; + + exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: [] + }; + + exports.help = { + name: "magikt", + category: "Fun", + description: "Colourifies an image", + usage: "colourify user hex1 hex2" + }; + \ No newline at end of file diff --git a/src/commands/ship.js b/src/commands/ship.js index cd187b9..2ef0477 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -1,14 +1,49 @@ const request = require('request') exports.run = async (client, message, args) => { + + + //NOT FINISHED + + if(!args[0] || !args[1]) { + return message.channel.send(`<:error:466995152976871434> Please include two users`) + } message.channel.startTyping(); var user = client.getUserFromMention(args[0]) var user2 = client.getUserFromMention(args[1]) + + if (!user) { + let users; + users = client.searchForMembers(message.guild, args[0]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0]; + }; + + if (!user2) { + let users; + users = client.searchForMembers(message.guild, args[0]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user2 = users[0]; + }; var secondLength = Math.floor(user2.username.length / 2); - var first = user.username.substr(0, user.username.length / 2) - var second = user2.username.substr(secondLength, user2.username.length / 2) + var first = user.username.slice(0, user.username.length / 2) + var second = user2.username.slice(secondLength, user2.username.length / 2) try { var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) @@ -22,7 +57,7 @@ exports.run = async (client, message, args) => { exports.conf = { enabled: true, - guildOnly: false, + guildOnly: true, aliases: [], permLevel: "User", requiredPerms: [] diff --git a/src/commands/ship1.js b/src/commands/ship1.js new file mode 100644 index 0000000..ca96edd --- /dev/null +++ b/src/commands/ship1.js @@ -0,0 +1,65 @@ +const request = require('request') +exports.run = async (client, message, args) => { + + + //NOT FINISHED + + if(!args[0] || !args[1]) { + return message.channel.send(`<:error:466995152976871434> Please include two to five users`) + } + message.channel.startTyping(); + + var user = client.getUserFromMention(args[0]) + var user2 = client.getUserFromMention(args[1]) + + if (!user) { + let users; + users = client.searchForMembers(message.guild, args[0]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0]; + }; + + if (!user2) { + let users; + users = client.searchForMembers(message.guild, args[0]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user2 = users[0]; + }; + + var secondLength = Math.floor(user2.username.length / 2); + + var first = user.username.slice(0, user.username.length / 2) + var second = user2.username.slice(secondLength, user2.username.length / 2) + + message.channel.send(`Your ship name is **${shipname}!**`) +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "ship1", + category: "Fun", + description: "Ship two people together <3", + usage: "ship name name2" +}; + diff --git a/src/commands/userinfo.js b/src/commands/userinfo.js index 8d7008b..ddec46f 100644 --- a/src/commands/userinfo.js +++ b/src/commands/userinfo.js @@ -1,5 +1,5 @@ const Discord = require("discord.js"); - +const coolPeople = require('../../resources/other/coolpeople.json') exports.run = (client, message, args) => { var user; var guild; @@ -13,6 +13,8 @@ exports.run = (client, message, args) => { var tag; var id; var bot; + var coolPerson = false; + var friendos = coolPeople.coolPeople; if(message.guild) { user = message.mentions.members.first(); @@ -39,6 +41,15 @@ exports.run = (client, message, args) => { nick = `\n• **Nickname:** ${user.nickname}`; }; + for (var i = 0; i < friendos.length; i++) { + if (user.user.id == friendos[i]) + coolPerson = true; + }; + + if(coolPerson == true) { + badges += "🌟" + } + if(user.user.id == message.guild.ownerID) { badges += "<:owner:685703193694306331>" } @@ -46,6 +57,7 @@ exports.run = (client, message, args) => { if(user.user.bot) { badges += "<:bot:686489601678114859>" } + if(badges.length > 0) { badges += "\n" diff --git a/src/commands/yoda.js b/src/commands/yoda.js index 293d786..8b61784 100644 --- a/src/commands/yoda.js +++ b/src/commands/yoda.js @@ -1,20 +1,22 @@ const request = require('request') exports.run = async (client, message, args) => { - const speech = args.join(' '); - if (!args[0]) { - return message.channel.send(`<:error:466995152976871434> Please include text for me to convert to yodish. Yes.`) - } - try { - const { text } = request({ uri: `http://yoda-api.appspot.com/api/v1/yodish?text=${encodeURIComponent(speech.toLowerCase())}`, json: true }, (error, response, body) => { - message.channel.send(JSON.parse(text).yodish) - }); - } catch(err) { - message.channel.send(`<:error:466995152976871434> API error: ${err}`); - message.channel.stopTyping(); - } + const speech = args.join(' '); + if (!speech) { + return message.channel.send(`<:error:466995152976871434> Please include text for me to convert to yodish. Yes.`) + }; -} + message.channel.startTyping(); + try{ + request({ uri: `http://yoda-api.appspot.com/api/v1/yodish?text=${encodeURIComponent(speech.toLowerCase())}`, json: true }, (error, response, body) => { + message.channel.send(body.yodish); + message.channel.stopTyping(); + }); + } catch(err) { + message.channel.send(`<:error:466995152976871434> API error: ${err}`); + message.channel.stopTyping(); + }; +}; exports.conf = { enabled: true, diff --git a/src/modules/functions.js b/src/modules/functions.js index 98cf223..bd30579 100644 --- a/src/modules/functions.js +++ b/src/modules/functions.js @@ -368,6 +368,6 @@ module.exports = client => { }); process.on("unhandledRejection", err => { - client.logger.error(`Unhandled rejection: ${err.stack}`); + client.logger.error(`Unhandled rejection: ${err}`); }); }; From a57dfd6808479dce9dbe524aa6921016d2d14c94 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Mon, 16 Mar 2020 12:21:19 +1100 Subject: [PATCH 02/27] Avatars are now larger --- src/commands/about.js | 2 +- src/commands/avatar.js | 2 +- src/commands/ban.js | 2 +- src/commands/giverole.js | 2 +- src/commands/hackban.js | 2 +- src/commands/kick.js | 2 +- src/commands/mute.js | 2 +- src/commands/nowplaying.js | 2 +- src/commands/purge.js | 2 +- src/commands/raidmode.js | 2 +- src/commands/servericon.js | 2 +- src/commands/serverinfo.js | 2 +- src/commands/softban.js | 2 +- src/commands/takerole.js | 2 +- src/commands/unmute.js | 2 +- src/commands/userinfo.js | 4 ++-- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/commands/about.js b/src/commands/about.js index 02b2c2c..5c1538f 100644 --- a/src/commands/about.js +++ b/src/commands/about.js @@ -28,7 +28,7 @@ exports.run = (client, message) => { embed = new Discord.MessageEmbed(); embed.setTitle(`Woomy`); embed.setColor(client.embedColour(message)); - embed.setThumbnail(client.user.avatarURL({format: "png", dynamic: true})) + embed.setThumbnail(client.user.avatarURL({format: "png", dynamic: true, size: 2048})) embed.addField( "General:", `• users: \`${client.users.cache.size}\`\n• channels: \`${client.channels.cache.size}\`\n• servers: \`${client.guilds.cache.size}\`\n• commands: \`${client.commands.size}\`\n• uptime: \`${duration}\``,true ); diff --git a/src/commands/avatar.js b/src/commands/avatar.js index 1bbb9e4..5832be2 100644 --- a/src/commands/avatar.js +++ b/src/commands/avatar.js @@ -19,7 +19,7 @@ exports.run = (client, message, args) => { user = users[0]; user = user.user; } - message.channel.send(`**${user.tag}'s** avatar is: ${user.avatarURL({format: "png", dynamic: true})}`); + message.channel.send(`**${user.tag}'s** avatar is: ${user.avatarURL({format: "png", dynamic: true, size: 2048})}`); }; exports.conf = { diff --git a/src/commands/ban.js b/src/commands/ban.js index fe403c2..affa882 100644 --- a/src/commands/ban.js +++ b/src/commands/ban.js @@ -58,7 +58,7 @@ exports.run = async (client, message, args) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#BC0057"); - embed.setAuthor("User banned!", user.user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("User banned!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription( `• User: ${user.user.tag} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${reason}` ); diff --git a/src/commands/giverole.js b/src/commands/giverole.js index 356cd74..f62a055 100644 --- a/src/commands/giverole.js +++ b/src/commands/giverole.js @@ -59,7 +59,7 @@ exports.run = async (client, message, [member, ...role2add], query) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#00c09a"); - embed.setAuthor("Role given:", user.user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("Role given:", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription(`‏‏‎• User: ${user} (${user.user.id})\n‏‏‎• Mod: ${message.author} (${message.author.id})\n‏‏‎• Role: ${gRole}`) try { channel.send({ embed }); diff --git a/src/commands/hackban.js b/src/commands/hackban.js index c18b880..ff4d1cb 100644 --- a/src/commands/hackban.js +++ b/src/commands/hackban.js @@ -31,7 +31,7 @@ exports.run = async (client, message, args) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#BC0057"); - embed.setAuthor("User banned!", user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("User banned!", user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription( `• User: ${user.tag} (${user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${reason}` ); diff --git a/src/commands/kick.js b/src/commands/kick.js index 0002f44..9070a98 100644 --- a/src/commands/kick.js +++ b/src/commands/kick.js @@ -58,7 +58,7 @@ if (settings.modlogsChannel !== "off") { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#fd0061"); - embed.setAuthor("User kicked!", user.user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("User kicked!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription( `• User: ${user.user.tag} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${reason}` ); diff --git a/src/commands/mute.js b/src/commands/mute.js index a59f72d..a52e7c5 100644 --- a/src/commands/mute.js +++ b/src/commands/mute.js @@ -85,7 +85,7 @@ exports.run = async (client, message, [args, ...reason], level) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#a652bb"); - embed.setAuthor("User muted!", user.user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("User muted!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription( `• User: ${user} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${muteReason}` ); diff --git a/src/commands/nowplaying.js b/src/commands/nowplaying.js index 9aa0487..e94f71a 100644 --- a/src/commands/nowplaying.js +++ b/src/commands/nowplaying.js @@ -23,7 +23,7 @@ exports.run = async (client, message) => { embed.setDescription(`**[${song.title}](https://www.youtube.com/watch?v=${song.id})**`) embed.addField("Channel:", song.author, true) embed.addField("Time:", timestamp, true) - embed.setFooter("Requested by " + song.requestedBy.tag, song.requestedBy.avatarURL({format: "png", dynamic: true})) + embed.setFooter("Requested by " + song.requestedBy.tag, song.requestedBy.avatarURL({format: "png", dynamic: true, size: 2048})) message.channel.send(embed) }; diff --git a/src/commands/purge.js b/src/commands/purge.js index 406bf64..79cf320 100644 --- a/src/commands/purge.js +++ b/src/commands/purge.js @@ -34,7 +34,7 @@ exports.run = async (client, message, args, level) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#a62019"); - embed.setAuthor(`${amount} messages purged!`, message.author.avatarURL({format: "png", dynamic: true})); + embed.setAuthor(`${amount} messages purged!`, message.author.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription(`• Channel: ${message.channel.name} (${message.channel.id})\n• Mod: ${message.author} (${message.author.id})\n• Amount: \`${amount}\``) try { channel.send({ embed }); diff --git a/src/commands/raidmode.js b/src/commands/raidmode.js index 976d2ae..68a70ec 100644 --- a/src/commands/raidmode.js +++ b/src/commands/raidmode.js @@ -43,7 +43,7 @@ exports.run = async (client, message, args, level) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor(embColour); - embed.setAuthor(raidToggle, message.author.avatarURL({dynamic: true})); + embed.setAuthor(raidToggle, message.author.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription(`• Mod: ${message.author} (${message.author.id})`) try { channel.send({ embed }); diff --git a/src/commands/servericon.js b/src/commands/servericon.js index 5a22748..2eb44c4 100644 --- a/src/commands/servericon.js +++ b/src/commands/servericon.js @@ -1,5 +1,5 @@ exports.run = (client, message) => { - message.channel.send(`**${message.guild}'s** icon is:\n${message.guild.iconURL({format: "png", dynamic: true})}`) + message.channel.send(`**${message.guild}'s** icon is:\n${message.guild.iconURL({format: "png", dynamic: true, size: 2048})}`) }; exports.conf = { diff --git a/src/commands/serverinfo.js b/src/commands/serverinfo.js index 41c8b0c..89c2230 100644 --- a/src/commands/serverinfo.js +++ b/src/commands/serverinfo.js @@ -78,7 +78,7 @@ exports.run = (client, message) => { .setColor(message.guild.member(client.user).displayHexColor) .setTitle(guild.name) .setDescription(`${badges}• **ID:** ${guild.id}\n• **Owner:** ${guild.owner}\n• **Region:** ${guild.region.toProperCase()}\n• **Boosts:** ${boosts}\n• **Members:** ${members}\n• **Channels:** ${channelString}\n• **Roles:** ${roles}\n• **Emojis:** ${emojiString}\n• **Creation date:** ${guild.createdAt}`) - .setThumbnail(message.guild.iconURL({format: "png", dynamic: true})); + .setThumbnail(message.guild.iconURL({format: "png", dynamic: true, size: 2048})); message.channel.send(embed); }; diff --git a/src/commands/softban.js b/src/commands/softban.js index ca95e60..1b602c5 100644 --- a/src/commands/softban.js +++ b/src/commands/softban.js @@ -71,7 +71,7 @@ exports.run = async (client, message, args) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#F38159"); - embed.setAuthor("User softbanned!", user.user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("User softbanned!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription( `• User: ${user.user.tag} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Days cleared: ${days}` ); diff --git a/src/commands/takerole.js b/src/commands/takerole.js index 4a11fa6..408d0e3 100644 --- a/src/commands/takerole.js +++ b/src/commands/takerole.js @@ -59,7 +59,7 @@ exports.run = async (client, message, [member, ...role2add], query) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#008369"); - embed.setAuthor("Role taken:", user.user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("Role taken:", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription(`‏‏‎• User: ${user} (${user.user.id})\n‏‏‎• Mod: ${message.author} (${message.author.id})\n‏‏‎• Role: ${gRole}`) try { channel.send({ embed }); diff --git a/src/commands/unmute.js b/src/commands/unmute.js index 448df4d..abf38f1 100644 --- a/src/commands/unmute.js +++ b/src/commands/unmute.js @@ -63,7 +63,7 @@ exports.run = async (client, message, args, level) => { if (channel) { let embed = new Discord.MessageEmbed(); embed.setColor("#7a2f8f"); - embed.setAuthor("User unmuted!", user.user.avatarURL({format: "png", dynamic: true})); + embed.setAuthor("User unmuted!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); embed.setDescription(`• User: ${user} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})`) try { channel.send({ embed }); diff --git a/src/commands/userinfo.js b/src/commands/userinfo.js index 1ad7ec0..7514de5 100644 --- a/src/commands/userinfo.js +++ b/src/commands/userinfo.js @@ -61,13 +61,13 @@ exports.run = (client, message, args) => { id = user.user.id; tag = user.user.tag; colour = user.displayHexColor; - avurl = user.user.avatarURL({format: "png", dynamic: true}); + avurl = user.user.avatarURL({format: "png", dynamic: true, size: 2048}); createdAt = user.user.createdAt; } else { id = user.id; tag = user.tag; colour = ["#ff9d68", "#ff97cb", "#d789ff", "#74FFFF"].random(); - avurl = user.avatarURL({format: "png", dynamic: true}); + avurl = user.avatarURL({format: "png", dynamic: true, size: 2048}); createdAt = user.createdAt; }; From 6bb1a160bd9074c841e7666279f553204c22deda Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Mon, 16 Mar 2020 12:21:33 +1100 Subject: [PATCH 03/27] Update version.json --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index b6a4488..edc38f2 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "number": "1.1.0", + "number": "1.1.1", "changelog": "**1.1.0 CHANGELOG:**\n> • Added `~softban`, bans and unbans a user to clear messages\n> • Added `~emoji`, enlarges custom emojis\n> • Added `~inspirobot`, generates an inspirational quote\n> • `~serverinfo` has been changed to be more consistent, and also now displays boosts and if the server is partnered and stuff\n> • `~userinfo` has been changed to be more consistent, also added some stuff\n> • `~about` has been changed, added a thumbnail and removed the description\n> • `~colour` has been changed, it can now generate colours from text\n> • `~hackban` no longer has its own embed\n> • `~eval` now logs to hastebin if output is too large\n> • role names are no longer case sensitive\n> • `~echo` renamed `~say`\n> • Users with the ADMINISTRATOR permission now automatically recieve woomy admin\n> • Fixed `~flip`, `~purge`, `~bohemian_rhapsody` and `~creeper`\n> • Guild join/leave messages no longer include the guild name\n> • Some emojis have been changed\n> • Woomy now supports discord.js v12\n> • Files have been restructured\n> • Logger now logs error stack\n> • Restart now exits with code 0" } From a411fb3af49c9c5c2d02a9bf23844c299223bc18 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Mon, 16 Mar 2020 16:30:43 +1100 Subject: [PATCH 04/27] Update about.js --- src/commands/about.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/about.js b/src/commands/about.js index 5c1538f..ad1666b 100644 --- a/src/commands/about.js +++ b/src/commands/about.js @@ -45,7 +45,7 @@ exports.run = (client, message) => { exports.conf = { enabled: true, guildOnly: false, - aliases: ["stats"], + aliases: ["stats", "botinfo"], permLevel: "User", requiredPerms: [] }; From e5aad749f5be27ce7d515a2474b7b819a75516ac Mon Sep 17 00:00:00 2001 From: FLGX Date: Thu, 19 Mar 2020 10:46:53 +0100 Subject: [PATCH 05/27] make weather command return if an error occured --- src/commands/weather.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/weather.js b/src/commands/weather.js index f5fc362..4af8b86 100644 --- a/src/commands/weather.js +++ b/src/commands/weather.js @@ -13,7 +13,7 @@ exports.run = async (client, message, args, error) => { message.channel.startTyping(); weather.find({search: args.join(" "), degreeType: 'C'}, function(err, result) { - if(err) client.logger.log(`weather.js error: ${JSON.stringify(error)}`, "error") + if(err) return client.logger.log(`weather.js error: ${JSON.stringify(error)}`, "error") if(result.length < 2 || !result) { message.channel.stopTyping(); return message.channel.send("<:error:466995152976871434> City not found!"); From ea52ce2fcf77d92ca6e85f308876f86a27839262 Mon Sep 17 00:00:00 2001 From: FLGX Date: Thu, 19 Mar 2020 11:20:18 +0100 Subject: [PATCH 06/27] woomy mention prefix support --- src/events/message.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/events/message.js b/src/events/message.js index 3505c1c..f91dd7e 100644 --- a/src/events/message.js +++ b/src/events/message.js @@ -131,12 +131,20 @@ module.exports = async (client, message) => { }; }; - const prefixMention = new RegExp(`^<@!?${client.user.id}>( |)$`); + //const prefixMention = new RegExp(`^<@!?${client.user.id}>( |)$`); + const myMention = `<@&${client.user.id}>`; + const myMention2 = `<@!${client.user.id}>`; - if (message.content.match(prefixMention)) { - return message.channel.send(`Current prefix: \`${prefix}\``); - } + console.log(message.content); + 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}\``); + }; + }; + if (message.content.indexOf(prefix) !== 0) return; const args = message.content.slice(prefix.length).trim().split(/ +/g); From 0360a5c581a4426fadd0f71aa45973e4be498532 Mon Sep 17 00:00:00 2001 From: FLGX Date: Thu, 19 Mar 2020 11:20:45 +0100 Subject: [PATCH 07/27] remove message content printing --- src/events/message.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/events/message.js b/src/events/message.js index f91dd7e..457706b 100644 --- a/src/events/message.js +++ b/src/events/message.js @@ -134,9 +134,7 @@ module.exports = async (client, message) => { //const prefixMention = new RegExp(`^<@!?${client.user.id}>( |)$`); const myMention = `<@&${client.user.id}>`; const myMention2 = `<@!${client.user.id}>`; - - console.log(message.content); - + 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) + ' '; @@ -144,7 +142,7 @@ module.exports = async (client, message) => { return message.channel.send(`Current prefix: \`${prefix}\``); }; }; - + if (message.content.indexOf(prefix) !== 0) return; const args = message.content.slice(prefix.length).trim().split(/ +/g); From 9853c9032be6272d0f3d78d36495263f6de0cea2 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 19 Mar 2020 21:37:34 +1100 Subject: [PATCH 08/27] synced changes --- LICENSE.md | 3 +- changes.txt | 2 +- resources/other/coolpeople.json | 3 +- resources/other/genders.json | 13 ++++++- src/commands/colourify.js | 53 --------------------------- src/commands/help.js | 24 +++++++----- src/commands/ship.js | 4 +- src/commands/ship1.js | 65 --------------------------------- src/commands/userinfo.js | 14 +------ 9 files changed, 35 insertions(+), 146 deletions(-) delete mode 100644 src/commands/colourify.js delete mode 100644 src/commands/ship1.js diff --git a/LICENSE.md b/LICENSE.md index f82dfa5..4e230a1 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,7 @@ MIT License -Copyright (c) 2020 mudkipscience +Copyright (c) 2018 YorkAARGH +Copyright (c) 2018-2020 mudkipscience Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/changes.txt b/changes.txt index e91c096..529e5aa 100644 --- a/changes.txt +++ b/changes.txt @@ -4,7 +4,7 @@ Bots now get a bot badge in the userinfo command Added dogfact and catfact command (terry) index.js now has better logging of when things fail to load/initialize (terry) added `dice`, rolls a 6 sided die (terry) -Help command changed, the amount of commands in each category and overall is now displayed +Help command changed, the amount of commands in each category and overall is now displayed and formatting changed added `inspire` as an alias for inspirobot ship command added find by mention to functions \ No newline at end of file diff --git a/resources/other/coolpeople.json b/resources/other/coolpeople.json index f0de195..a2ec0bf 100644 --- a/resources/other/coolpeople.json +++ b/resources/other/coolpeople.json @@ -14,6 +14,7 @@ "264970229514371072", "254310746450690048", "358390849807319040", - "211011138656272386" + "211011138656272386", + "266472557740425216" ] } \ No newline at end of file diff --git a/resources/other/genders.json b/resources/other/genders.json index 3b50663..e09ea2d 100644 --- a/resources/other/genders.json +++ b/resources/other/genders.json @@ -1,4 +1,15 @@ { + "agender": "A gender identity used by someone who has no gender, or sometimes by someone whose gender is neutral", + "aporagender": "A gender that is not male, female, or anything on the spectrum between male and female, but that still has a distinct gendered feeling.", + "bigender": "Bigender individuals have two gender identities, either simultaneously or varying between the two.", "cisgender": "Someone who identifies with their assigned gender at birth.", - "transgender": "Someone who identifies with a gender that is not their assigned gender at birth." + "demiboy": "Someone who identifies as partially male and partially another gender.", + "demiflux": "A gender where one part of someone’s gender is static, and the other part fluctuates in intensity.", + "demigender": "Someone who identifies as partially one gender, and partially another.", + "demigirl": "Someone who identifies as partially female and partially another gender.", + "enby": "Shortened term for “nonbinary”. Used as a noun, like “boy” or “girl” but for nonbinary people.", + "genderfluid": "Someone whos gender varies over time. This might be fluctuating between different genders, or expressing multiple aspects of various genders at the same time.", + "genderflux": "Someone whose gender fluctuates, usually between agender and something else.", + "" + "transgender": "Someone whos gender is different from what they were assigned at birth." } \ No newline at end of file diff --git a/src/commands/colourify.js b/src/commands/colourify.js deleted file mode 100644 index f13720d..0000000 --- a/src/commands/colourify.js +++ /dev/null @@ -1,53 +0,0 @@ -const isURL = require("is-url") -exports.run = async (client, message, args) => { - var img; - if(!args[0]) { - if(!message.attachments.first()) { - return message.channel.send("No attachment") - }; - img = message.attachments.first().attachment; - } else { - if(isURL(args[0]) == true ) { - img = args[0]; - } else { - user = message.mentions.members.first(); - - if (!user) { - let users; - users = client.searchForMembers(message.guild, args[0]); - if (users.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (users.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user = users[0]; - }; - - if(user) { - img = user.user.avatarURL({format: "png", dynamic: true}) - } - } - }; - - var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/filter/magik?image=${img}`) - message.channel.send(attachment) -}; - - exports.conf = { - enabled: true, - guildOnly: false, - aliases: [], - permLevel: "User", - requiredPerms: [] - }; - - exports.help = { - name: "magikt", - category: "Fun", - description: "Colourifies an image", - usage: "colourify user hex1 hex2" - }; - \ No newline at end of file diff --git a/src/commands/help.js b/src/commands/help.js index beeda6d..0dd8acf 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -3,7 +3,7 @@ exports.run = (client, message, args, level) => { embed.setColor(client.embedColour(message)); var ran = false; - var output = ""; + var output = "```"; var commands = 0; var prefix; var currentCategory; @@ -38,18 +38,22 @@ exports.run = (client, message, args, level) => { const cat = c.help.category.toProperCase(); if (currentCategory !== cat) { if(ran == true) { - embed.addField(currentCategory + ` [${commands}]`, output.slice(0, -2)) - output = ""; + output = output.slice(0, -2) + "```"; + embed.addField(currentCategory + ` [${commands}]`, output) + output = "```"; commands = 0; } currentCategory = cat; ran = true } - output += `\`${prefix}${c.help.name}\`, `; + output += `${prefix}${c.help.name}, `; commands = commands + 1; }); - embed.addField(currentCategory + ` [${commands}]`, output.slice(0, -2)); + output = output.slice(0, -2); + output = output + "```" + + embed.addField(currentCategory + ` [${commands}]`, output); embed.addField( "Invite me", @@ -87,18 +91,20 @@ exports.run = (client, message, args, level) => { const cat = c.help.category.toProperCase(); if (currentCategory !== cat) { if(ran == true) { - embed.addField(currentCategory + ` [${commands}]`, output.slice(0, -2)) - output = ""; + output = output.slice(0, -2) + "```"; + embed.addField(currentCategory + ` [${commands}]`, output) + output = "```"; commands = 0; } currentCategory = cat; ran = true } - output += `\`${prefix}${c.help.name}\`, `; + output += `${prefix}${c.help.name}, `; commands = commands + 1; }); - embed.addField(currentCategory + ` [${commands}]`, output.slice(0, -2)); + output = output.slice(0, -2) + "```"; + embed.addField(currentCategory + ` [${commands}]`, output); embed.addField( "Invite me", diff --git a/src/commands/ship.js b/src/commands/ship.js index 2ef0477..6264131 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -39,11 +39,9 @@ exports.run = async (client, message, args) => { ); user2 = users[0]; }; - - var secondLength = Math.floor(user2.username.length / 2); var first = user.username.slice(0, user.username.length / 2) - var second = user2.username.slice(secondLength, user2.username.length / 2) + var second = user2.username.slice(Math.floor(user2.username.length / 2), user2.username.length) try { var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) diff --git a/src/commands/ship1.js b/src/commands/ship1.js deleted file mode 100644 index ca96edd..0000000 --- a/src/commands/ship1.js +++ /dev/null @@ -1,65 +0,0 @@ -const request = require('request') -exports.run = async (client, message, args) => { - - - //NOT FINISHED - - if(!args[0] || !args[1]) { - return message.channel.send(`<:error:466995152976871434> Please include two to five users`) - } - message.channel.startTyping(); - - var user = client.getUserFromMention(args[0]) - var user2 = client.getUserFromMention(args[1]) - - if (!user) { - let users; - users = client.searchForMembers(message.guild, args[0]); - if (users.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (users.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user = users[0]; - }; - - if (!user2) { - let users; - users = client.searchForMembers(message.guild, args[0]); - if (users.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (users.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user2 = users[0]; - }; - - var secondLength = Math.floor(user2.username.length / 2); - - var first = user.username.slice(0, user.username.length / 2) - var second = user2.username.slice(secondLength, user2.username.length / 2) - - message.channel.send(`Your ship name is **${shipname}!**`) -}; - -exports.conf = { - enabled: true, - guildOnly: true, - aliases: [], - permLevel: "User", - requiredPerms: [] -}; - -exports.help = { - name: "ship1", - category: "Fun", - description: "Ship two people together <3", - usage: "ship name name2" -}; - diff --git a/src/commands/userinfo.js b/src/commands/userinfo.js index ddec46f..c5dcbac 100644 --- a/src/commands/userinfo.js +++ b/src/commands/userinfo.js @@ -1,18 +1,8 @@ const Discord = require("discord.js"); const coolPeople = require('../../resources/other/coolpeople.json') exports.run = (client, message, args) => { - var user; - var guild; - var nick = ""; - var roles = ""; - var presence = ""; - var badges = ""; - var status; - var createdAt; - var avurl; - var tag; - var id; - var bot; + var user, guild, status, createdAt, avurl, tag, id; + var nick, roles, presence, badges = ""; var coolPerson = false; var friendos = coolPeople.coolPeople; From 4948a5d1f5c8ed5bf9982a0297331312fad10346 Mon Sep 17 00:00:00 2001 From: FLGX Date: Thu, 19 Mar 2020 11:46:10 +0100 Subject: [PATCH 09/27] fix ship command --- src/commands/ship.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commands/ship.js b/src/commands/ship.js index 2ef0477..a3207e2 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -23,12 +23,12 @@ exports.run = async (client, message, args) => { return message.channel.send( "<:error:466995152976871434> That user doesn't seem to exist. Try again!" ); - user = users[0]; + user = users[0].user; }; if (!user2) { let users; - users = client.searchForMembers(message.guild, args[0]); + users = client.searchForMembers(message.guild, args[1]); if (users.length > 1) return message.channel.send( "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." @@ -37,13 +37,13 @@ exports.run = async (client, message, args) => { return message.channel.send( "<:error:466995152976871434> That user doesn't seem to exist. Try again!" ); - user2 = users[0]; + user2 = users[0].user; }; var secondLength = Math.floor(user2.username.length / 2); - var first = user.username.slice(0, user.username.length / 2) - var second = user2.username.slice(secondLength, user2.username.length / 2) + var first = user.username.slice(0, secondLength - 1) + var second = user2.username.slice(secondLength) try { var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) From f87c2834665f5f836ecbbdb5fd7645d95499f4f5 Mon Sep 17 00:00:00 2001 From: FLGX Date: Thu, 19 Mar 2020 11:50:30 +0100 Subject: [PATCH 10/27] a --- src/commands/ship1.js | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/commands/ship1.js diff --git a/src/commands/ship1.js b/src/commands/ship1.js new file mode 100644 index 0000000..39d2621 --- /dev/null +++ b/src/commands/ship1.js @@ -0,0 +1,70 @@ +const request = require('request') +exports.run = async (client, message, args) => { + + + //NOT FINISHED + + if(!args[0] || !args[1]) { + return message.channel.send(`<:error:466995152976871434> Please include two users`) + } + message.channel.startTyping(); + + var user = client.getUserFromMention(args[0]) + var user2 = client.getUserFromMention(args[1]) + + if (!user) { + let users; + users = client.searchForMembers(message.guild, args[0]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].user; + }; + + if (!user2) { + let users; + users = client.searchForMembers(message.guild, args[1]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user2 = users[0].user; + }; + + var first = user.username.slice(0, secondLength - 1) + var second = user2.username.slice(secondLength) + + try { + var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) + message.channel.send(`Your ship name is **${first+second}!**`, attachment) + message.channel.stopTyping(); + } catch(err) { + message.channel.send(`<:error:466995152976871434> API error: ${err}`); + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "ship1", + category: "Fun", + description: "Ship two people together <3", + usage: "ship1 name name2" +}; + From 8a1f87b993f8e99a6cf9872e32152e06b48a9afd Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Fri, 20 Mar 2020 12:08:52 +1100 Subject: [PATCH 11/27] Renamed ~gender to ~identity --- resources/other/genders.json | 15 ----- resources/other/identities.json | 110 ++++++++++++++++++++++++++++++++ src/commands/identity.js | 31 +++++++++ 3 files changed, 141 insertions(+), 15 deletions(-) delete mode 100644 resources/other/genders.json create mode 100644 resources/other/identities.json create mode 100644 src/commands/identity.js diff --git a/resources/other/genders.json b/resources/other/genders.json deleted file mode 100644 index e09ea2d..0000000 --- a/resources/other/genders.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "agender": "A gender identity used by someone who has no gender, or sometimes by someone whose gender is neutral", - "aporagender": "A gender that is not male, female, or anything on the spectrum between male and female, but that still has a distinct gendered feeling.", - "bigender": "Bigender individuals have two gender identities, either simultaneously or varying between the two.", - "cisgender": "Someone who identifies with their assigned gender at birth.", - "demiboy": "Someone who identifies as partially male and partially another gender.", - "demiflux": "A gender where one part of someone’s gender is static, and the other part fluctuates in intensity.", - "demigender": "Someone who identifies as partially one gender, and partially another.", - "demigirl": "Someone who identifies as partially female and partially another gender.", - "enby": "Shortened term for “nonbinary”. Used as a noun, like “boy” or “girl” but for nonbinary people.", - "genderfluid": "Someone whos gender varies over time. This might be fluctuating between different genders, or expressing multiple aspects of various genders at the same time.", - "genderflux": "Someone whose gender fluctuates, usually between agender and something else.", - "" - "transgender": "Someone whos gender is different from what they were assigned at birth." -} \ No newline at end of file diff --git a/resources/other/identities.json b/resources/other/identities.json new file mode 100644 index 0000000..c37d5d9 --- /dev/null +++ b/resources/other/identities.json @@ -0,0 +1,110 @@ +{ + "agender": { + "name": "agender", + "description": "A gender identity used by someone who has no gender, or sometimes by someone whose gender is neutral." + }, + "androgyne": { + "name": "androgyne", + "description": "A gender identity associated with androgyny. Androgynes have a gender which is simultaneously feminine and masculine, although not necessarily in equal amounts." + }, + "androgynous": { + "name": "androgynous", + "description": "A term used to refer to people who have both feminine and masculine characteristics." + }, + "aporagender": { + "name": "aporagender", + "description": "A gender that is not male, female, or anything in between that still has a distinct gendered feeling." + }, + "bigender": { + "name": "bigender", + "description": "Having two gender identities, either simultaneously or varying between the two." + }, + "cisgender": { + "name": "cisgender", + "description": "Someone who identifies with their assigned gender at birth." + }, + "demiboy": { + "name": "demiboy", + "description": "Someone who identifies as partially male and partially another gender." + }, + "demiflux": { + "name": "demiflux", + "description": "A gender where one part of someone’s gender is static, and the other part fluctuates in intensity." + }, + "demigender": { + "name": "demigender", + "description": "Someone who identifies as partially one gender, and partially another." + }, + "demigirl": { + "name": "demigirl", + "description": "Someone who identifies as partially female and partially another gender." + }, + "dyadic": { + "name": "dyadic", + "description": "A word used to refer to people who are not intersex" + }, + "enby": { + "name": "enby", + "description": "Shortened term for “nonbinary”. Used as a noun, like “boy” or “girl” but for nonbinary people." + }, + "fluidflux": { + "name": "fluidflux", + "description": "A gender identity which refers to someone with a gender that moves between two or more genders and also fluctuates in intensity." + }, + "genderfluid": { + "name": "genderfluid", + "description": "Someone whose gender varies over time. This might be fluctuating between different genders, or expressing multiple aspects of various genders at the same time." + }, + "genderflux": { + "name": "genderflux", + "description": "Someone whose gender fluctuates, usually between agender and something else." + }, + "genderqueer": { + "name": "genderqueer", + "description": "An umbrella term for all the nonbinary genders. Genderqueer can be a standalone identity, or can refer to a more specific gender identity." + }, + "gendervoid": { + "name": "gendervoid", + "description": "Someone who does not experience gender, or who feels an absence or void in the place of gender." + }, + "intersex": { + "name": "intersex", + "description": "An intersex person is someone with sex characteristics (sexual anatomy, reproductive organs, chromosomal patterns, etc.) that do not align with the typical descriptions of male and female." + }, + "libragender": { + "name": "libragender", + "description": "A gender identity that is mostly agender, but has a connection to masculinity and/or femininity and/or other gendered feelings. That connection may be static (libragender, librafeminine, libramasculine, etc) or fluid, where one feels that the gender one experiences changes (librafluid)." + }, + "neutrois": { + "name": "neutrois", + "description": "Having a null or neutral gender." + }, + "nonbinary": { + "name": "nonbinary", + "description": "An umbrella term for all the gender identities that aren't male or female (the binary genders)" + }, + "non-gendered": { + "name": "non-gendered", + "description": "Having no gender." + }, + "polygender": { + "name": "polygender", + "description": "Having more than one gender, either at the same time or at different times. A polygender person may identify with any combination of binary and nonbinary genders." + }, + "pangender": { + "name": "pangender", + "description": "Having more than one gender, especially someone who identifies as all genders." + }, + "transfeminine": { + "name": "transfeminine", + "description": "A transgender person who identifies with femininity, either as a binary female or a fem-leaning nonbinary identity." + }, + "transgender": { + "name": "transgender", + "description": "An umbrella term that refers to people whose identity differs from their assigned gender at birth." + }, + "transmasculine": { + "name": "transmasculine", + "description": "A transgender person who identifies with masculinity, either as a binary male or a masc-leaning nonbinary identity." + } +} \ No newline at end of file diff --git a/src/commands/identity.js b/src/commands/identity.js new file mode 100644 index 0000000..9be25a4 --- /dev/null +++ b/src/commands/identity.js @@ -0,0 +1,31 @@ +const identities = require ("../../resources/other/identities.json"); +exports.run = async (client, message, args) => { + var output = ""; + if(!args[0]) { + for (var key of Object.keys(identities)) { + output += `${key}, ` + }; + return message.channel.send(`__**Identities**__\n${output.slice(0, -2)}`); + } else { + output = identities[args[0].toLowerCase()]; + if(!output) { + return message.channel.send("<:error:466995152976871434> No results for that query."); + }; + return message.channel.send(`__**${output.name}**__\n${output.description}`); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "identity", + category: "Fun", + description: "Gives you information about the specified identity.", + usage: "identity [identity]" +}; From 29e8198126ed6c82ef6881604c7015b582e13296 Mon Sep 17 00:00:00 2001 From: FLGX Date: Sat, 21 Mar 2020 10:46:51 +0100 Subject: [PATCH 12/27] aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --- src/commands/ship.js | 80 ++++++++++++++++++++++++++----------------- src/commands/ship1.js | 70 ------------------------------------- 2 files changed, 48 insertions(+), 102 deletions(-) delete mode 100644 src/commands/ship1.js diff --git a/src/commands/ship.js b/src/commands/ship.js index c10855f..1fe3c57 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -9,43 +9,59 @@ exports.run = async (client, message, args) => { } message.channel.startTyping(); - var user = client.getUserFromMention(args[0]) - var user2 = client.getUserFromMention(args[1]) + let users = []; + let totalLength = 0; - if (!user) { - let users; - users = client.searchForMembers(message.guild, args[0]); - if (users.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (users.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user = users[0].user; + for(let i = 0; i < args.length; i++) { + let arg = args[i]; + + let user = client.getUserFromMention(arg); + + if(!user) { + let usersFound; + usersFound = client.searchForMembers(message.guild, arg); + if (usersFound.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." + ); + else if (usersFound.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = usersFound[0].user; + } + + users.push(user); + totalLength += user.username.length; + } + + let lengthPerUser = Math.floor(totalLength / users.length); + + let finalName = ''; + + let last = -1; + + for(let i = 0; i < users.length; i++) { + let user = users[i]; + let l = Math.min(lengthPerUser, user.username.length); + + let p = user.username.substr(last + 1, last + l); + + console.log(p); + + finalName = finalName + p; + + last = last + l; }; - if (!user2) { - let users; - users = client.searchForMembers(message.guild, args[1]); - if (users.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (users.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user2 = users[0].user; - }; - - var first = user.username.slice(0, user.username.length / 2) - var second = user2.username.slice(Math.floor(user2.username.length / 2), user2.username.length) + console.log(totalLength); + console.log(users.length); + console.log(lengthPerUser); + console.log(finalName); try { - var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) - message.channel.send(`Your ship name is **${first+second}!**`, attachment) + //var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) + message.channel.send(`Your ship name is **${finalName}!**`) message.channel.stopTyping(); } catch(err) { message.channel.send(`<:error:466995152976871434> API error: ${err}`); diff --git a/src/commands/ship1.js b/src/commands/ship1.js deleted file mode 100644 index 39d2621..0000000 --- a/src/commands/ship1.js +++ /dev/null @@ -1,70 +0,0 @@ -const request = require('request') -exports.run = async (client, message, args) => { - - - //NOT FINISHED - - if(!args[0] || !args[1]) { - return message.channel.send(`<:error:466995152976871434> Please include two users`) - } - message.channel.startTyping(); - - var user = client.getUserFromMention(args[0]) - var user2 = client.getUserFromMention(args[1]) - - if (!user) { - let users; - users = client.searchForMembers(message.guild, args[0]); - if (users.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (users.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user = users[0].user; - }; - - if (!user2) { - let users; - users = client.searchForMembers(message.guild, args[1]); - if (users.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (users.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user2 = users[0].user; - }; - - var first = user.username.slice(0, secondLength - 1) - var second = user2.username.slice(secondLength) - - try { - var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) - message.channel.send(`Your ship name is **${first+second}!**`, attachment) - message.channel.stopTyping(); - } catch(err) { - message.channel.send(`<:error:466995152976871434> API error: ${err}`); - message.channel.stopTyping(); - }; -}; - -exports.conf = { - enabled: true, - guildOnly: true, - aliases: [], - permLevel: "User", - requiredPerms: [] -}; - -exports.help = { - name: "ship1", - category: "Fun", - description: "Ship two people together <3", - usage: "ship1 name name2" -}; - From 282c61261dfa288d2d1d91997e149b42f720c74b Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Sun, 22 Mar 2020 22:13:41 +1100 Subject: [PATCH 13/27] Synced changes --- changes.txt | 5 +- package.json | 2 +- resources/images/attackhelicopter.jpg | Bin 0 -> 101789 bytes resources/other/coolpeople.json | 3 +- resources/other/identities.json | 2 +- resources/other/pronouns.json | 153 ++++++++++++++++++++++++- resources/other/sexualities.json | 101 +++++++++++++++- src/commands/{math.js => calculate.js} | 6 +- src/commands/emoji.js | 1 - src/commands/identity.js | 11 +- src/commands/pronoun.js | 36 ++++++ src/commands/sexuality.js | 36 ++++++ src/commands/ship.js | 64 ++++------- 13 files changed, 367 insertions(+), 53 deletions(-) create mode 100644 resources/images/attackhelicopter.jpg rename src/commands/{math.js => calculate.js} (92%) create mode 100644 src/commands/pronoun.js create mode 100644 src/commands/sexuality.js diff --git a/changes.txt b/changes.txt index 529e5aa..2648987 100644 --- a/changes.txt +++ b/changes.txt @@ -7,4 +7,7 @@ added `dice`, rolls a 6 sided die (terry) Help command changed, the amount of commands in each category and overall is now displayed and formatting changed added `inspire` as an alias for inspirobot ship command -added find by mention to functions \ No newline at end of file +added find by mention to functions +you can now @mention the bot to run commands +added identity command, has definitions of gender identities and stuff +renamed math calculate diff --git a/package.json b/package.json index 1c03415..901ffbf 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "better-sqlite3": "^5.4.1", "chalk": "^3.0.0", "dblapi.js": "^2.3.1", - "discord.js": "^12.0.1", + "discord.js": "^12.0.2", "enmap": "^5.2.4", "garfield": "^1.1.2", "get-youtube-id": "^1.0.1", diff --git a/resources/images/attackhelicopter.jpg b/resources/images/attackhelicopter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c077f0d0f97251402063f0982e20d381590fc427 GIT binary patch literal 101789 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

LP?s}>_8ENxMl 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 { exports.conf = { enabled: true, guildOnly: false, - aliases: ["calculate", "calc"], + aliases: ["calc", "math"], permLevel: "User", requiredPerms: [] }; exports.help = { - name: "math", + name: "calculate", category: "Utility", description: "Solves basic mathematical equations.", - usage: "math [equation]" + usage: "calculate [equation]" }; \ No newline at end of file diff --git a/src/commands/emoji.js b/src/commands/emoji.js index 795686c..ab6907b 100644 --- a/src/commands/emoji.js +++ b/src/commands/emoji.js @@ -11,7 +11,6 @@ exports.run = async (client, message, args) => { format = ".gif" }; - console.log(string.length) if(string.length > 18) { ID = string.slice(string.length - 18); } else { diff --git a/src/commands/identity.js b/src/commands/identity.js index 9be25a4..22e8693 100644 --- a/src/commands/identity.js +++ b/src/commands/identity.js @@ -6,8 +6,13 @@ exports.run = async (client, message, args) => { output += `${key}, ` }; return message.channel.send(`__**Identities**__\n${output.slice(0, -2)}`); - } else { - output = identities[args[0].toLowerCase()]; + } else { + if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { + return message.channel.send({ + files: [new Discord.MessageAttachment("./resources/images/attackhelicopter.jpg")] + }); + } + output = identities[args.join(" ").toLowerCase()]; if(!output) { return message.channel.send("<:error:466995152976871434> No results for that query."); }; @@ -18,7 +23,7 @@ exports.run = async (client, message, args) => { exports.conf = { enabled: true, guildOnly: false, - aliases: [], + aliases: ["identities"], permLevel: "User", requiredPerms: [] }; diff --git a/src/commands/pronoun.js b/src/commands/pronoun.js new file mode 100644 index 0000000..a535647 --- /dev/null +++ b/src/commands/pronoun.js @@ -0,0 +1,36 @@ +const pronouns = require ("../../resources/other/pronouns.json"); +exports.run = async (client, message, args) => { + var output = ""; + if(!args[0]) { + for (var key of Object.keys(pronouns)) { + output += `${key}, ` + }; + return message.channel.send(`__**Pronouns**__\n${output.slice(0, -2)}`); + } else { + if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { + return message.channel.send({ + files: [new Discord.MessageAttachment("./resources/images/attackhelicopter.jpg")] + }); + }; + output = pronouns[args.join(" ").toLowerCase()]; + if(!output) { + return message.channel.send("<:error:466995152976871434> No results for that query."); + }; + return message.channel.send(`__**Example sentences using ${output.name}**__\n${output.examples}`); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["pronouns"], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "pronoun", + category: "Fun", + description: "Gives you information on how to use the specified pronoun.", + usage: "pronoun [pronoun]" +}; diff --git a/src/commands/sexuality.js b/src/commands/sexuality.js new file mode 100644 index 0000000..8507dac --- /dev/null +++ b/src/commands/sexuality.js @@ -0,0 +1,36 @@ +const sexualities = require ("../../resources/other/sexualities.json"); +exports.run = async (client, message, args) => { + var output = ""; + if(!args[0]) { + for (var key of Object.keys(sexualities)) { + output += `${key}, ` + }; + return message.channel.send(`__**sexualities**__\n${output.slice(0, -2)}`); + } else { + if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { + return message.channel.send({ + files: [new Discord.MessageAttachment("./resources/images/attackhelicopter.jpg")] + }); + } + output = sexualities[args.join(" ").toLowerCase()]; + if(!output) { + return message.channel.send("<:error:466995152976871434> No results for that query."); + }; + return message.channel.send(`__**${output.name}**__\n${output.description}`); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["sexualities"], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "sexuality", + category: "Fun", + description: "Gives you information about the specified sexuality.", + usage: "sexuality [sexuality]" +}; diff --git a/src/commands/ship.js b/src/commands/ship.js index 1fe3c57..8d8fef3 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -1,51 +1,42 @@ -const request = require('request') exports.run = async (client, message, args) => { - - //NOT FINISHED + var hearts = [ + "❤️", + "🧡", + "💛", + "💚", + "💙", + "💜" + ]; if(!args[0] || !args[1]) { - return message.channel.send(`<:error:466995152976871434> Please include two users`) + return message.channel.send(`<:error:466995152976871434> Please include at least two names.`) } - message.channel.startTyping(); - let users = []; + let names = []; let totalLength = 0; for(let i = 0; i < args.length; i++) { let arg = args[i]; - - let user = client.getUserFromMention(arg); - - if(!user) { - let usersFound; - usersFound = client.searchForMembers(message.guild, arg); - if (usersFound.length > 1) - return message.channel.send( - "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." - ); - else if (usersFound.length == 0) - return message.channel.send( - "<:error:466995152976871434> That user doesn't seem to exist. Try again!" - ); - user = usersFound[0].user; - } - - users.push(user); - totalLength += user.username.length; + let name = client.getUserFromMention(arg).username; + if(!name) { + name = arg; + }; + names.push(name); + totalLength += arg.length; } - let lengthPerUser = Math.floor(totalLength / users.length); + let lengthPerName = Math.floor(totalLength / names.length); let finalName = ''; let last = -1; - for(let i = 0; i < users.length; i++) { - let user = users[i]; - let l = Math.min(lengthPerUser, user.username.length); + for(let i = 0; i < names.length; i++) { + let name = names[i]; + let l = Math.min(lengthPerName, name.length); - let p = user.username.substr(last + 1, last + l); + let p = name.substr(last + 1, last + l); console.log(p); @@ -55,18 +46,11 @@ exports.run = async (client, message, args) => { }; console.log(totalLength); - console.log(users.length); - console.log(lengthPerUser); + console.log(names.length); + console.log(lengthPerName); console.log(finalName); - try { - //var attachment = new Discord.MessageAttachment(`https://api.alexflipnote.dev/ship?user=${user.avatarURL({format: "png"})}&user2=${user2.avatarURL({format: "png"})}`) - message.channel.send(`Your ship name is **${finalName}!**`) - message.channel.stopTyping(); - } catch(err) { - message.channel.send(`<:error:466995152976871434> API error: ${err}`); - message.channel.stopTyping(); - }; + message.channel.send(`**Ship generator:**\n${hearts.random()} Ship name: \`${finalName}\`\n${hearts.random()} Compatibility rating:`) }; exports.conf = { From 063a5ab4659577cc7088ded6f84c86d7b4ba516b Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Mon, 23 Mar 2020 00:01:54 +1100 Subject: [PATCH 14/27] Synced changes --- changes.txt | 6 ++- src/commands/{creeper.js => dice.js} | 0 src/commands/diceroll.js | 2 +- src/commands/roleinfo.js | 45 +++++++++++++++++---- src/commands/ship.js | 59 ++++++++++------------------ src/events/message.js | 2 +- src/modules/functions.js | 6 +++ 7 files changed, 72 insertions(+), 48 deletions(-) rename src/commands/{creeper.js => dice.js} (100%) diff --git a/changes.txt b/changes.txt index 2648987..f121500 100644 --- a/changes.txt +++ b/changes.txt @@ -3,11 +3,15 @@ Links to avatars now lead to the original file size Bots now get a bot badge in the userinfo command Added dogfact and catfact command (terry) index.js now has better logging of when things fail to load/initialize (terry) -added `dice`, rolls a 6 sided die (terry) +added `dice`, rolls a sided die (terry) Help command changed, the amount of commands in each category and overall is now displayed and formatting changed added `inspire` as an alias for inspirobot ship command added find by mention to functions you can now @mention the bot to run commands added identity command, has definitions of gender identities and stuff +added pronouns command, tells you how to use pronouns +added sexuality command, has definitions of sexualities renamed math calculate +fixed woomy in dms +roleinfo now displays what permissions a role has and also the role colour in the thumbnail diff --git a/src/commands/creeper.js b/src/commands/dice.js similarity index 100% rename from src/commands/creeper.js rename to src/commands/dice.js diff --git a/src/commands/diceroll.js b/src/commands/diceroll.js index b307d4e..65900c8 100644 --- a/src/commands/diceroll.js +++ b/src/commands/diceroll.js @@ -22,6 +22,6 @@ exports.run = async (bot, message, args) => { name: "dice", category: "Fun", description: "Rolls a dice.", - usage: "dice" + usage: "dice **OR** dice " }; diff --git a/src/commands/roleinfo.js b/src/commands/roleinfo.js index f6fd0e0..e6c95a4 100644 --- a/src/commands/roleinfo.js +++ b/src/commands/roleinfo.js @@ -15,17 +15,48 @@ exports.run = async (client, message, args, level) => { return message.channel.send(`<:error:466995152976871434> Role not found.`) } - if(role.hoist === true) { - var hoist = `Yes` - } else { - var hoist = `No` - } + var permissions = "```"; + if(role.permissions.has("ADMINISTRATOR")) permissions += "ADMINISTRATOR, "; + if(role.permissions.has("CREATE_INSTANT_INVITE")) permissions += "CREATE_INSTANT_INVITE, "; + if(role.permissions.has("KICK_MEMBERS")) permissions += "KICK_MEMBERS, "; + if(role.permissions.has("BAN_MEMBERS")) permissions += "BAN_MEMBERS, "; + if(role.permissions.has("MANAGE_CHANNELS")) permissions += "MANAGE_CHANNELS, "; + if(role.permissions.has("MANAGE_GUILD")) permissions += "MANAGE_GUILD, "; + if(role.permissions.has("ADD_REACTIONS")) permissions += "ADD_REACTIONS, "; + if(role.permissions.has("VIEW_AUDIT_LOG")) permissions += "VIEW_AUDIT_LOG, "; + if(role.permissions.has("PRIORITY_SPEAKER")) permissions += "PRIORITY_SPEAKER, "; + if(role.permissions.has("STREAM")) permissions += "STREAM, "; + if(role.permissions.has("VIEW_CHANNEL")) permissions += "VIEW_CHANNEL, "; + if(role.permissions.has("SEND_MESSAGES")) permissions += "SEND_MESSAGES, "; + if(role.permissions.has("SEND_TTS_MESSAGES")) permissions += "SEND_TTS_MESSAGES, "; + if(role.permissions.has("MANAGE_MESSAGES")) permissions += "MANAGE_MESSAGES, "; + if(role.permissions.has("EMBED_LINKS")) permissions += "EMBED_LINKS, "; + if(role.permissions.has("ATTACH_FILES")) permissions += "ATTACH_FILES, "; + if(role.permissions.has("READ_MESSAGE_HISTORY")) permissions += "READ_MESSAGE_HISTORY, "; + if(role.permissions.has("MENTION_EVERYONE")) permissions += "MENTION_EVERYONE, "; + if(role.permissions.has("USE_EXTERNAL_EMOJIS")) permissions += "USE_EXTERNAL_EMOJIS, "; + if(role.permissions.has("CONNECT")) permissions += "CONNECT, "; + if(role.permissions.has("SPEAK")) permissions += "SPEAK, "; + if(role.permissions.has("MUTE_MEMBERS")) permissions += "MUTE_MEMBERS, "; + if(role.permissions.has("DEAFEN_MEMBERS")) permissions += "DEAFEN_MEMBERS, "; + if(role.permissions.has("MOVE_MEMBERS")) permissions += "MOVE_MEMBERS, "; + if(role.permissions.has("USE_VAD")) permissions += "USE_VAD, "; + if(role.permissions.has("CHANGE_NICKNAME")) permissions += "CHANGE_NICKNAME, "; + if(role.permissions.has("MANAGE_NICKNAMES")) permissions += "MANAGE_NICKNAMES, "; + if(role.permissions.has("MANAGE_ROLES")) permissions += "MANAGE_ROLES, "; + if(role.permissions.has("MANAGE_WEBHOOKS")) permissions += "MANAGE_WEBHOOKS, "; + if(role.permissions.has("MANAGE_EMOJIS")) permissions += "MANAGE_EMOJIS, "; + permissions = permissions.slice(0, -2); + permissions += "```"; var embed = new Discord.MessageEmbed(); - embed.setColor(role.color) + embed.setColor(role.color); + embed.setTitle(role.name); + embed.setThumbnail("https://api.alexflipnote.xyz/colour/image/" + role.hexColor.replace("#", "")); embed.setDescription( - `• **Name:** ${role.name}\n• **ID:** ${role.id}\n• **Hex:** ${role.hexColor}\n• **Members:** ${role.members.size}\n• **Position:** ${role.position}\n• **Hoisted:** ${hoist}` + `• **ID:** ${role.id}\n• **Hex:** ${role.hexColor}\n• **Members:** ${role.members.size}\n• **Position:** ${role.position}\n• **Hoisted:** ${role.hoist}` ); + embed.addField(`**Permissions:**`, permissions) message.channel.send(embed) }; diff --git a/src/commands/ship.js b/src/commands/ship.js index 8d8fef3..7a68e00 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -1,5 +1,7 @@ exports.run = async (client, message, args) => { + var name, name1; + var rating = Math.floor(Math.random() * 100) + 1; var hearts = [ "❤️", "🧡", @@ -9,53 +11,34 @@ exports.run = async (client, message, args) => { "💜" ]; - if(!args[0] || !args[1]) { - return message.channel.send(`<:error:466995152976871434> Please include at least two names.`) + if(args.length < 2) { + return message.channel.send(`<:error:466995152976871434> Please include two names/users.`) } - let names = []; - let totalLength = 0; - - for(let i = 0; i < args.length; i++) { - let arg = args[i]; - let name = client.getUserFromMention(arg).username; - if(!name) { - name = arg; - }; - names.push(name); - totalLength += arg.length; - } - - let lengthPerName = Math.floor(totalLength / names.length); - - let finalName = ''; - - let last = -1; - - for(let i = 0; i < names.length; i++) { - let name = names[i]; - let l = Math.min(lengthPerName, name.length); - - let p = name.substr(last + 1, last + l); - - console.log(p); - - finalName = finalName + p; - - last = last + l; + if(message.guild && message.mentions.members && message.mentions.members.size > 0) { + name = message.mentions.members.first().displayName; }; - console.log(totalLength); - console.log(names.length); - console.log(lengthPerName); - console.log(finalName); + if(message.guild && message.mentions.members && message.mentions.members.size > 1) { + name1 = message.mentions.members.last().displayName; + }; - message.channel.send(`**Ship generator:**\n${hearts.random()} Ship name: \`${finalName}\`\n${hearts.random()} Compatibility rating:`) + if(!name) { + name = args[0]; + }; + + if(!name1) { + name1 = args[1]; + }; + + shipName = name.substring(0, client.intBetween(1,name.length))+name1.substring(client.intBetween(0,name1.length)); + + message.channel.send(`__**Ship Generator:**__\n${hearts.random()} Ship Name: \`${shipName}\`\n${hearts.random()} Compatibility rating: \`${rating}%\``) }; exports.conf = { enabled: true, - guildOnly: true, + guildOnly: false, aliases: [], permLevel: "User", requiredPerms: [] diff --git a/src/events/message.js b/src/events/message.js index 457706b..0dfc019 100644 --- a/src/events/message.js +++ b/src/events/message.js @@ -158,7 +158,7 @@ module.exports = async (client, message) => { .then(m => m.delete(2000)); }; - if (!perms.has('SEND_MESSAGES')) { + if (message.guild && !perms.has('SEND_MESSAGES')) { return message.author.send(`<:error:466995152976871434> I don't have permission to speak in **#${message.channel.name}**, Please ask a moderator to give me the send messages permission!`); }; diff --git a/src/modules/functions.js b/src/modules/functions.js index bd30579..f51a34d 100644 --- a/src/modules/functions.js +++ b/src/modules/functions.js @@ -340,6 +340,12 @@ module.exports = client => { }; }; + // FIND RANDOM INT BETWEEN TWO INTEGERS + client.intBetween = function(min, max){ + return Math.round((Math.random() * (max - min))+min); + }; + + // .toPropercase() returns a proper-cased string Object.defineProperty(String.prototype, "toProperCase", { value: function() { From 0fc9659b9ca6231bdfe6c3169c7d528a400b9516 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Mon, 23 Mar 2020 00:02:30 +1100 Subject: [PATCH 15/27] oosp forgot a thing --- src/commands/ship.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/ship.js b/src/commands/ship.js index 7a68e00..b11a988 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -48,6 +48,6 @@ exports.help = { name: "ship", category: "Fun", description: "Ship two people together <3", - usage: "ship name name2" + usage: "ship [name/user] [name/user]" }; From 55d66f348d423decc5ddf29357b6c455cb896799 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Tue, 24 Mar 2020 05:47:26 +0000 Subject: [PATCH 16/27] Fixed woomy in DM's --- src/events/message.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/message.js b/src/events/message.js index 3505c1c..8904399 100644 --- a/src/events/message.js +++ b/src/events/message.js @@ -152,7 +152,7 @@ module.exports = async (client, message) => { .then(m => m.delete(2000)); }; - if (!perms.has('SEND_MESSAGES')) { + if (message.guild && !perms.has('SEND_MESSAGES')) { return message.author.send(`<:error:466995152976871434> I don't have permission to speak in **#${message.channel.name}**, Please ask a moderator to give me the send messages permission!`); }; @@ -224,4 +224,4 @@ module.exports = async (client, message) => { client.logger.cmd(`${client.config.permLevels.find(l => l.level === level).name} ${message.author.username} (${message.author.id}) ran command ${cmd.help.name}`); cmd.run(client, message, args, level); -}; \ No newline at end of file +}; From 51e307b3d63689646e9f40a52fe66a837882f5b0 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Tue, 24 Mar 2020 05:47:41 +0000 Subject: [PATCH 17/27] Update version.json --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index edc38f2..b7c8929 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "number": "1.1.1", + "number": "1.1.2", "changelog": "**1.1.0 CHANGELOG:**\n> • Added `~softban`, bans and unbans a user to clear messages\n> • Added `~emoji`, enlarges custom emojis\n> • Added `~inspirobot`, generates an inspirational quote\n> • `~serverinfo` has been changed to be more consistent, and also now displays boosts and if the server is partnered and stuff\n> • `~userinfo` has been changed to be more consistent, also added some stuff\n> • `~about` has been changed, added a thumbnail and removed the description\n> • `~colour` has been changed, it can now generate colours from text\n> • `~hackban` no longer has its own embed\n> • `~eval` now logs to hastebin if output is too large\n> • role names are no longer case sensitive\n> • `~echo` renamed `~say`\n> • Users with the ADMINISTRATOR permission now automatically recieve woomy admin\n> • Fixed `~flip`, `~purge`, `~bohemian_rhapsody` and `~creeper`\n> • Guild join/leave messages no longer include the guild name\n> • Some emojis have been changed\n> • Woomy now supports discord.js v12\n> • Files have been restructured\n> • Logger now logs error stack\n> • Restart now exits with code 0" } From 7fdeceee670d0d495f74810908f7ce415aacc67c Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Tue, 24 Mar 2020 09:05:32 +0000 Subject: [PATCH 18/27] Made readme friendlier --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 693f553..d0fde98 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ # Woomy -Woomy is a all-purpose discord bot built off the [guidebot](https://github.com/AnIdiotsGuide/guidebot) base and coded in node.js using discord.js. +Woomy is a all-purpose discord bot built off the [guidebot](https://github.com/AnIdiotsGuide/guidebot) base and coded in node.js using discord.js. # How to use The easiest way to use Woomy is to invite it to your server with [this link.](https://discordapp.com/oauth2/authorize?client_id=435961704145485835&permissions=2134240503&scope=bot) It is hosted 24/7 and automatically updates itself when a new release is made available, making sure you always get the newest features. -Self hosting is generally not recommended, but instructions are provided below if you still wish to do so. Woomy's code will need to be modified before it will run on your machine. +You can also self-host! Some modificatiomns to the code will need to be made before Woomy will run on your machine, but anyone who can read errors will figure out what needs to be changed pretty quickly :P # Requirements - git - node.js v12.0.0 or higher - node-gyp build tools -- ffmpeg +- ffmpeg (or ffmpeg-static) # Installation - Clone Woomy to your machine @@ -18,4 +18,4 @@ Self hosting is generally not recommended, but instructions are provided below i - Open config.js in your code editor and insert all the required information # Contributing -If you wish to contribute to Woomy, please fork the repository and open a pull request. +If you wish to contribute to Woomy, please fork the repository and open a pull request. Any contribution is appreciated <3 From 3ec4d08763874f06912cb8d1d31615a90e9df260 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 15:31:32 +1100 Subject: [PATCH 19/27] Update time woo --- changes.txt | 22 ++++++ index.js | 98 ++++++++------------------- package.json | 9 +-- src/commands/about.js | 2 +- src/commands/cat.js | 30 ++++++++ src/commands/catfact.js | 12 ++-- src/commands/{flip.js => coinflip.js} | 6 +- src/commands/credits.js | 4 +- src/commands/creeper.js | 45 ++++++++++++ src/commands/cuddle.js | 69 +++++++++++++++++++ src/commands/dice.js | 70 +++++++------------ src/commands/diceroll.js | 27 -------- src/commands/dog.js | 30 ++++++++ src/commands/dogfact.js | 17 +++-- src/commands/emojify.js | 2 +- src/commands/fact.js | 30 ++++++++ src/commands/feed.js | 69 +++++++++++++++++++ src/commands/feedback.js | 2 +- src/commands/foxgirl.js | 30 ++++++++ src/commands/help.js | 25 +++---- src/commands/hug.js | 69 +++++++++++++++++++ src/commands/identity.js | 2 +- src/commands/inspirobot.js | 25 +++---- src/commands/kemonomimi.js | 30 ++++++++ src/commands/kiss.js | 69 +++++++++++++++++++ src/commands/lizard.js | 30 ++++++++ src/commands/neko.js | 30 ++++++++ src/commands/nekogif.js | 30 ++++++++ src/commands/owoify.js | 4 +- src/commands/pat.js | 69 +++++++++++++++++++ src/commands/poke.js | 69 +++++++++++++++++++ src/commands/pronoun.js | 4 +- src/commands/roleinfo.js | 1 - src/commands/sexuality.js | 4 +- src/commands/ship.js | 2 +- src/commands/slap.js | 69 +++++++++++++++++++ src/commands/smug.js | 33 +++++++++ src/commands/spoilerise.js | 28 ++++++++ src/commands/support.js | 2 +- src/commands/tickle.js | 69 +++++++++++++++++++ src/commands/weather.js | 75 ++++++++++---------- src/commands/yoda.js | 37 +++++----- src/commands/zalgo.js | 30 ++++++++ src/events/ready.js | 19 ++++-- src/modules/functions.js | 19 +++--- 45 files changed, 1139 insertions(+), 279 deletions(-) create mode 100644 src/commands/cat.js rename src/commands/{flip.js => coinflip.js} (90%) create mode 100644 src/commands/creeper.js create mode 100644 src/commands/cuddle.js delete mode 100644 src/commands/diceroll.js create mode 100644 src/commands/dog.js create mode 100644 src/commands/fact.js create mode 100644 src/commands/feed.js create mode 100644 src/commands/foxgirl.js create mode 100644 src/commands/hug.js create mode 100644 src/commands/kemonomimi.js create mode 100644 src/commands/kiss.js create mode 100644 src/commands/lizard.js create mode 100644 src/commands/neko.js create mode 100644 src/commands/nekogif.js create mode 100644 src/commands/pat.js create mode 100644 src/commands/poke.js create mode 100644 src/commands/slap.js create mode 100644 src/commands/smug.js create mode 100644 src/commands/spoilerise.js create mode 100644 src/commands/tickle.js create mode 100644 src/commands/zalgo.js diff --git a/changes.txt b/changes.txt index f121500..8ca32e2 100644 --- a/changes.txt +++ b/changes.txt @@ -15,3 +15,25 @@ added sexuality command, has definitions of sexualities renamed math calculate fixed woomy in dms roleinfo now displays what permissions a role has and also the role colour in the thumbnail +request has been replaced with node-fetch +added neko +added fact +added nekogif +added dog +added cat +added hug +added kiss +added pat +added poke +added slap +added tickle +added cuddle +added feed +added smug +added lizard +added kemonomimi +added spoilerise +added zalgo +renamed flip coinflip +small changes to weather +recategorised some commands diff --git a/index.js b/index.js index 4e535ee..395e910 100644 --- a/index.js +++ b/index.js @@ -1,84 +1,55 @@ +if (Number(process.version.slice(1).split(".")[0]) < 12) { + throw new Error("Node 12.0.0 or higher is required. Please update Node on your system."); +}; + const Discord = require('discord.js'); const { promisify } = require('util'); const readdir = promisify(require('fs').readdir); const Enmap = require('enmap'); const chalk = require('chalk'); -const DBL = require("dblapi.js"); const client = new Discord.Client(); try { -client.config = require('./config'); + client.config = require('./config'); } catch (err) { - console.log('Could not load config.js: \n', err); - process.exit(); -} - + console.log('Failed to load config.js:', err); + process.exit(); +}; try{ -client.version = require('./version.json'); + client.version = require('./version.json'); } catch (err) { - console.log('Could not load version.json: \n', err); - process.exit(); -} - + console.log('Failed to load version.json:', err); + process.exit(); +}; try{ -client.logger = require('./src/modules/Logger'); + client.logger = require('./src/modules/Logger'); } catch (err) { - console.log('Could not load Logger.js: \n', err); - process.exit(); -} - -try{ -require("./src/modules/functions")(client); -} catch (err) { - console.log('Could not load functions.js: \n', err); - process.exit(); -} - -try{ + console.log('Failed to load Logger.js:', err); + process.exit(); +}; client.logger.setClient(client); + +try{ + require("./src/modules/functions")(client); } catch (err) { - console.log('Logger failed to initialize: \n', err); - process.exit(1); -} + console.log('Failed to load functions.js:', err); + process.exit(); +}; if(process.env['USER'] != 'container') { client.devmode = true; } else { client.devmode = false; - if(client.config.dblkey.length == 0) { + if(client.config.dblkey.length > 0) { + const DBL = require("dblapi.js"); const dblapi = new DBL(client.config.dblkey, client); - } -} + }; +}; -try{ client.commands = new Enmap(); -} catch (err) { - console.log('Failed to create the commands database: \n', err); - process.exit(); -} - -try{ client.aliases = new Enmap(); -} catch (err) { - console.log('Failed to create the aliases database: \n', err); - process.exit(); -} - -try{ client.settings = new Enmap({name: 'settings'}); -} catch (err) { - console.log('Failed to initialize the settings database: \n', err); - process.exit(); -} -try{ -client.blacklist = new Enmap({name: 'blacklist'}); -} catch (err) { - console.log('Failed to initialize the blacklist database: \n', err); - process.exit(1); -} - -try{ const init = async () => { const cmdFiles = await readdir("./src/commands/"); client.logger.info(`Loading ${cmdFiles.length} commands.`); @@ -103,30 +74,17 @@ const init = async () => { client.on(eventName, event.bind(null, client)); }); - try{ client.levelCache = {}; for (let i = 0; i < client.config.permLevels.length; i++) { const thisLevel = client.config.permLevels[i]; client.levelCache[thisLevel.name] = thisLevel.level; }; -} catch (err) { - console.log('Level cache failed to initialize: \n', err); - process.exit(); -} - try{ if(client.devmode === true) { client.login(client.config.devtoken); } else { client.login(client.config.token); }; -} catch (err) { - console.log('Could not login to Discord: \n', err); - process.exit(1); -} }; -init(); -} catch (err) { - console.log('Initialization failed: \n', err); - process.exit(1); -} + +init(); \ No newline at end of file diff --git a/package.json b/package.json index 901ffbf..4109849 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "dependencies": { "@discordjs/opus": "^0.1.0", - "better-sqlite3": "^5.4.1", + "better-sqlite3": "^5.4.3", "chalk": "^3.0.0", "dblapi.js": "^2.3.1", "discord.js": "^12.0.2", @@ -13,16 +13,17 @@ "garfield": "^1.1.2", "get-youtube-id": "^1.0.1", "hastebin-gen": "^2.0.5", - "is-url": "^1.2.4", "moment": "^2.24.0", "moment-duration-format": "^2.3.2", + "nekos.life": "^2.0.5", + "node-fetch": "^2.6.0", + "openweather-apis": "^4.2.0", "prism-media": "^1.2.1", "randomcolor": "^0.5.4", "relevant-urban": "^2.0.0", "request": "^2.88.2", + "to-zalgo": "^1.0.1", "urban": "^0.3.2", - "url-unshort": "^5.0.0", - "url-unshorten": "^1.0.6", "weather-js": "^2.0.0", "youtube-info": "^1.3.2", "ytdl-core-discord": "^1.1.0" diff --git a/src/commands/about.js b/src/commands/about.js index ad1666b..2049bfa 100644 --- a/src/commands/about.js +++ b/src/commands/about.js @@ -26,9 +26,9 @@ exports.run = (client, message) => { } embed = new Discord.MessageEmbed(); - embed.setTitle(`Woomy`); embed.setColor(client.embedColour(message)); embed.setThumbnail(client.user.avatarURL({format: "png", dynamic: true, size: 2048})) + embed.setTitle("About Woomy") embed.addField( "General:", `• users: \`${client.users.cache.size}\`\n• channels: \`${client.channels.cache.size}\`\n• servers: \`${client.guilds.cache.size}\`\n• commands: \`${client.commands.size}\`\n• uptime: \`${duration}\``,true ); diff --git a/src/commands/cat.js b/src/commands/cat.js new file mode 100644 index 0000000..afd627f --- /dev/null +++ b/src/commands/cat.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.meow().then((json) => { + message.channel.send(json.url) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("cat.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "cat", + category: "Image", + description: "Sends you cat pics.", + usage: "cat" +}; diff --git a/src/commands/catfact.js b/src/commands/catfact.js index 9fef875..a58aae4 100644 --- a/src/commands/catfact.js +++ b/src/commands/catfact.js @@ -1,14 +1,12 @@ -const request = require("request"); - +const fetch = require("node-fetch") exports.run = async (bot, message, args) => { message.channel.startTyping(); try{ - request({ uri: "https://catfact.ninja/facts", json: true }, (error, response, body) => { - message.channel.send(`**Did you know?**\n ${body.data[0].fact}`); - message.channel.stopTyping(); - }); + fetch('https://catfact.ninja/facts') + .then(res => res.json()) + .then(json => message.channel.send(`__**Did you know?**__\n${json.data[0].fact}`)) } catch(err) { - message.channel.send(`<:error:466995152976871434> API error: ${err}`); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); message.channel.stopTyping(); }; }; diff --git a/src/commands/flip.js b/src/commands/coinflip.js similarity index 90% rename from src/commands/flip.js rename to src/commands/coinflip.js index 99ba778..418a996 100644 --- a/src/commands/flip.js +++ b/src/commands/coinflip.js @@ -22,14 +22,14 @@ exports.run = (client, message, args) => { exports.conf = { enabled: true, guildOnly: false, - aliases: [], + aliases: ["flip"], permLevel: "User", requiredPerms: [] }; exports.help = { - name: "flip", + name: "coinflip", category: "Fun", description: "Flips a coin!", - usage: "flip [heads/tails]" + usage: "coinflip [heads/tails]" }; diff --git a/src/commands/credits.js b/src/commands/credits.js index b3f8516..5eb48ce 100644 --- a/src/commands/credits.js +++ b/src/commands/credits.js @@ -1,6 +1,6 @@ exports.run = async (client, message, args) => { message.channel.send( - `**Credits:**\n• \`mudkipscience#8904\` and \`FLGX#9896\`for developing the bot\n• \`An Idiots Guide\` for the Guidebot bot base\n• \`dellannie#6057\` for helping with the music commands\n• \`TheCakeChicken#9088\` and \`Tina the Cyclops girl#0064\` for helping me not suck at coding\n• \`AirVentTrent\` for the icon, find him on Instagram` + `__**Credits:**__\n• \`mudkipscience#8904\`, \`FLGX#9896\` and \`TheCakeChicken#9088\` for developing the bot\n• \`An Idiots Guide\` for the Guidebot bot base\n• \`Tina the Cyclops girl#0064\` for helping me not suck at coding\n• \`AirVentTrent\` for the icon, find him on Instagram\n• \`Terryiscool160\` for contributing to Woomy.` ); }; @@ -14,7 +14,7 @@ exports.conf = { exports.help = { name: "credits", - category: "Miscellaneous", + category: "Utility", description: "Cool people", usage: "credits" }; diff --git a/src/commands/creeper.js b/src/commands/creeper.js new file mode 100644 index 0000000..80ac90b --- /dev/null +++ b/src/commands/creeper.js @@ -0,0 +1,45 @@ + +const lyric = require('../../resources/other/lyrics.json') +exports.run = async (client, message, args, level) => { + var lyrics = lyric.creeper; + + var runtop = true; + var runbottom = false; + for(var br = 0; br < lyrics.length; br++) { + { + if (runtop === true) { + var response = await client.awaitReply(message, lyrics[br]); + runbottom = false; + }; + + if (runbottom === true) { + if (response !== lyrics[br]) { + return message.channel.send("Those aren't the lyrics!") + } + runtop = false + }; + } if (runtop === true) { + runtop = false + runbottom = true + } else if (runbottom === true) { + runtop = true + runbottom = false + } + } + message.channel.send("What a lovely duet!") +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "creeper", + category: "Fun", + description: "Aww man", + usage: "creeper" +}; diff --git a/src/commands/cuddle.js b/src/commands/cuddle.js new file mode 100644 index 0000000..63263ae --- /dev/null +++ b/src/commands/cuddle.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to cuddle! Usage: \`${client.commands.get(`cuddle`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.cuddle().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** cuddled **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("cuddle.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "cuddle", + category: "Action", + description: "cuddle someone!", + usage: "cuddle [@user/user] (you can cuddle as many people as you want!)" +}; diff --git a/src/commands/dice.js b/src/commands/dice.js index 80ac90b..be9edcf 100644 --- a/src/commands/dice.js +++ b/src/commands/dice.js @@ -1,45 +1,27 @@ - -const lyric = require('../../resources/other/lyrics.json') -exports.run = async (client, message, args, level) => { - var lyrics = lyric.creeper; - - var runtop = true; - var runbottom = false; - for(var br = 0; br < lyrics.length; br++) { - { - if (runtop === true) { - var response = await client.awaitReply(message, lyrics[br]); - runbottom = false; - }; - - if (runbottom === true) { - if (response !== lyrics[br]) { - return message.channel.send("Those aren't the lyrics!") +exports.run = async (bot, message, args) => { + if (args.length === 0) { + message.channel.send(`🎲 You rolled a ${Array.from(Array(6).keys()).random() + 1}!`); + } else { + if (args[0].match(/^\d+$/)) { + message.channel.send(`🎲 You rolled a ${Array.from(Array(parseInt(args[0])).keys()).random() + 1}!`); + } else { + message.channel.send(`🎲 You rolled a ${Array.from(Array(6).keys()).random() + 1}!`); } - runtop = false - }; - } if (runtop === true) { - runtop = false - runbottom = true - } else if (runbottom === true) { - runtop = true - runbottom = false - } - } - message.channel.send("What a lovely duet!") -}; - -exports.conf = { - enabled: true, - guildOnly: false, - aliases: [], - permLevel: "User", - requiredPerms: [] -}; - -exports.help = { - name: "creeper", - category: "Fun", - description: "Aww man", - usage: "creeper" -}; + } + }; + + exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["diceroll", "roll"], + permLevel: "User", + requiredPerms: [] + }; + + exports.help = { + name: "dice", + category: "Fun", + description: "Rolls a dice.", + usage: "dice " + }; + diff --git a/src/commands/diceroll.js b/src/commands/diceroll.js deleted file mode 100644 index 65900c8..0000000 --- a/src/commands/diceroll.js +++ /dev/null @@ -1,27 +0,0 @@ -exports.run = async (bot, message, args) => { - if (args.length === 0) { - message.channel.send(`🎲 You rolled a ${Array.from(Array(6).keys()).random() + 1}!`); - } else { - if (args[0].match(/^\d+$/)) { - message.channel.send(`🎲 You rolled a ${Array.from(Array(parseInt(args[0])).keys()).random() + 1}!`); - } else { - message.channel.send(`🎲 You rolled a ${Array.from(Array(6).keys()).random() + 1}!`); - } - } - }; - - exports.conf = { - enabled: true, - guildOnly: false, - aliases: ["diceroll"], - permLevel: "User", - requiredPerms: [] - }; - - exports.help = { - name: "dice", - category: "Fun", - description: "Rolls a dice.", - usage: "dice **OR** dice " - }; - diff --git a/src/commands/dog.js b/src/commands/dog.js new file mode 100644 index 0000000..39ce25c --- /dev/null +++ b/src/commands/dog.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.woof().then((json) => { + message.channel.send(json.url) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("dog.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "dog", + category: "Image", + description: "Sends you dog pics.", + usage: "dog" +}; diff --git a/src/commands/dogfact.js b/src/commands/dogfact.js index 31d1639..d0b80ed 100644 --- a/src/commands/dogfact.js +++ b/src/commands/dogfact.js @@ -1,16 +1,15 @@ -const request = require("request"); - +const fetch = require("node-fetch"); exports.run = async (bot, message, args) => { message.channel.startTyping(); try{ - request({ uri: "https://dog-api.kinduff.com/api/facts", json: true }, (error, response, body) => { - message.channel.send(`**Did you know?**\n ${body.facts[0]}`); + fetch('https://dog-api.kinduff.com/api/facts') + .then(res => res.json()) + .then(json => message.channel.send(`__**Did you know?**__\n ${json.facts[0]}`)); message.channel.stopTyping(); - }); -} catch(err) { - message.channel.send(`<:error:466995152976871434> API error: ${err}`); - message.channel.stopTyping(); -}; + } catch(err) { + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); + message.channel.stopTyping(); + }; }; exports.conf = { diff --git a/src/commands/emojify.js b/src/commands/emojify.js index 058faa3..46dfa35 100644 --- a/src/commands/emojify.js +++ b/src/commands/emojify.js @@ -34,7 +34,7 @@ exports.run = (client, message, args) => { if(emojified.length > 2000) { return message.channel.send("<:error:466995152976871434> The emojified message exceeds 2000 characters.") - } + }; message.channel.send(emojified); }; diff --git a/src/commands/fact.js b/src/commands/fact.js new file mode 100644 index 0000000..0e351a6 --- /dev/null +++ b/src/commands/fact.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.fact().then((json) => { + message.channel.send("__**Did you know?**__\n" + json.fact + "."); + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("fact.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["randomfact"], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "fact", + category: "Fun", + description: "Sends you a random fact.", + usage: "fact" +}; diff --git a/src/commands/feed.js b/src/commands/feed.js new file mode 100644 index 0000000..9749f45 --- /dev/null +++ b/src/commands/feed.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to feed! Usage: \`${client.commands.get(`feed`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.feed().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** fed **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("feed.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "feed", + category: "Action", + description: "feed someone!", + usage: "feed [@user/user] (you can feed as many people as you want!)" +}; diff --git a/src/commands/feedback.js b/src/commands/feedback.js index 9f4e436..6b4512b 100644 --- a/src/commands/feedback.js +++ b/src/commands/feedback.js @@ -22,7 +22,7 @@ exports.conf = { exports.help = { name: "feedback", - category: "Miscellaneous", + category: "Utility", description: "Send feedback to my developer.", usage: "feedback [message]" }; diff --git a/src/commands/foxgirl.js b/src/commands/foxgirl.js new file mode 100644 index 0000000..f3f3312 --- /dev/null +++ b/src/commands/foxgirl.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.foxGirl().then((json) => { + message.channel.send(json.url) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("foxgirl.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "foxgirl", + category: "Image", + description: "Sends you pictures of fox girls.", + usage: "foxgirl" +}; diff --git a/src/commands/help.js b/src/commands/help.js index 0dd8acf..5c07963 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -3,7 +3,7 @@ exports.run = (client, message, args, level) => { embed.setColor(client.embedColour(message)); var ran = false; - var output = "```"; + var output = ""; var commands = 0; var prefix; var currentCategory; @@ -15,7 +15,7 @@ exports.run = (client, message, args, level) => { }; if(!args[0]) { - embed.setTitle(`Commands [${client.commands.size}]`); + embed.setTitle(`Command list`); embed.setDescription(`⁣For more information on a specific command use \`${prefix}help \`\nFor the full command list use \`${prefix}help all\`\n`); const myCommands = message.guild ? client.commands.filter( @@ -35,24 +35,20 @@ exports.run = (client, message, args, level) => { ); sorted.forEach( c => { - const cat = c.help.category.toProperCase(); + const cat = c.help.category; if (currentCategory !== cat) { if(ran == true) { - output = output.slice(0, -2) + "```"; embed.addField(currentCategory + ` [${commands}]`, output) - output = "```"; + output = ""; commands = 0; } currentCategory = cat; ran = true } - output += `${prefix}${c.help.name}, `; + output += `\`${c.help.name}\` `; commands = commands + 1; }); - output = output.slice(0, -2); - output = output + "```" - embed.addField(currentCategory + ` [${commands}]`, output); embed.addField( @@ -72,7 +68,7 @@ exports.run = (client, message, args, level) => { }; if(args[0].toLowerCase() == "all") { - embed.setTitle(`Commands [${client.commands.size}]`); + embed.setTitle(`Command list`); embed.setDescription(`⁣For more information on a specific command use \`${prefix}help \`\nFor the full command list use \`${prefix}help all\`\n`); const myCommands = client.commands @@ -88,22 +84,21 @@ exports.run = (client, message, args, level) => { ); sorted.forEach( c => { - const cat = c.help.category.toProperCase(); + const cat = c.help.category; if (currentCategory !== cat) { if(ran == true) { - output = output.slice(0, -2) + "```"; embed.addField(currentCategory + ` [${commands}]`, output) - output = "```"; + output = ""; commands = 0; } currentCategory = cat; ran = true } - output += `${prefix}${c.help.name}, `; + output += `\`${c.help.name}\` `; commands = commands + 1; }); - output = output.slice(0, -2) + "```"; + embed.addField(currentCategory + ` [${commands}]`, output); embed.addField( diff --git a/src/commands/hug.js b/src/commands/hug.js new file mode 100644 index 0000000..30ef214 --- /dev/null +++ b/src/commands/hug.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to hug! Usage: \`${client.commands.get(`hug`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.hug().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** hugged **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("hug.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "hug", + category: "Action", + description: "Hug someone!", + usage: "hug [@user/user] (you can hug as many people as you want!)" +}; diff --git a/src/commands/identity.js b/src/commands/identity.js index 22e8693..b7f3809 100644 --- a/src/commands/identity.js +++ b/src/commands/identity.js @@ -16,7 +16,7 @@ exports.run = async (client, message, args) => { if(!output) { return message.channel.send("<:error:466995152976871434> No results for that query."); }; - return message.channel.send(`__**${output.name}**__\n${output.description}`); + return message.channel.send(`__**${output.name.toProperCase()}**__\n${output.description}`); }; }; diff --git a/src/commands/inspirobot.js b/src/commands/inspirobot.js index 5ba4e0a..17a028f 100644 --- a/src/commands/inspirobot.js +++ b/src/commands/inspirobot.js @@ -1,20 +1,15 @@ -const request = require('request') +const fetch = require("node-fetch") exports.run = async (client, message) => { message.channel.startTyping(); - request({ - url: "http://inspirobot.me/api?generate=true" - }, - function(error, res, body) { - if(body.length > 0) { - message.channel.send({ - files: [new Discord.MessageAttachment(body)] - }); - message.channel.stopTyping(); - } else { - message.channel.send('<:error:466995152976871434> API error, please retry.') - message.channel.stopTyping(); - }; - }); + try { + fetch('http://inspirobot.me/api?generate=true') + .then(res => res.text()) + .then(body => message.channel.send({files: [new Discord.MessageAttachment(body)]})); + message.channel.stopTyping(); + } catch (err) { + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; }; exports.conf = { diff --git a/src/commands/kemonomimi.js b/src/commands/kemonomimi.js new file mode 100644 index 0000000..3c4b70e --- /dev/null +++ b/src/commands/kemonomimi.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.kemonomimi().then((json) => { + message.channel.send(json.url) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("kemonomimi.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "kemonomimi", + category: "Image", + description: "Sends you pictures of people with animal characteristics.", + usage: "kemonomimi" +}; diff --git a/src/commands/kiss.js b/src/commands/kiss.js new file mode 100644 index 0000000..495ee62 --- /dev/null +++ b/src/commands/kiss.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to kiss! Usage: \`${client.commands.get(`kiss`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.kiss().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** kissed **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("kiss.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "kiss", + category: "Action", + description: "Kiss someone!", + usage: "kiss [@user/user] (you can kiss as many people as you want!)" +}; diff --git a/src/commands/lizard.js b/src/commands/lizard.js new file mode 100644 index 0000000..f476704 --- /dev/null +++ b/src/commands/lizard.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.lizard().then((json) => { + message.channel.send(json.url) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("lizard.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "lizard", + category: "Image", + description: "Sends pictures of lizards.", + usage: "lizard" +}; diff --git a/src/commands/neko.js b/src/commands/neko.js new file mode 100644 index 0000000..7ce0d6b --- /dev/null +++ b/src/commands/neko.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.neko().then((json) => { + message.channel.send(json.url); + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("neko.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["catgirl"], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "neko", + category: "Image", + description: "Sends you pictures of catgirls.", + usage: "neko" +}; diff --git a/src/commands/nekogif.js b/src/commands/nekogif.js new file mode 100644 index 0000000..0df6917 --- /dev/null +++ b/src/commands/nekogif.js @@ -0,0 +1,30 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.nekoGif().then((json) => { + message.channel.send(json.url); + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("nekogif.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["catgirlgif"], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "nekogif", + category: "Image", + description: "Sends you gifs of catgirls.", + usage: "nekogif" +}; diff --git a/src/commands/owoify.js b/src/commands/owoify.js index ae8b9a5..9587a6f 100644 --- a/src/commands/owoify.js +++ b/src/commands/owoify.js @@ -13,8 +13,8 @@ exports.run = (client, message, args) => { owoified = owoified.replace(/!+/g, ' ' + faces[~~(Math.random() * faces.length)] + ' ') if(owoified.length > 2000) { - return message.channel.send("<:error:466995152976871434> The owoified message exceeds 2000 characters.") - } + owoified = owoified.slice(0, -Math.abs(owoified.length - 2000)) + }; message.channel.send(owoified) }; diff --git a/src/commands/pat.js b/src/commands/pat.js new file mode 100644 index 0000000..fee469b --- /dev/null +++ b/src/commands/pat.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to pat! Usage: \`${client.commands.get(`pat`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.pat().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** patted **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("pat.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: ["headpat"], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "pat", + category: "Action", + description: "pat someone!", + usage: "pat [@user/user] (you can pat as many people as you want!)" +}; diff --git a/src/commands/poke.js b/src/commands/poke.js new file mode 100644 index 0000000..07c48bc --- /dev/null +++ b/src/commands/poke.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to poke! Usage: \`${client.commands.get(`poke`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.poke().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** poked **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("poke.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "poke", + category: "Action", + description: "poke someone!", + usage: "poke [@user/user] (you can poke as many people as you want!)" +}; diff --git a/src/commands/pronoun.js b/src/commands/pronoun.js index a535647..0d4b36a 100644 --- a/src/commands/pronoun.js +++ b/src/commands/pronoun.js @@ -5,7 +5,7 @@ exports.run = async (client, message, args) => { for (var key of Object.keys(pronouns)) { output += `${key}, ` }; - return message.channel.send(`__**Pronouns**__\n${output.slice(0, -2)}`); + return message.channel.send(`__**Pronouns:**__\n${output.slice(0, -2)}`); } else { if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { return message.channel.send({ @@ -16,7 +16,7 @@ exports.run = async (client, message, args) => { if(!output) { return message.channel.send("<:error:466995152976871434> No results for that query."); }; - return message.channel.send(`__**Example sentences using ${output.name}**__\n${output.examples}`); + return message.channel.send(`__**Example sentences using ${output.name}:**__\n${output.examples}`); }; }; diff --git a/src/commands/roleinfo.js b/src/commands/roleinfo.js index e6c95a4..10d8c4d 100644 --- a/src/commands/roleinfo.js +++ b/src/commands/roleinfo.js @@ -52,7 +52,6 @@ exports.run = async (client, message, args, level) => { var embed = new Discord.MessageEmbed(); embed.setColor(role.color); embed.setTitle(role.name); - embed.setThumbnail("https://api.alexflipnote.xyz/colour/image/" + role.hexColor.replace("#", "")); embed.setDescription( `• **ID:** ${role.id}\n• **Hex:** ${role.hexColor}\n• **Members:** ${role.members.size}\n• **Position:** ${role.position}\n• **Hoisted:** ${role.hoist}` ); diff --git a/src/commands/sexuality.js b/src/commands/sexuality.js index 8507dac..c41930b 100644 --- a/src/commands/sexuality.js +++ b/src/commands/sexuality.js @@ -5,7 +5,7 @@ exports.run = async (client, message, args) => { for (var key of Object.keys(sexualities)) { output += `${key}, ` }; - return message.channel.send(`__**sexualities**__\n${output.slice(0, -2)}`); + return message.channel.send(`__**Sexualities:**__\n${output.slice(0, -2)}`); } else { if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { return message.channel.send({ @@ -16,7 +16,7 @@ exports.run = async (client, message, args) => { if(!output) { return message.channel.send("<:error:466995152976871434> No results for that query."); }; - return message.channel.send(`__**${output.name}**__\n${output.description}`); + return message.channel.send(`__**${output.name.toProperCase()}:**__\n${output.description}`); }; }; diff --git a/src/commands/ship.js b/src/commands/ship.js index b11a988..3850d87 100644 --- a/src/commands/ship.js +++ b/src/commands/ship.js @@ -31,7 +31,7 @@ exports.run = async (client, message, args) => { name1 = args[1]; }; - shipName = name.substring(0, client.intBetween(1,name.length))+name1.substring(client.intBetween(0,name1.length)); + shipName = name.substr(0, client.intBetween(1,name.length))+name1.substr(client.intBetween(0,name1.length)); message.channel.send(`__**Ship Generator:**__\n${hearts.random()} Ship Name: \`${shipName}\`\n${hearts.random()} Compatibility rating: \`${rating}%\``) }; diff --git a/src/commands/slap.js b/src/commands/slap.js new file mode 100644 index 0000000..2e5189c --- /dev/null +++ b/src/commands/slap.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to slap! Usage: \`${client.commands.get(`kiss`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.slap().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** slapped **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("slap.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "slap", + category: "Action", + description: "Slap someone >:3", + usage: "slap [@user/user] (you can slap as many people as you want!)" +}; diff --git a/src/commands/smug.js b/src/commands/smug.js new file mode 100644 index 0000000..011f2bd --- /dev/null +++ b/src/commands/smug.js @@ -0,0 +1,33 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message) => { + message.channel.startTyping(); + try { + sfw.smug().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("smug.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "smug", + category: "Action", + description: "Sends a smug gif.", + usage: "smug" +}; diff --git a/src/commands/spoilerise.js b/src/commands/spoilerise.js new file mode 100644 index 0000000..25ab221 --- /dev/null +++ b/src/commands/spoilerise.js @@ -0,0 +1,28 @@ +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't provide any text! Usage: \`${client.commands.get(`spoiler`).help.usage}\``) + }; + + var output = `||${[...message.cleanContent.substring(9)].join("||||")}||`; + + if(output.length > 2000) { + output = output.slice(0, -Math.abs(output.length - 2000)) + }; + + message.channel.send(output) +}; + +exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["spoilerize", "spoiler"], + permLevel: "User", + requiredPerms: [] +}; + +exports.help = { + name: "spoilerise", + category: "Fun", + description: "Spoilers every letter in the provided text.", + usage: "spoiler [text]" +}; diff --git a/src/commands/support.js b/src/commands/support.js index 8fad6b2..c15de88 100644 --- a/src/commands/support.js +++ b/src/commands/support.js @@ -12,7 +12,7 @@ exports.conf = { exports.help = { name: "support", - category: "utility", + category: "Utility", description: "Sends a link to Woomy's support/development server.", usage: "support" }; diff --git a/src/commands/tickle.js b/src/commands/tickle.js new file mode 100644 index 0000000..e75a771 --- /dev/null +++ b/src/commands/tickle.js @@ -0,0 +1,69 @@ +const API = require('nekos.life'); +const {sfw} = new API(); +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to tickle! Usage: \`${client.commands.get(`tickle`).help.usage}\``) + }; + + var people = ""; + + for (var i = 0; i < args.length; i++) { + var user = client.getUserFromMention(args[i]) + if (user) { + user = message.guild.members.cache.get(user.id).displayName; + } else { + users = client.searchForMembers(message.guild, args[i]); + if (users.length > 1) + return message.channel.send( + "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." + ); + else if (users.length == 0) + return message.channel.send( + "<:error:466995152976871434> That user doesn't seem to exist. Try again!" + ); + user = users[0].displayName; + }; + if(i+1 == args.length && args.length > 1) { + people += `**and** ${user}!` + } else if(args.length < 2) { + people += `${user}!`; + } else if(args.length == 2 && i == 0) { + people += `${user} `; + } else { + people += `${user}, `; + }; + }; + + + + message.channel.startTyping(); + try { + sfw.tickle().then((json) => { + embed = new Discord.MessageEmbed(); + embed.setImage(json.url) + embed.setColor(client.embedColour(message)); + embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** tickled **${people}**`) + message.channel.send(embed) + message.channel.stopTyping(); + }); + } catch (err) { + client.logger.error("tickle.js: " + err); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) + message.channel.stopTyping(); + }; +}; + +exports.conf = { + enabled: true, + guildOnly: true, + aliases: [], + permLevel: "User", + requiredPerms: ["EMBED_LINKS"] +}; + +exports.help = { + name: "tickle", + category: "Action", + description: "Tickle someone!", + usage: "tickle [@user/user] (you can tickle as many people as you want!)" +}; diff --git a/src/commands/weather.js b/src/commands/weather.js index 4af8b86..ef01bc8 100644 --- a/src/commands/weather.js +++ b/src/commands/weather.js @@ -5,46 +5,47 @@ exports.run = async (client, message, args, error) => { `<:error:466995152976871434> You didn't give me a location. Usage: \`${client.commands.get(`weather`).help.usage}\`` ); }; - - if(args.join(" ").toLowerCase() == "antarctica") { - return; - } message.channel.startTyping(); - - weather.find({search: args.join(" "), degreeType: 'C'}, function(err, result) { - if(err) return client.logger.log(`weather.js error: ${JSON.stringify(error)}`, "error") - if(result.length < 2 || !result) { + + try { + weather.find({search: args.join(" "), degreeType: 'C'}, function(err, result) { + if(err) return message.channel.send(`<:error:466995152976871434> API error: \`${error}\``) + if(result.length < 2 || !result) { + message.channel.stopTyping(); + return message.channel.send("<:error:466995152976871434> City not found!"); + }; + + var location = result[0].location; + var current = result[0].current; + + var warning = (`${location.alert}` || "No warnings"); + + var embedColour; + if (current.temperature < 0) { + embedColour = "#addeff"; + }else if (current.temperature < 20) { + embedColour = "#4fb8ff"; + }else if (current.temperature < 26) { + embedColour = "#ffea4f"; + }else if (current.temperature < 31) { + embedColour = "#ffa14f" + } else { + embedColour = "#ff614f" + }; + + embed = new Discord.MessageEmbed(); + embed.setAuthor(`Weather for ${location.name}:`) + embed.setDescription(`• **Condition:** ${current.skytext}\n• **Temperature:** ${current.temperature}°C\n• **Feels like:** ${current.feelslike}°C\n• **Humidity:** ${current.humidity}%\n• **Wind:** ${current.winddisplay}\n• **Warnings:** ${warning}`) + embed.setThumbnail(current.imageUrl) + embed.setFooter(`Last updated at ${current.observationtime} ${current.date}`) + embed.setColor(embedColour) message.channel.stopTyping(); - return message.channel.send("<:error:466995152976871434> City not found!"); - }; - - var location = result[0].location; - var current = result[0].current; - - var warning = (`${location.alert}` || "No warnings"); - - var embedColour; - if (current.temperature < 0) { - embedColour = "#addeff"; - }else if (current.temperature < 20) { - embedColour = "#4fb8ff"; - }else if (current.temperature < 26) { - embedColour = "#ffea4f"; - }else if (current.temperature < 31) { - embedColour = "#ffa14f" - } else { - embedColour = "#ff614f" - }; - - embed = new Discord.MessageEmbed(); - embed.addField(`Weather for ${location.name}:`, `**Condition:** ${current.skytext}\n**Temperature:** ${current.temperature}C°\n**Feels like:** ${current.feelslike}C°\n**Humidity:** ${current.humidity}%\n**Wind:** ${current.winddisplay}\n**Warnings:** ${warning}`) - embed.setThumbnail(current.imageUrl) - embed.setFooter(`Last updated at ${current.observationtime} ${current.date}`) - embed.setColor(embedColour) - message.channel.stopTyping(); - message.channel.send(embed) - }); + message.channel.send(embed) + }); + } catch(err) { + return message.channel.send(`<:error:466995152976871434> API error: \`${err}\``) + }; }; exports.conf = { diff --git a/src/commands/yoda.js b/src/commands/yoda.js index 8b61784..496b929 100644 --- a/src/commands/yoda.js +++ b/src/commands/yoda.js @@ -1,34 +1,33 @@ -const request = require('request') +const fetch = require("node-fetch") exports.run = async (client, message, args) => { const speech = args.join(' '); if (!speech) { return message.channel.send(`<:error:466995152976871434> Please include text for me to convert to yodish. Yes.`) }; - message.channel.startTyping(); try{ - request({ uri: `http://yoda-api.appspot.com/api/v1/yodish?text=${encodeURIComponent(speech.toLowerCase())}`, json: true }, (error, response, body) => { - message.channel.send(body.yodish); - message.channel.stopTyping(); - }); + fetch(`http://yoda-api.appspot.com/api/v1/yodish?text=${encodeURIComponent(speech.toLowerCase())}`) + .then(res => res.json()) + .then(json => message.channel.send(json.yodish)); + message.channel.stopTyping(); } catch(err) { - message.channel.send(`<:error:466995152976871434> API error: ${err}`); + message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); message.channel.stopTyping(); }; }; exports.conf = { - enabled: true, - guildOnly: false, - aliases: ["yoda","yodasay"], - permLevel: "User", - requiredPerms: [] - }; - + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: [] +}; + exports.help = { - name: "yodish", - category: "Fun", - description: "Turns any text you input into yodish. Yes.", - usage: "yodish " - }; \ No newline at end of file + name: "yoda", + category: "Fun", + description: "Turns any text you input into yodish. Yes.", + usage: "yoda " +}; \ No newline at end of file diff --git a/src/commands/zalgo.js b/src/commands/zalgo.js new file mode 100644 index 0000000..bf2e082 --- /dev/null +++ b/src/commands/zalgo.js @@ -0,0 +1,30 @@ +const zalgo = require("to-zalgo") +exports.run = async (client, message, args) => { + if(!args[0]) { + return message.channel.send(`<:error:466995152976871434> You didn't provide any text! Usage: \`${client.commands.get(`zalgo`).help.usage}\``) + }; + + var output = zalgo(args.join(" ")) + + if(output.length > 2000) { + output = output.slice(0, -Math.abs(output.length - 2000)) + }; + + message.channel.send(output) + }; + + exports.conf = { + enabled: true, + guildOnly: false, + aliases: [], + permLevel: "User", + requiredPerms: [] + }; + + exports.help = { + name: "zalgo", + category: "Fun", + description: "Spoilers every letter in the provided text.", + usage: "zalgo [text]" + }; + \ No newline at end of file diff --git a/src/events/ready.js b/src/events/ready.js index 4a3ce44..f37a7d9 100644 --- a/src/events/ready.js +++ b/src/events/ready.js @@ -8,11 +8,15 @@ module.exports = client => { client.logger.log(`Connected to Discord as ${client.user.tag} | v${client.version.number}`, 'ready'); - let channel; - let channel1; + let channel, channel1; - try { channel = client.guilds.cache.get('410990517841690625').channels.cache.get('570963998342643732'); } catch(err) {}; - try { channel1 = client.guilds.cache.get('410990517841690625').channels.cache.get('570963481189154822'); } catch(err) {}; + try { + channel = client.guilds.cache.get('410990517841690625').channels.cache.get('570963998342643732'); + } catch(err) {}; + + try { + channel1 = client.guilds.cache.get('410990517841690625').channels.cache.get('570963481189154822'); + } catch(err) {}; if(client.devmode == true) { client.logger.warn("Running in development mode.") @@ -21,13 +25,16 @@ module.exports = client => { prefix = client.config.defaultSettings.prefix; channel.send(`\`${timestamp}\`: Ready event fired! Connected to ${client.users.cache.size} users in ${client.guilds.cache.size} guilds.`); channel1.send(`\`${timestamp}\`: **Ready event fired**`); - } + }; let randomActivity = activityArray.random(); client.user.setActivity(`${prefix + randomActivity} | v${client.version.number}`, {type: "PLAYING"}); + setInterval(() => { randomActivity = activityArray.random(); - if(client.lockActivity == false) client.user.setActivity(`${prefix + randomActivity} | v${client.version.number}`, {type: "PLAYING"}); + if(client.lockActivity == false) { + client.user.setActivity(`${prefix + randomActivity} | v${client.version.number}`, {type: "PLAYING"}); + }; }, 30000); }; diff --git a/src/modules/functions.js b/src/modules/functions.js index f51a34d..a30dd4b 100644 --- a/src/modules/functions.js +++ b/src/modules/functions.js @@ -1,7 +1,7 @@ const ytdl = require('ytdl-core-discord'); const youtubeInfo = require('youtube-info'); const getYoutubeId = require('get-youtube-id'); -const request = require('request'); +const fetch = require('node-fetch'); module.exports = client => { // Permission level function @@ -160,14 +160,17 @@ module.exports = client => { { return new Promise(function(resolve, reject) { - request("https://www.googleapis.com/youtube/v3/search?part=id&type=video&q=" + encodeURIComponent(query) + "&key=" + client.config.ytkey, function(error, response, body) - { - if(error) throw error; - - var json = JSON.parse(body); + try{ + fetch("https://www.googleapis.com/youtube/v3/search?part=id&type=video&q=" + encodeURIComponent(query) + "&key=" + client.config.ytkey) + .then(res => res.json()) + .then(json => { if(!json.items) { reject(); return; } resolve(json.items[0]); - }); + }); + } catch (err) { + client.logger.error("Music search err: ", err); + throw err; + }; }); } @@ -374,6 +377,6 @@ module.exports = client => { }); process.on("unhandledRejection", err => { - client.logger.error(`Unhandled rejection: ${err}`); + client.logger.error(`Unhandled rejection: ${err.stack}`); }); }; From da8e23e43466744bf910dd6a9d7db3e39e234a7a Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 15:38:00 +1100 Subject: [PATCH 20/27] Forgot some things oosp --- changes.txt | 39 --------------------------------------- version.json | 2 +- 2 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 changes.txt diff --git a/changes.txt b/changes.txt deleted file mode 100644 index 8ca32e2..0000000 --- a/changes.txt +++ /dev/null @@ -1,39 +0,0 @@ -Added a yodish command and made catfact and dogfact say if the api errors (terry) -Links to avatars now lead to the original file size -Bots now get a bot badge in the userinfo command -Added dogfact and catfact command (terry) -index.js now has better logging of when things fail to load/initialize (terry) -added `dice`, rolls a sided die (terry) -Help command changed, the amount of commands in each category and overall is now displayed and formatting changed -added `inspire` as an alias for inspirobot -ship command -added find by mention to functions -you can now @mention the bot to run commands -added identity command, has definitions of gender identities and stuff -added pronouns command, tells you how to use pronouns -added sexuality command, has definitions of sexualities -renamed math calculate -fixed woomy in dms -roleinfo now displays what permissions a role has and also the role colour in the thumbnail -request has been replaced with node-fetch -added neko -added fact -added nekogif -added dog -added cat -added hug -added kiss -added pat -added poke -added slap -added tickle -added cuddle -added feed -added smug -added lizard -added kemonomimi -added spoilerise -added zalgo -renamed flip coinflip -small changes to weather -recategorised some commands diff --git a/version.json b/version.json index 3e289f1..f89b995 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { "number": "1.2.0", - "changelog": "**1.1.0 CHANGELOG:**\n> • Added `~softban`, bans and unbans a user to clear messages\n> • Added `~emoji`, enlarges custom emojis\n> • Added `~inspirobot`, generates an inspirational quote\n> • `~serverinfo` has been changed to be more consistent, and also now displays boosts and if the server is partnered and stuff\n> • `~userinfo` has been changed to be more consistent, also added some stuff\n> • `~about` has been changed, added a thumbnail and removed the description\n> • `~colour` has been changed, it can now generate colours from text\n> • `~hackban` no longer has its own embed\n> • `~eval` now logs to hastebin if output is too large\n> • role names are no longer case sensitive\n> • `~echo` renamed `~say`\n> • Users with the ADMINISTRATOR permission now automatically recieve woomy admin\n> • Fixed `~flip`, `~purge`, `~bohemian_rhapsody` and `~creeper`\n> • Guild join/leave messages no longer include the guild name\n> • Some emojis have been changed\n> • Woomy now supports discord.js v12\n> • Files have been restructured\n> • Logger now logs error stack\n> • Restart now exits with code 0" + "changelog": "**1.2.0 CHANGELOG:**\n> • Added action commands! (`cuddle`, `feed`, `hug`, `kiss`, `pat`, `poke`, `slap`, `smug`, `tickle`)\n> • Added `fact`\n> • Added `catfact`\n> • Added `dogfact`\n> • Added `yoda`\n> • Added `dice`\n> • Added `spoilerise`\n> • Added `zalgo`\n> • Added `dog`\n> • Added `cat`\n> • Added `lizard`\n> • Added `neko`\n> • Added `nekogif`\n> • Added `kemonomimi`\n> • Added `foxgirl`\n> • Added `identity`\n> • Added `pronouns`\n> • Added `sexuality`\n> • Added `ship`\n> • Renamed `flip to `coinflip` (flip remains as an alias)\n> • Renamed `math` to `calculate` (math is an alias)\n> • @Woomy is now a prefix\n> • Added the `inspire` alias to `inspirobot`\n> • Help now displays the amount of commands in each category\n> • Bots now get a badge in `userinfo`\n> • `roleinfo` now displays what permissions a role has\n> • small changes to `weather`\n> • Woomy now has clear logging of issues that prevent her from starting\n> • request npm module has been swapped out for node-fetch\n**NOTES:**\n> Thank you to Terryiscool160 for creating multiple commands used in this update" } From 566c049b10e778e6c86327889922940130b6f2f8 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 15:42:33 +1100 Subject: [PATCH 21/27] downgrade better-sqlite3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4109849..891ab34 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "dependencies": { "@discordjs/opus": "^0.1.0", - "better-sqlite3": "^5.4.3", + "better-sqlite3": "^5.4.1", "chalk": "^3.0.0", "dblapi.js": "^2.3.1", "discord.js": "^12.0.2", From 3589373ce922774e701aa1427be7a0a1725ccc9f Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 15:57:53 +1100 Subject: [PATCH 22/27] Fixed cooldown --- src/events/message.js | 13 +++++++------ version.json | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/events/message.js b/src/events/message.js index dc5611e..fab2583 100644 --- a/src/events/message.js +++ b/src/events/message.js @@ -1,4 +1,4 @@ -const commandRanRecently = new Set(); +const cooldown = new Set(); module.exports = async (client, message) => { if (message.author.bot) return; @@ -151,11 +151,11 @@ module.exports = async (client, message) => { if (!cmd) return; - if (commandRanRecently.has(message.author.id)) { + if (cooldown.has(message.author.id)) { return message.channel.send( `⏱️ You are being ratelimited. Please try again in 2 seconds.` ) - .then(m => m.delete(2000)); + .then(m => m.delete(5000)); }; if (message.guild && !perms.has('SEND_MESSAGES')) { @@ -222,10 +222,11 @@ module.exports = async (client, message) => { message.flags.push(args.shift().slice(1)); }; - commandRanRecently.add(message.author.id); + cooldown.add(message.author.id); + setTimeout(() => { - commandRanRecently.delete(message.author.id); - }, {timeout: 2000}); + cooldown.delete(message.author.id); + }, 2000); client.logger.cmd(`${client.config.permLevels.find(l => l.level === level).name} ${message.author.username} (${message.author.id}) ran command ${cmd.help.name}`); diff --git a/version.json b/version.json index f89b995..92c7223 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "number": "1.2.0", + "number": "1.2.1", "changelog": "**1.2.0 CHANGELOG:**\n> • Added action commands! (`cuddle`, `feed`, `hug`, `kiss`, `pat`, `poke`, `slap`, `smug`, `tickle`)\n> • Added `fact`\n> • Added `catfact`\n> • Added `dogfact`\n> • Added `yoda`\n> • Added `dice`\n> • Added `spoilerise`\n> • Added `zalgo`\n> • Added `dog`\n> • Added `cat`\n> • Added `lizard`\n> • Added `neko`\n> • Added `nekogif`\n> • Added `kemonomimi`\n> • Added `foxgirl`\n> • Added `identity`\n> • Added `pronouns`\n> • Added `sexuality`\n> • Added `ship`\n> • Renamed `flip to `coinflip` (flip remains as an alias)\n> • Renamed `math` to `calculate` (math is an alias)\n> • @Woomy is now a prefix\n> • Added the `inspire` alias to `inspirobot`\n> • Help now displays the amount of commands in each category\n> • Bots now get a badge in `userinfo`\n> • `roleinfo` now displays what permissions a role has\n> • small changes to `weather`\n> • Woomy now has clear logging of issues that prevent her from starting\n> • request npm module has been swapped out for node-fetch\n**NOTES:**\n> Thank you to Terryiscool160 for creating multiple commands used in this update" } From 2408257b4471d6c911f08464f9272928cf8eca90 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 16:01:27 +1100 Subject: [PATCH 23/27] ACTUALLY fixed cooldown --- src/events/message.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/events/message.js b/src/events/message.js index fab2583..7c399a8 100644 --- a/src/events/message.js +++ b/src/events/message.js @@ -153,9 +153,10 @@ module.exports = async (client, message) => { if (cooldown.has(message.author.id)) { return message.channel.send( - `⏱️ You are being ratelimited. Please try again in 2 seconds.` - ) - .then(m => m.delete(5000)); + `⏱️ You are being ratelimited. Please try again in 2 seconds.` + ).then(msg => { + msg.delete({timeout: 2000}); + }); }; if (message.guild && !perms.has('SEND_MESSAGES')) { From 177f4e2b529c8e1c4c4a13e8142b624fa8e5a8fb Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 18:26:22 +1100 Subject: [PATCH 24/27] 1.2.2 --- configTemplate.js | 6 ++++++ index.js | 5 ++++- src/commands/prefix.js | 6 ------ src/commands/zalgo.js | 2 +- src/events/ready.js | 44 +++++++++++++++++++++++++++++++----------- src/modules/Logger.js | 37 +++++++++++++++++++++++------------ version.json | 2 +- 7 files changed, 70 insertions(+), 32 deletions(-) diff --git a/configTemplate.js b/configTemplate.js index 3828ed8..b6e96c3 100644 --- a/configTemplate.js +++ b/configTemplate.js @@ -2,6 +2,12 @@ const config = { // ID's "owners": [], // Adding your ID here will give you access to dangerous commands like eval. Please be careful with who you add here! Eval can be used to modify the host machine. + // Host options + "devmodeEnabled": false, // true or false + "loggingServer": "", // server ID, or blank to disable + "startupLogs": "", // Channel ID, or blank to disable + "consoleLogs": "", // Channel ID, or blank to disable + // Tokens "token": "", // Your bot's token. "devtoken": "", // (optional) another token, meant for a bot used for development diff --git a/index.js b/index.js index 395e910..49d5326 100644 --- a/index.js +++ b/index.js @@ -15,18 +15,21 @@ try { console.log('Failed to load config.js:', err); process.exit(); }; + try{ client.version = require('./version.json'); } catch (err) { console.log('Failed to load version.json:', err); process.exit(); }; + try{ client.logger = require('./src/modules/Logger'); } catch (err) { console.log('Failed to load Logger.js:', err); process.exit(); }; + client.logger.setClient(client); try{ @@ -36,7 +39,7 @@ try{ process.exit(); }; -if(process.env['USER'] != 'container') { +if(client.config.devmodeEnabled == true && process.env['USER'] != 'container') { client.devmode = true; } else { client.devmode = false; diff --git a/src/commands/prefix.js b/src/commands/prefix.js index 774a22b..1d72e74 100644 --- a/src/commands/prefix.js +++ b/src/commands/prefix.js @@ -1,10 +1,4 @@ exports.run = async (client, message, args) => { - if(client.devmode === true) { - return message.channel.send( - "<:error:466995152976871434> This command has been disabled because Woomy is in development mode." - ); - }; - const settings = message.settings; if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); diff --git a/src/commands/zalgo.js b/src/commands/zalgo.js index bf2e082..e34d404 100644 --- a/src/commands/zalgo.js +++ b/src/commands/zalgo.js @@ -14,7 +14,7 @@ exports.run = async (client, message, args) => { }; exports.conf = { - enabled: true, + enabled: false, guildOnly: false, aliases: [], permLevel: "User", diff --git a/src/events/ready.js b/src/events/ready.js index f37a7d9..be5792e 100644 --- a/src/events/ready.js +++ b/src/events/ready.js @@ -6,25 +6,45 @@ module.exports = client => { client.lockActivity = false; - client.logger.log(`Connected to Discord as ${client.user.tag} | v${client.version.number}`, 'ready'); + let guild, channel, channel1; + + if(client.config.loggingServer.length > 0) { + try { + guild = client.guilds.cache.get(client.config.loggingServer) + } catch(err) { + client.logger.error("Could not find loggingServer server (is the ID valid?):\n" + err); + process.exit(1); + }; + + if(client.config.consoleLogs.length > 0) { + try { + channel1 = client.guilds.cache.get(client.config.consoleLogs) + } catch(err) { + client.logger.error("Could not find consoleLogs channel (is the ID valid?):\n" + err); + process.exit(1); + }; + }; + + if(client.config.startupLogs.length > 0) { + try { + channel = guild.channels.cache.get(client.config.startupLogs) + } catch(err) { + client.logger.error("Could not find startupLogs channel (is the ID valid?):\n" + err); + process.exit(1); + }; + }; + }; - let channel, channel1; - try { - channel = client.guilds.cache.get('410990517841690625').channels.cache.get('570963998342643732'); - } catch(err) {}; - - try { - channel1 = client.guilds.cache.get('410990517841690625').channels.cache.get('570963481189154822'); - } catch(err) {}; if(client.devmode == true) { client.logger.warn("Running in development mode.") prefix = client.config.defaultSettings.devprefix; } else { prefix = client.config.defaultSettings.prefix; - channel.send(`\`${timestamp}\`: Ready event fired! Connected to ${client.users.cache.size} users in ${client.guilds.cache.size} guilds.`); - channel1.send(`\`${timestamp}\`: **Ready event fired**`); + if(channel1) { + channel1.send(`Bot started at \`${timestamp}\``); + }; }; let randomActivity = activityArray.random(); @@ -37,4 +57,6 @@ module.exports = client => { client.user.setActivity(`${prefix + randomActivity} | v${client.version.number}`, {type: "PLAYING"}); }; }, 30000); + + client.logger.log(`Connected to Discord as ${client.user.tag} | v${client.version.number}`, 'ready'); }; diff --git a/src/modules/Logger.js b/src/modules/Logger.js index 0c8614f..c1fed4b 100644 --- a/src/modules/Logger.js +++ b/src/modules/Logger.js @@ -2,17 +2,25 @@ const chalk = require("chalk"); const moment = require("moment"); exports.log = (content, type = "log") => { - const timestamp = chalk.grey(`[${moment().format("YYYY-MM-DD HH:mm:ss")}]`); + const timestamp = `[${moment().format("YYYY-MM-DD HH:mm:ss")}]`; let channel; + + try { + channel = client.guilds.cache.get(client.config.loggingServer).channels.cache.get(client.config.consoleLogs); + } catch(err) {}; - try { channel = client.guilds.cache.get('410990517841690625').channels.cache.get('570963481189154822'); } catch(err) {} + var logToServer = false; + + if(client.devmode === false && channel && guild.available) { + logToServer = true; + }; switch (type) { case "info": { try { - if (client.devmode == false) { - channel.send(`\`${timestamp}\`: ` + content); + if (logToServer == true) { + channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); }; } catch(err) {}; return console.log(`${timestamp} ${chalk.cyanBright(`[${type.toUpperCase()}]`)} ${content} `); @@ -20,8 +28,8 @@ exports.log = (content, type = "log") => { case "warn": { try { - if (client.devmode == false) { - channel.send(`\`${timestamp}\`: ` + content); + if (logToServer == true) { + channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); }; } catch(err) {}; return console.log(`${timestamp} ${chalk.yellowBright(`[${type.toUpperCase()}]`)} ${content} `); @@ -29,8 +37,8 @@ exports.log = (content, type = "log") => { case "error": { try { - if (client.devmode == false) { - channel.send(`\`${timestamp}\`: ` + content); + if (logToServer == true) { + channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); }; } catch(err) {} return console.log(`${timestamp} ${chalk.redBright(`[${type.toUpperCase()}]`)} ${content} `); @@ -38,8 +46,8 @@ exports.log = (content, type = "log") => { case "debug": { try { - if (client.devmode == false) { - channel.send(`\`${timestamp}\`: ` + content); + if (logToServer == true) { + channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); }; } catch(err) {}; return console.log(`${timestamp} ${chalk.magentaBright(`[${type.toUpperCase()}]`)} ${content} `); @@ -47,14 +55,19 @@ exports.log = (content, type = "log") => { case "cmd": { try { - if (client.devmode == false) { - channel.send(`\`${timestamp}\` ` + content); + if (logToServer == true) { + channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); }; } catch(err) {}; return console.log(`${timestamp} ${chalk.whiteBright(`[${type.toUpperCase()}]`)} ${content}`); }; case "ready": { + try { + if (logToServer == true) { + channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); + }; + } catch(err) {}; return console.log(`${timestamp} ${chalk.greenBright (`[${type.toUpperCase()}]`)} ${content}`); }; diff --git a/version.json b/version.json index 92c7223..19b07db 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "number": "1.2.1", + "number": "1.2.2", "changelog": "**1.2.0 CHANGELOG:**\n> • Added action commands! (`cuddle`, `feed`, `hug`, `kiss`, `pat`, `poke`, `slap`, `smug`, `tickle`)\n> • Added `fact`\n> • Added `catfact`\n> • Added `dogfact`\n> • Added `yoda`\n> • Added `dice`\n> • Added `spoilerise`\n> • Added `zalgo`\n> • Added `dog`\n> • Added `cat`\n> • Added `lizard`\n> • Added `neko`\n> • Added `nekogif`\n> • Added `kemonomimi`\n> • Added `foxgirl`\n> • Added `identity`\n> • Added `pronouns`\n> • Added `sexuality`\n> • Added `ship`\n> • Renamed `flip to `coinflip` (flip remains as an alias)\n> • Renamed `math` to `calculate` (math is an alias)\n> • @Woomy is now a prefix\n> • Added the `inspire` alias to `inspirobot`\n> • Help now displays the amount of commands in each category\n> • Bots now get a badge in `userinfo`\n> • `roleinfo` now displays what permissions a role has\n> • small changes to `weather`\n> • Woomy now has clear logging of issues that prevent her from starting\n> • request npm module has been swapped out for node-fetch\n**NOTES:**\n> Thank you to Terryiscool160 for creating multiple commands used in this update" } From 26da45afdc6067333fb9487de6c0bdeb0012a93f Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 18:28:36 +1100 Subject: [PATCH 25/27] oops --- src/modules/Logger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/Logger.js b/src/modules/Logger.js index c1fed4b..e924961 100644 --- a/src/modules/Logger.js +++ b/src/modules/Logger.js @@ -12,7 +12,7 @@ exports.log = (content, type = "log") => { var logToServer = false; - if(client.devmode === false && channel && guild.available) { + if(client.devmode === false && channel && client.guilds.cache.get(client.config.loggingServer).available) { logToServer = true; }; From 2df5337e2d3105d38b1be6fac27eabb5d68490e0 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 18:47:48 +1100 Subject: [PATCH 26/27] final fix (hopefully) --- src/events/ready.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/events/ready.js b/src/events/ready.js index be5792e..9818463 100644 --- a/src/events/ready.js +++ b/src/events/ready.js @@ -18,7 +18,7 @@ module.exports = client => { if(client.config.consoleLogs.length > 0) { try { - channel1 = client.guilds.cache.get(client.config.consoleLogs) + channel1 = guild.channels.cache.get(client.config.consoleLogs) } catch(err) { client.logger.error("Could not find consoleLogs channel (is the ID valid?):\n" + err); process.exit(1); @@ -35,15 +35,13 @@ module.exports = client => { }; }; - - - if(client.devmode == true) { + if(client.devmode !== true) { client.logger.warn("Running in development mode.") prefix = client.config.defaultSettings.devprefix; } else { prefix = client.config.defaultSettings.prefix; - if(channel1) { - channel1.send(`Bot started at \`${timestamp}\``); + if(channel) { + channel.send(`Bot started at \`${timestamp}\``); }; }; From 2623d6035c51d105c4514a16eb99ea0c76f78227 Mon Sep 17 00:00:00 2001 From: mudkipscience Date: Thu, 26 Mar 2020 18:48:03 +1100 Subject: [PATCH 27/27] Update ready.js --- src/events/ready.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/ready.js b/src/events/ready.js index 9818463..532cd8c 100644 --- a/src/events/ready.js +++ b/src/events/ready.js @@ -35,7 +35,7 @@ module.exports = client => { }; }; - if(client.devmode !== true) { + if(client.devmode == true) { client.logger.warn("Running in development mode.") prefix = client.config.defaultSettings.devprefix; } else {