commit ddd5972f723050995ab676fed0ebce996234fd06 Author: Ryahn Date: Mon May 12 12:57:59 2025 -0500 init diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f544ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.babelrc +/yarn.lock +/botconfig.json \ No newline at end of file diff --git a/botconfig.sample.json b/botconfig.sample.json new file mode 100644 index 0000000..cac75f9 --- /dev/null +++ b/botconfig.sample.json @@ -0,0 +1,38 @@ +{ + "token": "", + "api": "https://chat.f95.io/api", + "mongoDB": "mongodb://127.0.0.1:27017/zonies", + "defaultGuildId": "01HAT8SAMPMRD554Z9942EEHJ7", + "owners": ["01HATCHHMPTJBHH534H6VFYKK3"], + "prefix": "!", + "roles": [ + { + "mod": "01HB2G8GJHJS1ZA8XSQ6PECG12", + "staff": "01HATA3EAVF0H5T9QSD89Z4C9K", + "jrmod": "01HB2H2JFY9PWDW7GXRC1SBY4C", + "uploader": "01HF78H660P67QXEZPZ9MD1HBZ", + "jruploader": "01HF78RZDE32E5CXKS4P85PY54" + } + ], + + "rule7": { + "apiKey": "" + }, + "emojis": { + "one": "1️⃣", + "two": "2️⃣", + "three": "3️⃣", + "four": "4️⃣", + "five": "5️⃣", + "six": "6️⃣", + "seven": "7️⃣", + "eight": "8️⃣", + "nine": "9️⃣", + "ten": "🔟", + "confetti": "🎊", + "stop": "🛑", + "check": "✅", + "cross": "❌" + }, + "tenor_api_key": "" +} diff --git a/commands/avatar.js b/commands/avatar.js new file mode 100644 index 0000000..cc1afdf --- /dev/null +++ b/commands/avatar.js @@ -0,0 +1,26 @@ +const Embed = require("../functions/embed") + +module.exports = { + config: { + name: "avatar", + usage: true, + cooldown: 5000, + available: true, + permissions: [], + aliases: ['av'] + }, + run: async (client, message, args, db) => { + if (message.mentions?.length <= 0) return message.reply('Must mention a user!'); + const targetName = (message.mentions?.length >= 1 ? message.mentions[0]?.username : message.author.username) + const member = await (client.servers.get(message.server.id) || await client.servers.fetch(message.server.id))?.fetchMember(message.mentionIds[0]); + const target = message.mentions?.length >= 1 ? member.user.avatar.createFileURL({ max_side: 4096 }, true) ? member.user.avatar.createFileURL({ max_side: 4096 }, true) : message.mentions[0]?.defaultAvatarURL : member.user.avatar.createFileURL({ size: 4096 }, true) ? member.user.avatar.createFileURL({ size: 4096 }, true) : member.user.avatar.createFileURL({ size: 4096 }, true) ? message.author.avatarURL({ size: 4096 }, true) : message.author.avatarURL({ size: 4096 }, true) ? message.author.avatarURL({ size: 4096 }, true) : message.member.user.defaultAvatarURL + const embed = { description: "Avatar for [" + targetName + "](" + target + ")", colour: "#00FFFF", iconURL: target } + + await message.channel.sendMessage({ content: "[ ](" + target + ")", embeds: [embed] }).catch(err => { + console.log(`${Date(Date.now().toString()).slice(0, 25)}`); + console.log("User: " + message.author.username + ` [${message.authorId}] ` + " | Command: avatar | Args: " + (args?.join(" ") || "NONE")) + console.log(err.message); + return; + }); + }, +}; \ No newline at end of file diff --git a/commands/command.js b/commands/command.js new file mode 100644 index 0000000..bdfed1e --- /dev/null +++ b/commands/command.js @@ -0,0 +1,90 @@ +const Embed = require("../functions/embed") +const CommandsDB = require('../models/commands'); +const { random } = require('../functions/randomStr'); +const moment = require('moment'); + +module.exports = { + config: { + name: "command", + usage: true, + cooldown: 0, + available: true, + permissions: ['ManageServer'], + aliases: ['cmd'] + }, + run: async (client, message, args, db) => { + + /************************************************* + * HELP + *************************************************/ + if (args[0] === 'help') { + let embed = new Embed() + .setDescription(`### Custom Commands\n**add**: \`add [name] [content]\`\nEx: \`add soul Fucks his cousin|Is swedish\` or \`add zemax Is the punching bag for uploaders\`\nIf you want to add multiple options to a command use a pipe \`|\`\n\n**delete**: \`delete [name/id]\`\n\n**edit**: \`edit [name/id]\`\n\n**show**: \`show [name/id]\`\n\n`) + .setColor(`#A52F05`); + return message.reply({ embeds: [embed] }, false); + /************************************************* + * ADD + *************************************************/ + } else if (args[0] === 'add') { + let name = args[1]; + let content = args[2]; + const cmd = new CommandsDB(); + let check = await CommandsDB.findOne({ name: name }).select("name").lean(); + if (check) return message.reply('Command already exists with that name!'); + + if (content.includes('|')) { + cmd.id = random(5); + cmd.name = name; + cmd.content = JSON.stringify(content.split('|')); + cmd.createdBy = message.member.user.username; + cmd.save(); + return message.reply('Command saved!'); + } + cmd.id = random(5); + cmd.name = name; + cmd.content = args.slice(2).join(' '); + cmd.createdBy = message.member.user.username; + cmd.save(); + return message.reply('Command saved!'); + /************************************************* + * FIND + *************************************************/ + } else if (args[0] === 'find') { + let check = await (CommandsDB.findOne({ name: args[1] }).select("id name").lean() || CommandsDB.findOne({ id: args[1] }).select("id name").lean()); + if (!check) return message.reply('Command doesn\'t exists with that name or ID!'); + CommandsDB.findOne({ name: args[1] }).then((data) => { + let embed = new Embed() + .setDescription(`### Custom Commands: ${data.name}\n**ID**: ${data.id}\n**Content**: ${data.content}\n**Created by**: ${data.createdBy}\n**Created at**: ${moment.unix(data.created_at).format('YYYY/MMM/DD HH:MM:ss')} (UTC)`) + .setColor(`#A52F05`); + return message.reply({ embeds: [embed] }, false); + }); + /************************************************* + * DELETE + *************************************************/ + } else if (args[0] === 'delete') { + let check = await (CommandsDB.findOne({ name: args[1] }).select("id name").lean() || CommandsDB.findOne({ id: args[1] }).select("id name").lean()); + console.log(check) + if (!check) return message.reply('Command doesn\'t exists with that name or id!'); + CommandsDB.deleteMany({ id: check.id }).exec(); + return message.reply('Command Removed!'); + /************************************************* + * SHOW + *************************************************/ + } else if (args[0] === 'show') { + // let cmds = await CommandsDB.find({}).select('name').lean(); + // console.log(cmds.toString().join(',')) + let data = CommandsDB.find({}).select('name').then((data) => { + let names = []; + data.forEach((item) => { names.push(item.name) }); + message.reply('DM Sent with all available custom commands.'); + message.member.user.openDM().then((dm) => { dm.sendMessage(names.join(', ')) }); + }); + + /************************************************* + * NO ARGS + *************************************************/ + } else { + return message.reply(`First argument must be add, delete, edit, show, find or help. You put ${args[0]}`, false) + } + }, +}; diff --git a/commands/gaydar.js b/commands/gaydar.js new file mode 100644 index 0000000..6334ee1 --- /dev/null +++ b/commands/gaydar.js @@ -0,0 +1,40 @@ +const Embed = require("../functions/embed") +// const { } = require('revolt.js') + +module.exports = { + config: { + name: "gaydar", + usage: true, + cooldown: 5000, + available: true, + permissions: [], + aliases: ['gd'] + }, + run: async (client, message, args, db) => { + function randomInteger(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + const member = await (client.servers.get(message.server.id) || await client.servers.fetch(message.server.id))?.fetchMember(message.mentionIds[0]).then((user) => { + return console.log(); + }); + // const target = member.user.username; + // return console.log(member) + // let amount = randomInteger(1, 100); + + // const embed = { + // description: `#### ${target} is ${amount}% gay.`, + // colour: "#ff8080", + // image: 'https://overlord.lordainz.xyz/f/gaydar.jpg' + // } + + // await message.channel.sendMessage({ content: "", embeds: [embed] }).catch(err => { + // console.log(`${Date(Date.now().toString()).slice(0, 25)}`); + // console.log("User: " + message.author.username + ` [${message.authorId}] ` + " | Command: gardar | Args: " + (args?.join(" ") || "NONE")) + // console.log(err.message); + // return; + // }); + }, +}; \ No newline at end of file diff --git a/commands/gif.js b/commands/gif.js new file mode 100644 index 0000000..b354010 --- /dev/null +++ b/commands/gif.js @@ -0,0 +1,29 @@ +const Embed = require("../functions/embed") +const fetch = require('node-fetch-commonjs') +const config = require('../config') + +module.exports = { + config: { + name: "gif", + usage: true, + cooldown: 5000, + available: true, + permissions: [], + aliases: ['tenor', 'giphy', 'gify'] + }, + run: async (client, message, args, db) => { + if (!args[0]) return message.reply('Usage: !gif SEARCHTERM | Aliases: gif, tneor, giphy, gify'); + async function get_gif_url(query) { + // Fetches the gif url + const gif_response = await fetch(`https://tenor.googleapis.com/v2/search?q=${query}&key=${config.tenor_api_key}&limit=1&media_filter=gif`); + // Converts it to json + const gif_data = await gif_response.json(); + // Returns the url + return gif_data.results[0].media_formats.gif.url; + } + + let url = await get_gif_url(args.join(' ')); + + return message.reply(url); + }, +}; \ No newline at end of file diff --git a/commands/help.js b/commands/help.js new file mode 100644 index 0000000..fbe01ce --- /dev/null +++ b/commands/help.js @@ -0,0 +1,30 @@ +const Embed = require("../functions/embed") + +module.exports = { + config: { + name: "help", + usage: true, + cooldown: 5000, + available: true, + permissions: [], + aliases: ['h'] + }, + run: async (client, message, args, db) => { + const embed = { + description: `**!avatar**: \`!avatar @USER\`\n**Aliases**: \`!av\`\n + **!command**: \`!command add NAME CONTENT\`\n**Aliases**: \`!cmd\`\n + **!gif**: \`!gif TERM\`\n**Aliases**: \`!gify, !tenor, !giphy\`\n + **!polls**: \`!polls TIME | How are you? | Good | Bad\`\n**Aliases**: \`!poll\`\n + **!urban**: \`!urban TERM\`\n**Aliases**: \`!ub\`\n\n + **Tip**: You can run each command without an argument and it will return how to use it.`, colour: "#00FFFF", title: "Commands Help" + } + + + await message.channel.sendMessage({ content: "", embeds: [embed] }).catch(err => { + console.log(`${Date(Date.now().toString()).slice(0, 25)}`); + console.log("User: " + message.author.username + ` [${message.authorId}] ` + " | Command: help | Args: " + (args?.join(" ") || "NONE")) + console.log(err.message); + return; + }); + }, +}; \ No newline at end of file diff --git a/commands/info.js b/commands/info.js new file mode 100644 index 0000000..c7d41f2 --- /dev/null +++ b/commands/info.js @@ -0,0 +1,26 @@ +const Embed = require("../functions/embed"); +const Giveaway = require("../models/giveaways"); +const SavedPolls = require("../models/savedPolls"); +const { dependencies } = require("../package.json"); +module.exports = { + config: { + name: "info", + usage: false, + cooldown: 10000, + available: true, + permissions: [], + aliases: ["stats"] + }, + run: async (client, message, args, db) => { + const unixstamp = client.functions.get("fetchTime")(Math.floor(process.uptime() * 1000), client, db.language) + let beforeCall = Date.now(); + const polls = await SavedPolls.find(); + let dbPing = Date.now() - beforeCall; + + const embed = new Embed() + .setDescription(`### ${client.translate.get(db.language, 'Commands.info.start')}\n${client.translate.get(db.language, 'Commands.info.servers')}: ${client.servers.size().toLocaleString()}\n${client.translate.get(db.language, 'Commands.info.giveaways')}: ${(await Giveaway.find()).length.toLocaleString()}\n${client.translate.get(db.language, 'Commands.info.polls')}: ${polls.length.toLocaleString()}\n${client.translate.get(db.language, 'Commands.info.uptime')}: ${unixstamp}\n\n${client.translate.get(db.language, 'Commands.info.ping')}: ${client.events.ping()}ms\n${client.translate.get(db.language, 'Commands.info.database')}: ${dbPing}ms\n${client.translate.get(db.language, 'Commands.info.library')}: Revolt.js | ${dependencies["revolt.js"]}`) + .setColor(`#A52F05`); + + message.reply({ embeds: [embed] }, false) + }, +}; diff --git a/commands/polls.js b/commands/polls.js new file mode 100644 index 0000000..575e301 --- /dev/null +++ b/commands/polls.js @@ -0,0 +1,55 @@ +const Embed = require(`../functions/embed`) +const Polls = require(`../functions/poll`) +const dhms = require(`../functions/dhms`); +const PollDB = require("../models/polls"); +const SavedPolls = require(`../models/savedPolls`) + +module.exports = { + config: { + name: `polls`, + usage: true, + cooldown: 10000, + available: true, + permissions: ['ManageServer'], + aliases: ["poll"] + }, + run: async (client, message, args, db) => { + // const check = await PollDB.find({ owner: message.authorId }) + // if (check.length === 5) return message.reply({ embeds: [new Embed().setDescription(client.translate.get(db.language, "Commands.polls.tooMany")).setColor(`#FF0000`)] }, false); + const options = args.join(` `).split(`|`).map(x => x.trim()).filter(x => x); + if (!options[0]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validTime")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + const time = dhms(options[0]); + if (!time) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validTime")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (time === 0) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validTime")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (time < 30000) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.longerThan")} \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (time > 2592000000) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.shorterThan")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (!options[1]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validQuestion")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (!options[2]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validOption")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (!options[3]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validOption2")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (options.length >= 13) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.maxOptions")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + + const names = [options[2], options[3], options[4] ? options[4] : null, options[5] ? options[5] : null, options[6] ? options[6] : null, options[7] ? options[7] : null, options[8] ? options[8] : null, options[9] ? options[9] : null, options[10] ? options[10] : null, options[11] ? options[11] : null]; + const reactions = [client.config.emojis.one, client.config.emojis.two, options[4] ? client.config.emojis.three : null, options[5] ? client.config.emojis.four : null, options[6] ? client.config.emojis.five : null, options[7] ? client.config.emojis.six : null, options[8] ? client.config.emojis.seven : null, options[9] ? client.config.emojis.eight : null, options[10] ? client.config.emojis.nine : null, options[11] ? client.config.emojis.ten : null, client.config.emojis.stop]; + + const poll = new Polls({ time, client, name: { name: client.translate.get(db.language, "Commands.polls.polls"), description: options[1] }, options: { name: names.filter(a => a) }, owner: message.authorId, lang: db.language }) + await poll.update(); + + let tooMuch = []; + if (options[1].length > 75) tooMuch.push(`**${client.translate.get(db.language, "Commands.polls.title")}**: ${options[1]}`) + names.filter(e => e).forEach((e, i) => { + i++ + if (e.length > 70) { + tooMuch.push(`**${i}.** ${e}`) + } + }); + message.channel.sendMessage({ embeds: [new Embed().setDescription(tooMuch.length > 0 ? tooMuch.map(e => e).join("\n") : null).setMedia(await client.Uploader.upload(poll.canvas.toBuffer(), `Poll.png`)).setColor(`#A52F05`)], interactions: [reactions.filter(e => e)] }).then((msg) => { + poll.start(msg, poll); + }); + + await (new SavedPolls({ + owner: message.authorId, + desc: options[1], + options: { name: names } + }).save()); + }, +}; diff --git a/commands/prefix.js b/commands/prefix.js new file mode 100644 index 0000000..2fcf20d --- /dev/null +++ b/commands/prefix.js @@ -0,0 +1,22 @@ +const Embed = require("../functions/embed") + +module.exports = { + config: { + name: "prefix", + cooldown: 5000, + available: true, + usage: true, + permissions: ["ManageServer"], + aliases: [] + }, + run: async (client, message, args, db) => { + const embed = new Embed() + .setDescription(`${client.translate.get(db.language, "Commands.prefix.prefix")}: \`${db.prefix}\`\n\n${client.translate.get(db.language, "Commands.prefix.change")} \`${db.prefix}prefix <${client.translate.get(db.language, "Commands.prefix.new")}>\``) + if (!args[0]) return message.reply({ embeds: [embed] }, false); + if (args[0] === db.prefix) return message.reply({ embeds: [embed] }, false); + if (args[0].length > 8) return message.reply(client.translate.get(db.language, "Commands.prefix.tooMany"), false); + + await client.database.updateGuild(message.server.id, { prefix: args[0] }); + return message.reply(`${client.translate.get(db.language, "Commands.prefix.success")} \`${args[0]}\``, false); + }, +}; diff --git a/commands/register.js b/commands/register.js new file mode 100644 index 0000000..ac01350 --- /dev/null +++ b/commands/register.js @@ -0,0 +1,170 @@ +const axios = require(`axios`); +const botConfig = require('../botconfig.json'); +const { generateUniqueId } = require('../functions/randomStr'); +const https = require('https'); +const Invites = require('../models/registerInvite'); +const Embed = require('../functions/embed'); + +// Create axios instance outside of module.exports +const makeRequest = axios.create({ + baseURL: `https://rule7.zonies.xyz/api/v1`, + headers: { + "Authorization": `Bearer ${botConfig.rule7.apiKey}` + }, + httpsAgent: new https.Agent({ + rejectUnauthorized: false + }) +}); + +module.exports = { + config: { + name: `register`, + usage: true, + cooldown: 10000, + available: true, + permissions: [''], + roles: ['staff', 'uploader', 'jrmod', 'mod'], + aliases: ["reg"], + dm: true + }, + run: async (client, message, args, db) => { + try { + // If not in DM, check for permissions and roles + if (message.channel.type !== 'DirectMessage') { + // Check if user has any of the required roles + const hasRequiredRole = message.member.roles.some(role => + module.exports.config.roles.includes(role.toLowerCase()) + ); + + if (!hasRequiredRole && !client.config.owners.includes(message.authorId)) { + return message.reply({ + embeds: [ + new Embed() + .setColor("#FF0000") + .setDescription(`You don't have the required roles to use this command.`) + ] + }); + } + } + + // Check if the command is used in a DM + if (message.channel.type !== 'DirectMessage') { + const inviteCode = generateUniqueId(); + + const staffRoles = { + is_staff: 0, + is_mod: 0, + is_jrmod: 0, + is_uploader: 0, + is_jruploader: 0 + } + + let memberRoles = message.member.roles; + + // Set staff role values based on member's roles + if (memberRoles.includes(client.botConfig.roles[0].staff)) staffRoles.is_staff = 1; + if (memberRoles.includes(client.botConfig.roles[0].mod)) staffRoles.is_mod = 1; + if (memberRoles.includes(client.botConfig.roles[0].jrmod)) staffRoles.is_jrmod = 1; + if (memberRoles.includes(client.botConfig.roles[0].uploader)) staffRoles.is_uploader = 1; + if (memberRoles.includes(client.botConfig.roles[0].jruploader)) staffRoles.is_jruploader = 1; + + const registerInvite = new Invites({ + userId: message.author.id, + invite: inviteCode, + staffRoles, + createdAt: Date.now() + }); + + await registerInvite.save(); + + return message.reply({ + content: `Run this command in a DM to the bot and use this invite code: \`${inviteCode}\`\n + **Usage:** \`!register ${inviteCode} \`\n + **Note: This invite code will expire in 10 minutes.**` + }); + } + + const [invite, username, email, profileUrl] = args; + + if (!invite || !username || !email || !profileUrl) { + return message.reply({ + content: `[REG3] Please provide a invite code, username, email, and f95zone profile url. \n\n**Usage:** \`${client.prefix}register \`` + }); + } + + // DM flow - Use client.database instead of direct model + const registerInvite = await Invites.findOne({ invite: invite }); + + if (!registerInvite) { + return message.reply({ + content: `[REG1] You don't have an invite code. Please run the command outside of DMs.` + }); + } + + if (registerInvite.createdAt + 10 * 60 * 1000 < Date.now()) { + await registerInvite.deleteOne({ invite: invite }); + return message.reply({ + content: `[REG2] Your invite code has expired. Please run the command outside of DMs.` + }); + } + + if (invite !== registerInvite.invite) { + return message.reply({ + content: `[REG4] Invalid invite code. Please run the command outside of DMs.` + }); + } + + let f95zoneId = profileUrl.split('/')[4]; + f95zoneId = f95zoneId.split('.')[1]; + + try { + const { data } = await makeRequest.post(`/bot/register`, { + username, + email, + f95_id: f95zoneId, + is_staff: registerInvite.staffRoles.is_staff, + is_mod: registerInvite.staffRoles.is_mod, + is_jrmod: registerInvite.staffRoles.is_jrmod, + is_uploader: registerInvite.staffRoles.is_uploader, + is_jruploader: registerInvite.staffRoles.is_jruploader + }); + + if (data.status === 'success') { + await registerInvite.deleteOne({ invite: invite }); + return message.reply({ + content: `[REG5] You have been registered. Please check your email for verification.` + }); + } else if (data.status === 'invalid_email') { + return message.reply({ + content: `[REG5.1] An error occurred during registration. ${data.msg}` + }); + } else if (data.status === 'username_exists') { + return message.reply({ + content: `[REG5.2] An error occurred during registration. ${data.msg}` + }); + } else if (data.status === 'invalid_f95_id') { + return message.reply({ + content: `[REG5.3] An error occurred during registration. ${data.msg}` + }); + } else if (data.status === 'email_exists') { + return message.reply({ + content: `[REG5.4] An error occurred during registration. ${data.msg}` + }); + } else if (data.status === 'error') { + return message.reply({ + content: `[REG5.5] An error occurred during registration. ${data.msg}` + }); + } + } catch (apiError) { + return message.reply({ + content: `[REG6] An error occurred during registration. Please try again later.\n\`${apiError}\`` + }); + } + } catch (error) { + console.error('Registration Error:', error); + return message.reply({ + content: `[REG7] An unexpected error occurred. Please try again later.\n\`${error}\`` + }); + } + }, +}; diff --git a/commands/reload.js b/commands/reload.js new file mode 100644 index 0000000..8a8031a --- /dev/null +++ b/commands/reload.js @@ -0,0 +1,31 @@ +const Reload = require("../functions/reload") +module.exports = { + config: { + name: "reload", + cooldown: 0, + available: "Owner", + permissions: [], + aliases: ["r"] + }, + run: async (client, message, args) => { + if (!client.config.owners.includes(message.authorId)) return; + if (!args[0]) return message.reply("Provide either a category or a command to reload.", false) + if (args[0] === "category") { + let error = []; + let success = []; + + if (!args[1]) return message.reply("Provide a category's name to reload it.", false) + + client.commands.filter(c => c.config.category === args[1]).map(cc => { + Reload(client, cc.config.category, cc.config.name, args[2]) + + let check = client.reloadCommand(args[1], cc.config.name) + if (check.includes("Error")) return error.push(check) + else if (check.includes("Reloaded command:")) return success.push("1") + }) + + return message.reply(`\`\`\`css\nSuccessful Commands: ${success.length}\nErrored Commands: ${error.length} ${error.length > 0 ? "\n" + error.map(c => c).join("\n") : " "}`, false) + } + message.reply(Reload(client, args[0], args[1], args[2]), false) + } +} \ No newline at end of file diff --git a/commands/rule7.js b/commands/rule7.js new file mode 100644 index 0000000..356470a --- /dev/null +++ b/commands/rule7.js @@ -0,0 +1,55 @@ +const Embed = require(`../functions/embed`) +const Polls = require(`../functions/poll`) +const dhms = require(`../functions/dhms`); +const PollDB = require("../models/rule7"); +const SavedPolls = require(`../models/savedPolls`) + +module.exports = { + config: { + name: `rule7`, + usage: true, + cooldown: 10000, + available: true, + permissions: ['ManageServer'], + aliases: ["r7"] + }, + run: async (client, message, args, db) => { + // const check = await PollDB.find({ owner: message.authorId }) + // if (check.length === 5) return message.reply({ embeds: [new Embed().setDescription(client.translate.get(db.language, "Commands.polls.tooMany")).setColor(`#FF0000`)] }, false); + const options = args.join(` `).split(`|`).map(x => x.trim()).filter(x => x); + if (!options[0]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validTime")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + const time = dhms(options[0]); + if (!time) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validTime")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (time === 0) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validTime")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (time < 30000) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.longerThan")} \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (time > 2592000000) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.shorterThan")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (!options[1]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validQuestion")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (!options[2]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validOption")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (!options[3]) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.validOption2")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + if (options.length >= 13) return message.reply({ embeds: [new Embed().setDescription(`${client.translate.get(db.language, "Commands.polls.maxOptions")}: \`${client.config.prefix}polls 5m | ${client.translate.get(db.language, "Commands.polls.example")}\``).setColor(`#FF0000`)] }, false); + + const names = [options[2], options[3], options[4] ? options[4] : null, options[5] ? options[5] : null, options[6] ? options[6] : null, options[7] ? options[7] : null, options[8] ? options[8] : null, options[9] ? options[9] : null, options[10] ? options[10] : null, options[11] ? options[11] : null]; + const reactions = [client.config.emojis.one, client.config.emojis.two, options[4] ? client.config.emojis.three : null, options[5] ? client.config.emojis.four : null, options[6] ? client.config.emojis.five : null, options[7] ? client.config.emojis.six : null, options[8] ? client.config.emojis.seven : null, options[9] ? client.config.emojis.eight : null, options[10] ? client.config.emojis.nine : null, options[11] ? client.config.emojis.ten : null, client.config.emojis.stop]; + + const poll = new Polls({ time, client, name: { name: client.translate.get(db.language, "Commands.polls.polls"), description: options[1] }, options: { name: names.filter(a => a) }, owner: message.authorId, lang: db.language }) + await poll.update(); + + let tooMuch = []; + if (options[1].length > 75) tooMuch.push(`**${client.translate.get(db.language, "Commands.polls.title")}**: ${options[1]}`) + names.filter(e => e).forEach((e, i) => { + i++ + if (e.length > 70) { + tooMuch.push(`**${i}.** ${e}`) + } + }); + message.channel.sendMessage({ embeds: [new Embed().setDescription(tooMuch.length > 0 ? tooMuch.map(e => e).join("\n") : null).setMedia(await client.Uploader.upload(poll.canvas.toBuffer(), `Poll.png`)).setColor(`#A52F05`)], interactions: [reactions.filter(e => e)] }).then((msg) => { + poll.start(msg, poll); + }); + + await (new SavedPolls({ + owner: message.authorId, + desc: options[1], + options: { name: names } + }).save()); + }, +}; diff --git a/commands/template.txt b/commands/template.txt new file mode 100644 index 0000000..51ce821 --- /dev/null +++ b/commands/template.txt @@ -0,0 +1,19 @@ +const Embed = require("../functions/embed") + +module.exports = { + config: { + name: "", + usage: true, + cooldown: 5000, + available: true, + permissions: [], + aliases: [] + }, + run: async (client, message, args, db) => { + + new Paginator([], { timeout: 5 * 2e4, user: message.authorId, client: client }) + .add([embed, embed2]) + .start(message.channel); + }, +}; + \ No newline at end of file diff --git a/commands/urban.js b/commands/urban.js new file mode 100644 index 0000000..af7d77c --- /dev/null +++ b/commands/urban.js @@ -0,0 +1,36 @@ +const Embed = require("../functions/embed"); +const axios = require('axios'); + +module.exports = { + config: { + name: "urban", + usage: true, + cooldown: 5000, + available: true, + permissions: [], + aliases: ['ub'] + }, + run: async (client, message, args, db) => { + let query = args.join(' '); + const url = ('https://api.urbandictionary.com/v0/define?term=' + query) + const response = await axios.get(url); + const data = response.data; + const def = data.list[0]; + var length = data.list.length + if (parseInt(length) < 1) { + message.reply("No results") + return; + } + + const embed = { + description: `### Definition for ${query}\n\n${def.definition}\n\n**Example**:\n\`\`\`${def.example}\`\`\` \n\n:thumbsup: ${def.thumbs_up} :thumbsdown: ${def.thumbs_down}\n\n**Link**: [${query}](${def.permalink})`, + colour: "#00FFFF" + } + await message.channel.sendMessage({ content: "", embeds: [embed] }).catch(err => { + console.log(`${Date(Date.now().toString()).slice(0, 25)}`); + console.log("User: " + message.author.username + ` [${message.authorId}] ` + " | Command: urban | Args: " + (args?.join(" ") || "NONE")) + console.log(err.message); + return; + }); + }, +}; \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..2ac4e42 --- /dev/null +++ b/config.js @@ -0,0 +1,23 @@ +const config = { + "owners": ["01HATCHHMPTJBHH534H6VFYKK3"], + "prefix": "!", + "emojis": { + "one": "1️⃣", + "two": "2️⃣", + "three": "3️⃣", + "four": "4️⃣", + "five": "5️⃣", + "six": "6️⃣", + "seven": "7️⃣", + "eight": "8️⃣", + "nine": "9️⃣", + "ten": "🔟", + "confetti": "🎊", + "stop": "🛑", + "check": "✅", + "cross": "❌", + }, + "tenor_api_key": "AIzaSyCBUnqtNWMPn3f7F4Iu09KewGS8BfwUkDE", +}; + +module.exports = config; diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..997b371 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,7 @@ +module.exports = { + apps : [{ + name : "Zonies", + script : "./index.js", + node_args: "--experimental-specifier-resolution=node" + }] +} diff --git a/events/messageCreate.js b/events/messageCreate.js new file mode 100644 index 0000000..49a1fc0 --- /dev/null +++ b/events/messageCreate.js @@ -0,0 +1,145 @@ +const Embed = require("../functions/embed"); +const Collector = require("../functions/messageCollector"); +const EditCollector = require("../functions/messageEdit"); +const CommandDB = require('../models/commands'); +const { isJson } = require('../functions/randomStr'); +const logger = require('../functions/logger'); +const audit = require('../functions/audit'); + +module.exports = async (client, message) => { + // Early return checks + if (!message || !message.content || message.author.bot) return; + + const isDM = message.channel.type === "DirectMessage"; + + // Get guild settings (if not DM) + const db = isDM ? { prefix: client.botConfig.prefix, language: 'en' } : await client.database.getGuild(message.server.id, true); + + // Check if message starts with prefix + if (!message.content.startsWith(db.prefix)) { + // Handle bot mention + if (message.content && (new RegExp(`^(<@!?${client.user.id}>)`)).test(message.content)) { + const mention = new Embed() + .setColor("#A52F05") + .setTitle(client.user.username) + .setDescription(`${client.translate.get(db.language, "Events.messageCreate.prefix")} \`${db.prefix}\`\n${client.translate.get(db.language, "Events.messageCreate.prefix2")} \`${db.prefix}help\``) + + return message.reply({ + embeds: [mention] + }, false).catch(() => { return }); + } + return; + } + + let args = message.content.slice(db.prefix.length).trim().split(/ +/g); + let cmd = args.shift().toLowerCase(); + + // Handle collectors + if (client.messageCollector.has(message.authorId) && client.messageCollector.get(message.authorId).channelId === message.channelId && !client.messageCollector.get(message.authorId).messageId) return await Collector(client, message, db); + if (client.messageEdit.has(message.authorId) && client.messageEdit.get(message.authorId).channelId === message.channelId && !client.messageEdit.get(message.authorId).messageId) return await EditCollector(client, message, db); + + // Handle custom commands + let check = await CommandDB.findOne({ name: cmd }).select("name").lean(); + if (check) { + CommandDB.findOne({ name: cmd }).then((data) => { + if (isJson(data.content)) { + let items = JSON.parse(data.content); + let item = items[Math.floor(Math.random() * items.length)]; + return message.reply(item); + } + return message.reply(data.content); + }); + } + + // Command handling + let commandfile = client.commands.get(cmd) || client.commands.get(client.aliases.get(cmd)); + if (commandfile) { + // DM Check - if command doesn't allow DMs and we're in a DM, return + if (isDM && !commandfile.config.dm) { + return message.reply({ + embeds: [new Embed() + .setColor("#FF0000") + .setDescription(client.translate.get(db.language, "Events.messageCreate.noDM"))] + }, false).catch(() => { return }); + } + + // Permission checks for non-DM messages + if (!isDM) { + // Check bot permissions first + const canSendMessage = message.channel.havePermission("SendMessage"); + const canReact = message.channel.havePermission("React"); + + if (!canSendMessage) { + return message.member.user.openDM().then((dm) => { + dm.sendMessage(`${client.translate.get(db.language, "Events.messageCreate.unable")} <#${message.channelId}>. ${client.translate.get(db.language, "Events.messageCreate.contact")}.`) + }).catch(() => { return }); + } + + if (!canReact) { + return message.reply(`${client.translate.get(db.language, "Events.messageCreate.noPerms")}. ${client.translate.get(db.language, "Events.messageCreate.contact")}.`, false).catch(() => { return }); + } + + // Check if user has required roles + const hasRequiredRole = commandfile.config.roles && message.member.roles && client.botConfig.roles && client.botConfig.roles.length > 0 ? + message.member.roles.some(role => { + const whitelistedRoles = Object.values(client.botConfig.roles[0] || {}); + return whitelistedRoles.includes(role); + }) : false; + + // Command availability check (skip for DMs) + if (!commandfile.config.available && !hasRequiredRole && !client.botConfig.owners.includes(message.authorId)) { + return message.reply({ + embeds: [new Embed() + .setColor("#FF0000") + .setDescription(client.translate.get(db.language, "Events.messageCreate.unavail"))] + }, false).catch(() => { return }); + } + + // Permission and role checks (skip for DMs) + const needsPermissionCheck = commandfile.config.permissions && commandfile.config.permissions.length > 0; + const needsRoleCheck = commandfile.config.roles && commandfile.config.roles.length > 0; + + if (needsPermissionCheck || needsRoleCheck) { + let hasPermission = true; + + if (needsPermissionCheck) { + try { + hasPermission = message.member.hasPermission(commandfile.config.permissions[0]); + } catch (err) { + hasPermission = false; + } + } + + if (!hasPermission && !hasRequiredRole && !client.botConfig.owners.includes(message.authorId)) { + return message.reply({ + embeds: [new Embed() + .setColor("#FF0000") + .setDescription(`${client.translate.get(db.language, "Events.messageCreate.perms")}.\n${needsPermissionCheck ? `${client.translate.get(db.language, "Events.messageCreate.perms2")}: [${commandfile.config.permissions[0]}]` : ''}`)] + }, false).catch(() => { return }); + } + } + } + + // Cooldown handling + const used = client.used.get(`${message.authorId}-${cmd.toLowerCase()}`); + if (used) { + if (client.timeout.get(`${message.authorId}-${cmd.toLowerCase()}`)) return; + + client.timeout.set(`${message.authorId}-${cmd.toLowerCase()}`, used); + setTimeout(() => client.timeout.delete(`${message.authorId}-${cmd.toLowerCase()}`), used); + + const uremaining = client.functions.get("fetchTime")(used, client, db.language) + const embed = new Embed() + .setColor("#A52F05") + .setDescription(`<@${message.authorId}>, ${client.translate.get(db.language, "Events.messageCreate.wait")} \`${uremaining}\` ${client.translate.get(db.language, "Events.messageCreate.wait2")} \`${cmd.toLowerCase()}\` ${client.translate.get(db.language, "Events.messageCreate.wait3")}.`) + + return message.reply({ embeds: [embed] }, false).catch(() => { return }) + } else { + let cooldown = commandfile.config.cooldown; + client.used.set(`${message.authorId}-${cmd.toLowerCase()}`, cooldown); + setTimeout(() => client.used.delete(`${message.authorId}-${cmd.toLowerCase()}`), cooldown); + + return commandfile.run(client, message, args, db); + } + } +} diff --git a/events/messageDelete.js b/events/messageDelete.js new file mode 100644 index 0000000..b84633a --- /dev/null +++ b/events/messageDelete.js @@ -0,0 +1,25 @@ +const PollDB = require("../models/polls"); +const Giveaways = require("../models/giveaways"); +const GuildDB = require("../models/guilds"); +module.exports = async (client, msg) => { + const paginateCheck = client.paginate.get(msg.authorId); + const pollCheck = client.polls.get(msg.id); + if (paginateCheck) { + client.paginate.delete(msg.authorId); + } else if (pollCheck) { + client.polls.delete(msg.id); + await PollDB.findOneAndDelete({ messageId: msg.id }); + } else { + const db = await Giveaways.findOne({ messageId: msg.id }); + if (db) { + await db.updateOne({ ended: true, endDate: Date.now() }) + await db.save(); + } else { + const db2 = await GuildDB.findOne({ "roles": { $elemMatch: { msgId: msg.id } } }); + if (db2) { + db2.roles = db2.roles.filter(e => e.msgId !== msg.id); + await db2.save(); + } + } + } +} \ No newline at end of file diff --git a/events/messageReactionAdd.js b/events/messageReactionAdd.js new file mode 100644 index 0000000..b32a4f8 --- /dev/null +++ b/events/messageReactionAdd.js @@ -0,0 +1,220 @@ +const Embed = require("../functions/embed"); +const PollDB = require("../models/polls"); +const Giveaways = require("../models/giveaways"); +const emojis = [{ name: "1️⃣", id: 0 }, { name: "2️⃣", id: 1 }, { name: "3️⃣", id: 2 }, { name: "4️⃣", id: 3 }, { name: "5️⃣", id: 4 }, { name: "6️⃣", id: 5 }, { name: "7️⃣", id: 6 }, { name: "8️⃣", id: 7 }, { name: "9️⃣", id: 8 }, { name: "🔟", id: 9 }, { name: "🛑", id: "stop" }] +const colors = /^([A-Z0-9]+)/; + +module.exports = async (client, message, userId, emojiId) => { + const paginateCheck = client.paginate.get(userId); + const pollCheck = client.polls.get(message.id); + const collector = client.messageCollector.get(userId); + const editCollector = client.messageEdit.get(userId); + + if (collector && collector.messageId === message.id || collector?.oldMessageId && collector?.oldMessageId === message.id && collector.channelId === message.channelId) { + if (emojiId === client.config.emojis.check) { + if (collector.roles.length === 0) { + const db = await client.database.getGuild(message.server.id); + message.delete().catch(() => { }); + client.messages.get(collector?.oldMessageId)?.delete().catch(() => { }) + const reactions = [...collector.rolesDone.map(e => e.emoji)]; + message.channel.sendMessage(collector.type === "content" ? { content: `${message.content}\n\n##### ${client.translate.get(db.language, "Events.messageReactionAdd.cooldown")}`, interactions: [reactions] } : { embeds: [new Embed().setColor("#A52F05").setDescription(`${client.messages.get(message.id).embeds[0].description}\n\n##### ${client.translate.get(db.language, "Events.messageReactionAdd.cooldown")}`)], interactions: [reactions] }).then(async (msg) => { + db.roles.push({ msgId: msg.id, chanId: msg.channelId, roles: [...collector.rolesDone] }); + await client.database.updateGuild(msg.server.id, { roles: db.roles }); + }); + + clearTimeout(client.messageCollector.get(userId).timeout); + return client.messageCollector.delete(userId); + } else return; + } else if (emojiId === client.config.emojis.cross) { + const db = await client.database.getGuild(message.server.id); + client.messageCollector.delete(userId); + return message.reply({ embeds: [new Embed().setColor("#A52F05").setDescription(client.translate.get(db.language, "Events.messageReactionAdd.deleteCollector"))] },); + } else { + if (collector.roles.length === 0) return; + let emote; + if (colors.test(emojiId)) emote = `:${emojiId}:`; + else if (!colors.test(emojiId)) emote = emojiId + collector.rolesDone.push({ emoji: emojiId, role: collector.roles[0][0], name: collector.roles[0][1].name, color: collector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : collector.roles[0][1].colour }); + message.edit(collector.type === "content" ? { content: message.content.replace(`{role:${collector.regex[0]}}`, `${emote} $\\text{\\textcolor{${collector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : collector.roles[0][1].colour}}{${collector.roles[0][1].name}}}$`) } : { embeds: [new Embed().setColor("#A52F05").setDescription(client.messages.get(message.id).embeds[0].description.replace(`{role:${collector.regex[0]}}`, `:${emojiId}: $\\text{\\textcolor{${collector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : collector.roles[0][1].colour}}{${collector.roles[0][1].name}}}$`))] }) + collector.roles.shift(); + return collector.regex.shift(); + } + } else if (editCollector && editCollector.messageId === message.id || editCollector?.botMessage && editCollector?.botMessage === message.id && editCollector.channelId === message.channelId) { + if (emojiId === client.config.emojis.check) { + if (editCollector.roles.length === 0) { + const db = await client.database.getGuild(message.server.id); + message.delete().catch(() => { }); + client.messages.get(editCollector?.oldMessageId)?.delete().catch(() => { }) + client.messages.get(editCollector?.botMessage)?.delete().catch(() => { }) + const reactions = [...editCollector.rolesDone.map(e => e.emoji)]; + message.channel.sendMessage(editCollector.type === "content" ? { content: `${message.content}\n\n##### ${client.translate.get(db.language, "Events.messageReactionAdd.cooldown")}`, interactions: [reactions] } : { embeds: [new Embed().setColor("#A52F05").setDescription(`${client.messages.get(message.id).embeds[0].description}\n\n##### ${client.translate.get(db.language, "Events.messageReactionAdd.cooldown")}`)], interactions: [reactions] }).then(async (msg) => { + db.roles.push({ msgId: msg.id, chanId: msg.channelId, roles: [...editCollector.rolesDone] }); + await client.database.updateGuild(msg.server.id, { roles: db.roles.filter(e => e.msgId !== editCollector.oldMessageId) }); + }); + + clearTimeout(client.messageEdit.get(userId).timeout); + return client.messageEdit.delete(userId); + } else return; + } else if (emojiId === client.config.emojis.cross) { + const db = await client.database.getGuild(message.server.id); + client.messageEdit.delete(userId); + return message.reply({ embeds: [new Embed().setColor("#A52F05").setDescription(client.translate.get(db.language, "Events.messageReactionAdd.deleteCollector"))] },); + } else { + if (editCollector.roles.length === 0) return; + let emote; + if (colors.test(emojiId)) emote = `:${emojiId}:`; + else if (!colors.test(emojiId)) emote = emojiId + editCollector.rolesDone.push({ emoji: emojiId, role: editCollector.roles[0][0], name: editCollector.roles[0][1].name, color: editCollector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : editCollector.roles[0][1].colour }); + message.edit(editCollector.type === "content" ? { content: message.content.replace(`{role:${editCollector.regex[0]}}`, `${emote} $\\text{\\textcolor{${editCollector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : editCollector.roles[0][1].colour}}{${editCollector.roles[0][1].name}}}$`) } : { embeds: [new Embed().setColor("#A52F05").setDescription(client.messages.get(message.id).embeds[0].description.replace(`{role:${editCollector.regex[0]}}`, `:${emojiId}: $\\text{\\textcolor{${editCollector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : editCollector.roles[0][1].colour}}{${editCollector.roles[0][1].name}}}$`))] }) + editCollector.roles.shift(); + return editCollector.regex.shift(); + } + } else if (paginateCheck && paginateCheck.message == message.id) { + let pages = paginateCheck.pages; + let page = paginateCheck.page; + switch (emojiId) { + case "⏪": + if (page !== 0) { + message.edit({ + embeds: [pages[0]] + }).catch(() => { }); + return paginateCheck.page = 0 + } else { + return; + } + case "⬅️": + if (pages[page - 1]) { + message.edit({ + embeds: [pages[--page]] + }).catch(() => { }); + return paginateCheck.page = paginateCheck.page - 1 + } else { + return; + } + case "➡️": + if (pages[page + 1]) { + message.edit({ + embeds: [pages[++page]] + }).catch(() => { }); + return paginateCheck.page = paginateCheck.page + 1 + } else { + return; + } + case "⏩": + if (page !== pages.length) { + message.edit({ + embeds: [pages[pages.length - 1]] + }).catch(() => { }); + return paginateCheck.page = pages.length - 1 + } else { + return; + } + } + } else if (pollCheck) { + let tooMuch = []; + if (pollCheck.poll.options.description.length > 80) tooMuch.push(`**${client.translate.get(pollCheck.lang, "Events.messageReactionAdd.title")}**: ${pollCheck.poll.options.description}`) + pollCheck.poll.voteOptions.name.filter(e => e).forEach((e, i) => { + i++ + if (e.length > 70) { + tooMuch.push(`**${i}.** ${e}`) + } + }); + + let convert = emojis.findIndex(e => e.name === emojiId); + if (convert === 10 && pollCheck.owner === userId) { + await PollDB.findOneAndDelete({ messageId: message.id }); + await pollCheck.poll.update(); + message.edit({ content: `${client.translate.get(pollCheck.lang, "Events.messageReactionAdd.owner")} (<@${pollCheck.owner}>) ${client.translate.get(pollCheck.lang, "Events.messageReactionAdd.end")}:`, embeds: [new Embed().setDescription(tooMuch.length > 0 ? tooMuch.map(e => e).join("\n") : null).setMedia(await client.Uploader.upload(pollCheck.poll.canvas.toBuffer(), `Poll.png`)).setColor("#F24646")] }).catch(() => { }); + return client.polls.delete(message.id); + } else if (convert === 0 && convert !== 10 || convert !== -1 && convert !== 10) { + if (client.reactions.get(userId)) return client.users.get(userId)?.openDM().then(dm => dm.sendMessage(client.translate.get(pollCheck.lang, "Events.messageReactionAdd.tooFast"))).catch(() => { }); + if (pollCheck.users.includes(userId)) return; + pollCheck.users.push(userId); + const user = (client.users.get(userId)) || await client.users.fetch(userId); + // console.log(user.avatar.id ? user.avatar.createFileURL() : 'https://chat.f95.io/api/users/01HATCWS7XZ7KEHW64AV20SMKR/default_avatar') + await pollCheck.poll.addVote(convert, userId, 'https://chat.f95.io/api/users/01HATCWS7XZ7KEHW64AV20SMKR/default_avatar', message.id); + message.edit({ embeds: [new Embed().setDescription(tooMuch.length > 0 ? tooMuch.map(e => e).join("\n") : null).setMedia(await client.Uploader.upload(pollCheck.poll.canvas.toBuffer(), `Poll.png`)).setColor("#A52F05")] }).catch(() => { }); + client.reactions.set(userId, Date.now() + 3000) + return setTimeout(() => client.reactions.delete(userId), 3000) + } else return; + } else { + const db = await Giveaways.findOne({ messageId: message.id }); + if (db) { + if (emojiId === client.config.emojis.confetti && db && !db.ended) { + if (client.reactions.get(userId)) return; + if (db.users.find(u => u.userID === userId)) return; + db.users.push({ userID: userId }); + db.picking.push({ userID: userId }); + db.save(); + + client.reactions.set(userId, Date.now() + 3000) + setTimeout(() => client.reactions.delete(userId), 3000) + + client.users.get(userId)?.openDM().then(dm => dm.sendMessage(`${client.translate.get(db.lang, "Events.messageReactionAdd.joined")} [${db.prize}](https://chat.f95.io/server/${db.serverId}/channel/${db.channelId}/${db.messageId})!\n${client.translate.get(db.lang, "Events.messageReactionAdd.joined2")} **${db.users.length}** ${client.translate.get(db.lang, "Events.messageReactionAdd.joined3")}`)).catch(() => { }); + } else if (emojiId === client.config.emojis.stop && db && db.owner === userId && !db.ended) { + let endDate = Date.now(); + + if (db.users.length === 0) { + const noUsers = new Embed() + .setColor("#A52F05") + .setTitle(client.translate.get(db.lang, "Events.messageReactionAdd.giveaway")) + .setDescription(`${client.translate.get(db.lang, "Events.messageReactionAdd.owner")} (<@${userId}>) ${client.translate.get(db.lang, "Events.messageReactionAdd.early")}\n${client.translate.get(db.lang, "Events.messageReactionAdd.endNone")}!\n\n${client.translate.get(db.lang, "Events.messageReactionAdd.ended")}: \n${client.translate.get(db.lang, "Events.messageReactionAdd.prize")}: ${db.prize}\n${client.translate.get(db.lang, "Events.messageReactionAdd.winnersNone")}${db.requirement ? `\n${client.translate.get(db.lang, "Events.messageReactionAdd.reqs")}: ${db.requirement}` : ``}`) + + await db.updateOne({ ended: true, endDate: endDate }) + await db.save(); + return await client.api.patch(`/channels/${db.channelId}/messages/${db.messageId}`, { "embeds": [noUsers] }); + } + + for (let i = 0; i < db.winners; i++) { + let winner = db.picking[Math.floor(Math.random() * db.picking.length)]; + if (winner) { + const filtered = db.picking.filter(object => object.userID != winner.userID) + db.picking = filtered; + db.pickedWinners.push({ id: winner.userID }) + } + } + + await db.updateOne({ ended: true, endDate: endDate }) + await db.save(); + + const noUsers = new Embed() + .setColor("#A52F05") + .setTitle(client.translate.get(db.lang, "Events.messageReactionAdd.giveaway")) + .setDescription(`${client.translate.get(db.lang, "Events.messageReactionAdd.owner")} (<@${userId}>) ${client.translate.get(db.lang, "Events.messageReactionAdd.early")}\n${client.translate.get(db.lang, "Events.messageReactionAdd.partici")}: ${db.users.length}\n\n${client.translate.get(db.lang, "Events.messageReactionAdd.ended")}: \n${client.translate.get(db.lang, "Events.messageReactionAdd.prize")}: ${db.prize}\n${client.translate.get(db.lang, "Events.messageReactionAdd.winners")}: ${db.pickedWinners.length > 0 ? db.pickedWinners.map(w => `<@${w.id}>`).join(", ") : client.translate.get(db.lang, "Events.messageReactionAdd.none")}${db.requirement ? `\n${client.translate.get(db.lang, "Events.messageReactionAdd.reqs")}: ${db.requirement}` : ``}`) + + message.edit({ embeds: [noUsers] }).catch(() => { }); + await client.api.post(`/channels/${db.channelId}/messages`, { "content": `${client.translate.get(db.lang, "Events.messageReactionAdd.congrats")} ${db.pickedWinners.map(w => `<@${w.id}>`).join(", ")}! ${client.translate.get(db.lang, "Events.messageReactionAdd.youWon")} **[${db.prize}](https://chat.f95.io/server/${db.serverId}/channel/${db.channelId}/${db.messageId})**!` }).catch(() => { }); + client.reactions.set(userId, Date.now() + 3000) + setTimeout(() => client.reactions.delete(userId), 3000) + } + } else { + const db2 = await client.database.getGuild(message.server.id, true) + if (db2 && db2.roles.find(e => e.msgId === message.id) && db2.roles.find(e => e.roles.find(e => e.emoji === emojiId))) { + if (client.reactions.get(userId)) return; + + const roles = []; + db2.roles.find(e => e.msgId === message.id).roles.map(e => roles.push(e)); + const role = roles.find(e => e.emoji === emojiId); + const member = await (client.servers.get(message.server.id) || await client.servers.fetch(message.server.id))?.fetchMember(userId); + if (!member) return; + + let error = false; + let dataRoles = []; + if (member.roles) member.roles.map(e => dataRoles.push(e)); + if (dataRoles.includes(role.role)) return; + + client.reactions.set(userId, Date.now() + 3000); + setTimeout(() => client.reactions.delete(userId), 3000); + + dataRoles.push(role.role); + await member.edit({ roles: dataRoles }).catch(() => { error = true }) + + if (error && db2.dm) { + member?.user?.openDM().then((dm) => { dm.sendMessage(`${client.translate.get(db2.language, "Events.messageReactionAdd.noPerms").replace("{role}", `**${role.name}**`)}!`) }).catch(() => { }); + } else if (db2.dm) { + member?.user?.openDM().then((dm) => { dm.sendMessage(`${client.translate.get(db2.language, "Events.messageReactionAdd.success").replace("{role}", `**${role.name}**`)}!`) }).catch(() => { }); + } + } + } + } +} \ No newline at end of file diff --git a/events/messageReactionRemove.js b/events/messageReactionRemove.js new file mode 100644 index 0000000..5ad5dbf --- /dev/null +++ b/events/messageReactionRemove.js @@ -0,0 +1,100 @@ +const Embed = require("../functions/embed"); +const Giveaways = require("../models/giveaways"); +const emojis = [{ name: "1️⃣", id: 0 }, { name: "2️⃣", id: 1 }, { name: "3️⃣", id: 2 }, { name: "4️⃣", id: 3 }, { name: "5️⃣", id: 4 }, { name: "6️⃣", id: 5 }, { name: "7️⃣", id: 6 }, { name: "8️⃣", id: 7 }, { name: "9️⃣", id: 8 }, { name: "🔟", id: 9 }, { name: "🛑", id: "stop" }] +const colors = /^([A-Z0-9]+)/; + +module.exports = async (client, message, userId, emojiId) => { + const pollCheck = client.polls.get(message.id); + const collector = client.messageCollector.get(userId); + const editCollector = client.messageEdit.get(userId); + + if (collector && collector.messageId === message.id && collector.channelId === message.channelId) { + const emoji = collector.rolesDone.find(e => e.emoji === emojiId); + if (emoji) { + collector.rolesDone = collector.rolesDone.filter(object => object.emoji != emojiId); + collector.roles.push([emoji.role, { name: emoji.name, colour: emoji.color }]); + collector.regex.push(emoji.name); + + if (colors.test(emojiId)) emote = `:${emojiId}:`; + else if (!colors.test(emojiId)) emote = emojiId + return message.edit(collector.type === "content" ? { content: message.content.replace(`${emote} $\\text{\\textcolor{${emoji.color}}{${emoji.name}}}$`, `{role:${emoji.name}}`) } : { embeds: [new Embed().setColor("#A52F05").setDescription(client.messages.get(message.id).embeds[0].description.replace(`{role:${editCollector.regex[0]}}`, `:${emojiId}: $\\text{\\textcolor{${editCollector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : editCollector.roles[0][1].colour}}{${editCollector.roles[0][1].name}}}$`))] }).catch(() => { }); + } + } else if (editCollector && editCollector.messageId === message.id && editCollector.channelId === message.channelId) { + const emoji = editCollector.rolesDone.find(e => e.emoji === emojiId); + if (emoji) { + editCollector.rolesDone = editCollector.rolesDone.filter(object => object.emoji != emojiId); + editCollector.roles.push([emoji.role, { name: emoji.name, colour: emoji.color }]); + editCollector.regex.push(emoji.name); + + if (colors.test(emojiId)) emote = `:${emojiId}:`; + else if (!colors.test(emojiId)) emote = emojiId + return message.edit(editCollector.type === "content" ? { content: message.content.replace(`${emote} $\\text{\\textcolor{${emoji.color}}{${emoji.name}}}$`, `{role:${emoji.name}}`) } : { embeds: [new Embed().setColor("#A52F05").setDescription(client.messages.get(message.id).embeds[0].description.replace(`{role:${editCollector.regex[0]}}`, `:${emojiId}: $\\text{\\textcolor{${editCollector.roles[0][1].colour?.includes("linear-gradient") ? '#000000' : editCollector.roles[0][1].colour}}{${editCollector.roles[0][1].name}}}$`))] }).catch(() => { }); + } + } else if (pollCheck) { + if (client.reactions.get(userId)) return client.users.get(userId)?.openDM().then(dm => dm.sendMessage(client.translate.get(pollCheck.language, "Events.messageReactionRemove.tooFast"))).catch(() => { }); + let convert = emojis.findIndex(e => e.name === emojiId); + if (convert === 0 && convert !== 10 || convert !== -1 && convert !== 10) { + if (!pollCheck.users.includes(userId)) return; + + let tooMuch = []; + if (pollCheck.poll.options.description.length > 80) tooMuch.push(`**${client.translate.get(pollCheck.language, "Events.messageReactionRemove.title")}**: ${pollCheck.poll.options.description}`) + pollCheck.poll.voteOptions.name.filter(e => e).forEach((e, i) => { + i++ + if (e.length > 70) { + tooMuch.push(`**${i}.** ${e}`) + } + }); + + pollCheck.users = pollCheck.users.filter(object => object != userId); + const user = (client.users.get(userId)) || await client.users.fetch(userId); + await pollCheck.poll.removeVote(convert, userId, 'https://chat.f95.io/api/users/01HATCWS7XZ7KEHW64AV20SMKR/default_avatar', message.id); + message.edit({ embeds: [new Embed().setDescription(tooMuch.length > 0 ? tooMuch.map(e => e).join("\n") : null).setMedia(await client.Uploader.upload(pollCheck.poll.canvas.toBuffer(), `Poll.png`)).setColor("#A52F05")] }).catch(() => { }); + client.reactions.set(userId, Date.now() + 3000) + return setTimeout(() => client.reactions.delete(userId), 3000) + } else return; + } else { + if (client.reactions.get(userId)) return; + const db = await Giveaways.findOne({ messageId: message.id }); + if (db && !db.ended) { + if (emojiId === client.config.emojis.confetti) { + if (!db.users.find(u => u.userID === userId)) return; + const filtered = db.users.filter(object => object.userID != userId) + db.users = filtered; + const filtered2 = db.picking.filter(object => object.userID != userId) + db.picking = filtered2; + db.save(); + + client.reactions.set(userId, Date.now() + 3000) + setTimeout(() => client.reactions.delete(userId), 3000) + + client.users.get(userId)?.openDM().then(dm => dm.sendMessage(`${client.translate.get(pollCheck.language, "Events.messageReactionRemove.left")} [${db.prize}](https://chat.f95.io/server/${db.serverId}/channel/${db.channelId}/${db.messageId})!\n${client.translate.get(pollCheck.language, "Events.messageReactionRemove.left2")} **${db.users.length}** ${client.translate.get(pollCheck.language, "Events.messageReactionRemove.left")}!`)).catch(() => { }); + } + } else { + const db2 = await client.database.getGuild(message.server.id, true) + if (db2 && db2.roles.find(e => e.msgId === message.id) && db2.roles.find(e => e.roles.find(e => e.emoji === emojiId))) { + const roles = []; + db2.roles.find(e => e.msgId === message.id).roles.map(e => roles.push(e)); + const role = roles.find(e => e.emoji === emojiId); + const member = await (client.servers.get(message.server.id) || await client.servers.fetch(message.server.id))?.fetchMember(userId); + if (!member) return; + + let error = false; + let dataRoles = []; + if (member.roles) member.roles.map(e => dataRoles.push(e)); + if (!dataRoles.includes(role.role)) return; + + client.reactions.set(userId, Date.now() + 3000); + setTimeout(() => client.reactions.delete(userId), 3000); + + dataRoles = dataRoles.filter(object => object != role.role); + await member.edit({ roles: dataRoles }).catch(() => { error = true }) + + if (error) { + if (db2.dm) member?.user?.openDM().then((dm) => { dm.sendMessage(`${client.translate.get(db2.language, "Events.messageReactionRemove.noPerms").replace("{role}", `**${role.name}**`)}!`) }).catch(() => { }); + } else { + if (db2.dm) member?.user?.openDM().then((dm) => { dm.sendMessage(`${client.translate.get(db2.language, "Events.messageReactionRemove.success").replace("{role}", `**${role.name}**`)}!`) }).catch(() => { }); + } + } + } + } +} \ No newline at end of file diff --git a/events/serverCreate.js b/events/serverCreate.js new file mode 100644 index 0000000..8d3f0c5 --- /dev/null +++ b/events/serverCreate.js @@ -0,0 +1,12 @@ +const Embed = require("../functions/embed") +module.exports = async (client, server) => { + //console.log("join", server) + // await client.database.getGuild(server.id, true) + + // const embed = new Embed() + // .setColor("#A52F05") + // .setTitle(server.name || "Unknown") + // .setDescription(`**Owner**: ${server.ownerId}\n**Discoverable**: ${server.discoverable ? "true" : "false"}\n**Created**: \n**ID**: ${server.id}`) + + // await client.api.post(`/channels/01H1KQ4GVP96MEHA95YT2F0NT4/messages`, { embeds: [embed] }).catch(() => { }) +} \ No newline at end of file diff --git a/events/serverDelete.js b/events/serverDelete.js new file mode 100644 index 0000000..e4dde77 --- /dev/null +++ b/events/serverDelete.js @@ -0,0 +1,13 @@ +const Embed = require("../functions/embed") +module.exports = async (client, server) => { + //console.log("delete",server) + // await client.database.deleteGuild(server.id) + + // const embed = new Embed() + // .setColor("#FF0000") + // .setTitle(server.name || "Unknown") + // .setIcon(server.icon ? `https://autumn.revolt.chat/icons/${server.icon._id}/${server.icon.filename}` : null) + // .setDescription(`**Owner**: ${server.ownerId}\n**Discoverable**: ${server.discoverable ? "true" : "false"}\n**Created**: \n**ID**: ${server.id}`) + + // await client.api.post(`/channels/01H1KQ4GVP96MEHA95YT2F0NT4/messages`, { embeds: [embed] }) +} \ No newline at end of file diff --git a/events/serverMemberUpdate.js b/events/serverMemberUpdate.js new file mode 100644 index 0000000..18f5a6d --- /dev/null +++ b/events/serverMemberUpdate.js @@ -0,0 +1,17 @@ +let type; +module.exports = async (client, member, memberOld) => { + // Work in progress + if (member.roles > memberOld.roles && member.id.user === client.user.id) type = "add" + else if (member.roles < memberOld.roles) type = "remove" + else return; + + switch (type) { + case "add": + let channel = await client.channels.fetch() + break; + + case "remove": + + break; + } +} \ No newline at end of file diff --git a/functions/audit.js b/functions/audit.js new file mode 100644 index 0000000..ba48964 --- /dev/null +++ b/functions/audit.js @@ -0,0 +1,12 @@ +const db = require("../models/logging"); + +async function audit(type, message, cmd) { + const audit = new db(); + audit.ranBy = message.member.user.username; + audit.name = cmd; + audit.type = type; + audit.channel = message.channel.name; + audit.save() +} + +module.exports = audit; \ No newline at end of file diff --git a/functions/checkPolls.js b/functions/checkPolls.js new file mode 100644 index 0000000..3618366 --- /dev/null +++ b/functions/checkPolls.js @@ -0,0 +1,24 @@ +const db = require("../models/polls"); +const Polls = require("./poll"); +async function checkPolls(client) { + let polls = await db.find(); + if (!polls || polls.length === 0) return; + let i = 0; + for (let poll of polls) { + i++ + setTimeout(async () => { + const time = poll.now - (Date.now() - poll.time), users = poll.users, avatars = poll.avatars, votes = poll.votes, desc = poll.desc, name = poll.name, names = poll.options, owner = poll.owner, lang = poll.lang; + const newPoll = new Polls({ time, client, name: { name: name, description: desc }, options: names, votes: votes, users: users, avatars: avatars, owner: owner, lang: lang }) + + try { + await client.channels.get(poll.channelId).fetchMessage(poll.messageId).catch(() => { return }); + const msg = await client.messages.get(poll.messageId); + if (msg) newPoll.start(msg, newPoll); + } catch (e) { } + + poll.deleteOne({ messageId: poll.messageId }); + }, i * 700); + } +} + +module.exports = checkPolls; \ No newline at end of file diff --git a/functions/checkRoles.js b/functions/checkRoles.js new file mode 100644 index 0000000..9fa1c4a --- /dev/null +++ b/functions/checkRoles.js @@ -0,0 +1,24 @@ +const db = require("../models/guilds"); +async function checkRoles(client) { + let rr = await db.find({ $expr: { $gt: [{ $size: "$roles" }, 0] } }); + if (!rr || rr.length === 0) return; + let i = 0; + let ii = 0; + for (let r of rr) { + i++ + setTimeout(async () => { + r.roles.map((role) => { + ii++ + setTimeout(async () => { + if (!client.channels.get(role.chanId) && role.roles.length === 0) { + return await client.database.updateGuild(r.id, { roles: r.roles.filter(e => e.msgId !== role.msgId) }); + } + + await client.channels.get(role.chanId)?.fetchMessage(role.msgId).catch(() => { }); + }, ii * 700); + }); + }, i * 600); + } +} + +module.exports = checkRoles; \ No newline at end of file diff --git a/functions/colorCodes.js b/functions/colorCodes.js new file mode 100644 index 0000000..c2d6977 --- /dev/null +++ b/functions/colorCodes.js @@ -0,0 +1,26 @@ +function colors(altColorChar, textToTranslate) { + const colorMap = { + [`${altColorChar}0`]: '\x1b[30m', // Black + [`${altColorChar}1`]: '\x1b[34m', // Dark Blue + [`${altColorChar}2`]: '\x1b[32m', // Dark Green + [`${altColorChar}3`]: '\x1b[36m', // Dark Aqua + [`${altColorChar}4`]: '\x1b[31m', // Dark Red + [`${altColorChar}5`]: '\x1b[35m', // Dark Purple + [`${altColorChar}6`]: '\x1b[33m', // Gold + [`${altColorChar}7`]: '\x1b[37m', // Gray + [`${altColorChar}8`]: '\x1b[90m', // Dark Gray + [`${altColorChar}9`]: '\x1b[94m', // Blue + [`${altColorChar}a`]: '\x1b[92m', // Green + [`${altColorChar}b`]: '\x1b[96m', // Aqua + [`${altColorChar}c`]: '\x1b[91m', // Red + [`${altColorChar}d`]: '\x1b[95m', // Light Purple + [`${altColorChar}e`]: '\x1b[93m', // Yellow + [`${altColorChar}f`]: '\x1b[97m', // White + [`${altColorChar}r`]: '\x1b[0m', // Reset + }; + + const regex = new RegExp(`${altColorChar}([0-9a-fr])`, 'g'); + return textToTranslate.replace(regex, (match, code) => colorMap[`${altColorChar}${code}`] || ''); +}; + +module.exports = colors; diff --git a/functions/dhms.js b/functions/dhms.js new file mode 100644 index 0000000..69239f3 --- /dev/null +++ b/functions/dhms.js @@ -0,0 +1,11 @@ +function dhms(str, sec = false) { + const x = sec ? 1 : 1000; + if (typeof str !== 'string') return 0; + const fixed = str.replace(/\s/g, ''); + const tail = +fixed.match(/-?\d+$/g) || 0; + const parts = (fixed.match(/-?\d+[^-0-9]+/g) || []) + .map(v => +v.replace(/[^-0-9]+/g, '') * ({ s: x, m: 60 * x, h: 3600 * x, d: 86400 * x }[v.replace(/[-0-9]+/g, '')] || 0)); + return [tail, ...parts].reduce((a, b) => a + b, 0); +}; + +module.exports = dhms; \ No newline at end of file diff --git a/functions/embed.js b/functions/embed.js new file mode 100644 index 0000000..780caab --- /dev/null +++ b/functions/embed.js @@ -0,0 +1,69 @@ +class Embed { + url = null; + title = null; + description = null; + image = null; + icon_url = null; + color = null; + thumbnail = null; + media = null; + +constructor(data) { + Object.assign(this, data) +} + +setTitle(title) { + this.title = title + return this +} + +setMedia(media) { + this.media = media + return this +} + +setIcon(iconURL) { + this.icon_url = iconURL + return this +} + +setColor(color) { + this.color = color + return this +} + +setImage(image) { + this.image = image + return this +} + +setThumbnail(thumbnail) { + this.thumbnail = thumbnail + return this +} + +setDescription(description) { + this.description = description + return this +} + +setURL(url) { + this.url = url + return this +} + +toJSON() { + return { + title: this.title, + description: this.description, + url: this.url, + icon_url: this.icon_url, + image: this.image, + thumbnail: this.thumbnail, + colour: this.color, + media: this.media + } +} +} + +module.exports = Embed; \ No newline at end of file diff --git a/functions/fetchTime.js b/functions/fetchTime.js new file mode 100644 index 0000000..a8d40b3 --- /dev/null +++ b/functions/fetchTime.js @@ -0,0 +1,16 @@ +function fetchTime(ms, client, lang) { + var totalSeconds = (ms / 1000); + let years = Math.floor(totalSeconds / 31536000); + totalSeconds %= 31536000; + let days = Math.floor(totalSeconds / 86400); + totalSeconds %= 86400; + let hours = Math.floor(totalSeconds / 3600); + totalSeconds %= 3600; + let minutes = Math.floor(totalSeconds / 60); + let seconds = totalSeconds % 60; + seconds = Math.floor(seconds); + + return `${years ? `${years} ${client.translate.get(lang, "Functions.fetchTime.years")},` : ""} ${days ? `${days} ${client.translate.get(lang, "Functions.fetchTime.days")},` : ""} ${hours ? `${hours} ${client.translate.get(lang, "Functions.fetchTime.hours")},` : ""} ${minutes ? `${minutes} ${client.translate.get(lang, "Functions.fetchTime.minutes")},` : ""} ${seconds} ${client.translate.get(lang, "Functions.fetchTime.seconds")}`; +} + +module.exports = fetchTime; \ No newline at end of file diff --git a/functions/logger.js b/functions/logger.js new file mode 100644 index 0000000..23f332d --- /dev/null +++ b/functions/logger.js @@ -0,0 +1,85 @@ +/** + * base code taken from https://github.com/Mirasaki/logger + */ + +const chalk = require('chalk'), + moment = require('moment'); + +const tagList = { + SYSLOG: chalk.greenBright('[SYSLOG]'), + SYSERR: chalk.redBright('[SYSERR]'), + SUCCESS: chalk.greenBright('[SUCCESS]'), + INFO: chalk.blueBright('[INFO]'), + DEBUG: chalk.magentaBright('[DEBUG]'), + DATA: chalk.yellowBright('[DATA]'), + COMMAND: chalk.whiteBright('[CMD]'), + EVENT: chalk.cyanBright('[EVENT]'), + ERROR: chalk.redBright('[EVENT]'), + WARN: chalk.yellowBright('[WARN]') +}; + +const longestTagLength = Math.max(...Object.values(tagList).map(t => t.length)); +const getTag = (tag) => `${tagList[tag]}${''.repeat(longestTagLength - tagList[tag].length)}`; +const timestamp = () => `${chalk.whiteBright.bold(`[${moment.utc().format('YYYY-MM-DD HH:mm:ss')}]`)}`; + +module.exports = { + syslog: (type, str) => console.info(`${timestamp()} ${type ? `${getTag('SYSLOG')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('SYSLOG')}:`} ${str}`), + syserr: (type, str) => console.error(`${timestamp()} ${type ? `${getTag('SYSERR')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('SYSERR')} :`} ${str}`), + success: (type, str) => console.log(`${timestamp()} ${type ? `${getTag('SUCCESS')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('SUCCESS')}:`} ${str}`), + info: (type, str) => console.info(`${timestamp()} ${type ? `${getTag('INFO')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('INFO')}:`} ${str}`), + debug: (type, str) => console.log(`${timestamp()} ${type ? `${getTag('DEBUG')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('DEBUG')}:`} ${str}`), + data: (type, str) => console.log(`${timestamp()} ${type ? `${getTag('DATA')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('DATA')}:`} ${str}`), + command: (type, str) => console.log(`${timestamp()} ${type ? `${getTag('COMMAND')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('COMMAND')}:`} ${str}`), + event: (type, str) => console.log(`${timestamp()} ${type ? `${getTag('EVENT')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('EVENT')}:`} ${str}`), + error: (type, str) => console.log(`${timestamp()} ${type ? `${getTag('ERROR')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('ERROR')}:`} ${str}`), + warn: (type, str) => console.log(`${timestamp()} ${type ? `${getTag('WARN')} ${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : `${getTag('WARN')}:`} ${str}`), + + startLog: (identifier) => console.log(`${timestamp()} ${getTag('DEBUG')} ${chalk.greenBright('[START]')} ${identifier}`), + endLog: (identifier) => console.log(`${timestamp()} ${getTag('DEBUG')} ${chalk.redBright('[ END ]')} ${identifier}`), + + timestamp, + getExecutionTime: (hrtime) => { + const timeSinceHrMs = ( + process.hrtime(hrtime)[0] * 1000 + + hrtime[1] / 1000000 + ).toFixed(2); + return `${chalk.yellowBright( + (timeSinceHrMs / 1000).toFixed(2)) + } seconds (${chalk.yellowBright(timeSinceHrMs)} ms)`; + }, + + printErr: (err) => { + if (!(err instanceof Error)) { + console.error(err) + return; + } + + console.error( + !err.stack + ? chalk.red(err) + : err.stack + .split('\n') + .map((msg, index) => { + if (index === 0) { + return chalk.red(msg); + } + + const isFailedFunctionCall = index === 1; + const traceStartIndex = msg.indexOf('('); + const traceEndIndex = msg.lastIndexOf(')'); + const hasTrace = traceStartIndex !== -1; + const functionCall = msg.slice( + msg.indexOf('at') + 3, + hasTrace ? traceStartIndex - 1 : msg.length + ); + const trace = msg.slice(traceStartIndex, traceEndIndex + 1); + + return ` ${chalk.grey('at')} ${isFailedFunctionCall + ? `${chalk.redBright(functionCall)} ${chalk.red.underline(trace)}` + : `${chalk.greenBright(functionCall)} ${chalk.grey(trace)}` + }`; + }) + .join('\n') + ) + } +}; \ No newline at end of file diff --git a/functions/members.js b/functions/members.js new file mode 100644 index 0000000..a79dff7 --- /dev/null +++ b/functions/members.js @@ -0,0 +1,26 @@ +async function Members(client, server) { + if (typeof client !== 'object') return { + error: true, + msg: 'First argument isn\'t available or a valid client!' + }; + if (typeof server !== 'string') return { + error: true, + msg: 'Second argument isn\'t available or a valid serverID string!' + }; + + try { + const member = await client.api.get(`/servers/${server}/members`) + return { + error: false, + users: member.users, + members: member.members + }; + } catch { + return { + error: true, + msg: "Unknown Server" + } + } +} + +module.exports = Members; \ No newline at end of file diff --git a/functions/messageCollector.js b/functions/messageCollector.js new file mode 100644 index 0000000..5c41fe2 --- /dev/null +++ b/functions/messageCollector.js @@ -0,0 +1,72 @@ +const Embed = require("../functions/embed"); +async function Collector(client, message, db) { + const regex = /{role:(.*?)}/; + const regexAll = /{role:(.*?)}/g; + const collector = client.messageCollector.get(message.authorId); + if (!message.content.match(regexAll) || message.content.match(regexAll)?.length === 0) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.noRoles")}: \`{role:Red}\``)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + const roles = message.content.match(regexAll).map((r) => r?.match(regex)[1]); + if (roles.length > 20) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(client.translate.get(db.language, "Events.messageCreate.maxRoles"))] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + collector.regex = roles + const roleIds = [] + let newRoles = roles.map((r) => { + return [...message.server.roles].map((r) => r).find((role) => r.toLowerCase() === role[1]?.name?.toLowerCase()); + }) + newRoles.map((r) => roleIds.push(r)); + + if (roleIds.map((r) => !r).includes(true)) { + let unknown = []; + roleIds.map((r, i) => { + i++ + if (!r) { + unknown.push(roles[i - 1]); + } + }); + + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.unknown")}\n${unknown.map(e => `\`{role:${e}}\``).join(", ")}`)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + let duplicate = []; + roleIds.map((r, i) => { + i++ + if (roleIds.filter(e => e[0] === r[0]).length > 1) duplicate.push(roleIds[i - 1]); + }); + + if (duplicate.length > 0) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.duplicate")}\n${duplicate.map(e => `\`{role:${e[1].name}}\``)}`)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + let positions = []; + const botRole = message.channel.server.member.orderedRoles.reverse()[0] + if (!botRole) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(client.translate.get(db.language, "Events.messageCreate.noBotRole"))] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + roleIds.map((r, i) => { + i++ + if (r[1].rank <= botRole.rank) positions.push(roleIds[i - 1]) + }); + + if (positions.length > 0) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.positions")}\n${positions.map(e => `\`{role:${e[1].name}}\``)}`)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + message.delete().catch(() => { }); + collector.roles = roleIds; + const react = [client.config.emojis.check]; + return message.channel.sendMessage(collector.type === "content" ? { content: message.content, interactions: [react] } : { embeds: [new Embed().setDescription(message.content).setColor("#A52F05")], interactions: [react] }).then((msg) => { + collector.messageId = msg.id; + }); +} + +module.exports = Collector; \ No newline at end of file diff --git a/functions/messageEdit.js b/functions/messageEdit.js new file mode 100644 index 0000000..14f3a49 --- /dev/null +++ b/functions/messageEdit.js @@ -0,0 +1,72 @@ +const Embed = require("../functions/embed"); +async function Collector(client, message, db) { + const regex = /{role:(.*?)}/; + const regexAll = /{role:(.*?)}/g; + const collector = client.messageEdit.get(message.authorId); + if (!message.content.match(regexAll) || message.content.match(regexAll)?.length === 0) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.noRoles")}: \`{role:Red}\``)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + const roles = message.content.match(regexAll).map((r) => r?.match(regex)[1]); + if (roles.length > 20) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(client.translate.get(db.language, "Events.messageCreate.maxRoles"))] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + collector.regex = roles + const roleIds = [] + let newRoles = roles.map((r) => { + return [...message.server.roles].map((r) => r).find((role) => r.toLowerCase() === role[1]?.name?.toLowerCase()); + }) + newRoles.map((r) => roleIds.push(r)); + + if (roleIds.map((r) => !r).includes(true)) { + let unknown = []; + roleIds.map((r, i) => { + i++ + if (!r) { + unknown.push(roles[i - 1]); + } + }); + + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.unknown")}\n${unknown.map(e => `\`{role:${e}}\``).join(", ")}`)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + let duplicate = []; + roleIds.map((r, i) => { + i++ + if (roleIds.filter(e => e[0] === r[0]).length > 1) duplicate.push(roleIds[i - 1]); + }); + + if (duplicate.length > 0) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.duplicate")}\n${duplicate.map(e => `\`{role:${e[1].name}}\``)}`)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + let positions = []; + const botRole = message.channel.server.member.orderedRoles.reverse()[0] + if (!botRole) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(client.translate.get(db.language, "Events.messageCreate.noBotRole"))] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + roleIds.map((r, i) => { + i++ + if (r[1].rank <= botRole.rank) positions.push(roleIds[i - 1]) + }); + + if (positions.length > 0) { + message.reply({ embeds: [new Embed().setColor("#FF0000").setDescription(`${client.translate.get(db.language, "Events.messageCreate.positions")}\n${positions.map(e => `\`{role:${e[1].name}}\``)}`)] }, false).catch(() => { return }); + return message.react(client.config.emojis.cross).catch(() => { return }); + } + + message.delete().catch(() => { }); + collector.roles = roleIds; + const react = [client.config.emojis.check]; + return message.channel.sendMessage(collector.type === "content" ? { content: message.content, interactions: [react] } : { embeds: [new Embed().setDescription(message.content).setColor("#A52F05")], interactions: [react] }).then((msg) => { + collector.messageId = msg.id; + }); +} + +module.exports = Collector; \ No newline at end of file diff --git a/functions/pagination.js b/functions/pagination.js new file mode 100644 index 0000000..7509ec1 --- /dev/null +++ b/functions/pagination.js @@ -0,0 +1,29 @@ +class Paginator { + constructor({ user, client, timeout }) { + this.pages = []; + this.client = client; + this.user = user; + this.page = 0; + this.timeout = timeout; + } + + add(page) { + if (page.length) { + page.forEach((x) => { this.pages.push(x) }); + return this; + } + this.pages.push(page); + return this; + } + + async start(channel) { + if (!this.pages.length) return; + const reactions = ["⏪", "⬅️", "➡️", "⏩"]; + this.pages.forEach((e, i=0) => { e.description = `${e.description}\n\nPage ${i+1} / ${this.pages.length}` }) + const message1 = await channel.sendMessage({ embeds: [this.pages[0]], interactions: { reactions } }); + this.client.paginate.set(this.user, { pages: this.pages, page: this.page, message: message1.id }); + setTimeout(() => { if (this.client.paginate.get(this.user)) this.client.paginate.delete(this.user) }, this.timeout); + } +} + +module.exports = Paginator; \ No newline at end of file diff --git a/functions/poll.js b/functions/poll.js new file mode 100644 index 0000000..9a49c70 --- /dev/null +++ b/functions/poll.js @@ -0,0 +1,250 @@ +const PollDB = require("../models/polls"); +const Embed = require("./embed"); +const Canvas = require('canvas'); +const format = `${(new Date().getMonth() + 1) < 10 ? `0${new Date().getMonth() + 1}` : new Date().getMonth() + 1}/${new Date().getDate()}/${new Date().getFullYear()} ${new Date().getHours()}:${(new Date().getMinutes() < 10 ? '0' : '') + new Date().getMinutes()}`; +class Polls { + constructor({ time, client, name, options, users, avatars, votes, owner, lang }) { + this.client = client; + this.time = time; + if (votes) this.votes = votes; + else this.votes = options.name.length === 2 ? [0, 0] : options.name.length === 3 ? [0, 0, 0] : options.name.length === 4 ? [0, 0, 0, 0] : options.name.length === 5 ? [0, 0, 0, 0, 0] : options.name.length === 6 ? [0, 0, 0, 0, 0, 0] : options.name.length === 7 ? [0, 0, 0, 0, 0, 0, 0] : options.name.length === 8 ? [0, 0, 0, 0, 0, 0, 0, 0] : options.name.length === 9 ? [0, 0, 0, 0, 0, 0, 0, 0, 0] : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + this.users = users || []; + this.avatars = avatars || []; + this.options = { name: name.name, description: name.description }; + this.voteOptions = options; + this.owner = owner; + this.lang = lang; + this.size = { canvas: options.name.length === 2 ? 200 : options.name.length === 3 ? 250 : options.name.length === 4 ? 300 : options.name.length === 5 ? 350 : options.name.length === 6 ? 400 : options.name.length === 7 ? 450 : options.name.length === 8 ? 500 : options.name.length === 9 ? 550 : 600, bar: options.name.length === 2 ? 150 : options.name.length === 3 ? 200 : options.name.length === 4 ? 250 : options.name.length === 5 ? 300 : options.name.length === 6 ? 350 : options.name.length === 7 ? 400 : options.name.length === 8 ? 450 : options.name.length === 9 ? 500 : 550 }; + } + + async start(message, poll) { + this.client.polls.set(message.id, { poll, messageId: message.id, users: this.users, owner: this.owner, lang: this.lang }) + setTimeout(async () => { + if (!this.client.polls.get(message.id)) return; + await this.update(); + message.edit({ embeds: [new Embed().setMedia(await this.client.Uploader.upload(poll.canvas.toBuffer(), `Poll.png`)).setColor(`#F24646`)], content: this.client.translate.get(this.lang, "Functions.poll.end") }).catch(() => { }) + this.client.polls.delete(message.id); + await PollDB.findOneAndDelete({ messageId: message.id }); + }, this.time); + + if (this.time < 0) return; + await (new PollDB({ + owner: this.owner, + channelId: message.channelId, + messageId: message.id, + avatars: this.avatars, + users: this.users, + votes: this.votes, + name: this.options.name, + desc: this.options.description, + options: this.voteOptions, + time: this.time, + lang: this.lang, + now: Date.now(), + }).save()); + } + + textHeight(text, ctx, m) { + let metrics = m || ctx.measureText(text); + return metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; + } + + roundRect(ctx, x, y, width, height, radius, fill, stroke) { // Credit to https://stackoverflow.com/users/227299/juan-mendes + if (typeof stroke === 'undefined') { + stroke = true; + } + if (typeof radius === 'undefined') { + radius = 5; + } + if (typeof radius === 'number') { + radius = { tl: radius, tr: radius, br: radius, bl: radius }; + } else { + var defaultRadius = { tl: 0, tr: 0, br: 0, bl: 0 }; + for (var side in defaultRadius) { + radius[side] = radius[side] || defaultRadius[side]; + } + } + ctx.beginPath(); + ctx.moveTo(x + radius.tl, y); + ctx.lineTo(x + width - radius.tr, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr); + ctx.lineTo(x + width, y + height - radius.br); + ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height); + ctx.lineTo(x + radius.bl, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl); + ctx.lineTo(x, y + radius.tl); + ctx.quadraticCurveTo(x, y, x + radius.tl, y); + ctx.closePath(); + if (fill) { + ctx.fill(); + } + if (stroke) { + ctx.stroke(); + } + } + + async update() { + let roundRect = this.roundRect; + let textHeight = this.textHeight; + + var width = 600, height = this.size.canvas, padding = 10; + const canvas = Canvas.createCanvas(width, height); + this.canvas = canvas; + const ctx = this.canvas.getContext('2d'); + this.ctx = ctx; + + let name = this.options.name?.length > 70 ? this.options?.name.slice(0, 67) + "..." : this.options.name; + var nameHeight = textHeight(name, ctx); + + let description = this.options.description.length > 80 ? this.options.description.slice(0, 77) + "..." : this.options.description; + var descHeight = textHeight(description, ctx); + + ctx.fillStyle = "#23272A"; + roundRect(ctx, 0, 0, width, height, 5, true, false); // background + + ctx.fillStyle = "#4E535A"; + ctx.font = `normal 12px Sans-Serif`; + ctx.fillText(name, padding, padding + 2 + nameHeight / 2); // name + + ctx.fillStyle = "#FFFFFF"; + ctx.font = `normal 17px Sans-Serif`; + ctx.fillText(description, padding, padding + 15 + nameHeight + descHeight / 2); // description + + var headerHeight = padding + descHeight + nameHeight + 15; + var dataWidth = width - padding * 2; + var barHeight = 40; + var votes = this.votes; + var names = this.voteOptions.name; + + this.drawVoteBars(ctx, dataWidth - 20, barHeight, votes, { pad: padding, hHeight: headerHeight }, names); + await this.drawFooter(ctx, padding, padding + headerHeight + barHeight * 2 + 20, width, height, padding, this.avatars); + } + + async addVote(option, user, avatar, id) { + if (this.avatars.length === 6) this.avatars.shift(); + this.avatars.push(avatar); + this.votes[option]++; + await PollDB.findOneAndUpdate({ messageId: id }, { $push: { users: user, avatars: avatar }, $inc: { [`votes.${option}`]: 1 } }); + await this.update(); + return this.canvas; + } + + async removeVote(option, user, avatar, id) { + this.avatars.splice(this.avatars.indexOf(avatar), 1); + this.votes[option]--; + await PollDB.findOneAndUpdate({ messageId: id }, { $pull: { users: user, avatars: avatar }, $inc: { [`votes.${option}`]: -1 } }); + await this.update(); + return this.canvas; + } + + drawVoteBars(ctx, width, height, votes, vars, names, vote) { + let roundRect = this.roundRect; + let textHeight = this.textHeight; + let padding = vars.pad; + let headerHeight = vars.hHeight; + let sum = votes.reduce((prev, curr) => prev + curr); + let percentages = votes.map((v) => Math.floor(v / (sum / 100) * 10) / 10); + ctx.save(); + ctx.translate(padding, padding + headerHeight); + + var barPadding = 5; + percentages.forEach((percentage, i) => { + if (!percentage) percentage = 0; + let paddingLeft = (vote != undefined) ? 30 : 0; + + ctx.fillStyle = "#2C2F33"; + let y = (height + 10) * i; + roundRect(ctx, 20, y, width, height, 5, true, false); // full bar + + if (vote == i || percentage) { ctx.fillStyle = "#A52F05"; } + else { ctx.fillStyle = "#24282B"; } // percentage display + roundRect(ctx, 20, y, width * (votes[i] / (sum / 100) / 100), height, 5, true, false); + + ctx.fillStyle = "#4E535A"; + let h = textHeight(i + 1, ctx); + ctx.fillText(i + 1, 0, y + height / 2 + h / 2); + + ctx.fillStyle = "#FFFFFF"; // Option names + h = textHeight(names[i], ctx); + ctx.fillText(names[i].length > 65 ? names[i].slice(0, 62) + "..." : names[i], 30 + paddingLeft, y + 13 + h); + + if (vote != undefined) { + ctx.strokeStyle = "#FFFFFF"; // selection circle + ctx.fillStyle = "#717cf4"; + ctx.beginPath(); + ctx.arc(35, y + 10 + h * 0.75, 6, 0, 2 * Math.PI); + ctx.closePath(); + ctx.stroke(); + if (vote == i) { + ctx.beginPath(); + ctx.arc(35, y + 10 + h * 0.75, 3, 0, 2 * Math.PI); + ctx.closePath(); + ctx.fill(); + } + } + + ctx.fillStyle = "#2C2F33"; // percentage and vote count background + let metrics = ctx.measureText(percentage + "% (" + votes[i] + ")"); + let w = metrics.width; + h = textHeight(percentage + "% (" + votes[i] + ")", ctx, metrics); + y = y + (height - h - barPadding * 2) + barPadding * 2.6; + if (vote == i || vote == undefined) roundRect(ctx, width - barPadding - w - 3, y - h - 4, w + 5, h + 12, 5, true, false); + + ctx.fillStyle = "#A52F05"; // percentage and vote count + ctx.fillText(percentage + "% (" + votes[i] + ")", width - barPadding - w, y); + }); + ctx.restore(); + } + + async drawFooter(ctx, x, y, width, height, padding, users) { + ctx.save(); + ctx.translate(10, this.size.bar); + + var rad = 18; + ctx.fillStyle = "#4E535A"; + ctx.lineWidth = 2; + ctx.strokeStyle = "#4E535A"; + ctx.beginPath(); + ctx.moveTo(0 - padding, 0); + ctx.lineTo(width, 0); + ctx.stroke(); + + let votes = (this.votes.reduce((p, c) => p + c) == 1) ? `${this.votes.reduce((p, c) => p + c)} vote` : `${this.votes.reduce((p, c) => p + c)} votes`; + let metrics = ctx.measureText(votes); + let h = this.textHeight(votes, ctx, metrics); + ctx.fillText(votes, 5, rad + h); + + // Avatars + var pos = rad * users.length + 10 + metrics.width; + var yPos = 6; + users.reverse(); + for (let i = 0; i < users.length; i++) { + ctx.beginPath(); + let user = users[i]; + + const a = Canvas.createCanvas(rad * 2, rad * 2); + const context = a.getContext("2d"); + + context.beginPath(); + context.arc(rad, rad, rad, 0, Math.PI * 2, true); + context.closePath(); + context.clip(); + + const avatar = await Canvas.loadImage(user); + context.drawImage(avatar, 0, 0, rad * 2, rad * 2); + ctx.drawImage(a, pos, yPos); + + ctx.closePath(); + pos -= rad; + } + + // Date + let date = format; + metrics = ctx.measureText(date); + h = this.textHeight(date, ctx, metrics); + ctx.fillText(date, width - 15 - metrics.width, rad + h); + ctx.restore(); + } +} + +module.exports = Polls; \ No newline at end of file diff --git a/functions/randomStr.js b/functions/randomStr.js new file mode 100644 index 0000000..32bf9ed --- /dev/null +++ b/functions/randomStr.js @@ -0,0 +1,60 @@ +const crypt = require("crypto"); +// const FlakeId = require('flakeid'); + +module.exports = { + /** + * Generates a unique ID + * @returns {string} 12-character base64 ID + */ + generateUniqueId: () => crypt.randomBytes(9) + .toString('base64') + .replace(/[/+]/g, c => c === '/' ? '_' : '-') + .slice(0, 12), + + /** + * + * @param {number} len How long to set character length + * @returns alphanumeric string + */ + random: function random(len) { + len = len || 64; + return crypt.randomBytes(len).toString("hex"); + }, + + // snowflake: function snowflake() { + + // const flake = new FlakeId({ + // mid: 64, + // timeOffset: 1431669781, + // }); + + // return flake.gen(); + // }, + + shortid: function shortid() { + let str = Buffer.from(crypt.randomUUID()).toString('base64'); + let n = 12; + + return (str.length > n) ? str.substr(0, n - 1) : str + }, + + truncate: function truncate(str, n) { + return (str.length > n) ? str.substr(0, n - 1) : str; + }, + + randomNum: function (len1) { + const len2 = len1 || 17; + const { customAlphabet } = require('nanoid') + const nanoid = customAlphabet('1234567890', len2) + return nanoid(); + }, + + isJson: function (str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + } +}; diff --git a/functions/reload.js b/functions/reload.js new file mode 100644 index 0000000..339423d --- /dev/null +++ b/functions/reload.js @@ -0,0 +1,49 @@ +function Reload(client, category, name) { + if (category === "events") { + if (!name) return 'Provide an event name to reload!' + try { + const evtName = name; + delete require.cache[require.resolve(`../events/${name}.js`)]; + const pull = require(`../events/${name}`); + + client.off(evtName, typeof client._events[evtName] == 'function' ? client._events[evtName] : client._events[evtName][0]) + client.event.delete(evtName) + + client.on(evtName, pull.bind(null, client)) + client.event.set(evtName, pull.bind(null, client)) + } catch (e) { + return `Couldn't reload: **${category}/${name}**\n**Error**: ${e.message}` + } + return `Reloaded event: **${name}**.js` + } + + if (category === "functions") { + if (!name) return 'Provide a function name to reload!' + try { + const evtName = name; + delete require.cache[require.resolve(`../functions/${name}.js`)]; + const pull = require(`../functions/${name}`); + + client.functions.delete(evtName) + client.functions.set(evtName, pull) + } catch (e) { + return `Couldn't reload: **functions/${name}**\n**Error**: ${e.message}` + } + return `Reloaded function: **${name}**.js` + } + + try { + if (!category) return 'Provide a command name to reload!' + delete require.cache[require.resolve(`../commands/${category}.js`)]; + const pull = require(`../commands/${category}.js`); + if (client.commands.get(category).config.aliases) client.commands.get(category).config.aliases.forEach(a => client.aliases.delete(a)); + client.commands.delete(category); + client.commands.set(category, pull); + if (client.commands.get(category).config.aliases) client.commands.get(category).config.aliases.forEach(a => client.aliases.set(a, category)); + return `Reloaded command: **commands/${category}**.js` + } catch (e) { + return `Couldn't reload: **commands/${category}**\n**Error**: ${e.message}` + } +} + +module.exports = Reload; \ No newline at end of file diff --git a/handlers/command.js b/handlers/command.js new file mode 100644 index 0000000..ce381b4 --- /dev/null +++ b/handlers/command.js @@ -0,0 +1,12 @@ +const { readdirSync } = require("fs") +const color = require("../functions/colorCodes") +module.exports = (client) => { + const commands = readdirSync(`./commands/`).filter(d => d.endsWith('.js')); + for (let file of commands) { + let pull = require(`../commands/${file}`); + client.commands.set(pull.config.name, pull); + if (pull.config.aliases) pull.config.aliases.forEach(a => client.aliases.set(a, pull.config.name)); + }; + + console.log(color("%", `%b[Command_Handler]%7 :: Loaded %e${client.commands.size} %7commands`)); +} \ No newline at end of file diff --git a/handlers/database.js b/handlers/database.js new file mode 100644 index 0000000..338615d --- /dev/null +++ b/handlers/database.js @@ -0,0 +1,103 @@ +const { connect } = require("mongoose").set('strictQuery', true); +const color = require("../functions/colorCodes") + +module.exports = class DatabaseHandler { + constructor(connectionString) { + this.cache = new Map(); + this.guildModel = require('../models/guilds'); + this.connectionString = connectionString; + } + + cacheSweeper(client) { + setInterval(() => { + const guilds = this.cache.values(); + for (const g of guilds) { + if (!client?.servers?.has(g?.id)) { + this.cache.delete(g?.id); + } + } + }, 60 * 60 * 1000); + } + + guildSweeper(client) { + setInterval(async () => { + const guilds = await this.getAll(); + let i = 0; + for (const g of guilds) { + setTimeout(async () => { + i++; + if (!client?.servers?.has(g?.id)) { + this.cache.delete(g?.id) + this.deleteGuild(g?.id); + } + }, i * 600) + } + }, 180 * 180 * 1000); + } + + async connectToDatabase() { + await connect(this.connectionString, { + useNewUrlParser: true, + }).catch((err) => { + console.log(color("%", `%4[Mongoose]%7 :: ${err}`)); + }).then(() => console.log( + color("%", "%6[Mongoose]%7 :: Connected to MongoDB"), + )); + } + + async fetchGuild(guildId, createIfNotFound = false) { + const fetched = await this.guildModel.findOne({ id: guildId }); + + if (fetched) return fetched; + if (!fetched && createIfNotFound) { + await this.guildModel.create({ + id: guildId, + language: 'en_EN', + botJoined: Date.now() / 1000 | 0, + }); + + return this.guildModel.findOne({ id: guildId }); + } return null; + } + + async getGuild(guildId, createIfNotFound = true, force = false) { + if (force) return this.fetchGuild(guildId, createIfNotFound); + + if (this.cache.has(guildId)) { + return this.cache.get(guildId); + } + + const fetched = await this.fetchGuild(guildId, createIfNotFound); + if (fetched) { + this.cache.set(guildId, fetched?.toObject() ?? fetched); + + return this.cache.get(guildId); + } return null; + } + + async deleteGuild(guildId, onlyCache = false) { + if (this.cache.has(guildId)) this.cache.delete(guildId); + + return !onlyCache ? this.guildModel.deleteMany({ id: guildId }) : true; + } + + async updateGuild(guildId, data = {}, createIfNotFound = false) { + let oldData = await this.getGuild(guildId, createIfNotFound); + + if (oldData) { + if (oldData?._doc) oldData = oldData?._doc; + + data = { ...oldData, ...data }; + + this.cache.set(guildId, data); + + return this.guildModel.updateOne({ + id: guildId, + }, data); + } return null; + } + + async getAll() { + return this.guildModel.find(); + } +}; \ No newline at end of file diff --git a/handlers/event.js b/handlers/event.js new file mode 100644 index 0000000..55c74dd --- /dev/null +++ b/handlers/event.js @@ -0,0 +1,12 @@ +const { readdirSync } = require("fs") +const color = require("../functions/colorCodes") +module.exports = (client) => { + const events = readdirSync(`./events/`).filter(d => d.endsWith('.js')); + for (let file of events) { + let evt = require(`../events/${file}`); + client.event.set(file.split(".")[0], evt.bind(null, client)); + client.on(file.split('.')[0], evt.bind(null, client)); + }; + + console.log(color("%", `%b[Event_Handler]%7 :: Loaded %e${client.event.size} %7events`)); +}; \ No newline at end of file diff --git a/handlers/function.js b/handlers/function.js new file mode 100644 index 0000000..be5637c --- /dev/null +++ b/handlers/function.js @@ -0,0 +1,11 @@ +const { readdirSync } = require("fs") +const logger = require("../functions/logger") +module.exports = (client) => { + const functions = readdirSync(`./functions`).filter(d => d.endsWith('.js')); + for (let file of functions) { + let evt = require(`../functions/${file}`); + client.functions.set(file.split(".")[0], evt); + }; + + logger.event('Function_Handler', `Loaded ${client.functions.size} functions`); +}; \ No newline at end of file diff --git a/handlers/translation.js b/handlers/translation.js new file mode 100644 index 0000000..bae266e --- /dev/null +++ b/handlers/translation.js @@ -0,0 +1,98 @@ +const color = require("../functions/colorCodes") +class TranslationHandler { + constructor(languages) { + + this.availableLanguages = languages ?? [ + 'en_EN', + // 'es_ES', + //'ar_AR', + // 'pt_BR', + //'sk_SK', + ]; + + this.translations = {}; + + for (const l of this.availableLanguages) { + const data = require(`../languages/${l}.json`); + this.initLanguage(l, data); + } + + console.log(color("%", `%b[Translation_Handler]%7 :: Loaded %e${this.availableLanguages.length} %7languages`)); + } + + initLanguage(key, language) { + this.translations[key] = language; + } + + checkRegex(value) { + return /^[a-z]{2}_[A-Z]{2}$/.test(value); + } + + getLanguage(language) { + if (!this.checkRegex(language)) return this.translations['en_EN']; + return this.translations[language]; + } + + addLanguage(language) { + if (!this.checkRegex(language)) { + throw new Error('Invalid language format. Example: en_EN'); + } + + this.availableLanguages.push(language); + } + + reload() { + this.translations = {}; + for (const l of this.availableLanguages) { + try { + const d = require(`../languages/${l}.json`); + + if (!d) continue; + + this.initLanguage(l, d); + return "Success" + } catch (e) { + return e.message; + } + } + } + + get(language, path, data = {}) { + if (!language) language = 'en_EN'; + const l = this.getLanguage(language); + const p = path.split('.'); + let c = null; + + if (p.length > 0) { + for (const i of p) { + try { + if (!c) { + if (!l.hasOwnProperty(i)) break; + c = l[i]; + } else { + if (!c.hasOwnProperty(i)) break; + c = c[i]; + } + } catch (err) { + break; + } + } + } else { + return `Unknown translation: ${language} | ${path}`;; + } + + if (!c) return `Unknown translation: ${language} | ${path}`;; + + if (data) { + try { + return c.replace(/{(\w+)}/g, (match, key) => data[key] ?? match); + } catch (e) { + return `Unknown translation: ${language} | ${path}`; + } + } + + return c; + } +}; + +module.exports = TranslationHandler; \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..bb29e1e --- /dev/null +++ b/index.js @@ -0,0 +1,58 @@ +const { Client } = require("revolt.js"); +const { Collection } = require('@discordjs/collection'); +const { token, mongoDB, api } = require("./botconfig.json"); +const logger = require('./functions/logger'); +const checkPolls = require('./functions/checkPolls') + +const color = require("./functions/colorCodes"); + +const client = new Client({ baseURL: api }); +const Uploader = require("revolt-uploader"); +const fetch = require("wumpfetch"); +const TranslationHandler = require('./handlers/translation'); +const DatabaseHandler = require('./handlers/database'); + +client.Uploader = new Uploader(client); +client.config = require("./config"); +client.translate = new TranslationHandler(); +client.logger = require('./functions/logger'); +client.botConfig = require("./botconfig.json"); + +client.database = new DatabaseHandler(mongoDB); +client.database.connectToDatabase(); +client.database.cacheSweeper(client); +client.database.guildSweeper(client); + +["reactions", "paginate", "timeout", "polls", "used", "messageCollector", "messageEdit"].forEach(x => client[x] = new Map()); +["aliases", "commands", "event", "functions"].forEach(x => client[x] = new Collection()); +["command", "event", "function"].forEach(x => require(`./handlers/${x}`)(client)); + +client.once("ready", async () => { + logger.success('Bot Ready', `${client.user.username} is ready`); + +//client.database.connectToDatabase(); +//client.database.cacheSweeper(client); +//client.database.guildSweeper(client); + + await checkPolls(client); + +}); + + +process.on("unhandledRejection", (reason, p) => { + console.log(color("%", "%4[Error_Handling] :: Unhandled Rejection/Catch%c")); + console.log(reason); + console.log(p) +}); +process.on("uncaughtException", (err, origin) => { + console.log(color("%", "%4[Error_Handling] :: Uncaught Exception/Catch%c")); + console.log(err); + console.log(origin) +}); +process.on("uncaughtExceptionMonitor", (err, origin) => { + console.log(color("%", "%4[Error_Handling] :: Uncaught Exception/Catch (MONITOR)%c")); + console.log(err); + console.log(origin) +}); + +client.loginBot(token); diff --git a/languages/en_EN.json b/languages/en_EN.json new file mode 100644 index 0000000..752d7c5 --- /dev/null +++ b/languages/en_EN.json @@ -0,0 +1,257 @@ +{ + "Events": { + "messageCreate": { + "wait": "wait", + "wait2": "before using", + "wait3": "again", + "unable": "Unable to send messages in", + "contact": "please contact a server administrator to get this settled", + "noPerms": "Need permission to react as all of my features use reactions", + "unavail": "This command is currently unavailable", + "perms": "You don't have the required permissions to use this command", + "perms2": "Permission needed", + "prefix": "My prefix is", + "prefix2": "To get started, type", + "noRoles": "There are no roles in your message, provide some by following this example", + "noReact": "I don't have permission to add reactions so this may not work correctly.", + "maxRoles": "You can only have a maximum of 20 roles in your message.", + "unknown": "There are unknown roles in your message, please remove them and try again.", + "duplicate": "There are duplicate roles in your message, please remove them and try again", + "positions": "There are roles with higher ranks (position) than my highest role in your message, please remove them and try again" + }, + "messageReactionAdd": { + "title": "title", + "owner": "Owner", + "end": "ended the poll early. These are the final results", + "tooFast": "You are reacting too fast! Please wait a few seconds before reacting again.", + "joined": "You joined giveaway", + "joined2": "There's currently", + "joined3": "user(s) in this giveaway!", + "early": "ended the giveaway early", + "endNone": "No one entered into the giveaway, so there are no winners", + "ended": "Ended", + "prize": "Prize", + "winnersNone": "Winner(s): None", + "none": "None", + "reqs": "Requirement", + "giveaway": "Giveaway", + "partici": "Participants", + "winners": "Winner(s)", + "congrats": "Congratulations", + "youWon": "You won the giveaway for", + "cooldown": "Reaction cooldown is 3 seconds", + "success": "Successfully added role {role}", + "noPerms": "I do not have permission to give role {role}", + "role": "role", + "deleteCollector": "Successfully stopped reaction collector!" + }, + "messageReactionRemove": { + "title": "Title", + "tooFast": "You are reacting too fast! Please wait a few seconds before reacting again.", + "left": "You left giveaway", + "left2": "There are now", + "left3": "user(s) in this giveaway", + "success": "Successfully removed role {role}", + "noPerms": "I do not have permission to remove role {role}" + } + }, + "Commands": { + "roles": { + "description": "Setup a reaction role message for your server", + "usage": "help", + "already": "You already have an active message collector going on! Finish that first before starting a new one.", + "pick": "Provide what you would like the type of message to be sent. Options: `embed`, `content`", + "ended": "The message collector has ended after 25 minutes.", + "success": "Successfully sent message collector to", + "react": "Send a message you would like to be as your reaction role message. After that is done, react with emojis in order of the roles you want to be added to the message.", + "react2": "Once you're done, react with ✅ to complete it.\nTo cancel this reaction collector, react with ❌ to stop it!", + "noPerms": "I require the `AssignRoles` permission to add roles to users.", + "max": "You can only have a maximum of 12 reaction role messages in your server.", + "noRoles": "There are no reaction role messages setup currently. To add some, type", + "jump": "Jump", + "roles": "Roles", + "delete": "Provide an ID for the reaction role message to delete it", + "edit": "Provide an ID for the reaction role message to edit it", + "notFound": "I could not find a reaction role message with that ID.", + "deleted": "Successfully deleted that reaction role message.", + "view": "Viewing Reaction Role Messages", + "dms": "Successfully toggled DM messages", + "on": "On", + "off": "Off", + "create": "Creating", + "createExample": "create [Channel Mention] [Type: content | embed]", + "editing": "Editing", + "viewing": "Viewing", + "deleting": "Deleting", + "msgId": "Message", + "explain": "Explanation", + "explain2": "When you create a reaction message (`f!roles create`), you will need to provide it with roles (format: `{role:Blue}`) and I will copy your message. React to my message to automatically update the roles and once you are finished, react with ✅ to complete it.", + "dm": "Direct Messages" + }, + "help": { + "description": "Help command", + "usage": "[Command (Optional)]", + "embeds": { + "first": { + "cmdName": "Command", + "cmdDesc": "Description", + "cmdAvail": "Availability", + "cmdAvail2": "Available", + "cmdAvail3": "Unavailable", + "cmdCool": "Cooldown", + "cmdCool2": "seconds", + "cmdPerms": "Permissions", + "cmdPerms2": "None", + "cmdAlias": "Aliases", + "cmdUsage": "Usage" + }, + "second": { + "start": "Available Commands", + "middle": "Unavailable Commands", + "end": "To get more information about a command, type", + "end2": "command" + } + } + }, + "info": { + "description": "Stats on the bot", + "start": "Random Information", + "servers": "Servers", + "giveaways": "Giveaways", + "polls": "Polls", + "uptime": "Uptime", + "ping": "Ping", + "database": "Database", + "library": "Library", + "links": "Links", + "links2": "Invite", + "links3": "Support" + }, + "giveaway": { + "description": "Creates a giveaway. Reactions have 3 second cooldown.", + "usage": "[Time, E.g. 20m] | [Winners] | [Prize] | [Requirement (Optional)] [Channel (Optional), E.g. channel:#giveaways]", + "tooMany": "This server has 15 giveaways currently running. Wait until one finishes before making anymore!", + "validChannel": "Please provide a valid channel mention or channel ID.\nExample", + "validChannel2": "Note: If you are using a channel ID, provide it after the requirement text", + "validTime": "Please provide a valid time.\nExample", + "validWinners": "Please provide the amount of winners. Maximum: 5\nExample", + "validPrize": "Please provide the prize.\nExample", + "ormore": "Giveaways can only be 5 minutes or above in time!\nExample", + "orless": "Please provide a time shorter than 365 days.\nExample", + "format": "You failed to follow the giveaway format.\nExample", + "formatWinners": "You failed to properly specific how many winners there are\nExample", + "maxwins": "When making a giveaway, you can only have a maximum of 5 winners.\nExample", + "giveaway": "Giveaway", + "react": "React with", + "react2": "to enter!", + "hosted": "Hosted by", + "time": "Time", + "prize": "Prize", + "winners": "Winners", + "reqs": "Requirement", + "noperms": "I do not have permission to send messages in", + "noperms2": "I do not have permission to view", + "noperms3": "I do not have permission to add reactions in", + "success": "Successfully sent giveaway to" + }, + "polls": { + "description": "Creates a poll. Reactions have 3 second cooldown.", + "usage": "[Time, E.g. 10m] | [Question] | [Option 1] | [Option 2] | [Options 3-10 (Optional)]", + "tooMany": "You already have 5 polls running. Wait for one to end before creating anymore.", + "validTime": "Please provide a valid time.\nExample", + "longerThan": "Please provide a time longer than 30 seconds.\nExample", + "shorterThan": "Please provide a time shorter than 30 days.\nExample", + "validQuestion": "Please provide a question.\nExample", + "validOption": "Please provide the first option for the question. Maximum of 10 options.\nExample", + "validOption2": "Please provide the second option for the question. Maximum of 10 options.\nExample", + "maxOptions": "Please provide a maximum of 10 options.\nExample", + "polls": "Polls", + "title": "Title", + "example": "How are you? | Good | Bad" + }, + "reroll": { + "description": "Reroll winners from giveaways. Winner number is based on the order of the winners in the embed.", + "usage": "[Message ID] [Winner Number, E.g. 1, 2, all | Default: all]", + "validID": "Please provide a valid message ID.", + "notValid": "I could not find a giveaway message with that ID.", + "winners": "Please provide a winner number (E.g. 1, 2, 3) or use `all` to reroll all winners!", + "notEnded": "This giveaway hasn't ended yet!", + "notHosted": "You can't reroll this giveaway because you didn't host it!", + "noUsers": "There are no users in this giveaway to reroll!", + "noPicks": "There are no more users that can be picked for rerolling!", + "onlyWinners": "There are only", + "onlyWinners2": "winner(s) to pick from!\nExample", + "winnerNum": "Winner Number", + "giveaway": "Giveaway", + "owner": "Owner", + "rerolled": "rerolled", + "winners1": "all winners!", + "winners2": "winner position", + "partici": "Participants", + "ended": "Ended", + "prize": "Prize", + "winner": "Winner(s)", + "reqs": "Requirement", + "reroll": "The giveaway was rerolled! New winner(s)", + "reroll2": "won the giveaway for", + "error": "Unable to send message for new winners", + "error2": "Unable to edit embed" + }, + "prefix": { + "success": "Prefix successfully changed to", + "tooMany": "Prefix cannot be longer than 8 characters.", + "prefix": "Prefix", + "change": "To change the prefix, use", + "new": "new prefix", + "description": "Changes default prefix to your own", + "usage": "" + }, + "credits": { + "thankyou": "As developer of Functious, I wanted to thank everyone who contributed toward the bot.", + "thankyou2": "The bot wouldn't be where it is without all of you, thank you!", + "translators": "Translators", + "title": "Credits", + "description": "Credits for everyone who helped" + }, + "language": { + "description": "Changes the language of the bot", + "usage": "", + "example": "Example", + "current": "Current", + "change": "You can change your server's language by picking an available language.", + "avail": "Available", + "notAvailable": "Chosen language is not supported! ", + "success": "Successfully changed the language to" + } + }, + "Functions": { + "fetchTime": { + "years": "year(s)", + "days": "day(s)", + "hours": "hour(s)", + "minutes": "minute(s)", + "seconds": "second(s)" + }, + "giveawaysEnd": { + "giveaway": "Giveaway", + "noUsers": "No one entered into the giveaway so I couldn't pick a winner", + "ended": "Ended", + "prize": "Prize", + "winnersNone": "Winner(s): None", + "winners": "Winner(s)", + "reqs": "Requirement", + "noOne": "No one entered into giveaway", + "warn": "[Channel Edit] Unable to edit message", + "warn1": "in channel", + "warn2": "[Channel Post] Unable to post to channel", + "givEnd": "Giveaway Ended", + "partici": "Participants", + "congrats": "Congratulations", + "youWon": "You won the giveaway for" + }, + "poll": { + "end": "This poll has ended and these are the results" + } + }, + "links4": "Vote" +} \ No newline at end of file diff --git a/models/commands.js b/models/commands.js new file mode 100644 index 0000000..9f75b48 --- /dev/null +++ b/models/commands.js @@ -0,0 +1,13 @@ +const { Schema, model } = require("mongoose"); +const moment = require('moment'); +const timestamp = moment().valueOf() / 1000; + +const commands = new Schema({ + id: { type: String }, + name: { type: String }, + content: { type: String }, + createdBy: { type: String }, + created_at: { type: String, default: timestamp } +}); + +module.exports = model("commands", commands); diff --git a/models/giveaways.js b/models/giveaways.js new file mode 100644 index 0000000..d81b15e --- /dev/null +++ b/models/giveaways.js @@ -0,0 +1,21 @@ +const { Schema, model } = require("mongoose"); + +const giveaways = new Schema({ + owner: { type: String, required: true }, + serverId: { type: String, required: true }, + channelId: { type: String, required: true }, + messageId: { type: String, required: true }, + users: [{ type: Object }], + time: { type: String, required: true }, + now: { type: String, required: true }, + prize: { type: String, required: true }, + winners: { type: Number, required: true }, + pickedWinners: [{ type: Object }], + picking: [{ type: Object }], + ended: { type: Boolean, default: false }, + lang: { type: String, required: true, default: "en_EN" }, + requirement: { type: String }, + endDate: { type: String } +}); + +module.exports = model("giveaways", giveaways); diff --git a/models/guilds.js b/models/guilds.js new file mode 100644 index 0000000..3d6704a --- /dev/null +++ b/models/guilds.js @@ -0,0 +1,12 @@ +const { Schema, model } = require("mongoose"); + +const guilds = new Schema({ + id: { type: String }, + prefix: { type: String, default: "f!" }, + language: { type: String, default: "en_EN" }, + joined: { type: String, default: Date.now() / 1000 | 0 }, + dm: { type: Boolean, default: true }, + roles: { type: Array, default: [] }, +}); + +module.exports = model("guilds", guilds); diff --git a/models/logging.js b/models/logging.js new file mode 100644 index 0000000..8ad27c2 --- /dev/null +++ b/models/logging.js @@ -0,0 +1,12 @@ +const { Schema, model } = require("mongoose"); + +const logging = new Schema({ + id: { type: String }, + type: { type: String }, + ranBy: { type: String }, + name: { type: String }, + channel: { type: String }, + created_at: { type: String, default: Date.now() / 1000 } +}); + +module.exports = model("logging", logging); diff --git a/models/polls.js b/models/polls.js new file mode 100644 index 0000000..9302bef --- /dev/null +++ b/models/polls.js @@ -0,0 +1,17 @@ +const { Schema, model } = require("mongoose"); + +const polls = new Schema({ + owner: { type: String }, + serverId: { type: String }, + channelId: { type: String }, + messageId: { type: String }, + avatars: { type: Object }, + votes: { type: Object }, + users: { type: Object }, + time: { type: Number }, + now: { type: Number }, + desc: { type: String }, + options: { type: Object }, +}); + +module.exports = model("polls", polls); diff --git a/models/registerInvite.js b/models/registerInvite.js new file mode 100644 index 0000000..e477cba --- /dev/null +++ b/models/registerInvite.js @@ -0,0 +1,10 @@ +const { Schema, model } = require("mongoose"); + +const registerInvite = new Schema({ + userId: { type: String }, + invite: { type: String }, + staffRoles: { type: Object }, + createdAt: { type: Number }, +}); + +module.exports = model("registerInvite", registerInvite); diff --git a/models/rule7.js b/models/rule7.js new file mode 100644 index 0000000..35269c8 --- /dev/null +++ b/models/rule7.js @@ -0,0 +1,19 @@ +const { Schema, model } = require("mongoose"); + +const rule7 = new Schema({ + owner: { type: String }, + serverId: { type: String }, + channelId: { type: String }, + messageId: { type: String }, + avatars: { type: Object }, + votes: { type: Object }, + users: { type: Object }, + time: { type: Number }, + now: { type: Number }, + desc: { type: String }, + options: { type: Object }, + threadId: { type: String }, + reportId: { type: String }, +}); + +module.exports = model("rule7", rule7); diff --git a/models/savedPolls.js b/models/savedPolls.js new file mode 100644 index 0000000..6fc91fe --- /dev/null +++ b/models/savedPolls.js @@ -0,0 +1,9 @@ +const { Schema, model } = require("mongoose"); + +const savedPolls = new Schema({ + owner: { type: String }, + desc: { type: String }, + options: { type: Object }, +}); + +module.exports = model("savedPolls", savedPolls); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..37a1cc1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1715 @@ +{ + "name": "zonies", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "license": "MIT", + "dependencies": { + "@discordjs/collection": "^1.5.1", + "axios": "^1.9.0", + "canvas": "^2.11.2", + "chalk": "^4.1.2", + "date-fns": "^4.1.0", + "fs": "^0.0.1-security", + "moment": "^2.29.4", + "mongoose": "^7.2.0", + "nanoid": "3.3.4", + "node-fetch-commonjs": "^3.3.2", + "revolt-uploader": "^1.1.1", + "revolt.js": "npm:revolt.js-update@^7.0.0-beta.9", + "screen": "^0.2.10", + "wumpfetch": "^0.3.1" + } + }, + "node_modules/@discordjs/collection": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", + "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.11.0" + } + }, + "node_modules/@insertish/oapi": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/@insertish/oapi/-/oapi-0.1.18.tgz", + "integrity": "sha512-LZLUk3WmzUjCM0quensexvQx/Kk1MpFBtCLJRnRrPOiaFT37JpOmWUFlrdu0sPS6B9wi2edEBeLcsnIiq85WMA==", + "license": "MIT", + "dependencies": { + "typescript": "^4.6.2" + }, + "bin": { + "oapilib": "cli.js" + }, + "optionalDependencies": { + "axios": "^0.26.1", + "openapi-typescript": "^5.2.0" + } + }, + "node_modules/@insertish/oapi/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "license": "MIT", + "optional": true, + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", + "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "license": "MIT", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@mxssfd/typedoc-theme": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@mxssfd/typedoc-theme/-/typedoc-theme-1.1.3.tgz", + "integrity": "sha512-/yP5rqhvibMpzXpmw0YLLRCpoj3uVWWlwyJseZXzGxTfiA6/fd1uubUqNoQAi2U19atMDonq8mQc+hlVctrX4g==", + "license": "MIT", + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "typedoc": "^0.25.1" + } + }, + "node_modules/@solid-primitives/map": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@solid-primitives/map/-/map-0.4.8.tgz", + "integrity": "sha512-p9zhIaIWOQVxLaUEjg6nzrBLZUOzozJFHatdKqISSIq7iJhVXX1M1MPzDHHqKyJw/nSENoKgvZehnG3HErnamw==", + "license": "MIT", + "dependencies": { + "@solid-primitives/trigger": "^1.0.8" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/set": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@solid-primitives/set/-/set-0.4.8.tgz", + "integrity": "sha512-kYZ5o4w2oeaDBvQyBeBB7gmGWeR4MWIP36SuMqRwOPzOWyxA2QFlwQr+iL4zo8lNJVssvBhSdm5HwFzWbob/hA==", + "license": "MIT", + "dependencies": { + "@solid-primitives/trigger": "^1.0.8" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/trigger": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@solid-primitives/trigger/-/trigger-1.0.8.tgz", + "integrity": "sha512-p9e3FGhCk8sRPxDiCT8vnTE+DOEtrAnJZP4zV0NAV6YGnpV50JATVXNiLjKgyiI/mTIRkWB0+9c5SUbRlqFx6A==", + "license": "MIT", + "dependencies": { + "@solid-primitives/utils": "^6.2.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/utils": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.1.tgz", + "integrity": "sha512-TsecNzxiO5bLfzqb4OOuzfUmdOROcssuGqgh5rXMMaasoFZ3GoveUgdY1wcf17frMJM7kCNGNuK34EjErneZkg==", + "license": "MIT", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@types/node": { + "version": "20.7.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz", + "integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==", + "license": "MIT" + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.1.tgz", + "integrity": "sha512-8hKOnOan+Uu+NgMaCouhg3cT9x5fFZ92Jwf+uDLXLu/MFRbXxlWwGeQY7KVHkeSft6RvY+tdxklUBuyY9eIEKg==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "license": "MIT" + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0", + "optional": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/bson": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.0.tgz", + "integrity": "sha512-B+QB4YmDx9RStKv8LLSl/aVIEV3nYJc3cJNNTK2Cd1TL+7P+cNpw9mAPeCgc5K+j01Dv6sxUzcITXDx7ZU3F0w==", + "license": "Apache-2.0", + "engines": { + "node": ">=14.20.1" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "optional": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "license": "MIT", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", + "license": "ISC" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "license": "MIT", + "optional": true + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "license": "MIT", + "optional": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "license": "MIT" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "optional": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "license": "MIT" + }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/lodash.defaultsdeep": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", + "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "license": "MIT" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT", + "optional": true + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.8.1.tgz", + "integrity": "sha512-wKyh4kZvm6NrCPH8AxyzXm3JBoEf4Xulo0aUWh3hCgwgYJxyQ1KLST86ZZaSWdj6/kxYUA3+YZuyADCE61CMSg==", + "license": "Apache-2.0", + "dependencies": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "optionalDependencies": { + "@mongodb-js/saslprep": "^1.1.0" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.0.0", + "kerberos": "^1.0.0 || ^2.0.0", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongoose": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.5.3.tgz", + "integrity": "sha512-QyYzhZusux0wIJs+4rYyHvel0kJm0CT887trNd1WAB3iQnDuJow0xEnjETvuS/cTjHQUVPihOpN7OHLlpJc52w==", + "license": "MIT", + "dependencies": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.8.1", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "license": "MIT", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-commonjs": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch-commonjs/-/node-fetch-commonjs-3.3.2.tgz", + "integrity": "sha512-VBlAiynj3VMLrotgwOS3OyECFxas5y7ltLcK4t41lMUZeaK15Ym4QRkqN0EQKAFL42q9i21EPKjzLUPfltR72A==", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openapi-typescript": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-5.4.1.tgz", + "integrity": "sha512-AGB2QiZPz4rE7zIwV3dRHtoUC/CWHhUjuzGXvtmMQN2AFV8xCTLKcZUHLcdPQmt/83i22nRE7+TxXOXkK+gf4Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "js-yaml": "^4.1.0", + "mime": "^3.0.0", + "prettier": "^2.6.2", + "tiny-glob": "^0.2.9", + "undici": "^5.4.0", + "yargs-parser": "^21.0.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "license": "MIT", + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/revolt-api": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/revolt-api/-/revolt-api-0.6.7.tgz", + "integrity": "sha512-CfMs8xCy9VcZIzyaJ9/t6ixcUR+YJ1hahIiunHd2FcoSKKiPgJNZvCXSV2vSWW1b8y2ftFeFygU/+AfdZocOeQ==", + "license": "MIT", + "dependencies": { + "@insertish/oapi": "0.1.18", + "axios": "^0.26.1", + "lodash.defaultsdeep": "^4.6.1" + } + }, + "node_modules/revolt-api/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/revolt-uploader": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/revolt-uploader/-/revolt-uploader-1.1.4.tgz", + "integrity": "sha512-hnUCc1grg6Yq1J2q0HcsbfbWCvHIR6hPHzk3/75EjWEjP7bPYwAAVsHOwwtfdMtwMUPN9EAmBj3NvU4t+o1JJw==", + "license": "ISC", + "dependencies": { + "form-data": "^4.0.0", + "node-fetch": "^2.6.7" + } + }, + "node_modules/revolt.js": { + "name": "revolt.js-update", + "version": "7.0.0-beta.9", + "resolved": "https://registry.npmjs.org/revolt.js-update/-/revolt.js-update-7.0.0-beta.9.tgz", + "integrity": "sha512-xldgq8l1YaLv8c29mnA0ivmcb6SJCCB4hdXrJ6OXJpvrBq54KcDVNqyjI7Fy+FZkze78IQrYV5laVpg85BLVkg==", + "license": "MIT", + "dependencies": { + "@mxssfd/typedoc-theme": "^1.1.1", + "@solid-primitives/map": "^0.4.3", + "@solid-primitives/set": "^0.4.3", + "eventemitter3": "^5.0.0", + "isomorphic-ws": "^5.0.0", + "long": "^5.2.1", + "revolt-api": "0.6.7", + "solid-js": "^1.7.3", + "typedoc": "^0.24.1", + "ulid": "^2.3.0", + "ws": "^8.13.0" + } + }, + "node_modules/revolt.js/node_modules/typedoc": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/screen": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/screen/-/screen-0.2.10.tgz", + "integrity": "sha512-T6viduhAMpKFJgnsCmdde25n1QRao5mpRqJ4MyKHD3Y2f1sLP4XVzJJfYeyxsOFcTieVcaB6B61KwS65OVMN/g==", + "dependencies": { + "xtend": "~1.0.3" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz", + "integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/shiki": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.4.tgz", + "integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==", + "license": "MIT", + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==", + "license": "MIT" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "license": "MIT", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "license": "MIT", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/solid-js": { + "version": "1.7.12", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.12.tgz", + "integrity": "sha512-QoyoOUKu14iLoGxjxWFIU8+/1kLT4edQ7mZESFPonsEXZ//VJtPKD8Ud1aTKzotj+MNWmSs9YzK6TdY+fO9Eww==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.0", + "seroval": "^0.5.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "license": "MIT", + "optional": true, + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/typedoc": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.1.tgz", + "integrity": "sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA==", + "peer": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ulid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", + "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", + "license": "MIT", + "bin": { + "ulid": "bin/cli.js" + } + }, + "node_modules/undici": { + "version": "5.25.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.25.2.tgz", + "integrity": "sha512-tch8RbCfn1UUH1PeVCXva4V8gDpGAud/w0WubD6sHC46vYQ3KDxL+xv1A2UxK0N6jrVedutuPHxe1XIoqerwMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "license": "MIT" + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wumpfetch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/wumpfetch/-/wumpfetch-0.3.1.tgz", + "integrity": "sha512-KbvB4asL0z/Uh1eavIXjhdo6rFudT5WtEudNfK3z9KGbvBE0JvGqRntRRjtKPOW1lEh85kcKzIOmRo8KHU5myQ==", + "license": "MIT" + }, + "node_modules/xtend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-1.0.3.tgz", + "integrity": "sha512-wv78b3q8kHDveC/C7Yq/UUrJXsAAM1t/j5m28h/ZlqYy0+eqByglhsWR88D2j3VImQzZlNIDsSbZ3QItwgWEGw==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a1e4348 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "main": "index.js", + "scripts": { + "start": "node index.js" + }, + "license": "MIT", + "dependencies": { + "@discordjs/collection": "^1.5.1", + "axios": "^1.9.0", + "canvas": "^2.11.2", + "chalk": "^4.1.2", + "date-fns": "^4.1.0", + "fs": "^0.0.1-security", + "moment": "^2.29.4", + "mongoose": "^7.2.0", + "nanoid": "3.3.4", + "node-fetch-commonjs": "^3.3.2", + "revolt-uploader": "^1.1.1", + "revolt.js": "npm:revolt.js-update@^7.0.0-beta.9", + "screen": "^0.2.10", + "wumpfetch": "^0.3.1" + }, + "information": { + "Developer": "Ryahn", + "Discord": "ainzooalgown", + "Revolt": "Ryahn#1337", + "GitHub": "https://github.com/Ryahn/zonies" + } +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..ef8dda1 --- /dev/null +++ b/test.js @@ -0,0 +1,27 @@ +// const { token, mongoDB, api } = require("./botconfig.json"); +// const DatabaseHandler = require('./handlers/database'); +// const util = require('util'); +// const { isJson } = require('./functions/randomStr') + +// const database = new DatabaseHandler(mongoDB); +// database.connectToDatabase(); + +// const CommandDB = require('./models/commands'); + +// let data = CommandDB.find({}).select('name').then((data) => { +// let names = []; +// data.forEach((item) => { names.push(item.name) }) +// console.log(names.join(', ')) +// }) +(async () => { + + const axios = require("axios"); + const query = 'yeet' + const url = ('https://api.urbandictionary.com/v0/define?term=' + query) + const response = await axios.get(url); + const data = response.data; + const def = data.list[0]; + + + +})(); \ No newline at end of file