diff --git a/assets/launchFail.gif b/assets/launchFail.gif new file mode 100644 index 0000000..56bfb8a Binary files /dev/null and b/assets/launchFail.gif differ diff --git a/assets/launchSuccess.gif b/assets/launchSuccess.gif new file mode 100644 index 0000000..f54e119 Binary files /dev/null and b/assets/launchSuccess.gif differ diff --git a/assets/takeOff.jpeg b/assets/takeOff.jpeg new file mode 100644 index 0000000..88465f5 Binary files /dev/null and b/assets/takeOff.jpeg differ diff --git a/bughuntertracker.json b/bughuntertracker.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/bughuntertracker.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/colors.json b/colors.json index e0e8001..5f5b6f3 100644 --- a/colors.json +++ b/colors.json @@ -3,5 +3,12 @@ "standby": "#ded82a", "valid": "#2ade2d", "error": "#de2a2a", - "dev": "#ffffff" + "dev": "#ffffff", + "user": "#000000", + "tier0": "#c6c6c6", + "tier1": "#c8ae99", + "tier2": "#4ad46b", + "tier3": "#3dff66", + "tier4": "#6cff00", + "tier5": "#f7ff00" } \ No newline at end of file diff --git a/commands/addBugHunter.js b/commands/addBugHunter.js new file mode 100644 index 0000000..80ae65d --- /dev/null +++ b/commands/addBugHunter.js @@ -0,0 +1,55 @@ +const Discord = require("discord.js"); +const fs = require("fs"); +const Perks = require("../utils/perks.js"); +const devsio = require('../utils/devsio.js'); +const colors = require("../colors.json"); +const botsettings = require("../botsettings.json"); +const prefix = botsettings.prefix; + +module.exports.run = async (bot, message, args) => { + const member = message.guild.member(message.mentions.members.first() || args[0]); + const confirmationEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("SUCCESS") + .setDescription("This user is now a bug hunter! :tada:") + .setColor(colors.valid) + + message.delete() + + if(!member) return error(`ERROR: Incorrect usage. You must specify the member to add as a bug hunter. Correct Usage: \`${prefix}addbughunter bug_hunter\``); + + devsio.readdevs(devs => { + if(!devs.includes(message.author.id)) return error("ERROR: Missing Permissions. You are not allowed to run this command.") + fs.readFile("./bughuntertracker.json", "utf8", async (err, data) => { + if(err) return console.error(err); + const bughunterArr = await JSON.parse(data); + const bughunter = bughunterArr.find(bughunter => bughunter.id === member.id); + if(!bughunter) + bughunterArr.push({id: member.id, tokens: 0, tier: 0, perks: new Perks()}) + else return error("ERROR: This user is already a bug hunter"); + const bughunterJSON = JSON.stringify(bughunterArr); + fs.writeFile("./bughuntertracker.json", bughunterJSON, "utf8", err => { + if(err) console.error(err); + }); + message.channel.sendEmbed(confirmationEmbed).then(msg => msg.delete(5000)); + }); + }); + + // Error Handler + + function error(errorMessage) { + const errorEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("ERROR") + .setDescription(`${errorMessage}\nBug Hunter Addition process halted. Please run the command again to restart.`) + .setColor(colors.error); + message.channel.send(errorEmbed).then(msg => { + message.delete(0); + msg.delete(10000); + }); + } +} +module.exports.help = { + name: "addbughunter", + description:"Adds a bug hunter." +}; diff --git a/commands/buy.js b/commands/buy.js new file mode 100644 index 0000000..7c6a2d9 --- /dev/null +++ b/commands/buy.js @@ -0,0 +1,101 @@ +const Discord = require("discord.js"); +const fs = require("fs"); +const Perks = require("../utils/perks.js") +const colors = require("../colors.json"); +const botsettings = require("../botsettings.json"); +const storeJSON = require("../store.json"); +const prefix = botsettings.prefix; +const bugHunterRoleID = botsettings.roleid_bughunter; + +const perksPath = "../utils/Perks/"; + +/** + * + * @param {Discord.Client} bot + * @param {Discord.TextChannel} channel + */ +module.exports.run = async (bot, message, args) => { + let channel = message.channel; + let member = message.author; + let item = args.slice(0).join(" "); + let storeItems = {}; + Object.entries(storeJSON).forEach(([key, val]) => storeItems[key.split("_").map(perk => perk.charAt(0).toUpperCase() + perk.slice(1)).join(" ")] = val); + + if(!item) return error(`ERROR: Incorrect usage. Please specify an item to buy using: \`${prefix}buy Item_Name\`. If you are unsure of this item's name, you can use \`${prefix}store\` to check it.`) + item = item.split(" ").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" "); + if(!(storeItems.hasOwnProperty(item) || item.startsWith("Color Roles"))) return error(`ERROR: Incorrect usage. Could not find an item with the name of \`${item}\`. If you are unsure of this item's name, you can use \`${prefix}store\` to check it.`) + + const tierColors = [colors.tier0, colors.tier1, colors.tier2, colors.tier3, colors.tier4, colors.tier5] + const tierRomanNumerals = ["I", "II", "III", "IV", "V"] + // Get user info + fs.readFile("./bughuntertracker.json", "utf8", async (err, data) => { + if(err) return console.error(err); + const bugHunterArr = JSON.parse(data); + const bugHunter = bugHunterArr.find(bughunter => bughunter.id === member.id); + if(bugHunter) { + const storeItem = storeItems[item] || storeItems["Color Roles"]; + if(bugHunter.tokens < storeItem.tokens) return error(`ERROR: You do not have enough tokens to buy this item, you need \`${storeItem.tokens - bugHunter.tokens}\` more Bug Token.`); + try { + if(item.startsWith("Color Roles")) { + const perkUnlockResponse = await buyColorRole(args[2]); + if(perkUnlockResponse !== true) return error(perkUnlockResponse); + } else { + const perk = require(`${perksPath + item}.js`) + const perkUnlockResponse = perk.unlock(channel.guild, bugHunter); + if(perkUnlockResponse !== true) return error(perkUnlockResponse); + } + bugHunter.tokens -= storeItem.tokens; + } catch (err) { + return error(`ERROR: This item has not been implemented: \`(${err})\``) + } + } else return error("ERROR: Only Bug Hunters can use the store! If you would like to become a bug hunter, check out the <#711987145392390254> channel."); + const bugHunterJSON = JSON.stringify(bugHunterArr); + fs.writeFile("./bughuntertracker.json", bugHunterJSON, "utf8", err => { + if(err) { + console.error(err); + return error(`ERROR: Write to database failed. Please send the following message to Whimpers: (${err})`); + } + }); + const confirmationEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("SUCCESS") + .setDescription("Your purchase was successfull! :tada:") + .setColor(colors.valid); + channel.sendEmbed(confirmationEmbed).then(msg => msg.delete(5000)); + }); + + message.delete(0); + + async function buyColorRole(color) { + if(!color) return `ERROR: Incorrect Usage. Please specify a color. Correct usage: \`${prefix}buy Color Roles color\``; + if(!(/^#[0-9A-Fa-f]{6}$/).test(color)) return "ERROR: Color must be in a hex format. Example: #f00ba7"; + const bugHunterRole = message.guild.roles.find(r => r.id === bugHunterRoleID); + const colorRole = await channel.guild.createRole({ + name: color, + color: color, + position: bugHunterRole.position + }) + message.guild.member(member).addRole(colorRole) + return true; + } + + // Error Handler + + function error(errorMessage) { + const errorEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("ERROR") + .setDescription(`${errorMessage}\nPurchase process halted. Please run the command again to restart.`) + .setColor(colors.error); + channel.send(errorEmbed).then(msg => { + message.delete(0); + msg.delete(10000); + }); + } +}; + + +module.exports.help = { + name: "buy", + description:"Purchases a perk from the store." +}; diff --git a/commands/embed.js b/commands/embed.js new file mode 100644 index 0000000..6f44b8f --- /dev/null +++ b/commands/embed.js @@ -0,0 +1,47 @@ +const Discord = require("discord.js"); +const {isBugHunter} = require("../utils/isBugHunter.js") +const botSettings = require("../botsettings.json"); +const colors = require("../colors.json"); +const prefix = botSettings.prefix; + +module.exports.run = async (bot, message, args) => { + message.delete(); + + if(!(isBugHunter(message.author.id) && isBugHunter(message.author.id).embederUnlocked)) return error(`ERROR: Missing permissions. You do not have the embeder perk unlocked.`) + if(args.length < 1) return error(`ERROR: Incorrect usage. You must specify a message to embed. Correct usage: \`${prefix}embed color message\``); + + const colorTester = args[0]; + let color; + let msg = args.slice(1).join(" "); + + if((/[0-9A-Fa-f]{6}/g).test(colorTester)) { + color = colorTester; + } else { + msg = args.slice(0).join(" "); + } + + let embed = new Discord.RichEmbed() + .setTitle(msg) + .setColor(color || colors.info) + .setFooter("- " + message.author.tag) + message.channel.send(embed); + + // Error Handler + + function error(errorMessage) { + const errorEmbed = new Discord.RichEmbed() + .setAuthor('Reviewer -', bot.avatarURL) + .setTitle("ERROR") + .setDescription(`${errorMessage}\nEmbeder process halted. Please run the command again to restart your report.`) + .setColor(colors.error) + message.channel.send(errorEmbed).then(msg => { + message.delete(0) + msg.delete(5000) + }); + } +} + +module.exports.help = { + name: "embed", + description: "Creates an embed with specified message" +} \ No newline at end of file diff --git a/commands/forceAcceptReport.js b/commands/forceAcceptReport.js index ba48178..1455ece 100644 --- a/commands/forceAcceptReport.js +++ b/commands/forceAcceptReport.js @@ -2,6 +2,7 @@ const Discord = require("discord.js"); const colors = require("../colors.json"); const BugReport = require("../utils/bugReport.js"); const devsio = require('../utils/devsio.js'); +const {isBugHunter} = require("../utils/isBugHunter.js") const fs = require("fs"); const botSettings = require("../botsettings.json") const pending_channelid = botSettings.channelid_pendingbugs; @@ -65,6 +66,7 @@ module.exports.run = async (bot, message, args) => { }) message.delete(0); }) + // Error Handler function error(errorMessage) { diff --git a/commands/forceDenyReport.js b/commands/forceDenyReport.js index 92934c0..1738182 100644 --- a/commands/forceDenyReport.js +++ b/commands/forceDenyReport.js @@ -2,6 +2,7 @@ const Discord = require("discord.js"); const colors = require("../colors.json"); const BugReport = require("../utils/bugReport.js"); const devsio = require('../utils/devsio.js'); +const {isBugHunter} = require("../utils/isBugHunter.js") const fs = require("fs"); const botSettings = require("../botsettings.json"); const pending_channelid = botSettings.channelid_pendingbugs; diff --git a/commands/giveTokens.js b/commands/giveTokens.js new file mode 100644 index 0000000..91233ee --- /dev/null +++ b/commands/giveTokens.js @@ -0,0 +1,57 @@ +const Discord = require("discord.js"); +const fs = require("fs"); +const Perks = require("../utils/perks.js"); +const devsio = require('../utils/devsio.js'); +const colors = require("../colors.json"); +const botsettings = require("../botsettings.json"); +const prefix = botsettings.prefix; + +module.exports.run = async (bot, message, args) => { + const member = message.guild.member(message.mentions.members.first() || args[0]); + const tokens = Number(args[1]); + + const confirmationEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("SUCCESS") + .setDescription("Tokens given! :tada:") + .setColor(colors.valid) + + message.delete() + + if(!member || !tokens) return error(`ERROR: Incorrect usage. You must specify the bug hunter and the amount of tokens you want to give. Correct Usage: \`${prefix}givetokens bug_hunter token_count\``); + + devsio.readdevs(devs => { + if(!devs.includes(message.author.id)) return error("ERROR: Missing Permissions. You are not allowed to run this command.") + fs.readFile("./bughuntertracker.json", "utf8", (err, data) => { + if(err) return console.error(err); + const bughunterArr = JSON.parse(data); + const bughunter = bughunterArr.find(bughunter => bughunter.id === member.id); + if(!bughunter) + bughunterArr.push({id: member.id, tokens: tokens, tier: 0, perks: new Perks()}) + else bughunter.tokens += tokens; + const bughunterJSON = JSON.stringify(bughunterArr); + fs.writeFile("./bughuntertracker.json", bughunterJSON, "utf8", err => { + if(err) console.error(err); + }); + message.channel.sendEmbed(confirmationEmbed).then(msg => msg.delete(5000)); + }); + }); + + // Error Handler + + function error(errorMessage) { + const errorEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("ERROR") + .setDescription(`${errorMessage}\nToken addition process halted. Please run the command again to restart.`) + .setColor(colors.error); + message.channel.send(errorEmbed).then(msg => { + message.delete(0); + msg.delete(10000); + }); + } +} +module.exports.help = { + name: "givetokens", + description:"Gives tokens a bug hunter." +}; diff --git a/commands/launch.js b/commands/launch.js new file mode 100644 index 0000000..c535591 --- /dev/null +++ b/commands/launch.js @@ -0,0 +1,50 @@ +const Discord = require('discord.js'); +const {isBugHunter} = require("../utils/isBugHunter.js") +const colors = require("../colors.json"); +const takeOff = new Discord.Attachment("./assets/takeOff.jpeg", "takeOff.jpeg"); +const launchSuccess = new Discord.Attachment("./assets/launchSuccess.gif", "launchSuccess.gif"); +const launchFail = new Discord.Attachment("./assets/launchFail.gif", "launchFail.gif"); + +module.exports.run = async (bot, message, args) => { + const user = message.mentions.users.first() || message.author; + const randomNumber = Math.round(Math.random()); + + message.delete() + if(!(isBugHunter(message.author.id) && isBugHunter(message.author.id).launcherUnlocked)) return error(`ERROR: Missing permissions. You do not have the launcher perk unlocked.`) + + const launchEmbed = new Discord.RichEmbed() + .setAuthor('Reviewer -', bot.avatarURL) + .setTitle('LAUNCH') + + if(randomNumber) { + launchEmbed.addField(`${user.username} was launched into space by ${message.author.username}!`, `${user.username}'s rocket flew to space!`); + launchEmbed.attachFile(launchSuccess) + launchEmbed.setImage("attachment://launchSuccess.gif"); + launchEmbed.setColor(colors.valid) + } else { + launchEmbed.addField(`${user.username} was launched into space by ${message.author.username}!`, `${user.username}'s rocket blew up!`); + launchEmbed.attachFile(launchFail) + launchEmbed.setImage("attachment://launchFail.gif"); + launchEmbed.setColor(colors.error) + } + + message.channel.sendEmbed(launchEmbed) + + // Error Handler + + function error(errorMessage) { + const errorEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("ERROR") + .setDescription(`${errorMessage}\nLauncher process halted. Please run the command again to restart.`) + .setColor(colors.error); + message.channel.send(errorEmbed).then(msg => { + msg.delete(10000); + }); + } +} + +module.exports.help = { + name: "launch", + description:"Launch someone into space!" +} \ No newline at end of file diff --git a/commands/mock.js b/commands/mock.js new file mode 100644 index 0000000..5e7f463 --- /dev/null +++ b/commands/mock.js @@ -0,0 +1,42 @@ +const Discord = require("discord.js"); +const {isBugHunter} = require("../utils/isBugHunter.js") +const fetch = require("node-fetch"); +const colors = require("../colors.json"); +const botSettings = require("../botsettings.json"); +const prefix = botSettings.prefix; + +module.exports.run = async (bot, message, args) => { + const mockMsg = args.slice(0).join(" "); + + message.delete() + if(!(isBugHunter(message.author.id) && isBugHunter(message.author.id).mockerUnlocked)) return error(`ERROR: Missing permissions. You do not have the mocker perk unlocked.`) + if(!mockMsg) return error(`ERROR: Incorrect Usage. You must specify a message to mock. Correct Usage: \`${prefix}mock message\``) + + const mockURL = await (await fetch(`https://wt-22f5e1b994607080041c947354b7f9a5-0.run.webtask.io/sponge?message=${mockMsg}`)).text() + + const mockEmbed = new Discord.RichEmbed() + .setAuthor('Reviewer -', bot.avatarURL) + .setTitle("MOCK") + .setColor(colors.info) + .setImage(mockURL.slice(1, mockURL.length - 1)) + .setFooter(`Requested by ${message.author.tag}.`) + message.channel.sendEmbed(mockEmbed) + + // Error Handler + + function error(errorMessage) { + const errorEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("ERROR") + .setDescription(`${errorMessage}\n Mocker process halted. Please run the command again to restart.`) + .setColor(colors.error); + message.channel.send(errorEmbed).then(msg => { + msg.delete(10000); + }); + } +}; + +module.exports.help = { + name: "mock", + description:"Mock some text just like ~~spongebob~~ spongemock." +}; \ No newline at end of file diff --git a/commands/profile.js b/commands/profile.js new file mode 100644 index 0000000..4538714 --- /dev/null +++ b/commands/profile.js @@ -0,0 +1,5 @@ +module.exports.run = async (bot, message, args) => bot.commands.get("user").run(bot, message, args); +module.exports.help = { + name: "profile", + description:"Gets user info for a user." +}; diff --git a/commands/shop.js b/commands/shop.js new file mode 100644 index 0000000..6e19695 --- /dev/null +++ b/commands/shop.js @@ -0,0 +1,5 @@ +module.exports.run = async (bot, message, args) => bot.commands.get("store").run(bot, message, args); +module.exports.help = { + name: "shop", + description:"The store where you can exchange bug tokens for cool perks!" +}; diff --git a/commands/store.js b/commands/store.js new file mode 100644 index 0000000..94f8b49 --- /dev/null +++ b/commands/store.js @@ -0,0 +1,26 @@ +const Discord = require("discord.js"); +const colors = require("../colors.json"); +const storeJSON = require("../store.json"); + +/** + * + * @param {Discord.Client} bot + * @param {Discord.TextChannel} channel + */ +module.exports.run = async (bot, message, args) => { + let storeEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("STORE") + .setDescription("The store where you can exchange bug tokens for cool perks!\n\nNOTE: BT stands for Bug Tokens and is not part of the item's name.") + .setColor(colors.info); + Object.entries(storeJSON).forEach(([key, val]) => { + storeEmbed.addField(key.split("_").map(perk => perk.charAt(0).toUpperCase() + perk.slice(1)).join(" ") + ` (${val.tokens} BT)`, val.description, true) + }) + message.channel.send(storeEmbed); +}; + + +module.exports.help = { + name: "store", + description:"The store where you can exchange bug tokens for cool perks!" +}; diff --git a/commands/user.js b/commands/user.js new file mode 100644 index 0000000..707037e --- /dev/null +++ b/commands/user.js @@ -0,0 +1,64 @@ +const Discord = require("discord.js"); +const fs = require("fs"); +const Perks = require("../utils/perks.js") +const colors = require("../colors.json"); + +/** + * + * @param {Discord.Client} bot + * @param {Discord.TextChannel} channel + */ +module.exports.run = async (bot, message, args) => { + let member = message.guild.member(message.mentions.members.first() || args[0] || message.author); + + if(!member) return error(`ERROR: \`${args[0]}\` is not a user.`) + + const tierColors = [colors.tier0, colors.tier1, colors.tier2, colors.tier3, colors.tier4, colors.tier5] + const tierRomanNumerals = ["I", "II", "III", "IV", "V"] + // Get user info + fs.readFile("./bughuntertracker.json", "utf8", (err, data) => { + if(err) return console.error(err); + const bugHunterArr = JSON.parse(data); + const bugHunter = bugHunterArr.find(bughunter => bughunter.id === member.id); + if(bugHunter) { + const bugHunterPerks = bugHunter.perks; + let userInfoEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("USERINFO") + .setDescription(`**User info for \`${member.user.tag}\`\n\n${bugHunter.tier ? `Tier ${tierRomanNumerals[bugHunter.tier - 1]} ` : ``}Bug Hunter**`) + .addField("Tokens", bugHunter.tokens) + .addField("Unlocked Perks", Perks.unlockedToString(bugHunterPerks)) + .setColor(tierColors[bugHunter.tier]) + .setFooter("Requested by: " + message.author.tag, message.author.displayAvatarURL); + message.channel.send(userInfoEmbed); + } else { + let userInfoEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("USERINFO") + .setDescription(`**User info for \`${member.user.tag}\`\n\nNot a bug hunter.**`) + .setColor(colors.user) + .setFooter("Requested by: " + message.author.tag, message.author.displayAvatarURL); + message.channel.send(userInfoEmbed); + } + }); + + // Error Handler + + function error(errorMessage) { + const errorEmbed = new Discord.RichEmbed() + .setAuthor("Reviewer -", bot.avatarURL) + .setTitle("ERROR") + .setDescription(`${errorMessage}\nUser info process halted. Please run the command again to restart.`) + .setColor(colors.error); + message.channel.send(errorEmbed).then(msg => { + message.delete(0); + msg.delete(5000); + }); + } +}; + + +module.exports.help = { + name: "user", + description:"Gets user info for a user." +}; diff --git a/events/guildMemberAdd.js b/events/guildMemberAdd.js index 786402c..41c7f23 100644 --- a/events/guildMemberAdd.js +++ b/events/guildMemberAdd.js @@ -6,6 +6,8 @@ const mintime = botsettings.mintime; const roleid = botsettings.roleid_member; exports.run = (bot, member) => { + // Because the skids can't read... + return; let dialogue = [ "Welcome to the ProdigyMathGameHacking Discord!", "Before we get you started, we need you to become familiar with our rules and faq.", diff --git a/store.json b/store.json new file mode 100644 index 0000000..e8af05b --- /dev/null +++ b/store.json @@ -0,0 +1,38 @@ +{ + "color_roles": { + "tokens": 20, + "description": "Gives you a colored role of your choice for a week!" + }, + "tier_1": { + "tokens": 45, + "description": "The first tier of the bug hunter progression, requires buyer to be a bug hunter. Comes with a cool role that stays with you for a week." + }, + "tier_2": { + "tokens": 70, + "description": "The second tier of the bug hunter progression, requires buyer to be a tier 1 bug hunter. Comes with a cool role that stays with you for a week." + }, + "tier_3": { + "tokens": 100, + "description": "The third tier of the bug hunter progression, requires buyer to be a tier 2 bug hunter. Comes with a cool role that stays with you for a week." + }, + "tier_4": { + "tokens": 150, + "description": "The fourth tier of the bug hunter progression, requires buyer to be a tier 3 bug hunter. Comes with a cool role that stays with you for a week." + }, + "tier_5": { + "tokens": 230, + "description": "The fifth and last tier of the bug hunter progression, requires buyer to be a tier 4 bug hunter. Comes with a cool role that stays with you forever. :o" + }, + "launcher": { + "tokens": 60, + "description": "Gives you access to the ?launch command, which lets you launch others into space!" + }, + "embeder": { + "tokens": 60, + "description": "Gives you access to the ?embed command, which lets you turn your messages into embeds with C O L O R!" + }, + "mocker": { + "tokens": 60, + "description": "Gives you access to the ?mock command, which lets you mock others!" + } +} \ No newline at end of file diff --git a/utils/Perks/Embeder.js b/utils/Perks/Embeder.js new file mode 100644 index 0000000..629bd85 --- /dev/null +++ b/utils/Perks/Embeder.js @@ -0,0 +1,8 @@ +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.perks.embederUnlocked) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Unlock Perk + bugHunter.perks.embederUnlocked = true; + + return true; +} \ No newline at end of file diff --git a/utils/Perks/Launcher.js b/utils/Perks/Launcher.js new file mode 100644 index 0000000..e8c3b86 --- /dev/null +++ b/utils/Perks/Launcher.js @@ -0,0 +1,8 @@ +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.perks.launcherUnlocked) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Unlock Perk + bugHunter.perks.launcherUnlocked = true; + + return true; +} \ No newline at end of file diff --git a/utils/Perks/Mocker.js b/utils/Perks/Mocker.js new file mode 100644 index 0000000..e97424b --- /dev/null +++ b/utils/Perks/Mocker.js @@ -0,0 +1,8 @@ +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.perks.mockerUnlocked) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Unlock Perk + bugHunter.perks.mockerUnlocked = true; + + return true; +} \ No newline at end of file diff --git a/utils/Perks/Tier 1.js b/utils/Perks/Tier 1.js new file mode 100644 index 0000000..aa2c986 --- /dev/null +++ b/utils/Perks/Tier 1.js @@ -0,0 +1,15 @@ +const role_id = require("../../botsettings.json").roleid_bughunter_tiers[0] + +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.tier > 0) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Give Tier Role + const role = guild.roles.find(r => r.id === role_id); + const member = guild.members.find(m => m.id === bugHunter.id) + member.addRole(role); + + // Update Tier + bugHunter.tier = 1; + + return true; +} \ No newline at end of file diff --git a/utils/Perks/Tier 2.js b/utils/Perks/Tier 2.js new file mode 100644 index 0000000..0601628 --- /dev/null +++ b/utils/Perks/Tier 2.js @@ -0,0 +1,16 @@ +const role_id = require("../../botsettings.json").roleid_bughunter_tiers[1] + +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.tier < 1) return `ERROR: You can't purchase this tier without purchasing the previous one first.` + if(bugHunter.tier > 1) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Give Tier Role + const role = guild.roles.find(r => r.id === role_id); + const member = guild.members.find(m => m.id === bugHunter.id) + member.addRole(role); + + // Update Tier + bugHunter.tier = 2; + + return true; +} \ No newline at end of file diff --git a/utils/Perks/Tier 3.js b/utils/Perks/Tier 3.js new file mode 100644 index 0000000..379e97e --- /dev/null +++ b/utils/Perks/Tier 3.js @@ -0,0 +1,16 @@ +const role_id = require("../../botsettings.json").roleid_bughunter_tiers[2] + +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.tier < 2) return `ERROR: You can't purchase this tier without purchasing the previous one first.` + if(bugHunter.tier > 2) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Give Tier Role + const role = guild.roles.find(r => r.id === role_id); + const member = guild.members.find(m => m.id === bugHunter.id) + member.addRole(role); + + // Update Tier + bugHunter.tier = 3; + + return true; +} \ No newline at end of file diff --git a/utils/Perks/Tier 4.js b/utils/Perks/Tier 4.js new file mode 100644 index 0000000..af1e816 --- /dev/null +++ b/utils/Perks/Tier 4.js @@ -0,0 +1,16 @@ +const role_id = require("../../botsettings.json").roleid_bughunter_tiers[3] + +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.tier < 3) return `ERROR: You can't purchase this tier without purchasing the previous one first.` + if(bugHunter.tier > 3) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Give Tier Role + const role = guild.roles.find(r => r.id === role_id); + const member = guild.members.find(m => m.id === bugHunter.id) + member.addRole(role); + + // Update Tier + bugHunter.tier = 4; + + return true; +} \ No newline at end of file diff --git a/utils/Perks/Tier 5.js b/utils/Perks/Tier 5.js new file mode 100644 index 0000000..3e041c3 --- /dev/null +++ b/utils/Perks/Tier 5.js @@ -0,0 +1,16 @@ +const role_id = require("../../botsettings.json").roleid_bughunter_tiers[4] + +module.exports.unlock = function (guild, bugHunter) { + if(bugHunter.tier < 4) return `ERROR: You can't purchase this tier without purchasing the previous one first.` + if(bugHunter.tier > 4) return `ERROR: We stopped you from purchasing this perk because you already have it.`; + + // Give Tier Role + const role = guild.roles.find(r => r.id === role_id); + const member = guild.members.find(m => m.id === bugHunter.id) + member.addRole(role); + + // Update Tier + bugHunter.tier = 5; + + return true; +} \ No newline at end of file diff --git a/utils/bugReport.js b/utils/bugReport.js index 2202dd7..8eace2f 100644 --- a/utils/bugReport.js +++ b/utils/bugReport.js @@ -1,5 +1,7 @@ const Discord = require("discord.js"); +const fs = require("fs") const fetch = require("node-fetch"); +const Perks = require("./perks.js") const colors = require("../colors.json"); const botsettings = require("../botsettings.json"); const github_token = botsettings.github_token; @@ -7,6 +9,7 @@ const pending_channelid = botsettings.channelid_pendingbugs; const approved_channelid = botsettings.channelid_approvedbugs; const bughunter_roleid = botsettings.roleid_bughunter; const mintesters = botsettings.mintesters; +const tokensPerBug = botsettings.tokens_per_bug; const version = botsettings.version; @@ -28,61 +31,6 @@ module.exports = class BugReport { this.notes = []; this.version = version; } - /** - * Better System by Top down Inheritance and bottom to top functionality - * BugReport takes an id (this is all it takes) - * Constructor - * takes data from user - * Message (takes a message id of embed) - * edit (edits message) - * submit (submits message) - * TesterLists - * CONST MAX - * TOTAL - * AcceptorList - * submit(): Update total after check total < max - * Denier List - * submit(): Update total after check total < max - * NoteList - * CONST MAX - * TOTAL - * Note - * submit(): Update total after check total < max - * - * Embed titles are limited to 256 characters - * Embed descriptions are limited to 2048 characters - * There can be up to 25 fields - * A field's name is limited to 256 characters and its value to 1024 characters - * The footer text is limited to 2048 characters - * The author name is limited to 256 characters - * In addition, the sum of all characters in an embed structure must not exceed 6000 characters - * A bot can have 1 embed per message - * A webhook can have 10 embeds per message - * - * - * - * TODO: - * Seperate functions by purpose - * Standardize classes/functions? - * Keep functions in correct parent class - * Create classes based on functions needed - * Attach github link to completed issue (ill do that now) - * - * - * If a report is not pending, it shouldn't accept more testers. - * Max testers --> (2 * AcceptedTesters) - 1 - * Max reason --> (8 * 100) / MaxTesters - * - * While the report is pending, you can accept/deny. - * If you've already accepted/denied that issue - * Remove your previous accept/deny - * Add the new accept/deny + reason to the end - * - * Notes should be added to the github - * - * Once a report is accepted, make an issue on github, and attach the resulting link onto the embed - * - */ static createEmbed(report, bot) { function createTestersList(report) { const acceptersList = report.acceptersList.map(acceptor => acceptor.reason || acceptor) @@ -231,6 +179,20 @@ module.exports = class BugReport { let role = guild.roles.find(r => r.id === bughunter_roleid); let member = guild.members.find(m => m.id === report.authorID); member.addRole(role); + + // Give user bug tokens + fs.readFile("./bughuntertracker.json", "utf8", (err, data) => { + if(err) return console.error(err); + const bughunterArr = JSON.parse(data); + const bughunter = bughunterArr.find(bughunter => bughunter.id === report.authorID); + if(bughunter) { + bughunter.tokens += tokensPerBug; + } else bughunterArr.push({id: report.authorID, tokens: tokensPerBug, tier: 0, perks: new Perks()}) + const bughunterJSON = JSON.stringify(bughunterArr); + fs.writeFile("./bughuntertracker.json", bughunterJSON, "utf8", err => { + if(err) console.error(err); + }); + }); } BugReport.edit(report, bot); } diff --git a/utils/isBugHunter.js b/utils/isBugHunter.js new file mode 100644 index 0000000..4e26db0 --- /dev/null +++ b/utils/isBugHunter.js @@ -0,0 +1,8 @@ +const fs = require("fs"); + +module.exports.isBugHunter = function (id) { + const data = fs.readFileSync("./bughuntertracker.json", "utf8") + const bugHunterArr = JSON.parse(data); + const bugHunter = bugHunterArr.find(bughunter => bughunter.id === id); + return bugHunter ? bugHunter.perks : false; +} \ No newline at end of file diff --git a/utils/perks.js b/utils/perks.js new file mode 100644 index 0000000..0593627 --- /dev/null +++ b/utils/perks.js @@ -0,0 +1,12 @@ +module.exports = class Perks { + constructor() { + this.launcherUnlocked = false; + this.embederUnlocked = false; + this.mockerUnlocked = false; + } + static unlockedToString(perks) { + if(!Object.entries(perks).some(([key, val]) => val)) return "**NONE**"; + const unlockedList = Object.entries(perks).map(([key, val]) => val ? "- " + key.charAt(0).toUpperCase() + key.slice(1, key.indexOf("Unlocked")) : "") + return unlockedList.filter(perk => perk !== "").join("\n"); + } +}