diff --git a/base/Atlanta.js b/base/Atlanta.js index 2a42b67c..7717b0d8 100644 --- a/base/Atlanta.js +++ b/base/Atlanta.js @@ -1,7 +1,7 @@ -const { MessageEmbed, Util, Client, Collection } = require("discord.js"); -const { GiveawaysManager } = require("discord-giveaways"); -const { Player } = require("discord-player"); -const { Client: Joker } = require("blague.xyz"); +const { MessageEmbed, Util, Client, Collection } = require("discord.js"), + { GiveawaysManager } = require("discord-giveaways"), + { Player } = require("discord-player"), + { Client: Joker } = require("blague.xyz"); const util = require("util"), AmeClient = require("amethyste-api"), @@ -44,15 +44,8 @@ class Atlanta extends Client { this.databaseCache.usersReminds = new Collection(); // members with active reminds this.databaseCache.mutedUsers = new Collection(); // members who are currently muted - if (this.config.apiKeys.amethyste) { - this.AmeAPI = new AmeClient(this.config.apiKeys.amethyste); - }; - - if (this.config.apiKeys.blagueXYZ) { - this.joker = new Joker(this.config.apiKeys.blagueXYZ, { - defaultLanguage: "en" - }); - }; + if (this.config.apiKeys.amethyste) this.AmeAPI = new AmeClient(this.config.apiKeys.amethyste); + if (this.config.apiKeys.blagueXYZ) this.joker = new Joker(this.config.apiKeys.blagueXYZ, { defaultLanguage: "en" }); this.player = new Player(this, { ytdlDownloadOptions: { @@ -68,16 +61,10 @@ class Atlanta extends Client { this.player .on("trackStart", (message, track) => { - message.success("music/play:NOW_PLAYING", { - songName: track.title - }); + message.success("music/play:NOW_PLAYING", { songName: track.title }); }) .on("playlistStart", (message, queue, playlist, track) => { - message.channel.send(this.customEmojis.success+" | "+message.translate("music/play:PLAYING_PLAYLIST", { - playlistTitle: playlist.title, - playlistEmoji: this.customEmojis.playlist, - songName: track.title - })); + message.channel.send(`${this.customEmojis.success} ${message.translate("music/play:PLAYING_PLAYLIST", { playlistTitle: playlist.title, playlistEmoji: this.customEmojis.playlist, songName: track.title })}`); }) .on("searchResults", (message, query, tracks) => { if (tracks.length > 10) tracks = tracks.slice(0, 10); @@ -93,10 +80,7 @@ class Atlanta extends Client { return message.success("music/play:RESULTS_CANCEL"); }; - message.error("misc:INVALID_NUMBER_RANGE", { - min: 1, - max: tracks.length - }); + message.error("misc:INVALID_NUMBER_RANGE", { min: 1, max: tracks.length }); }) .on("searchCancel", (message) => { message.error("misc:TIMES_UP"); @@ -111,14 +95,10 @@ class Atlanta extends Client { message.success("music/play:QUEUE_ENDED"); }) .on("playlistAdd", (message, queue, playlist) => { - message.success("music/play:ADDED_QUEUE_COUNT", { - songCount: playlist.items.length - }); + message.success("music/play:ADDED_QUEUE_COUNT", { songCount: playlist.items.length }); }) .on("trackAdd", (message, queue, track) => { - message.success("music/play:ADDED_QUEUE", { - songName: track.title - }); + message.success("music/play:ADDED_QUEUE", { songName: track.title }); }) .on("channelEmpty", () => { // do nothing, leaveOnEmpty is not enabled @@ -155,7 +135,7 @@ class Atlanta extends Client { default: { botsCanWin: false, // exemptPermissions: [ "MANAGE_MESSAGES", "ADMINISTRATOR" ], - embedColor: "#FF0000", + embedColor: this.config.embed.color, reaction: "π" } }); @@ -169,6 +149,7 @@ class Atlanta extends Client { if (!locale) locale = this.defaultLanguage; const language = this.translations.get(locale); if (!language) throw "Invalid language set in data."; + return language(key, args); }; @@ -176,6 +157,7 @@ class Atlanta extends Client { if (!locale) locale = this.defaultLanguage; const languageData = this.languages.find((language) => language.name === locale || language.aliases.includes(locale)); if (!format) format = languageData.defaultMomentFormat; + return moment(new Date(date)) .locale(languageData.moment) .format(format); @@ -185,8 +167,8 @@ class Atlanta extends Client { if (!type) time = "to"; if (!locale) locale = this.defaultLanguage; const languageData = this.languages.find((language) => language.name === locale || language.aliases.includes(locale)); - const m = moment(time) - .locale(languageData.moment); + const m = moment(time).locale(languageData.moment); + return (type === "to" ? m.toNow(noPrefix) : m.fromNow(noPrefix)); }; @@ -196,13 +178,13 @@ class Atlanta extends Client { const props = new (require(`.${commandPath}${path.sep}${commandName}`))(this); this.logger.log(`Loading Command: ${props.help.name}. π`, "log"); props.conf.location = commandPath; - if (props.init) { - props.init(this); - }; + if (props.init) props.init(this); + this.commands.set(props.help.name, props); props.help.aliases.forEach((alias) => { this.aliases.set(alias, props.help.name); }); + return false; } catch (e) { return `Unable to load command ${commandName}: ${e}`; @@ -212,34 +194,31 @@ class Atlanta extends Client { // This function is used to unload a command (you need to load them again) async unloadCommand (commandPath, commandName) { let command; - if (this.commands.has(commandName)) { - command = this.commands.get(commandName); - } else if (this.aliases.has(commandName)) { - command = this.commands.get(this.aliases.get(commandName)); - }; - if (!command) { - return `The command \`${commandName}\` doesn't seem to exist, nor is it an alias. Try again!`; - }; - if (command.shutdown) { - await command.shutdown(this); - }; + if (this.commands.has(commandName)) command = this.commands.get(commandName); + else if (this.aliases.has(commandName)) command = this.commands.get(this.aliases.get(commandName)); + + if (!command) return `The command \`${commandName}\` doesn't seem to exist, nor is it an alias. Try again!`; + if (command.shutdown) await command.shutdown(this); + delete require.cache[require.resolve(`.${commandPath}${path.sep}${commandName}.js`)]; + return false; }; // This function is used to find a user data or create it async findOrCreateUser({ id: userID }, isLean) { - if (this.databaseCache.users.get(userID)) { - return isLean ? this.databaseCache.users.get(userID).toJSON() : this.databaseCache.users.get(userID); - } else { + if (this.databaseCache.users.get(userID)) return isLean ? this.databaseCache.users.get(userID).toJSON() : this.databaseCache.users.get(userID); + else { let userData = (isLean ? await this.usersData.findOne({ id: userID }).lean() : await this.usersData.findOne({ id: userID })); if (userData) { if (!isLean) this.databaseCache.users.set(userID, userData); + return userData; } else { userData = new this.usersData({ id: userID }); await userData.save(); this.databaseCache.users.set(userID, userData); + return isLean ? userData.toJSON() : userData; }; }; @@ -247,12 +226,12 @@ class Atlanta extends Client { // This function is used to find a member data or create it async findOrCreateMember({ id: memberID, guildID }, isLean) { - if (this.databaseCache.members.get(`${memberID}${guildID}`)) { - return isLean ? this.databaseCache.members.get(`${memberID}${guildID}`).toJSON() : this.databaseCache.members.get(`${memberID}${guildID}`); - } else { + if (this.databaseCache.members.get(`${memberID}${guildID}`)) return isLean ? this.databaseCache.members.get(`${memberID}${guildID}`).toJSON() : this.databaseCache.members.get(`${memberID}${guildID}`); + else { let memberData = (isLean ? await this.membersData.findOne({ guildID, id: memberID }).lean() : await this.membersData.findOne({ guildID, id: memberID })); if (memberData) { if (!isLean) this.databaseCache.members.set(`${memberID}${guildID}`, memberData); + return memberData; } else { memberData = new this.membersData({ id: memberID, guildID: guildID }); @@ -263,6 +242,7 @@ class Atlanta extends Client { await guild.save(); }; this.databaseCache.members.set(`${memberID}${guildID}`, memberData); + return isLean ? memberData.toJSON() : memberData; }; }; @@ -270,17 +250,18 @@ class Atlanta extends Client { // This function is used to find a guild data or create it async findOrCreateGuild({ id: guildID }, isLean) { - if (this.databaseCache.guilds.get(guildID)) { - return isLean ? this.databaseCache.guilds.get(guildID).toJSON() : this.databaseCache.guilds.get(guildID); - } else { + if (this.databaseCache.guilds.get(guildID)) return isLean ? this.databaseCache.guilds.get(guildID).toJSON() : this.databaseCache.guilds.get(guildID); + else { let guildData = (isLean ? await this.guildsData.findOne({ id: guildID }).populate("members").lean() : await this.guildsData.findOne({ id: guildID }).populate("members")); if (guildData) { if (!isLean) this.databaseCache.guilds.set(guildID, guildData); + return guildData; } else { guildData = new this.guildsData({ id: guildID }); await guildData.save(); this.databaseCache.guilds.set(guildID, guildData); + return isLean ? guildData.toJSON() : guildData; }; }; @@ -290,12 +271,14 @@ class Atlanta extends Client { async resolveUser(search) { let user = null; if (!search || typeof search !== "string") return; + // Try ID search if (search.match(/^<@!?(\d+)>$/)) { const id = search.match(/^<@!?(\d+)>$/)[1]; user = this.users.fetch(id).catch(() => {}); if (user) return user; }; + // Try username search if (search.match(/^!?(\w+)#(\d+)$/)) { const username = search.match(/^!?(\w+)#(\d+)$/)[0]; @@ -304,18 +287,21 @@ class Atlanta extends Client { if (user) return user; }; user = await this.users.fetch(search).catch(() => {}); + return user; }; async resolveMember(search, guild) { let member = null; if (!search || typeof search !== "string") return; + // Try ID search if (search.match(/^<@!?(\d+)>$/)) { const id = search.match(/^<@!?(\d+)>$/)[1]; member = await guild.members.fetch(id).catch(() => {}); if (member) return member; }; + // Try username search if (search.match(/^!?(\w+)#(\d+)$/)) { guild = await guild.fetch(); @@ -323,22 +309,26 @@ class Atlanta extends Client { if (member) return member; }; member = await guild.members.fetch(search).catch(() => {}); + return member; }; async resolveRole(search, guild) { let role = null; if (!search || typeof search !== "string") return; + // Try ID search if (search.match(/^<@&!?(\d+)>$/)) { const id = search.match(/^<@&!?(\d+)>$/)[1]; role = guild.roles.cache.get(id); if (role) return role; }; + // Try name search role = guild.roles.cache.find((r) => search === r.name); if (role) return role; role = guild.roles.cache.get(search); + return role; }; }; diff --git a/base/User.js b/base/User.js index 8b354d2e..e3587299 100644 --- a/base/User.js +++ b/base/User.js @@ -107,7 +107,7 @@ userSchema.method("getAchievements", async function() { await Canvas.loadImage(`./assets/img/achievements/achievement${this.achievements.invite.achieved ? "_colored" : ""}7.png`) ]; let dim = 0; - for(let i = 0; i < images.length; i++) { + for (let i = 0; i < images.length; i++) { await ctx.drawImage(images[i], dim, 10, 350, 200); dim += 200; }; diff --git a/dashboard/app.js b/dashboard/app.js index dcdf25cc..7d84fbe3 100644 --- a/dashboard/app.js +++ b/dashboard/app.js @@ -4,7 +4,6 @@ const config = require("../config"), module.exports.load = async(client) => { /* Init express app */ - const express = require("express"), session = require("express-session"), path = require("path"), @@ -56,7 +55,7 @@ module.exports.load = async(client) => { .use("/", mainRouter) .use("/commands", commandsManagerRouter) .use("/updates", updatesManagerRouter) - .use(CheckAuth, function(req, res){ + .use(CheckAuth, function(req, res) { res.status(404).render("404", { user: req.userInfos, translate: req.translate, diff --git a/dashboard/auth/CheckAuth.js b/dashboard/auth/CheckAuth.js index dbff89a6..a850b20c 100644 --- a/dashboard/auth/CheckAuth.js +++ b/dashboard/auth/CheckAuth.js @@ -1,7 +1,6 @@ module.exports = async (req, res, next) => { - if (req.session.user) { - return next(); - } else { + if (req.session.user) return next(); + else { const redirectURL = ((req.originalUrl.includes("login") || req.originalUrl === "/") ? "/selector" : req.originalUrl); const state = Math.random().toString(36).substring(5); req.client.states[state] = redirectURL; diff --git a/dashboard/routes/discord.js b/dashboard/routes/discord.js index 0bacdaa6..5b8f0a68 100644 --- a/dashboard/routes/discord.js +++ b/dashboard/routes/discord.js @@ -7,9 +7,8 @@ const fetch = require("node-fetch"), // Gets login page router.get("/login", async function(req, res) { - if (!req.user || !req.user.id || !req.user.guilds) { - return res.redirect(`https://discordapp.com/api/oauth2/authorize?client_id=${req.client.user.id}&scope=identify%20guilds&response_type=code&redirect_uri=${encodeURIComponent(req.client.config.dashboard.baseURL+"/api/callback")}&state=${req.query.state || "no"}`); - }; + if (!req.user || !req.user.id || !req.user.guilds) return res.redirect(`https://discordapp.com/api/oauth2/authorize?client_id=${req.client.user.id}&scope=identify%20guilds&response_type=code&redirect_uri=${encodeURIComponent(req.client.config.dashboard.baseURL+"/api/callback")}&state=${req.query.state || "no"}`); + res.redirect("/selector"); }); @@ -19,9 +18,11 @@ router.get("/callback", async (req, res) => { if (req.query.code) { const guildID = req.query.state.substr("invite".length, req.query.state.length); req.client.knownGuilds.push({ id: guildID, user: req.user.id }); + return res.redirect("/manage/"+guildID); }; }; + const redirectURL = req.client.states[req.query.state] || "/selector"; const params = new URLSearchParams(); params.set("grant_type", "authorization_code"); @@ -35,8 +36,10 @@ router.get("/callback", async (req, res) => { "Content-Type": "application/x-www-form-urlencoded" } }); + // Fetch tokens (used to fetch user informations) const tokens = await response.json(); + // If the code isn't valid if (tokens.error || !tokens.access_token) return res.redirect(`/api/login&state=${req.query.state}`); const userData = { @@ -54,6 +57,7 @@ router.get("/callback", async (req, res) => { if (json.retry_after) await req.client.wait(json.retry_after); else userData.infos = json; }; + /* User guilds */ if (!userData.guilds) { response = await fetch("https://discordapp.com/api/users/@me/guilds", { @@ -65,9 +69,11 @@ router.get("/callback", async (req, res) => { else userData.guilds = json; }; }; + /* Change format (from "0": { data }, "1": { data }, etc... to [ { data }, { data } ]) */ const guilds = []; - for(const guildPos in userData.guilds) guilds.push(userData.guilds[guildPos]); + for (const guildPos in userData.guilds) guilds.push(userData.guilds[guildPos]); + // Update session req.session.user = { ... userData.infos, ... { guilds } }; const user = await req.client.users.fetch(req.session.user.id); diff --git a/dashboard/routes/guild-manager.js b/dashboard/routes/guild-manager.js index 5b6a5398..18a37dc9 100644 --- a/dashboard/routes/guild-manager.js +++ b/dashboard/routes/guild-manager.js @@ -42,12 +42,9 @@ router.post("/:serverID", CheckAuth, async(req, res) => { if (data.language) { const language = req.client.languages.find((language) => language.aliases[0].toLowerCase() === data.language.toLowerCase()); - if (language) { - guildData.language = language.name; - }; - if (data.prefix.length >= 1 && data.prefix.length < 2000) { - guildData.prefix = data.prefix; - }; + if (language) guildData.language = language.name; + if (data.prefix.length >= 1 && data.prefix.length < 2000) guildData.prefix = data.prefix; + await guildData.save(); }; @@ -120,21 +117,15 @@ router.post("/:serverID", CheckAuth, async(req, res) => { }; if (Object.prototype.hasOwnProperty.call(data, "suggestions")) { - if (data.suggestions === req.translate("common:NO_CHANNEL")) { - guildData.plugins.suggestions = false; - } else { - guildData.plugins.suggestions = guild.channels.cache.find((ch) => "#"+ch.name === data.suggestions).id; - }; - if (data.modlogs === req.translate("common:NO_CHANNEL")) { - guildData.plugins.modlogs = false; - } else { - guildData.plugins.modlogs = guild.channels.cache.find((ch) => "#"+ch.name === data.modlogs).id; - }; - if (data.fortniteshop === req.translate("common:NO_CHANNEL")) { - guildData.plugins.fortniteshop = false; - } else { - guildData.plugins.fortniteshop = guild.channels.cache.find((ch) => "#"+ch.name === data.fortniteshop).id; - }; + if (data.suggestions === req.translate("common:NO_CHANNEL")) guildData.plugins.suggestions = false; + else guildData.plugins.suggestions = guild.channels.cache.find((ch) => "#"+ch.name === data.suggestions).id; + + if (data.modlogs === req.translate("common:NO_CHANNEL")) guildData.plugins.modlogs = false; + else guildData.plugins.modlogs = guild.channels.cache.find((ch) => "#"+ch.name === data.modlogs).id; + + if (data.fortniteshop === req.translate("common:NO_CHANNEL")) guildData.plugins.fortniteshop = false; + else guildData.plugins.fortniteshop = guild.channels.cache.find((ch) => "#"+ch.name === data.fortniteshop).id; + guildData.markModified("plugins"); }; diff --git a/dashboard/routes/guild-stats.js b/dashboard/routes/guild-stats.js index 8a776e62..863e0336 100644 --- a/dashboard/routes/guild-stats.js +++ b/dashboard/routes/guild-stats.js @@ -25,14 +25,16 @@ router.get("/:serverID", CheckAuth, async(req, res) => { level: sortArrayOfObjects("level", membersData) }; - for(const cat in leaderboards){ + for (const cat in leaderboards) { const e = leaderboards[cat]; if (e.length > 10) e.length = 10; - } + }; + const stats = { money: await utils.fetchUsers(leaderboards.money, req.client), level: await utils.fetchUsers(leaderboards.level, req.client) }; + res.render("stats/guild", { stats, commands: getCommands(guildInfos.commands.filter((c) => c.date > Date.now()-604800000)), @@ -49,22 +51,17 @@ function getCommands(commands) { const aDateCommand = {}; commands.forEach((cmd) => { const tDate = formatDate(new Date(cmd.date)); - if (aDateCommand[tDate]) { - aDateCommand[tDate]++; - } else { - aDateCommand[tDate] = 1; - }; + if (aDateCommand[tDate]) aDateCommand[tDate]++; + else aDateCommand[tDate] = 1; }); return aDateCommand; }; function getCommandsUsage(commands) { const objectCount = commands.reduce((acc, curr) => { - if (typeof acc[curr.command] == "undefined") { - acc[curr.command] = 1; - } else { - acc[curr.command] += 1; - } + if (typeof acc[curr.command] == "undefined") acc[curr.command] = 1; + else acc[curr.command] += 1; + return acc; }, {}); const percentages = getPercentagePerKey(objectCount); // [ { key: "help", percentage: 20 } ] @@ -74,6 +71,7 @@ function getCommandsUsage(commands) { p.color = colors[i]; i++; }); + return percentages; }; @@ -85,14 +83,14 @@ function getPercentagePerKey(myArray) { const percentage = Math.round((val / sum) * 100); arrayWithPercentages.push({key, percentage}); }; + return arrayWithPercentages; }; function getSum(myArray) { let sum = 0; - for (const key in myArray) { - sum += myArray[key]; - }; + for (const key in myArray) sum += myArray[key]; + return sum; }; @@ -109,5 +107,6 @@ function formatDate(date) { if (dd < 10) dd = `0${dd}` if (mm < 10) mm = `0${mm}` date = `${mm}/${dd}` + return date; }; \ No newline at end of file diff --git a/dashboard/routes/settings.js b/dashboard/routes/settings.js index 7177a8e9..72eadda4 100644 --- a/dashboard/routes/settings.js +++ b/dashboard/routes/settings.js @@ -12,18 +12,18 @@ router.get("/", CheckAuth, async function(req, res) { }); }); -router.post("/", CheckAuth, async function(req, res){ +router.post("/", CheckAuth, async function(req, res) { const user = await req.client.findOrCreateUser({ id: req.user.id }); const data = req.body; - if (data.bio) { - user.bio = data.bio; - }; + if (data.bio) user.bio = data.bio; + if (data.birthdate) { if (checkDate(data.birthdate)) { user.birthdate = checkDate(data.birthdate); user.markModified("birthdate"); }; }; + await user.save(); res.redirect(303, "/settings"); }); @@ -33,19 +33,18 @@ module.exports = router; /** * @returns {Boolean} */ -function checkDate(birthdate){ +function checkDate(birthdate) { const [day, month, year] = birthdate; if (!day || !month || !year) return false; const match = birthdate.match(/\d+/g); if (!match) return false; const tday = + match[0], tmonth = + match[1] - 1; let tyear = + match[2]; - if (tyear < 100) { - tyear += tyear < 50 ? 2000 : 1900; - }; + if (tyear < 100) tyear += tyear < 50 ? 2000 : 1900; const d = new Date(tyear, tmonth, tday); if (!(tday == d.getDate() && tmonth == d.getMonth() && tyear == d.getFullYear())) return false; if (d.getTime() > Date.now()) return false; if (d.getTime() < (Date.now() - 2.523e+12)) return false; + return d; }; \ No newline at end of file diff --git a/dashboard/utils.js b/dashboard/utils.js index 6c40e0bf..5a755c0f 100644 --- a/dashboard/utils.js +++ b/dashboard/utils.js @@ -6,9 +6,10 @@ const Discord = require("discord.js"); * @param {object} client The discord client instance * @param {array} guilds The user guilds */ -async function fetchGuild(guildID, client, guilds){ +async function fetchGuild(guildID, client, guilds) { const guild = client.guilds.cache.get(guildID); - const conf = await client.findOrCreateGuild({id:guild.id}); + const conf = await client.findOrCreateGuild({ id:guild.id }); + return { ...guild, ...conf.toJSON(), ...guilds.find((g) => g.id === guild.id) }; }; @@ -19,27 +20,25 @@ async function fetchGuild(guildID, client, guilds){ * @param {string} query The optional query for guilds * @returns {object} The user informations */ -async function fetchUser(userData, client, query){ +async function fetchUser(userData, client, query) { if (userData.guilds) { userData.guilds.forEach((guild) => { if (!client.guilds.cache.get(guild.id)) return; const perms = new Discord.Permissions(guild.permissions); - if (perms.has("MANAGE_GUILD")) { - guild.admin = true; - }; + if (perms.has("MANAGE_GUILD")) guild.admin = true; + guild.settingsUrl = (client.guilds.cache.get(guild.id) ? `/manage/${guild.id}/` : `https://discordapp.com/oauth2/authorize?client_id=${client.user.id}&scope=bot&permissions=8&guild_id=${guild.id}`); guild.statsUrl = (client.guilds.cache.get(guild.id) ? `/stats/${guild.id}/` : `https://discordapp.com/oauth2/authorize?client_id=${client.user.id}&scope=bot&permissions=8&guild_id=${guild.id}`); guild.iconURL = (guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.png?size=128` : "https://discordemoji.com/assets/emoji/discordcry.png"); guild.displayed = (query ? guild.name.toLowerCase().includes(query.toLowerCase()) : true); }); userData.displayedGuilds = userData.guilds.filter((g) => g.displayed && g.admin); - if (userData.displayedGuilds.length < 1) { - delete userData.displayedGuilds; - }; + if (userData.displayedGuilds.length < 1) delete userData.displayedGuilds; }; const user = await client.users.fetch(userData.id); const userDb = await client.findOrCreateUser({ id: user.id }, true); const userInfos = { ...user.toJSON(), ...userDb, ...userData, ...user.presence }; + return userInfos; }; diff --git a/dashboard/views/404.ejs b/dashboard/views/404.ejs index 480c17a1..89ee5592 100644 --- a/dashboard/views/404.ejs +++ b/dashboard/views/404.ejs @@ -1,17 +1,17 @@ - <%- include('includes/head') %> -
-