From 449acec174629bc8a1031068832586ac968babdf Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 18:23:20 +1100 Subject: [PATCH 01/27] Delete message after filtering prohibited content. --- listeners/filter.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/listeners/filter.js b/listeners/filter.js index ae6c3e75..45938864 100644 --- a/listeners/filter.js +++ b/listeners/filter.js @@ -15,38 +15,40 @@ export class GuildMessageListener extends Listener { async run(message) { // Check if the author is a bot if (message.author.bot) return; - + if (features.filter.link || features.filter.phrase) { try { const filterURL = `${process.env.siteAddress}/api/filter`; const bodyJSON = { content: message.content }; - + const response = await fetch(filterURL, { method: 'POST', body: JSON.stringify(bodyJSON), headers: { - 'Content-Type': 'application/json', - 'x-access-token': process.env.apiKey + 'Content-Type': 'application/json', + 'x-access-token': process.env.apiKey } }) - + const dataResponse = await response.json(); console.log(dataResponse); - + if (message.author.isbot) return - + if (dataResponse.success == false) { + message.delete(); // Delete the message + let embed = new EmbedBuilder() - .setTitle(`Prohibited content has been detected!`) - .setDescription(`${message.author.username} please don't advertise or say prohibited content/phrases. If you continue, you will be punished.`) - .setColor(`#ff3333`) - message.reply({embeds: [embed]}); + .setTitle(`Prohibited content has been detected!`) + .setDescription(`${message.author.username} please don't advertise or say prohibited content/phrases. If you continue, you will be punished.`) + .setColor(`#ff3333`) + message.reply({ embeds: [embed] }); } - + } catch (error) { console.log(error); return - } + } } } } \ No newline at end of file From 3f3ab8742706dfdd53258f6a088d16fe18802c61 Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 18:29:28 +1100 Subject: [PATCH 02/27] Fix spacing in network log messages. --- api/routes/discord.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/routes/discord.js b/api/routes/discord.js index 72de598c..fefa23f0 100644 --- a/api/routes/discord.js +++ b/api/routes/discord.js @@ -12,7 +12,7 @@ export default function discordApiRoute(app, client, config, db, features, lang) const guild = client.guilds.cache.get(config.discord.guildId); const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - channel.send(`:twisted_rightwards_arrows: | \`${username}\` switched to \`${server}\``); + channel.send(`:twisted_rightwards_arrows: | \`${username}\` switched to \`${server}\``); return res.send({ success: true @@ -37,7 +37,7 @@ export default function discordApiRoute(app, client, config, db, features, lang) const guild = client.guilds.cache.get(config.discord.guildId); const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - channel.send(`**${server}** | \`${username}\` :: ${content}`); + channel.send(`**${server}** | \`${username}\` :: ${content}`); return res.send({ success: true @@ -58,7 +58,7 @@ export default function discordApiRoute(app, client, config, db, features, lang) const guild = client.guilds.cache.get(config.discord.guildId); const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - channel.send(`:ballot_box_with_check: | \`${username}\` has joined the Network.`); + channel.send(`:ballot_box_with_check: | \`${username}\` has joined the Network.`); } catch (error) { return res.send({ success: false, @@ -75,7 +75,7 @@ export default function discordApiRoute(app, client, config, db, features, lang) const guild = client.guilds.cache.get(config.discord.guildId); const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - channel.send(`:negative_squared_cross_mark: | \`${username}\` has left the Network.`); + channel.send(`:negative_squared_cross_mark: | \`${username}\` has left the Network.`); res.send({ success: true From 08276c85afc331b88c221f941508e3dcbee74fb0 Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 18:32:24 +1100 Subject: [PATCH 03/27] Make usernames more presentable in logs. --- listeners/filter.js | 2 +- listeners/messageDelete.js | 3 +-- listeners/messageUpdate.js | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/listeners/filter.js b/listeners/filter.js index 45938864..6e5245e0 100644 --- a/listeners/filter.js +++ b/listeners/filter.js @@ -40,7 +40,7 @@ export class GuildMessageListener extends Listener { let embed = new EmbedBuilder() .setTitle(`Prohibited content has been detected!`) - .setDescription(`${message.author.username} please don't advertise or say prohibited content/phrases. If you continue, you will be punished.`) + .setDescription(`\`${message.author.username}\` please don't advertise or say prohibited content/phrases. If you continue, you will be punished.`) .setColor(`#ff3333`) message.reply({ embeds: [embed] }); } diff --git a/listeners/messageDelete.js b/listeners/messageDelete.js index 9d4fe186..a940732b 100644 --- a/listeners/messageDelete.js +++ b/listeners/messageDelete.js @@ -18,11 +18,10 @@ export class GuildMessageDeleteListener extends Listener { let adminLogChannel = message.guild.channels.cache.find(c => c.id === config.discord.channels.adminLog); if (!adminLogChannel) return; - const embed = new EmbedBuilder() .setTitle('Message Delete') .setColor(Colors.Red) - .setDescription(`Message deleted from ${message.author.username} in ${message.channel.name}`) + .setDescription(`Message deleted from \`${message.author.username}\` in \`#${message.channel.name}\``) .addFields( { name: 'Channel', value: `${message.channel.name}`, inline: false }, { name: 'Deleted Message', value: `${message.content}`, inline: false } diff --git a/listeners/messageUpdate.js b/listeners/messageUpdate.js index f4af83ac..dad4eea3 100644 --- a/listeners/messageUpdate.js +++ b/listeners/messageUpdate.js @@ -21,9 +21,9 @@ export class GuildMessageUpdateListener extends Listener { const embed = new EmbedBuilder() .setTitle('Message Edit') .setColor(Colors.Yellow) - .setDescription(`Message edit from ${oldMessage.author.username} in ${oldMessage.channel.name}`) + .setDescription(`Message edit from \`${oldMessage.author.username}\` in \`#${oldMessage.channel.name}\``) .addFields( - { name: 'Channel', value: `${oldMessage.channel.name}`, inline: false }, + { name: 'Channel', value: `\`$#{oldMessage.channel.name}\``, inline: false }, { name: 'Old Message', value: `${oldMessage.content}`, inline: false }, { name: 'Edited Message', value: `${newMessage.content}`, inline: false } ); From 6dffe68e67d8bd4c5a7d466c864f8a9cae209ecf Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 18:36:18 +1100 Subject: [PATCH 04/27] Remove deleted channel field from being mentioned twice. --- listeners/messageDelete.js | 1 - listeners/messageUpdate.js | 1 - 2 files changed, 2 deletions(-) diff --git a/listeners/messageDelete.js b/listeners/messageDelete.js index a940732b..a0d266d5 100644 --- a/listeners/messageDelete.js +++ b/listeners/messageDelete.js @@ -23,7 +23,6 @@ export class GuildMessageDeleteListener extends Listener { .setColor(Colors.Red) .setDescription(`Message deleted from \`${message.author.username}\` in \`#${message.channel.name}\``) .addFields( - { name: 'Channel', value: `${message.channel.name}`, inline: false }, { name: 'Deleted Message', value: `${message.content}`, inline: false } ); diff --git a/listeners/messageUpdate.js b/listeners/messageUpdate.js index dad4eea3..b1bd3b91 100644 --- a/listeners/messageUpdate.js +++ b/listeners/messageUpdate.js @@ -23,7 +23,6 @@ export class GuildMessageUpdateListener extends Listener { .setColor(Colors.Yellow) .setDescription(`Message edit from \`${oldMessage.author.username}\` in \`#${oldMessage.channel.name}\``) .addFields( - { name: 'Channel', value: `\`$#{oldMessage.channel.name}\``, inline: false }, { name: 'Old Message', value: `${oldMessage.content}`, inline: false }, { name: 'Edited Message', value: `${newMessage.content}`, inline: false } ); From e6e86b3eeb4c8f5316ebcea1dd6e6b87096fba57 Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 18:48:15 +1100 Subject: [PATCH 05/27] Fixed issue where filter errors after response is sent. --- api/routes/filter.js | 70 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/api/routes/filter.js b/api/routes/filter.js index bb9c1bda..76037af8 100644 --- a/api/routes/filter.js +++ b/api/routes/filter.js @@ -1,71 +1,73 @@ -import {expandString, isFeatureEnabled, required} from '../common'; -import filter from '../../filter.json' assert {type: "json"}; +import { expandString, isFeatureEnabled, required } from '../common'; +import filter from '../../filter.json' assert { type: "json" }; export default function filterApiRoute(app, config, db, features, lang) { const baseEndpoint = '/api/filter'; - app.post(baseEndpoint, async function(req, res) { + app.post(baseEndpoint, async function (req, res) { function expandString(string, filter) { var regexString = ""; for (var i = 0; i < string.length; i++) { - // If the character does not have any aliases then just - // use the character. Note, this is a regex character. if (string[i] in filter.alias) regexString += "[" + filter.alias[string[i]] + "]"; else regexString += string[i] } - regexString = regexString.replace(".", "\\.") - return regexString + regexString = regexString.replace(".", "\\."); + return regexString; } - - // Hack to show the error we expect when both are disabled + if (!features.filter.phrase && !features.filter.link) - return isFeatureEnabled(false, res, lang) - + return isFeatureEnabled(false, res, lang); + const content = required(req.body, "content", res); - var bannedWords = [] + var bannedWords = []; if (features.filter.phrase) - bannedWords = bannedWords.concat(filter.phrases) + bannedWords = bannedWords.concat(filter.phrases); if (features.filter.link) - bannedWords = bannedWords.concat(filter.links) - - var bannedRegex = [] - // Usually compiling regex on the fly like this isn't recommended. - // You can compile regex once and then reuse it. Since performance - // isn't a big deal and the word list is yet to expand, this will - // suffice for now. + bannedWords = bannedWords.concat(filter.links); + + var bannedRegex = []; bannedWords.forEach(bannedWord => { - bannedRegex.push(new RegExp(expandString(bannedWord, filter))) - }) + bannedRegex.push(new RegExp(expandString(bannedWord, filter))); + }); + + let responseSent = false; try { const wordList = content.split(" "); - bannedRegex.forEach(re => { - wordList.forEach(word => { + for (let i = 0; i < bannedRegex.length; i++) { + const re = bannedRegex[i]; + for (let j = 0; j < wordList.length; j++) { + const word = wordList[j]; if (re.test(word)) { - return res.send({ + res.send({ success: false, message: lang.filter.phraseCaught }); + responseSent = true; + break; } + } + if (responseSent) { + break; + } + } + + if (!responseSent) { + res.send({ + success: true, + message: `Content Clean` }); - }); - return res.send({ - success: true, - message: `Content Clean` - }); + } } catch (error) { console.log(error); - return res.send({ + res.send({ success: false, message: lang.web.registrationError }); } - - return res; }); - } \ No newline at end of file From 9461d6db60c8be7da27cbcbaeb85ceb01da2bf9e Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 19:12:00 +1100 Subject: [PATCH 06/27] Changed from HEX to Colour --- listeners/guildMemberBoostUpdate.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/listeners/guildMemberBoostUpdate.js b/listeners/guildMemberBoostUpdate.js index 33d169e3..ff33e7a0 100644 --- a/listeners/guildMemberBoostUpdate.js +++ b/listeners/guildMemberBoostUpdate.js @@ -1,6 +1,6 @@ import { Listener } from '@sapphire/framework'; import config from '../config.json' assert {type: "json"}; -import { EmbedBuilder } from 'discord.js'; +import { Colors, EmbedBuilder } from 'discord.js'; import features from '../features.json' assert {type: "json"}; export class GuildMemberBoostUpdateListener extends Listener { @@ -25,8 +25,8 @@ export class GuildMemberBoostUpdateListener extends Listener { if (!oldStatus && newStatus) { let embed = new EmbedBuilder() - .setTitle(`${newMember.user.username} has boosted the Server! :tada:`) - .setColor(`#f47fff`) + .setTitle(`\`${newMember.user.username}\` has boosted the Server! :tada:`) + .setColor(Colors.DarkVividPink) welcomechannel.send({embeds: [embed]}); } return; From bb011d4aead1f5ebeeddea308d55c13573623768 Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 19:44:37 +1100 Subject: [PATCH 07/27] Add /poll command. --- commands/poll.mjs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 commands/poll.mjs diff --git a/commands/poll.mjs b/commands/poll.mjs new file mode 100644 index 00000000..96fce5fa --- /dev/null +++ b/commands/poll.mjs @@ -0,0 +1,35 @@ +import { Command, RegisterBehavior } from '@sapphire/framework'; +import { Colors, EmbedBuilder } from 'discord.js'; + +export class PollCommand extends Command { + constructor(context, options) { + super(context, { ...options }); + } + + registerApplicationCommands(registry) { + registry.registerChatInputCommand((builder) => + builder.setName('poll').setDescription('Ask everyone a question or something to vote on!') + .addStringOption((option) => + option // + .setName('question') + .setDescription('Question to ask in the poll.') + .setRequired(true) + ) + ); + } + + async chatInputRun(interaction) { + const pollQuestion = interaction.options.getString('question'); + + const embed = new EmbedBuilder() + .setTitle(`Poll by \`${interaction.user.username}\``) + .setDescription(`${pollQuestion}`) + .setFooter({ text: 'Vote using the reactions below to have your say!' }) + .setColor(Colors.Blue) + + const message = await interaction.reply({ embeds: [embed], fetchReply: true }); + + await message.react('⬆️'); + await message.react('⬇️'); + } +} \ No newline at end of file From 8c8c14d023fe5a8dcea2ba10366ea8be414b3e30 Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 20:02:25 +1100 Subject: [PATCH 08/27] Add page descriptions to headers. --- .../announcements/announcements-editor.ejs | 2 +- .../announcements/announcements-list.ejs | 2 +- .../applications/application-editor.ejs | 2 +- .../applications/application-list.ejs | 2 +- views/dashboard/dashboard-index.ejs | 2 +- views/dashboard/index.ejs | 20 ------------------- views/dashboard/logs.ejs | 2 +- views/dashboard/servers/server-editor.ejs | 2 +- views/dashboard/servers/server-list.ejs | 2 +- views/modules/header.ejs | 17 +--------------- views/modules/play/play.ejs | 2 +- views/partials/miniHeader.ejs | 2 +- views/session/notFound.ejs | 2 +- 13 files changed, 12 insertions(+), 47 deletions(-) delete mode 100644 views/dashboard/index.ejs diff --git a/views/dashboard/announcements/announcements-editor.ejs b/views/dashboard/announcements/announcements-editor.ejs index 3b4c1916..0f1ef905 100644 --- a/views/dashboard/announcements/announcements-editor.ejs +++ b/views/dashboard/announcements/announcements-editor.ejs @@ -1,6 +1,6 @@ <%- include("../../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Dashboard for platform" + pageDescription: "Editor for Network Announcements." }) %> <%- include("../../modules/navigationBar.ejs") %> diff --git a/views/dashboard/announcements/announcements-list.ejs b/views/dashboard/announcements/announcements-list.ejs index 50be0ed8..c390fe18 100644 --- a/views/dashboard/announcements/announcements-list.ejs +++ b/views/dashboard/announcements/announcements-list.ejs @@ -1,6 +1,6 @@ <%- include("../../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Dashboard for platform" + pageDescription: "List of all Network Announcements" }) %> <%- include("../../modules/navigationBar.ejs") %> diff --git a/views/dashboard/applications/application-editor.ejs b/views/dashboard/applications/application-editor.ejs index 948488f1..fed4f7df 100644 --- a/views/dashboard/applications/application-editor.ejs +++ b/views/dashboard/applications/application-editor.ejs @@ -1,6 +1,6 @@ <%- include("../../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Dashboard for platform" + pageDescription: "Editor for Network Applications" }) %> <%- include("../../modules/navigationBar.ejs") %> diff --git a/views/dashboard/applications/application-list.ejs b/views/dashboard/applications/application-list.ejs index f2b884ce..9e9ce269 100644 --- a/views/dashboard/applications/application-list.ejs +++ b/views/dashboard/applications/application-list.ejs @@ -1,6 +1,6 @@ <%- include("../../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Dashboard for platform" + pageDescription: "List of all Network Applications" }) %> <%- include("../../modules/navigationBar.ejs") %> diff --git a/views/dashboard/dashboard-index.ejs b/views/dashboard/dashboard-index.ejs index 61ebe928..553a8bd4 100644 --- a/views/dashboard/dashboard-index.ejs +++ b/views/dashboard/dashboard-index.ejs @@ -1,6 +1,6 @@ <%- include("../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Dashboard for platform" + pageDescription: "The dashboard for the Network Administration Panel" }) %> <%- include("../modules/navigationBar.ejs") %> diff --git a/views/dashboard/index.ejs b/views/dashboard/index.ejs deleted file mode 100644 index b946f554..00000000 --- a/views/dashboard/index.ejs +++ /dev/null @@ -1,20 +0,0 @@ -<%- include("../modules/dashboard/header.ejs", { - pageTitle: pageTitle, - pageDescription: "The backend dashboard." -}) %> - -<%- include("../modules/dashboard/sidebar.ejs") %> - -<%- include("../modules/dashboard/navigation.ejs") %> - -
-
-
-
- <%- include("../modules/dashboard/statCards.ejs") %> - -
- -
- -<%- include("../modules/dashboard/footer.ejs") %> \ No newline at end of file diff --git a/views/dashboard/logs.ejs b/views/dashboard/logs.ejs index aefcf817..087cb5de 100644 --- a/views/dashboard/logs.ejs +++ b/views/dashboard/logs.ejs @@ -1,6 +1,6 @@ <%- include("../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Logs" + pageDescription: "Logs of all Network Administration events." }) %> <%- include("../modules/navigationBar.ejs") %> diff --git a/views/dashboard/servers/server-editor.ejs b/views/dashboard/servers/server-editor.ejs index 8ad3927a..a0394e83 100644 --- a/views/dashboard/servers/server-editor.ejs +++ b/views/dashboard/servers/server-editor.ejs @@ -1,6 +1,6 @@ <%- include("../../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Dashboard for platform" + pageDescription: "Editor for Network Servers." }) %> <%- include("../../modules/navigationBar.ejs") %> diff --git a/views/dashboard/servers/server-list.ejs b/views/dashboard/servers/server-list.ejs index baafa944..5cb70721 100644 --- a/views/dashboard/servers/server-list.ejs +++ b/views/dashboard/servers/server-list.ejs @@ -1,6 +1,6 @@ <%- include("../../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "Dashboard for platform" + pageDescription: "List of all Network Servers." }) %> <%- include("../../modules/navigationBar.ejs") %> diff --git a/views/modules/header.ejs b/views/modules/header.ejs index 389b0ac7..3d1715b4 100644 --- a/views/modules/header.ejs +++ b/views/modules/header.ejs @@ -22,7 +22,7 @@ - + @@ -34,15 +34,6 @@ - - @@ -55,12 +46,6 @@ - - - - - - diff --git a/views/modules/play/play.ejs b/views/modules/play/play.ejs index d9004d28..8f99b51a 100644 --- a/views/modules/play/play.ejs +++ b/views/modules/play/play.ejs @@ -1,6 +1,6 @@ <%- include("../../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "The home page." + pageDescription: "List of all of our Network Servers to connect." }) %> <%- include("../../modules/navigationBar.ejs") %> diff --git a/views/partials/miniHeader.ejs b/views/partials/miniHeader.ejs index 8af54844..13377189 100644 --- a/views/partials/miniHeader.ejs +++ b/views/partials/miniHeader.ejs @@ -1,4 +1,4 @@ -
+
diff --git a/views/session/notFound.ejs b/views/session/notFound.ejs index 7ab75c3e..9c4e74d3 100644 --- a/views/session/notFound.ejs +++ b/views/session/notFound.ejs @@ -1,6 +1,6 @@ <%- include("../modules/header.ejs", { pageTitle: pageTitle, - pageDescription: "An error has occured and cannot load this page." + pageDescription: "An error has occurred and cannot load this page." }) %> <%- include("../modules/navigationBar.ejs") %> From 582aa41abb6dbbf99cf89c413baa2ca32d121448 Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 14 Nov 2023 22:20:15 +1100 Subject: [PATCH 09/27] Added keywords and SEO option to configuration. --- config.json | 1 + views/modules/header.ejs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/config.json b/config.json index f496814e..a77a2f9a 100644 --- a/config.json +++ b/config.json @@ -3,6 +3,7 @@ "siteConfiguration": { "siteName": "Crafting For Christ", "tagline": "Crafting A Christ Centred Gaming Community", + "keywords": "Christian, Minecraft, Faith, Gaming, Ministry, Community, Believers, Experience, Crafting, Creativity, Worship, Scripture, Fellowship, Gameplay, Builds, Christian Minecraft Server, Faith-based Gaming Community, Minecraft for Christians, Christ-Centered Gameplay, Bible-inspired Builds, Virtual Fellowship, Gaming Ministry, Christian Gaming Experience, Building Faith in Minecraft, Community of Faithful Gamers, Gaming and Worship, Scripture-based Creativity, Christian Fellowship in Minecraft", "email": "support@craftingforchrist.net", "policy": { "termsOfService": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/terms.md", diff --git a/views/modules/header.ejs b/views/modules/header.ejs index 3d1715b4..687a44c8 100644 --- a/views/modules/header.ejs +++ b/views/modules/header.ejs @@ -16,7 +16,10 @@ <%= pageTitle %> + + + From 7d3f93d3420c5be05e50433ae9da0e4dd9f01f48 Mon Sep 17 00:00:00 2001 From: benrobson Date: Wed, 15 Nov 2023 20:51:04 +1100 Subject: [PATCH 10/27] Add documentation badges for list and editors. --- api/common.js | 2 +- views/dashboard/announcements/announcements-editor.ejs | 5 +++++ views/dashboard/announcements/announcements-list.ejs | 3 +++ views/dashboard/applications/application-editor.ejs | 5 +++++ views/dashboard/applications/application-list.ejs | 3 +++ views/dashboard/servers/server-editor.ejs | 3 ++- views/dashboard/servers/server-list.ejs | 3 +++ views/partials/documentationLink.ejs | 6 +++--- 8 files changed, 25 insertions(+), 5 deletions(-) diff --git a/api/common.js b/api/common.js index e5912ede..ed4585c6 100644 --- a/api/common.js +++ b/api/common.js @@ -192,7 +192,7 @@ export async function getGlobalImage() { // Now files is an Array of the name of the files in the folder and you can pick a random name inside of that array. let chosenFile = await files[Math.floor(Math.random() * files.length)] - return "../images/globalImages/" + chosenFile; + return "../../../images/globalImages/" + chosenFile; } /* diff --git a/views/dashboard/announcements/announcements-editor.ejs b/views/dashboard/announcements/announcements-editor.ejs index 0f1ef905..51752193 100644 --- a/views/dashboard/announcements/announcements-editor.ejs +++ b/views/dashboard/announcements/announcements-editor.ejs @@ -15,6 +15,11 @@ <%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
+ <%- include("../../partials/documentationLink.ejs", { + doclink: "https://modularsoft.org/docs/products/zander/features/announcement/" + }) %> +

+
<% if (type === 'create') { %>
diff --git a/views/dashboard/announcements/announcements-list.ejs b/views/dashboard/announcements/announcements-list.ejs index c390fe18..5aa25ab7 100644 --- a/views/dashboard/announcements/announcements-list.ejs +++ b/views/dashboard/announcements/announcements-list.ejs @@ -16,6 +16,9 @@
+ <%- include("../../partials/documentationLink.ejs", { + doclink: "https://modularsoft.org/docs/products/zander/features/announcement/" + }) %>

<% if (req.cookies.alertType) { %> diff --git a/views/dashboard/applications/application-editor.ejs b/views/dashboard/applications/application-editor.ejs index fed4f7df..c2599d3f 100644 --- a/views/dashboard/applications/application-editor.ejs +++ b/views/dashboard/applications/application-editor.ejs @@ -15,6 +15,11 @@ <%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
+ <%- include("../../partials/documentationLink.ejs", { + doclink: "https://modularsoft.org/docs/products/zander/features/application/" + }) %> +

+
<% if (type === 'create') { %> diff --git a/views/dashboard/applications/application-list.ejs b/views/dashboard/applications/application-list.ejs index 9e9ce269..461259ce 100644 --- a/views/dashboard/applications/application-list.ejs +++ b/views/dashboard/applications/application-list.ejs @@ -16,6 +16,9 @@
+ <%- include("../../partials/documentationLink.ejs", { + doclink: "https://modularsoft.org/docs/products/zander/features/application/" + }) %>

<% if (req.cookies.alertType) { %> diff --git a/views/dashboard/servers/server-editor.ejs b/views/dashboard/servers/server-editor.ejs index a0394e83..713a6ee7 100644 --- a/views/dashboard/servers/server-editor.ejs +++ b/views/dashboard/servers/server-editor.ejs @@ -16,8 +16,9 @@
<%- include("../../partials/documentationLink.ejs", { - doclink: "https://modularsoft.org/docs/products/zander/" + doclink: "https://modularsoft.org/docs/products/zander/features/server/" }) %> +

<% if (type === 'create') { %> diff --git a/views/dashboard/servers/server-list.ejs b/views/dashboard/servers/server-list.ejs index 5cb70721..c44eb1fc 100644 --- a/views/dashboard/servers/server-list.ejs +++ b/views/dashboard/servers/server-list.ejs @@ -16,6 +16,9 @@
+ <%- include("../../partials/documentationLink.ejs", { + doclink: "https://modularsoft.org/docs/products/zander/features/server/" + }) %>

<% if (req.cookies.alertType) { %> diff --git a/views/partials/documentationLink.ejs b/views/partials/documentationLink.ejs index 82ed99b7..9b349ce8 100644 --- a/views/partials/documentationLink.ejs +++ b/views/partials/documentationLink.ejs @@ -1,3 +1,3 @@ - - -

\ No newline at end of file + + + \ No newline at end of file From af0bce56eb01bd2c7e2cbf19e983b36275ef1317 Mon Sep 17 00:00:00 2001 From: benrobson Date: Wed, 15 Nov 2023 21:41:34 +1100 Subject: [PATCH 11/27] Push mobile view changes for session views. --- features.json | 2 +- views/session/error.ejs | 31 ++++++++++++++++--------------- views/session/featureDisabled.ejs | 13 +++++++------ views/session/login.ejs | 16 ++++++++-------- views/session/noPermission.ejs | 31 ++++++++++++++++--------------- views/session/notFound.ejs | 31 ++++++++++++++++--------------- views/session/notLoggedIn.ejs | 25 +++++++++++++------------ views/session/register.ejs | 25 +++++++++---------------- 8 files changed, 86 insertions(+), 88 deletions(-) diff --git a/features.json b/features.json index 32d62640..88c40d64 100644 --- a/features.json +++ b/features.json @@ -18,7 +18,7 @@ }, "web": { "login": true, - "register": true + "register": false }, "smDiscord": true, diff --git a/views/session/error.ejs b/views/session/error.ejs index 8272b490..0916d8d1 100644 --- a/views/session/error.ejs +++ b/views/session/error.ejs @@ -1,25 +1,26 @@ <%- include("../modules/header.ejs", { - pageTitle: pageTitle, - pageDescription: "An error has occured and cannot load this page." + pageTitle: pageTitle, + pageDescription: "This feature has been disabled and is not accessible." }) %> -<%- include("../modules/navigationBar.ejs") %> +<%- include("../modules/navigationBar.ejs", { + features: features +}) %> <%- include("../partials/miniHeader.ejs", { - headerTitle: "Server Error", - backgroundImage: "../images/banner/error.png" + headerTitle: "Feature Disabled", + backgroundImage: globalImage }) %> -
-
-
-
-
- -
+
+
+
+
+
-
+
+

There was an error ;-;

<% if (error.message) { %> <%= error.message %> @@ -31,9 +32,9 @@


If this continues to happen, please report this by either e-mailing our Support Team or join our Community Discord and open a ticket. -
+
-<%- include("../modules/footer.ejs") %> \ No newline at end of file +<%- include("../modules/footer.ejs") %> \ No newline at end of file diff --git a/views/session/featureDisabled.ejs b/views/session/featureDisabled.ejs index 4051fa1d..7ebb316c 100644 --- a/views/session/featureDisabled.ejs +++ b/views/session/featureDisabled.ejs @@ -15,18 +15,19 @@
-
+
- +
-
+

This feature is disabled

-

This feature has been disabled by the System Administator.

+

This feature has been disabled by the System Administrator.




- +
diff --git a/views/session/login.ejs b/views/session/login.ejs index 29cc0891..7761eb25 100644 --- a/views/session/login.ejs +++ b/views/session/login.ejs @@ -13,12 +13,7 @@
-
-
- -
-
-
+
<% if (req.cookies.alertType) { %> <%- include("../partials/alert.ejs", { alertType: req.cookies.alertType, @@ -36,14 +31,19 @@
- +

Don't have an account? You can register here.
+
+
+ +
+
-<%- include("../modules/footer.ejs") %> \ No newline at end of file +<%- include("../modules/footer.ejs") %> \ No newline at end of file diff --git a/views/session/noPermission.ejs b/views/session/noPermission.ejs index 684ff48a..237bab3c 100644 --- a/views/session/noPermission.ejs +++ b/views/session/noPermission.ejs @@ -1,34 +1,35 @@ <%- include("../modules/header.ejs", { - pageTitle: pageTitle, - pageDescription: "Permission to this page is restricted, please ensure you are logged in and have the required access." + pageTitle: pageTitle, + pageDescription: "Permission Denied" }) %> -<%- include("../modules/navigationBar.ejs") %> +<%- include("../modules/navigationBar.ejs", { + features: features +}) %> <%- include("../partials/miniHeader.ejs", { headerTitle: "Permission Denied", - backgroundImage: "../images/banner/error.png" + backgroundImage: globalImage }) %> -
-
-
-
-
- -
+
+
+
+
+
-
-

You do not have permission.

+
+
+

You do not have permission.

Permission to this page is restricted, please ensure you are logged in and have the required access.




-
+
-<%- include("../modules/footer.ejs") %> \ No newline at end of file +<%- include("../modules/footer.ejs") %> \ No newline at end of file diff --git a/views/session/notFound.ejs b/views/session/notFound.ejs index 9c4e74d3..8836349a 100644 --- a/views/session/notFound.ejs +++ b/views/session/notFound.ejs @@ -1,34 +1,35 @@ <%- include("../modules/header.ejs", { - pageTitle: pageTitle, - pageDescription: "An error has occurred and cannot load this page." + pageTitle: pageTitle, + pageDescription: "404: Content Not Found" }) %> -<%- include("../modules/navigationBar.ejs") %> +<%- include("../modules/navigationBar.ejs", { + features: features +}) %> <%- include("../partials/miniHeader.ejs", { headerTitle: "404: Not Found", - backgroundImage: "../images/banner/error.png" + backgroundImage: globalImage }) %> -
-
-
-
-
- -
+
+
+
+
+
-
-

Page cannot be found

+
+
+

Page cannot be found

Looks like you've been greeted by the 404 Horse. It's okay, he won't bite, but he will guide you back to safety. Press the big green button...

Sorry, the page you are looking for no longer exists or has been moved to another location.


-
+
-<%- include("../modules/footer.ejs") %> \ No newline at end of file +<%- include("../modules/footer.ejs") %> \ No newline at end of file diff --git a/views/session/notLoggedIn.ejs b/views/session/notLoggedIn.ejs index e8f8a0e4..dac77f18 100644 --- a/views/session/notLoggedIn.ejs +++ b/views/session/notLoggedIn.ejs @@ -3,32 +3,33 @@ pageDescription: "You must be logged in to use this feature." }) %> -<%- include("../modules/navigationBar.ejs") %> +<%- include("../modules/navigationBar.ejs", { + features: features +}) %> <%- include("../partials/miniHeader.ejs", { headerTitle: "Not Logged In", - backgroundImage: "../images/banner/error.png" + backgroundImage: globalImage }) %> -
-
-
-
-
- -
+
+
+
+
+
-
+
+

You must be logged in to use this feature.

Permission to this page is restricted, please ensure you are logged in to use this feature.




-
+
-<%- include("../modules/footer.ejs") %> \ No newline at end of file +<%- include("../modules/footer.ejs") %> \ No newline at end of file diff --git a/views/session/register.ejs b/views/session/register.ejs index 5bab45bf..ac9c0273 100644 --- a/views/session/register.ejs +++ b/views/session/register.ejs @@ -13,19 +13,7 @@
-
- <% if (req.cookies.alertType) { %> - <%- include("../partials/alert.ejs", { - alertType: req.cookies.alertType, - content: req.cookies.alertContent - }) %> - <% } %> - -
- -
-
-
+
@@ -44,14 +32,19 @@
- +

- Have an account? You can login here. + Have an account? You can login here. +
+
+
+ +
-<%- include("../modules/footer.ejs") %> \ No newline at end of file +<%- include("../modules/footer.ejs") %> \ No newline at end of file From e55c5d979dee49a4b911a3f037575e3d703a238c Mon Sep 17 00:00:00 2001 From: benrobson Date: Wed, 15 Nov 2023 22:02:46 +1100 Subject: [PATCH 12/27] Resolved mobile styling issues with dashboard views. --- assets/css/style.css | 6 +++ .../announcements/announcements-editor.ejs | 4 +- .../announcements/announcements-list.ejs | 4 +- .../applications/application-editor.ejs | 4 +- .../applications/application-list.ejs | 4 +- views/dashboard/dashboard-index.ejs | 8 +-- views/dashboard/servers/server-editor.ejs | 4 +- views/dashboard/servers/server-list.ejs | 4 +- views/modules/dashboard/dashboard-sidebar.ejs | 4 +- views/modules/dashboard/footer.ejs | 43 ---------------- views/modules/dashboard/header.ejs | 30 ------------ views/modules/dashboard/navigation.ejs | 18 ------- views/modules/dashboard/sidebar.ejs | 28 ----------- views/modules/dashboard/statCards.ejs | 49 ------------------- 14 files changed, 24 insertions(+), 186 deletions(-) delete mode 100644 views/modules/dashboard/footer.ejs delete mode 100644 views/modules/dashboard/header.ejs delete mode 100644 views/modules/dashboard/navigation.ejs delete mode 100644 views/modules/dashboard/sidebar.ejs delete mode 100644 views/modules/dashboard/statCards.ejs diff --git a/assets/css/style.css b/assets/css/style.css index 67337c3a..0bb1e59f 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1545,4 +1545,10 @@ a:focus { background-color: #92b4f2; text-align: center; padding: 15px; +} + +@media only screen and (max-width: 767px) { + .dashboard-sidebar { + display: block !important; + } } \ No newline at end of file diff --git a/views/dashboard/announcements/announcements-editor.ejs b/views/dashboard/announcements/announcements-editor.ejs index 51752193..7b36edcc 100644 --- a/views/dashboard/announcements/announcements-editor.ejs +++ b/views/dashboard/announcements/announcements-editor.ejs @@ -11,10 +11,10 @@ }) %>
-
+
<%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
-
+
<%- include("../../partials/documentationLink.ejs", { doclink: "https://modularsoft.org/docs/products/zander/features/announcement/" }) %> diff --git a/views/dashboard/announcements/announcements-list.ejs b/views/dashboard/announcements/announcements-list.ejs index 5aa25ab7..d5734f94 100644 --- a/views/dashboard/announcements/announcements-list.ejs +++ b/views/dashboard/announcements/announcements-list.ejs @@ -11,10 +11,10 @@ }) %>
-
+
<%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
-
+
<%- include("../../partials/documentationLink.ejs", { doclink: "https://modularsoft.org/docs/products/zander/features/announcement/" diff --git a/views/dashboard/applications/application-editor.ejs b/views/dashboard/applications/application-editor.ejs index c2599d3f..2e59e9d3 100644 --- a/views/dashboard/applications/application-editor.ejs +++ b/views/dashboard/applications/application-editor.ejs @@ -11,10 +11,10 @@ }) %>
-
+
<%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
-
+
<%- include("../../partials/documentationLink.ejs", { doclink: "https://modularsoft.org/docs/products/zander/features/application/" }) %> diff --git a/views/dashboard/applications/application-list.ejs b/views/dashboard/applications/application-list.ejs index 461259ce..9c93ce06 100644 --- a/views/dashboard/applications/application-list.ejs +++ b/views/dashboard/applications/application-list.ejs @@ -11,10 +11,10 @@ }) %>
-
+
<%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
-
+
<%- include("../../partials/documentationLink.ejs", { doclink: "https://modularsoft.org/docs/products/zander/features/application/" diff --git a/views/dashboard/dashboard-index.ejs b/views/dashboard/dashboard-index.ejs index 553a8bd4..0797ec2a 100644 --- a/views/dashboard/dashboard-index.ejs +++ b/views/dashboard/dashboard-index.ejs @@ -11,12 +11,12 @@ }) %>
-
+
<%- include("../modules/dashboard/dashboard-sidebar.ejs") %>
-
+

Test

-
+
-<%- include("../modules/footer.ejs") %> \ No newline at end of file +<%- include("../modules/footer.ejs") %> \ No newline at end of file diff --git a/views/dashboard/servers/server-editor.ejs b/views/dashboard/servers/server-editor.ejs index 713a6ee7..e8b55484 100644 --- a/views/dashboard/servers/server-editor.ejs +++ b/views/dashboard/servers/server-editor.ejs @@ -11,10 +11,10 @@ }) %>
-
+
<%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
-
+
<%- include("../../partials/documentationLink.ejs", { doclink: "https://modularsoft.org/docs/products/zander/features/server/" }) %> diff --git a/views/dashboard/servers/server-list.ejs b/views/dashboard/servers/server-list.ejs index c44eb1fc..a00907ed 100644 --- a/views/dashboard/servers/server-list.ejs +++ b/views/dashboard/servers/server-list.ejs @@ -11,10 +11,10 @@ }) %>
-
+
<%- include("../../modules/dashboard/dashboard-sidebar.ejs") %>
-
+
<%- include("../../partials/documentationLink.ejs", { doclink: "https://modularsoft.org/docs/products/zander/features/server/" diff --git a/views/modules/dashboard/dashboard-sidebar.ejs b/views/modules/dashboard/dashboard-sidebar.ejs index 158c8b47..aac445b8 100644 --- a/views/modules/dashboard/dashboard-sidebar.ejs +++ b/views/modules/dashboard/dashboard-sidebar.ejs @@ -8,7 +8,7 @@
-
-
+
\ No newline at end of file diff --git a/views/modules/dashboard/footer.ejs b/views/modules/dashboard/footer.ejs deleted file mode 100644 index 7be84c3e..00000000 --- a/views/modules/dashboard/footer.ejs +++ /dev/null @@ -1,43 +0,0 @@ -
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/views/modules/dashboard/header.ejs b/views/modules/dashboard/header.ejs deleted file mode 100644 index 09c7b350..00000000 --- a/views/modules/dashboard/header.ejs +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - <%= pageTitle %> - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/views/modules/dashboard/navigation.ejs b/views/modules/dashboard/navigation.ejs deleted file mode 100644 index 44132806..00000000 --- a/views/modules/dashboard/navigation.ejs +++ /dev/null @@ -1,18 +0,0 @@ -
-
-
-
-
- -
-
- -
-
-
-
-
\ No newline at end of file diff --git a/views/modules/dashboard/sidebar.ejs b/views/modules/dashboard/sidebar.ejs deleted file mode 100644 index e098258e..00000000 --- a/views/modules/dashboard/sidebar.ejs +++ /dev/null @@ -1,28 +0,0 @@ - - \ No newline at end of file diff --git a/views/modules/dashboard/statCards.ejs b/views/modules/dashboard/statCards.ejs deleted file mode 100644 index 6eedf319..00000000 --- a/views/modules/dashboard/statCards.ejs +++ /dev/null @@ -1,49 +0,0 @@ -
-
-
-
-
-
-
-
Total Profit
-
1,012
-
-
-
-
-
-
-
-
-
-
-
New Customer
-
961
-
-
-
-
-
-
-
-
-
-
-
Active Projects
-
770
-
-
-
-
-
-
-
-
-
-
Referral
-
2,781
-
-
-
-
-
\ No newline at end of file From 7b4b73e1c9de94290c12fae9542777b0fb32ef03 Mon Sep 17 00:00:00 2001 From: benrobson Date: Wed, 15 Nov 2023 22:42:03 +1100 Subject: [PATCH 13/27] Added a staffChannel config option and a /staffhelp command --- commands/staffhelp.mjs | 49 ++++++++++++++++++++++++++++++++++++++++++ config.json | 3 ++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 commands/staffhelp.mjs diff --git a/commands/staffhelp.mjs b/commands/staffhelp.mjs new file mode 100644 index 00000000..be0c5d7b --- /dev/null +++ b/commands/staffhelp.mjs @@ -0,0 +1,49 @@ +import { Command, RegisterBehavior } from '@sapphire/framework'; +import { Colors, EmbedBuilder } from 'discord.js'; +import config from '../config.json' assert {type: "json"}; + +export class StaffHelpCommand extends Command { + constructor(context, options) { + super(context, { ...options }); + } + + registerApplicationCommands(registry) { + registry.registerChatInputCommand((builder) => + builder + .setName('staffhelp') + .setDescription('Sends a message to our Staff for help or assistance.') + .addStringOption((option) => + option // + .setName('query') + .setDescription('Question to ask in the poll.') + .setRequired(true) + ) + ); + } + + async chatInputRun(interaction) { + const userQuery = interaction.options.getString('query'); + + const staffAssistanceEmbed = new EmbedBuilder() + .setTitle(`Staff Assistance Requested by \`${interaction.user.username}\``) + .setDescription(`**Request:** ${userQuery}`) + .setColor(Colors.Gold); + + const staffAssistanceConfirmed = new EmbedBuilder() + .setTitle(`Staff Assistance Requested`) + .setDescription(`Assistance request has been sent.`) + .setColor(Colors.Green); + + const guild = interaction.guild; + const channel = guild.channels.cache.get(config.discord.channels.staffChannel); + + channel.send({ + embeds: [staffAssistanceEmbed] + }); + + interaction.reply({ + embeds: [staffAssistanceConfirmed], + ephemeral: true + }); + } +} \ No newline at end of file diff --git a/config.json b/config.json index a77a2f9a..aca9e2dc 100644 --- a/config.json +++ b/config.json @@ -29,7 +29,8 @@ "channels": { "welcome": "926380663953821736", "networkChatLog": "925702393423859724", - "adminLog": "926380052155867146" + "adminLog": "926380052155867146", + "staffChannel": "926380052155867146" }, "roles": { "verified": "926259482319794246" From ed2c96e5dad6dcbc21f44dbd88407ef07462aac0 Mon Sep 17 00:00:00 2001 From: benrobson Date: Wed, 15 Nov 2023 22:55:11 +1100 Subject: [PATCH 14/27] Resolve issues with cookie banner not showing on /register --- api/internal_redirect/web.js | 4 ++-- features.json | 2 +- views/session/register.ejs | 7 +++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/api/internal_redirect/web.js b/api/internal_redirect/web.js index e2ce9a49..1aa09500 100644 --- a/api/internal_redirect/web.js +++ b/api/internal_redirect/web.js @@ -3,8 +3,8 @@ import { postAPIRequest } from '../common' export default function webRedirectRoute(app, config, lang) { const baseEndpoint = '/redirect/web'; - app.post(baseEndpoint + '/register', async function(req, res) { - postAPIRequest( + app.post(baseEndpoint + '/register', async function (req, res) { + await postAPIRequest( `${process.env.siteAddress}/api/web/register/create`, req.body, `${process.env.siteAddress}/register`, diff --git a/features.json b/features.json index 88c40d64..32d62640 100644 --- a/features.json +++ b/features.json @@ -18,7 +18,7 @@ }, "web": { "login": true, - "register": false + "register": true }, "smDiscord": true, diff --git a/views/session/register.ejs b/views/session/register.ejs index ac9c0273..e0c9dbf5 100644 --- a/views/session/register.ejs +++ b/views/session/register.ejs @@ -14,6 +14,13 @@
+ <% if (req.cookies.alertType) { %> + <%- include("../partials/alert.ejs", { + alertType: req.cookies.alertType, + content: req.cookies.alertContent + }) %> + <% } %> +
From 75e2f8d03cffce846a0c2bbe1f115af868032100 Mon Sep 17 00:00:00 2001 From: benrobson Date: Thu, 16 Nov 2023 20:41:24 +1100 Subject: [PATCH 15/27] Made urgent change to hasPermission, allowing non-logged in users to view admin panel. --- api/common.js | 3 +-- routes/dashboard/dashboard.js | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/common.js b/api/common.js index ed4585c6..6fd1aba2 100644 --- a/api/common.js +++ b/api/common.js @@ -110,7 +110,7 @@ export function isLoggedIn(req) { */ export async function hasPermission(permissionNode, req, res, features) { if (!isLoggedIn(req) || !req.session.user || !req.session.user.permissions) { - res.view('session/noPermission', { + return res.view('session/noPermission', { "pageTitle": `Access Restricted`, config: config, req: req, @@ -119,7 +119,6 @@ export async function hasPermission(permissionNode, req, res, features) { globalImage: await getGlobalImage(), announcementWeb: await getWebAnnouncement() }); - return false; } else { const userPermissions = req.session.user.permissions; diff --git a/routes/dashboard/dashboard.js b/routes/dashboard/dashboard.js index 9340d302..c02fc52b 100644 --- a/routes/dashboard/dashboard.js +++ b/routes/dashboard/dashboard.js @@ -9,7 +9,8 @@ export default function dashbordSiteRoute(app, config, features, lang) { // Dashboard // app.get('/dashboard', async function (req, res) { - if (!hasPermission('zander.web.dashboard', req, res, features)) + const permissionBoolean = await hasPermission('zander.web.dashboard', req, res, features) + if (!permissionBoolean) return; return res.view('dashboard/dashboard-index', { From 89f78341b2a760f5b58994a39e6e72c6e14f4e4a Mon Sep 17 00:00:00 2001 From: Ben Robson Date: Mon, 20 Nov 2023 21:19:30 +1100 Subject: [PATCH 16/27] Reformat all project files using Prettier. (#90) * Commit not found. * Prettify all JS and JSON files. --- api/common.js | 326 ++++++++++---------- api/internal_redirect/announcement.js | 99 +++--- api/internal_redirect/application.js | 100 +++--- api/internal_redirect/index.js | 18 +- api/internal_redirect/server.js | 76 +++-- api/internal_redirect/web.js | 27 +- api/routes/announcement.js | 418 +++++++++++++------------ api/routes/application.js | 386 +++++++++++++---------- api/routes/discord.js | 206 +++++++------ api/routes/filter.js | 120 ++++---- api/routes/index.js | 46 ++- api/routes/server.js | 337 +++++++++++---------- api/routes/session.js | 202 +++++++------ api/routes/user.js | 210 +++++++------ api/routes/verifyToken.js | 43 ++- api/routes/web.js | 308 ++++++++++--------- app.js | 224 +++++++------- commands/legoflip.mjs | 40 ++- commands/play.mjs | 86 +++--- commands/policy.mjs | 42 ++- commands/poll.mjs | 37 ++- commands/rules.mjs | 24 +- commands/staffhelp.mjs | 32 +- commands/website.mjs | 24 +- config.json | 72 ++--- controllers/announcementController.js | 44 +-- controllers/databaseController.js | 10 +- controllers/discordController.js | 46 +-- controllers/userController.js | 98 +++--- features.json | 62 ++-- filter.json | 71 ++--- joinMessages.json | 38 +-- lang.json | 106 +++---- listeners/filter.js | 33 +- listeners/generalKenobi.js | 16 +- listeners/guildMemberBoostUpdate.js | 24 +- listeners/guildMemberUpdate.js | 35 ++- listeners/messageDelete.js | 28 +- listeners/messageUpdate.js | 26 +- listeners/ready.js | 8 +- routes/dashboard/announcement.js | 145 ++++----- routes/dashboard/applications.js | 130 ++++---- routes/dashboard/dashboard.js | 82 ++--- routes/dashboard/index.js | 30 +- routes/dashboard/servers.js | 140 ++++----- routes/index.js | 169 ++++++----- routes/policyRoutes.js | 76 +++-- routes/sessionRoutes.js | 420 ++++++++++++++------------ 48 files changed, 2856 insertions(+), 2484 deletions(-) diff --git a/api/common.js b/api/common.js index 6fd1aba2..5c031e87 100644 --- a/api/common.js +++ b/api/common.js @@ -1,9 +1,9 @@ -import config from '../config.json' assert {type: "json"}; -import fetch from 'node-fetch'; -import { readdirSync } from 'fs'; +import config from "../config.json" assert { type: "json" }; +import fetch from "node-fetch"; +import { readdirSync } from "fs"; import crypto from "crypto"; import db from "../controllers/databaseController"; -import { getWebAnnouncement } from '../controllers/announcementController'; +import { getWebAnnouncement } from "../controllers/announcementController"; /* Check if a specific feature is enabled. @@ -13,13 +13,12 @@ import { getWebAnnouncement } from '../controllers/announcementController'; @param lang Passing through lang. */ export function isFeatureEnabled(isFeatureEnabled, res, lang) { - if (isFeatureEnabled) - return; + if (isFeatureEnabled) return; - res.send({ - success: false, - message: `${lang.api.featureDisabled}` - }); + res.send({ + success: false, + message: `${lang.api.featureDisabled}`, + }); } /* @@ -31,25 +30,24 @@ export function isFeatureEnabled(isFeatureEnabled, res, lang) { @param res Passing through res. */ export function required(body, field, res) { - // Prematurely exits an API request if a required field has not been - // defined or null. If the body is not defined then we error as well. - // This can happen when no parameters exist. - if (!body || !(field in body)) - return res.send({ - success: false, - message: `Body requires field '${field}'` - }); + // Prematurely exits an API request if a required field has not been + // defined or null. If the body is not defined then we error as well. + // This can happen when no parameters exist. + if (!body || !(field in body)) + return res.send({ + success: false, + message: `Body requires field '${field}'`, + }); - if (body[field] === null) - return res.send({ - success: false, - message: `Field ${field} cannot be null` - }); + if (body[field] === null) + return res.send({ + success: false, + message: `Field ${field} cannot be null`, + }); - return body[field]; + return body[field]; } - /* Check if an optional field is present in the body object, and return its value if it is. @@ -57,14 +55,13 @@ export function required(body, field, res) { @param field The name of the field. */ export function optional(body, field) { - // Jaedan: I am aware that this is pretty much default behaviour, however - // this takes into consideration times where no body is included. Without - // this check requests with only optional fields (that are all unused) will - // cause a null object to be referenced, causing an error. - if (!body || !(field in body) || body[field] === null) - return null; - - return body[field]; + // Jaedan: I am aware that this is pretty much default behaviour, however + // this takes into consideration times where no body is included. Without + // this check requests with only optional fields (that are all unused) will + // cause a null object to be referenced, causing an error. + if (!body || !(field in body) || body[field] === null) return null; + + return body[field]; } /* @@ -75,19 +72,24 @@ export function optional(body, field) { @param res Passing through res @param features Passing through features */ -export async function isFeatureWebRouteEnabled(isFeatureEnabled, req, res, features) { - if (!isFeatureEnabled) { - res.view('session/featureDisabled', { - "pageTitle": `Feature Disabled`, - config: config, - req: req, - res: res, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement(), - }); - } - return true; +export async function isFeatureWebRouteEnabled( + isFeatureEnabled, + req, + res, + features +) { + if (!isFeatureEnabled) { + res.view("session/featureDisabled", { + pageTitle: `Feature Disabled`, + config: config, + req: req, + res: res, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), + }); + } + return true; } /* @@ -96,8 +98,8 @@ export async function isFeatureWebRouteEnabled(isFeatureEnabled, req, res, featu @param req Passing through req */ export function isLoggedIn(req) { - if (req.session.user) return true; - else return false; + if (req.session.user) return true; + else return false; } /* @@ -109,37 +111,37 @@ export function isLoggedIn(req) { @param features Passing through features */ export async function hasPermission(permissionNode, req, res, features) { - if (!isLoggedIn(req) || !req.session.user || !req.session.user.permissions) { - return res.view('session/noPermission', { - "pageTitle": `Access Restricted`, - config: config, - req: req, - res: res, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); - } else { - const userPermissions = req.session.user.permissions; - - function hasSpecificPerm(node, permissionArray) { - return permissionArray.some(permission => permission === node); - } - - if (!hasSpecificPerm(permissionNode, userPermissions)) { - res.view('session/noPermission', { - "pageTitle": `Access Restricted`, - config: config, - req: req, - res: res, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); - return false; - } - return true; + if (!isLoggedIn(req) || !req.session.user || !req.session.user.permissions) { + return res.view("session/noPermission", { + pageTitle: `Access Restricted`, + config: config, + req: req, + res: res, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), + }); + } else { + const userPermissions = req.session.user.permissions; + + function hasSpecificPerm(node, permissionArray) { + return permissionArray.some((permission) => permission === node); + } + + if (!hasSpecificPerm(permissionNode, userPermissions)) { + res.view("session/noPermission", { + pageTitle: `Access Restricted`, + config: config, + req: req, + res: res, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), + }); + return false; } + return true; + } } /* @@ -154,28 +156,33 @@ export async function hasPermission(permissionNode, req, res, features) { @param failureRedirectURL If the request returns false, where the API will redirect the user to. @param res Passing through res. */ -export async function postAPIRequest(postURL, apiPostBody, failureRedirectURL, res) { - const response = await fetch(postURL, { - method: 'POST', - body: JSON.stringify(apiPostBody), - headers: { - 'Content-Type': 'application/json', - 'x-access-token': process.env.apiKey - } - }); - const data = await response.json(); - - console.log(data); - - if (data.alertType) { - setBannerCookie(`${data.alertType}`, `${data.alertContent}`, res); - } - - if (!data.success) { - return res.redirect(failureRedirectURL); - } - - return console.log(data); +export async function postAPIRequest( + postURL, + apiPostBody, + failureRedirectURL, + res +) { + const response = await fetch(postURL, { + method: "POST", + body: JSON.stringify(apiPostBody), + headers: { + "Content-Type": "application/json", + "x-access-token": process.env.apiKey, + }, + }); + const data = await response.json(); + + console.log(data); + + if (data.alertType) { + setBannerCookie(`${data.alertType}`, `${data.alertContent}`, res); + } + + if (!data.success) { + return res.redirect(failureRedirectURL); + } + + return console.log(data); } /* @@ -185,13 +192,13 @@ export async function postAPIRequest(postURL, apiPostBody, failureRedirectURL, r Finally, the function returns the path of the chosen file by concatenating the file name with the relative path to the directory. */ export async function getGlobalImage() { - var path = './assets/images/globalImages/'; - var files = await readdirSync(path); + var path = "./assets/images/globalImages/"; + var files = await readdirSync(path); - // Now files is an Array of the name of the files in the folder and you can pick a random name inside of that array. - let chosenFile = await files[Math.floor(Math.random() * files.length)] + // Now files is an Array of the name of the files in the folder and you can pick a random name inside of that array. + let chosenFile = await files[Math.floor(Math.random() * files.length)]; - return "../../../images/globalImages/" + chosenFile; + return "../../../images/globalImages/" + chosenFile; } /* @@ -203,26 +210,26 @@ export async function getGlobalImage() { @param res Passing through res */ export async function setBannerCookie(alertType, alertContent, res) { - try { - var expiryTime = new Date(); - expiryTime.setSeconds(expiryTime.getSeconds() + 2); - - // Set Alert Type - res.setCookie('alertType', alertType, { - path: '/', - expires: expiryTime - }) - - // Set Content Type - res.setCookie('alertContent', alertContent, { - path: '/', - expires: expiryTime - }) - - return true; - } catch (error) { - console.log(error); - } + try { + var expiryTime = new Date(); + expiryTime.setSeconds(expiryTime.getSeconds() + 2); + + // Set Alert Type + res.setCookie("alertType", alertType, { + path: "/", + expires: expiryTime, + }); + + // Set Content Type + res.setCookie("alertContent", alertContent, { + path: "/", + expires: expiryTime, + }); + + return true; + } catch (error) { + console.log(error); + } } /* @@ -232,14 +239,14 @@ export async function setBannerCookie(alertType, alertContent, res) { @param email The email address to hash. */ export async function hashEmail(email) { - // Create a new MD5 hash object - const md5Hash = crypto.createHash('md5'); + // Create a new MD5 hash object + const md5Hash = crypto.createHash("md5"); - // Update the hash object with the email address - md5Hash.update(email); + // Update the hash object with the email address + md5Hash.update(email); - // Get the hexadecimal representation of the hash and return it - return md5Hash.digest('hex'); + // Get the hexadecimal representation of the hash and return it + return md5Hash.digest("hex"); } /* @@ -250,20 +257,30 @@ export async function hashEmail(email) { @param logType The type of log. @param description A short description of the log. */ -export async function generateLog(userId, logType, logFeature, description, res) { - db.query(`INSERT INTO logs (creatorId, logType, logFeature, description) VALUES (?, ?, ?, ?)`, [userId, logType, logFeature, description], function (error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - +export async function generateLog( + userId, + logType, + logFeature, + description, + res +) { + db.query( + `INSERT INTO logs (creatorId, logType, logFeature, description) VALUES (?, ?, ?, ?)`, + [userId, logType, logFeature, description], + function (error, results, fields) { + if (error) { return res.send({ - success: true, - message: `Log created.` + success: false, + message: `${error}`, }); - }); + } + + return res.send({ + success: true, + message: `Log created.`, + }); + } + ); } /* @@ -273,17 +290,16 @@ export async function generateLog(userId, logType, logFeature, description, res) @param filter the JSON output of the filter.json file */ export async function expandString(string, filter) { - var regexString = ""; - for (var i = 0; i < string.length; i++) { - // If the character does not have any aliases then just - // use the character. Note, this is a regex character. - if (string[i] in filter.alias) - regexString += "[" + filter.alias[string[i]] + "]"; - else - regexString += string[i] - } - regexString = regexString.replace(".", "\\.") - return regexString + var regexString = ""; + for (var i = 0; i < string.length; i++) { + // If the character does not have any aliases then just + // use the character. Note, this is a regex character. + if (string[i] in filter.alias) + regexString += "[" + filter.alias[string[i]] + "]"; + else regexString += string[i]; + } + regexString = regexString.replace(".", "\\."); + return regexString; } /* @@ -293,5 +309,5 @@ export async function expandString(string, filter) { @param filter the JSON output of the filter.json file */ export function removeHtmlTags(html) { - return html.replace(/<(?!\/?(a)\b)[^<]*?>/gi, ''); + return html.replace(/<(?!\/?(a)\b)[^<]*?>/gi, ""); } diff --git a/api/internal_redirect/announcement.js b/api/internal_redirect/announcement.js index 8659f2d3..af14600f 100644 --- a/api/internal_redirect/announcement.js +++ b/api/internal_redirect/announcement.js @@ -1,53 +1,50 @@ -import {hasPermission, setBannerCookie, postAPIRequest} from '../common' +import { hasPermission, postAPIRequest } from "../common"; export default function announcementRedirectRoute(app, config, lang) { - const baseEndpoint = '/redirect/announcement'; - - app.post(baseEndpoint + '/create', async function(req, res) { - if (!hasPermission('zander.web.announcements', req, res)) - return; - - postAPIRequest( - `${process.env.siteAddress}/api/announcement/create`, - req.body, - `${process.env.siteAddress}/dashboard/announcements`, - res - ) - - res.redirect(`${process.env.siteAddress}/dashboard/announcements`); - - return res; - }); - - app.post(baseEndpoint + '/edit', async function(req, res) { - if (!hasPermission('zander.web.announcements', req, res)) - return; - - postAPIRequest( - `${process.env.siteAddress}/api/announcement/edit`, - req.body, - `${process.env.siteAddress}/dashboard/announcements`, - res - ) - - res.redirect(`${process.env.siteAddress}/dashboard/announcements`); - - return res; - }); - - app.post(baseEndpoint + '/delete', async function(req, res) { - if (!hasPermission('zander.web.announcements', req, res)) - return; - - postAPIRequest( - `${process.env.siteAddress}/api/announcement/delete`, - req.body, - `${process.env.siteAddress}/dashboard/announcements`, - res - ) - - res.redirect(`${process.env.siteAddress}/dashboard/announcements`); - - return res; - }); -} \ No newline at end of file + const baseEndpoint = "/redirect/announcement"; + + app.post(baseEndpoint + "/create", async function (req, res) { + if (!hasPermission("zander.web.announcements", req, res)) return; + + postAPIRequest( + `${process.env.siteAddress}/api/announcement/create`, + req.body, + `${process.env.siteAddress}/dashboard/announcements`, + res + ); + + res.redirect(`${process.env.siteAddress}/dashboard/announcements`); + + return res; + }); + + app.post(baseEndpoint + "/edit", async function (req, res) { + if (!hasPermission("zander.web.announcements", req, res)) return; + + postAPIRequest( + `${process.env.siteAddress}/api/announcement/edit`, + req.body, + `${process.env.siteAddress}/dashboard/announcements`, + res + ); + + res.redirect(`${process.env.siteAddress}/dashboard/announcements`); + + return res; + }); + + app.post(baseEndpoint + "/delete", async function (req, res) { + if (!hasPermission("zander.web.announcements", req, res)) return; + + postAPIRequest( + `${process.env.siteAddress}/api/announcement/delete`, + req.body, + `${process.env.siteAddress}/dashboard/announcements`, + res + ); + + res.redirect(`${process.env.siteAddress}/dashboard/announcements`); + + return res; + }); +} diff --git a/api/internal_redirect/application.js b/api/internal_redirect/application.js index 8c5945f8..903c97d2 100644 --- a/api/internal_redirect/application.js +++ b/api/internal_redirect/application.js @@ -1,54 +1,50 @@ -import {hasPermission, setBannerCookie, postAPIRequest} from '../common' +import { hasPermission, postAPIRequest } from "../common"; export default function applicationRedirectRoute(app, config, lang) { - const baseEndpoint = '/redirect/application'; - - app.post(baseEndpoint + '/create', async function(req, res) { - if (!hasPermission('zander.web.application', req, res)) - return; - - postAPIRequest( - `${process.env.siteAddress}/api/application/create`, - req.body, - `${process.env.siteAddress}/dashboard/applications`, - res - ) - - res.redirect(`${process.env.siteAddress}/dashboard/applications`); - - return res; - }); - - app.post(baseEndpoint + '/edit', async function(req, res) { - if (!hasPermission('zander.web.application', req, res)) - return; - - postAPIRequest( - `${process.env.siteAddress}/api/application/edit`, - req.body, - `${process.env.siteAddress}/dashboard/applications`, - res - ) - - res.redirect(`${process.env.siteAddress}/dashboard/applications`); - - return res; - }); - - app.post(baseEndpoint + '/delete', async function(req, res) { - if (!hasPermission('zander.web.application', req, res)) - return; - - postAPIRequest( - `${process.env.siteAddress}/api/application/delete`, - req.body, - `${process.env.siteAddress}/dashboard/applications`, - res - ) - - res.redirect(`${process.env.siteAddress}/dashboard/applications`); - - return res; - }); - -} \ No newline at end of file + const baseEndpoint = "/redirect/application"; + + app.post(baseEndpoint + "/create", async function (req, res) { + if (!hasPermission("zander.web.application", req, res)) return; + + postAPIRequest( + `${process.env.siteAddress}/api/application/create`, + req.body, + `${process.env.siteAddress}/dashboard/applications`, + res + ); + + res.redirect(`${process.env.siteAddress}/dashboard/applications`); + + return res; + }); + + app.post(baseEndpoint + "/edit", async function (req, res) { + if (!hasPermission("zander.web.application", req, res)) return; + + postAPIRequest( + `${process.env.siteAddress}/api/application/edit`, + req.body, + `${process.env.siteAddress}/dashboard/applications`, + res + ); + + res.redirect(`${process.env.siteAddress}/dashboard/applications`); + + return res; + }); + + app.post(baseEndpoint + "/delete", async function (req, res) { + if (!hasPermission("zander.web.application", req, res)) return; + + postAPIRequest( + `${process.env.siteAddress}/api/application/delete`, + req.body, + `${process.env.siteAddress}/dashboard/applications`, + res + ); + + res.redirect(`${process.env.siteAddress}/dashboard/applications`); + + return res; + }); +} diff --git a/api/internal_redirect/index.js b/api/internal_redirect/index.js index 6934eb00..c734885b 100644 --- a/api/internal_redirect/index.js +++ b/api/internal_redirect/index.js @@ -1,11 +1,11 @@ -import applicationRedirectRoute from './application' -import serverRedirectRoute from './server' -import webRedirectRoute from './web' -import announcementsRedirectRoute from './announcement' +import applicationRedirectRoute from "./application"; +import serverRedirectRoute from "./server"; +import webRedirectRoute from "./web"; +import announcementsRedirectRoute from "./announcement"; export default (app, config, lang) => { - applicationRedirectRoute(app, config, lang); - serverRedirectRoute(app, config, lang); - webRedirectRoute(app, config, lang); - announcementsRedirectRoute(app, config, lang); -} \ No newline at end of file + applicationRedirectRoute(app, config, lang); + serverRedirectRoute(app, config, lang); + webRedirectRoute(app, config, lang); + announcementsRedirectRoute(app, config, lang); +}; diff --git a/api/internal_redirect/server.js b/api/internal_redirect/server.js index 56082a98..2bf1cdcb 100644 --- a/api/internal_redirect/server.js +++ b/api/internal_redirect/server.js @@ -1,54 +1,50 @@ -import {hasPermission, setBannerCookie, postAPIRequest} from '../common' +import { hasPermission, postAPIRequest } from "../common"; export default function serverRedirectRoute(app, config, lang) { - const baseEndpoint = '/redirect/server'; - - app.post(baseEndpoint + '/create', async function(req, res) { - if (!hasPermission('zander.web.server', req, res)) - return; + const baseEndpoint = "/redirect/server"; - postAPIRequest( - `${process.env.siteAddress}/api/server/create`, - req.body, - `${process.env.siteAddress}/dashboard/servers`, - res - ) + app.post(baseEndpoint + "/create", async function (req, res) { + if (!hasPermission("zander.web.server", req, res)) return; - res.redirect(`${process.env.siteAddress}/dashboard/servers`); + postAPIRequest( + `${process.env.siteAddress}/api/server/create`, + req.body, + `${process.env.siteAddress}/dashboard/servers`, + res + ); - return res; - }); + res.redirect(`${process.env.siteAddress}/dashboard/servers`); - app.post(baseEndpoint + '/edit', async function(req, res) { - if (!hasPermission('zander.web.server', req, res)) - return; + return res; + }); - postAPIRequest( - `${process.env.siteAddress}/api/server/edit`, - req.body, - `${process.env.siteAddress}/dashboard/servers`, - res - ) + app.post(baseEndpoint + "/edit", async function (req, res) { + if (!hasPermission("zander.web.server", req, res)) return; - res.redirect(`${process.env.siteAddress}/dashboard/servers`); + postAPIRequest( + `${process.env.siteAddress}/api/server/edit`, + req.body, + `${process.env.siteAddress}/dashboard/servers`, + res + ); - return res; - }); + res.redirect(`${process.env.siteAddress}/dashboard/servers`); - app.post(baseEndpoint + '/delete', async function(req, res) { - if (!hasPermission('zander.web.server', req, res)) - return; + return res; + }); - postAPIRequest( - `${process.env.siteAddress}/api/server/delete`, - req.body, - `${process.env.siteAddress}/dashboard/servers`, - res - ) + app.post(baseEndpoint + "/delete", async function (req, res) { + if (!hasPermission("zander.web.server", req, res)) return; - res.redirect(`${process.env.siteAddress}/dashboard/servers`); + postAPIRequest( + `${process.env.siteAddress}/api/server/delete`, + req.body, + `${process.env.siteAddress}/dashboard/servers`, + res + ); - return res; - }); + res.redirect(`${process.env.siteAddress}/dashboard/servers`); -} \ No newline at end of file + return res; + }); +} diff --git a/api/internal_redirect/web.js b/api/internal_redirect/web.js index 1aa09500..a318a215 100644 --- a/api/internal_redirect/web.js +++ b/api/internal_redirect/web.js @@ -1,19 +1,18 @@ -import { postAPIRequest } from '../common' +import { postAPIRequest } from "../common"; export default function webRedirectRoute(app, config, lang) { - const baseEndpoint = '/redirect/web'; + const baseEndpoint = "/redirect/web"; - app.post(baseEndpoint + '/register', async function (req, res) { - await postAPIRequest( - `${process.env.siteAddress}/api/web/register/create`, - req.body, - `${process.env.siteAddress}/register`, - res - ) + app.post(baseEndpoint + "/register", async function (req, res) { + await postAPIRequest( + `${process.env.siteAddress}/api/web/register/create`, + req.body, + `${process.env.siteAddress}/register`, + res + ); - res.redirect(`${process.env.siteAddress}/register`); + res.redirect(`${process.env.siteAddress}/register`); - return res; - }); - -} \ No newline at end of file + return res; + }); +} diff --git a/api/routes/announcement.js b/api/routes/announcement.js index e6b564ee..f96e76e8 100644 --- a/api/routes/announcement.js +++ b/api/routes/announcement.js @@ -1,146 +1,162 @@ -import {isFeatureEnabled, required, optional, generateLog} from '../common' +import { isFeatureEnabled, required, optional, generateLog } from "../common"; export default function announcementApiRoute(app, config, db, features, lang) { - const baseEndpoint = '/api/announcement'; - - app.get(baseEndpoint + '/get', async function(req, res) { - isFeatureEnabled(features.announcements, res, lang); - const announcementId = optional(req.query, "announcementId"); - const announcementType = optional(req.query, "announcementType"); - const enabled = optional(req.query, "enabled"); - - try { - function getAnnouncements(dbQuery) { - db.query(dbQuery, function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - if (!results.length) { - return res.send({ - success: false, - message: lang.announcement.noAnnouncements - }); - } - - res.send({ - success: true, - data: results - }); - }); - } - - // Get Announcement by specific ID. - if (req.query === 'announcementId') { - let dbQuery = `SELECT * FROM announcements WHERE announcementId=${announcementId};` - getAnnouncements(dbQuery); - return res; - } - - // Get 1 web announcement - if (announcementType === 'web') { - let dbQuery = `SELECT * FROM announcements WHERE announcementType='web' AND enabled=1 ORDER BY RAND() LIMIT 1;` - getAnnouncements(dbQuery); - return res; - } - - // Get 1 tip announcement - if (announcementType === 'tip') { - let dbQuery = `SELECT * FROM announcements WHERE announcementType='tip' AND enabled=1 ORDER BY RAND() LIMIT 1;` - getAnnouncements(dbQuery); - return res; - } - - // Get 1 motd announcement - if (announcementType === 'motd') { - let dbQuery = `SELECT * FROM announcements WHERE announcementType='motd' AND enabled=1 ORDER BY RAND() LIMIT 1;` - getAnnouncements(dbQuery); - return res; - } - - // Show all public announcements - if (enabled === 1) { - let dbQuery = `SELECT * FROM announcements WHERE enabled=1;` - getAnnouncements(dbQuery); - return res; - } - - // Show all hidden announcements - if (enabled === 0) { - let dbQuery = `SELECT * FROM announcements WHERE enabled=0;` - getAnnouncements(dbQuery); - return res; - } - - // Show all announcements - let dbQuery = `SELECT * FROM announcements;` - getAnnouncements(dbQuery); - return res; - - } catch (error) { - res.send({ - success: false, - message: `${error}` + const baseEndpoint = "/api/announcement"; + + app.get(baseEndpoint + "/get", async function (req, res) { + isFeatureEnabled(features.announcements, res, lang); + const announcementId = optional(req.query, "announcementId"); + const announcementType = optional(req.query, "announcementType"); + const enabled = optional(req.query, "enabled"); + + try { + function getAnnouncements(dbQuery) { + db.query(dbQuery, function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, }); - } + } - return res; - }); - - app.post(baseEndpoint + '/create', async function(req, res) { - isFeatureEnabled(features.announcements, res, lang); - - const actioningUser = required(req.body, "actioningUser", res); - const enabled = required(req.body, "enabled", res); - const announcementType = required(req.body, "announcementType", res); - const body = optional(req.body, "body", res); - const colourMessageFormat = optional(req.body, "colourMessageFormat", res); - const link = optional(req.body, "link", res); - - try { - db.query(`INSERT INTO announcements (enabled, body, announcementType, link, colourMessageFormat) VALUES (?, ?, ?, ?, ?)`, [enabled, body, announcementType, link, colourMessageFormat, Date.now()], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "SUCCESS", "ANNOUNCEMENT", `Created ${announcementType}`, res); - - res.send({ - success: true, - alertType: "success", - content: lang.announcement.announcementCreated - }); + if (!results.length) { + return res.send({ + success: false, + message: lang.announcement.noAnnouncements, }); + } + + res.send({ + success: true, + data: results, + }); + }); + } + + // Get Announcement by specific ID. + if (req.query === "announcementId") { + let dbQuery = `SELECT * FROM announcements WHERE announcementId=${announcementId};`; + getAnnouncements(dbQuery); + return res; + } - } catch (error) { - res.send({ - success: false, - message: `${error}` - }); - } + // Get 1 web announcement + if (announcementType === "web") { + let dbQuery = `SELECT * FROM announcements WHERE announcementType='web' AND enabled=1 ORDER BY RAND() LIMIT 1;`; + getAnnouncements(dbQuery); + return res; + } + // Get 1 tip announcement + if (announcementType === "tip") { + let dbQuery = `SELECT * FROM announcements WHERE announcementType='tip' AND enabled=1 ORDER BY RAND() LIMIT 1;`; + getAnnouncements(dbQuery); return res; - }); + } - app.post(baseEndpoint + '/edit', async function(req, res) { - isFeatureEnabled(features.announcements, res, lang); + // Get 1 motd announcement + if (announcementType === "motd") { + let dbQuery = `SELECT * FROM announcements WHERE announcementType='motd' AND enabled=1 ORDER BY RAND() LIMIT 1;`; + getAnnouncements(dbQuery); + return res; + } - const actioningUser = required(req.body, "actioningUser", res); - const announcementId = required(req.body, "announcementId", res); - const enabled = required(req.body, "enabled", res); - const announcementType = required(req.body, "announcementType", res); - const body = optional(req.body, "body", res); - const colourMessageFormat = optional(req.body, "colourMessageFormat", res); - const link = optional(req.body, "link", res); + // Show all public announcements + if (enabled === 1) { + let dbQuery = `SELECT * FROM announcements WHERE enabled=1;`; + getAnnouncements(dbQuery); + return res; + } - try { - db.query(` + // Show all hidden announcements + if (enabled === 0) { + let dbQuery = `SELECT * FROM announcements WHERE enabled=0;`; + getAnnouncements(dbQuery); + return res; + } + + // Show all announcements + let dbQuery = `SELECT * FROM announcements;`; + getAnnouncements(dbQuery); + return res; + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/create", async function (req, res) { + isFeatureEnabled(features.announcements, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const enabled = required(req.body, "enabled", res); + const announcementType = required(req.body, "announcementType", res); + const body = optional(req.body, "body", res); + const colourMessageFormat = optional(req.body, "colourMessageFormat", res); + const link = optional(req.body, "link", res); + + try { + db.query( + `INSERT INTO announcements (enabled, body, announcementType, link, colourMessageFormat) VALUES (?, ?, ?, ?, ?)`, + [ + enabled, + body, + announcementType, + link, + colourMessageFormat, + Date.now(), + ], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + + generateLog( + actioningUser, + "SUCCESS", + "ANNOUNCEMENT", + `Created ${announcementType}`, + res + ); + + res.send({ + success: true, + alertType: "success", + content: lang.announcement.announcementCreated, + }); + } + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/edit", async function (req, res) { + isFeatureEnabled(features.announcements, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const announcementId = required(req.body, "announcementId", res); + const enabled = required(req.body, "enabled", res); + const announcementType = required(req.body, "announcementType", res); + const body = optional(req.body, "body", res); + const colourMessageFormat = optional(req.body, "colourMessageFormat", res); + const link = optional(req.body, "link", res); + + try { + db.query( + ` UPDATE announcements SET enabled=?, @@ -149,68 +165,84 @@ export default function announcementApiRoute(app, config, db, features, lang) { colourMessageFormat=?, link=? WHERE announcementId=?;`, - [ - enabled, - announcementType, - body, - colourMessageFormat, - link, - announcementId - ], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "SUCCESS", "ANNOUNCEMENT", `Edited ${announcementId}`, res); - - return res.send({ - success: true, - message: lang.announcement.announcementEdited - }); - }); - - } catch (error) { - res.send({ - success: false, - message: `${error}` + [ + enabled, + announcementType, + body, + colourMessageFormat, + link, + announcementId, + ], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, }); + } + + generateLog( + actioningUser, + "SUCCESS", + "ANNOUNCEMENT", + `Edited ${announcementId}`, + res + ); + + return res.send({ + success: true, + message: lang.announcement.announcementEdited, + }); } - - return res; - }); - - app.post(baseEndpoint + '/delete', async function(req, res) { - isFeatureEnabled(features.announcements, res, lang); - - const announcementId = required(req.body, "announcementId", res); - - try { - db.query(`DELETE FROM announcements WHERE announcementId=?;`, [announcementId], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "WARNING", "ANNOUNCEMENT", `Deleted ${announcementId}`, res); - - return res.send({ - success: true, - message: lang.announcement.announcementDeleted - }); - }); - - } catch (error) { - res.send({ - success: false, - message: `${error}` + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/delete", async function (req, res) { + isFeatureEnabled(features.announcements, res, lang); + + const announcementId = required(req.body, "announcementId", res); + + try { + db.query( + `DELETE FROM announcements WHERE announcementId=?;`, + [announcementId], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, }); + } + + generateLog( + actioningUser, + "WARNING", + "ANNOUNCEMENT", + `Deleted ${announcementId}`, + res + ); + + return res.send({ + success: true, + message: lang.announcement.announcementDeleted, + }); } - - return res; - }); -} \ No newline at end of file + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); +} diff --git a/api/routes/application.js b/api/routes/application.js index 2dd02047..ed8481d6 100644 --- a/api/routes/application.js +++ b/api/routes/application.js @@ -1,119 +1,146 @@ -import {isFeatureEnabled, required, optional, generateLog} from '../common' +import { isFeatureEnabled, required, optional, generateLog } from "../common"; export default function applicationApiRoute(app, config, db, features, lang) { - const baseEndpoint = '/api/application'; - - app.get(baseEndpoint + '/get', async function(req, res) { - isFeatureEnabled(features.applications, res, lang); - const applicationId = optional(req.query, "applicationId"); - - try { - function getApplications(dbQuery) { - db.query(dbQuery, function(error, results, fields) { - if (error) { - res.send({ - success: false, - message: `${error}` - }); - } - - if (!results.length) { - return res.send({ - success: false, - message: lang.applications.noApplicationsFound - }); - } - - return res.send({ - success: true, - data: results - }); - }); - } - - // Get Application by ID - if (applicationId) { - let dbQuery = `SELECT * FROM applications WHERE applicationId=${applicationId};` - getApplications(dbQuery); - } - - // Return all Servers by default - let dbQuery = `SELECT * FROM applications ORDER BY position ASC;` - getApplications(dbQuery); - } catch (error) { - res.send({ - success: false, - message: `${error}` - }); - } + const baseEndpoint = "/api/application"; - return res; - }); - - app.post(baseEndpoint + '/create', async function(req, res) { - isFeatureEnabled(features.applications, res, lang); - - const actioningUser = required(req.body, "actioningUser", res); - const displayName = required(req.body, "displayName", res); - const description = required(req.body, "description", res); - const displayIcon = required(req.body, "displayIcon", res); - const requirementsMarkdown = required(req.body, "requirementsMarkdown", res); - const redirectUrl = required(req.body, "redirectUrl", res); - const position = required(req.body, "position", res); - const applicationStatus = required(req.body, "applicationStatus", res); - - let applicationCreatedLang = lang.applications.applicationCreated; - - console.log(req.body); - - try { - db.query(` - INSERT INTO applications - (displayName, description, displayIcon, requirementsMarkdown, redirectUrl, position, applicationStatus) - VALUES (?, ?, ?, ?, ?, ?, ?)`, - [displayName, description, displayIcon, requirementsMarkdown, redirectUrl, position, applicationStatus], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "SUCCESS", "APPLICATION", `Created ${displayName}`, res); - - return res.send({ - success: true, - message: applicationCreatedLang.replace("%DISPLAYNAME%", displayName) - }); - }); + app.get(baseEndpoint + "/get", async function (req, res) { + isFeatureEnabled(features.applications, res, lang); + const applicationId = optional(req.query, "applicationId"); - } catch (error) { + try { + function getApplications(dbQuery) { + db.query(dbQuery, function (error, results, fields) { + if (error) { res.send({ - success: false, - message: `${error}` + success: false, + message: `${error}`, }); - } + } - return res; - }); - - app.post(baseEndpoint + '/edit', async function(req, res) { - isFeatureEnabled(features.applications, res, lang); - - const actioningUser = required(req.body, "actioningUser", res); - const applicationId = required(req.body, "applicationId", res); - const displayName = required(req.body, "displayName", res); - const description = required(req.body, "description", res); - const displayIcon = required(req.body, "displayIcon", res); - const requirementsMarkdown = required(req.body, "requirementsMarkdown", res); - const redirectUrl = required(req.body, "redirectUrl", res); - const position = required(req.body, "position", res); - const applicationStatus = required(req.body, "applicationStatus", res); - - let applicationEditedLang = lang.applications.applicationEdited; - - try { - db.query(` + if (!results.length) { + return res.send({ + success: false, + message: lang.applications.noApplicationsFound, + }); + } + + return res.send({ + success: true, + data: results, + }); + }); + } + + // Get Application by ID + if (applicationId) { + let dbQuery = `SELECT * FROM applications WHERE applicationId=${applicationId};`; + getApplications(dbQuery); + } + + // Return all Servers by default + let dbQuery = `SELECT * FROM applications ORDER BY position ASC;`; + getApplications(dbQuery); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/create", async function (req, res) { + isFeatureEnabled(features.applications, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const displayName = required(req.body, "displayName", res); + const description = required(req.body, "description", res); + const displayIcon = required(req.body, "displayIcon", res); + const requirementsMarkdown = required( + req.body, + "requirementsMarkdown", + res + ); + const redirectUrl = required(req.body, "redirectUrl", res); + const position = required(req.body, "position", res); + const applicationStatus = required(req.body, "applicationStatus", res); + + let applicationCreatedLang = lang.applications.applicationCreated; + + console.log(req.body); + + try { + db.query( + `INSERT INTO applications + (displayName, description, displayIcon, requirementsMarkdown, redirectUrl, position, applicationStatus) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + [ + displayName, + description, + displayIcon, + requirementsMarkdown, + redirectUrl, + position, + applicationStatus, + ], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + + generateLog( + actioningUser, + "SUCCESS", + "APPLICATION", + `Created ${displayName}`, + res + ); + + return res.send({ + success: true, + message: applicationCreatedLang.replace( + "%DISPLAYNAME%", + displayName + ), + }); + } + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/edit", async function (req, res) { + isFeatureEnabled(features.applications, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const applicationId = required(req.body, "applicationId", res); + const displayName = required(req.body, "displayName", res); + const description = required(req.body, "description", res); + const displayIcon = required(req.body, "displayIcon", res); + const requirementsMarkdown = required( + req.body, + "requirementsMarkdown", + res + ); + const redirectUrl = required(req.body, "redirectUrl", res); + const position = required(req.body, "position", res); + const applicationStatus = required(req.body, "applicationStatus", res); + + let applicationEditedLang = lang.applications.applicationEdited; + + try { + db.query( + ` UPDATE applications SET @@ -125,63 +152,90 @@ export default function applicationApiRoute(app, config, db, features, lang) { position=?, applicationStatus=? WHERE applicationId=?;`, - [displayName, displayIcon, description, requirementsMarkdown, redirectUrl, position, applicationStatus, applicationId], function(error, results, fields) { - - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "SUCCESS", "APPLICATION", `Edited ${displayName}`, res); - - return res.send({ - success: true, - message: applicationEditedLang.replace("%DISPLAYNAME%", displayName) - }); - }); - } catch (error) { - res.send({ - success: false, - message: `${error}` - }); - } - - return res; - }); - - app.post(baseEndpoint + '/delete', async function(req, res) { - isFeatureEnabled(features.applications, res, lang); - - const actioningUser = required(req.body, "actioningUser", res); - const applicationId = required(req.body, "applicationId", res); - - try { - db.query(`DELETE FROM applications WHERE applicationId=?;`, [applicationId], function(error, results, fields) { - if (error) { - res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "WARNING", "APPLICATION", `Deleted ${applicationId}`, res); - - return res.send({ - success: true, - message: `Deletion of application with the id ${applicationId} has been successful` - }); + [ + displayName, + displayIcon, + description, + requirementsMarkdown, + redirectUrl, + position, + applicationStatus, + applicationId, + ], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, }); - - } catch (error) { + } + + generateLog( + actioningUser, + "SUCCESS", + "APPLICATION", + `Edited ${displayName}`, + res + ); + + return res.send({ + success: true, + message: applicationEditedLang.replace( + "%DISPLAYNAME%", + displayName + ), + }); + } + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/delete", async function (req, res) { + isFeatureEnabled(features.applications, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const applicationId = required(req.body, "applicationId", res); + + try { + db.query( + `DELETE FROM applications WHERE applicationId=?;`, + [applicationId], + function (error, results, fields) { + if (error) { res.send({ - success: false, - message: `${error}` - }); + success: false, + message: `${error}`, + }); + } + + generateLog( + actioningUser, + "WARNING", + "APPLICATION", + `Deleted ${applicationId}`, + res + ); + + return res.send({ + success: true, + message: `Deletion of application with the id ${applicationId} has been successful`, + }); } - - return res; - }); - -} \ No newline at end of file + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); +} diff --git a/api/routes/discord.js b/api/routes/discord.js index fefa23f0..d53af94a 100644 --- a/api/routes/discord.js +++ b/api/routes/discord.js @@ -1,93 +1,113 @@ -import { isFeatureEnabled, required } from '../common' - -export default function discordApiRoute(app, client, config, db, features, lang) { - const baseEndpoint = '/api/discord'; - - app.post(baseEndpoint + '/switch', async function(req, res) { - isFeatureEnabled(features.discord, res, lang); - const username = required(req.body, "username", res); - const server = required(req.body, "server", res); - - try { - const guild = client.guilds.cache.get(config.discord.guildId); - const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - - channel.send(`:twisted_rightwards_arrows: | \`${username}\` switched to \`${server}\``); - - return res.send({ - success: true - }); - } catch (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - return res; - }); - - app.post(baseEndpoint + '/chat', async function(req, res) { - isFeatureEnabled(features.discord, res, lang); - const username = required(req.body, "username", res); - const server = required(req.body, "server", res); - const content = required(req.body, "content", res); - - try { - const guild = client.guilds.cache.get(config.discord.guildId); - const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - - channel.send(`**${server}** | \`${username}\` :: ${content}`); - - return res.send({ - success: true - }); - } catch (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - }); - - app.post(baseEndpoint + '/join', async function (req, res) { - isFeatureEnabled(features.discord, res, lang); - const username = required(req.body, "username", res); - - try { - const guild = client.guilds.cache.get(config.discord.guildId); - const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - - channel.send(`:ballot_box_with_check: | \`${username}\` has joined the Network.`); - } catch (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - }); - - app.post(baseEndpoint + '/leave', async function(req, res) { - isFeatureEnabled(features.discord, res, lang); - const username = required(req.body, "username", res); - - try { - const guild = client.guilds.cache.get(config.discord.guildId); - const channel = guild.channels.cache.get(config.discord.channels.networkChatLog); - - channel.send(`:negative_squared_cross_mark: | \`${username}\` has left the Network.`); - - res.send({ - success: true - }); - } catch (error) { - res.send({ - success: false, - message: `${error}` - }); - } - - return res; - }); - -} \ No newline at end of file +import { isFeatureEnabled, required } from "../common"; + +export default function discordApiRoute( + app, + client, + config, + db, + features, + lang +) { + const baseEndpoint = "/api/discord"; + + app.post(baseEndpoint + "/switch", async function (req, res) { + isFeatureEnabled(features.discord, res, lang); + const username = required(req.body, "username", res); + const server = required(req.body, "server", res); + + try { + const guild = client.guilds.cache.get(config.discord.guildId); + const channel = guild.channels.cache.get( + config.discord.channels.networkChatLog + ); + + channel.send( + `:twisted_rightwards_arrows: | \`${username}\` switched to \`${server}\`` + ); + + return res.send({ + success: true, + }); + } catch (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/chat", async function (req, res) { + isFeatureEnabled(features.discord, res, lang); + const username = required(req.body, "username", res); + const server = required(req.body, "server", res); + const content = required(req.body, "content", res); + + try { + const guild = client.guilds.cache.get(config.discord.guildId); + const channel = guild.channels.cache.get( + config.discord.channels.networkChatLog + ); + + channel.send(`**${server}** | \`${username}\` :: ${content}`); + + return res.send({ + success: true, + }); + } catch (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + }); + + app.post(baseEndpoint + "/join", async function (req, res) { + isFeatureEnabled(features.discord, res, lang); + const username = required(req.body, "username", res); + + try { + const guild = client.guilds.cache.get(config.discord.guildId); + const channel = guild.channels.cache.get( + config.discord.channels.networkChatLog + ); + + channel.send( + `:ballot_box_with_check: | \`${username}\` has joined the Network.` + ); + } catch (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + }); + + app.post(baseEndpoint + "/leave", async function (req, res) { + isFeatureEnabled(features.discord, res, lang); + const username = required(req.body, "username", res); + + try { + const guild = client.guilds.cache.get(config.discord.guildId); + const channel = guild.channels.cache.get( + config.discord.channels.networkChatLog + ); + + channel.send( + `:negative_squared_cross_mark: | \`${username}\` has left the Network.` + ); + + res.send({ + success: true, + }); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); +} diff --git a/api/routes/filter.js b/api/routes/filter.js index 76037af8..5e1096a1 100644 --- a/api/routes/filter.js +++ b/api/routes/filter.js @@ -1,73 +1,71 @@ -import { expandString, isFeatureEnabled, required } from '../common'; -import filter from '../../filter.json' assert { type: "json" }; +import { expandString, isFeatureEnabled, required } from "../common"; +import filter from "../../filter.json" assert { type: "json" }; export default function filterApiRoute(app, config, db, features, lang) { - const baseEndpoint = '/api/filter'; + const baseEndpoint = "/api/filter"; - app.post(baseEndpoint, async function (req, res) { - function expandString(string, filter) { - var regexString = ""; - for (var i = 0; i < string.length; i++) { - if (string[i] in filter.alias) - regexString += "[" + filter.alias[string[i]] + "]"; - else - regexString += string[i] - } - regexString = regexString.replace(".", "\\."); - return regexString; - } - - if (!features.filter.phrase && !features.filter.link) - return isFeatureEnabled(false, res, lang); + app.post(baseEndpoint, async function (req, res) { + function expandString(string, filter) { + var regexString = ""; + for (var i = 0; i < string.length; i++) { + if (string[i] in filter.alias) + regexString += "[" + filter.alias[string[i]] + "]"; + else regexString += string[i]; + } + regexString = regexString.replace(".", "\\."); + return regexString; + } - const content = required(req.body, "content", res); + if (!features.filter.phrase && !features.filter.link) + return isFeatureEnabled(false, res, lang); - var bannedWords = []; - if (features.filter.phrase) - bannedWords = bannedWords.concat(filter.phrases); - if (features.filter.link) - bannedWords = bannedWords.concat(filter.links); + const content = required(req.body, "content", res); - var bannedRegex = []; - bannedWords.forEach(bannedWord => { - bannedRegex.push(new RegExp(expandString(bannedWord, filter))); - }); + var bannedWords = []; + if (features.filter.phrase) + bannedWords = bannedWords.concat(filter.phrases); + if (features.filter.link) bannedWords = bannedWords.concat(filter.links); - let responseSent = false; - - try { - const wordList = content.split(" "); - for (let i = 0; i < bannedRegex.length; i++) { - const re = bannedRegex[i]; - for (let j = 0; j < wordList.length; j++) { - const word = wordList[j]; - if (re.test(word)) { - res.send({ - success: false, - message: lang.filter.phraseCaught - }); - responseSent = true; - break; - } - } - if (responseSent) { - break; - } - } + var bannedRegex = []; + bannedWords.forEach((bannedWord) => { + bannedRegex.push(new RegExp(expandString(bannedWord, filter))); + }); - if (!responseSent) { - res.send({ - success: true, - message: `Content Clean` - }); - } - } catch (error) { - console.log(error); + let responseSent = false; + try { + const wordList = content.split(" "); + for (let i = 0; i < bannedRegex.length; i++) { + const re = bannedRegex[i]; + for (let j = 0; j < wordList.length; j++) { + const word = wordList[j]; + if (re.test(word)) { res.send({ - success: false, - message: lang.web.registrationError + success: false, + message: lang.filter.phraseCaught, }); + responseSent = true; + break; + } } - }); -} \ No newline at end of file + if (responseSent) { + break; + } + } + + if (!responseSent) { + res.send({ + success: true, + message: `Content Clean`, + }); + } + } catch (error) { + console.log(error); + + res.send({ + success: false, + message: lang.web.registrationError, + }); + } + }); +} diff --git a/api/routes/index.js b/api/routes/index.js index f40429eb..0736c7c4 100644 --- a/api/routes/index.js +++ b/api/routes/index.js @@ -1,28 +1,26 @@ -import announcementApiRoute from './announcement' -import applicationApiRoute from './application' -import discordApiRoute from './discord' -import serverApiRoute from './server' -import sessionApiRoute from './session' -import userApiRoute from './user' -import webApiRoute from './web' -import filterApiRoute from './filter' +import announcementApiRoute from "./announcement"; +import applicationApiRoute from "./application"; +import discordApiRoute from "./discord"; +import serverApiRoute from "./server"; +import sessionApiRoute from "./session"; +import userApiRoute from "./user"; +import webApiRoute from "./web"; +import filterApiRoute from "./filter"; export default (app, client, moment, config, db, features, lang) => { + announcementApiRoute(app, config, db, features, lang); + applicationApiRoute(app, config, db, features, lang); + discordApiRoute(app, client, config, db, features, lang); + serverApiRoute(app, config, db, features, lang); + sessionApiRoute(app, config, db, features, lang); + userApiRoute(app, config, db, features, lang); + webApiRoute(app, config, db, features, lang); + filterApiRoute(app, config, db, features, lang); - announcementApiRoute(app, config, db, features, lang); - applicationApiRoute(app, config, db, features, lang); - discordApiRoute(app, client, config, db, features, lang); - serverApiRoute(app, config, db, features, lang); - sessionApiRoute(app, config, db, features, lang); - userApiRoute(app, config, db, features, lang); - webApiRoute(app, config, db, features, lang); - filterApiRoute(app, config, db, features, lang); - - app.get('/api/heartbeat', async function (req, res) { - return res.send({ - success: true, - message: `OK` - }); + app.get("/api/heartbeat", async function (req, res) { + return res.send({ + success: true, + message: `OK`, }); - -} \ No newline at end of file + }); +}; diff --git a/api/routes/server.js b/api/routes/server.js index 0ffb8bbb..70a6cf6e 100644 --- a/api/routes/server.js +++ b/api/routes/server.js @@ -1,112 +1,130 @@ -import {isFeatureEnabled, required, optional, generateLog} from '../common' +import { isFeatureEnabled, required, optional, generateLog } from "../common"; export default function serverApiRoute(app, config, db, features, lang) { - const baseEndpoint = '/api/server'; - - // TODO: Update docs - app.get(baseEndpoint + '/get', async function(req, res) { - isFeatureEnabled(features.server, res, lang); - const serverId = optional(req.query, "serverId"); - - try { - function getServers(dbQuery) { - db.query(dbQuery, function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - if (!results.length) { - return res.send({ - success: false, - message: `There are no servers available.` - }); - } - - return res.send({ - success: true, - data: results - }); - }); - } - - // Get Server by ID - if (serverId) { - let dbQuery = `SELECT * FROM servers WHERE serverId=${serverId};` - getServers(dbQuery); - } - - // Return all Servers by default - let dbQuery = `SELECT * FROM servers ORDER BY position ASC;` - getServers(dbQuery); - return res; - } catch (error) { - res.send({ - success: false, - message: `${error}` - }); - } - - return res; - }); - - app.post(baseEndpoint + '/create', async function(req, res) { - isFeatureEnabled(features.server, res, lang); + const baseEndpoint = "/api/server"; - const actioningUser = required(req.body, "actioningUser", res); - const displayName = required(req.body, "displayName", res); - const serverConnectionAddress = required(req.body, "serverConnectionAddress", res); - const position = required(req.body, "position", res); + // TODO: Update docs + app.get(baseEndpoint + "/get", async function (req, res) { + isFeatureEnabled(features.server, res, lang); + const serverId = optional(req.query, "serverId"); - const serverCreatedLang = lang.server.serverCreated + try { + function getServers(dbQuery) { + db.query(dbQuery, function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } - try { - db.query(` + if (!results.length) { + return res.send({ + success: false, + message: `There are no servers available.`, + }); + } + + return res.send({ + success: true, + data: results, + }); + }); + } + + // Get Server by ID + if (serverId) { + let dbQuery = `SELECT * FROM servers WHERE serverId=${serverId};`; + getServers(dbQuery); + } + + // Return all Servers by default + let dbQuery = `SELECT * FROM servers ORDER BY position ASC;`; + getServers(dbQuery); + return res; + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/create", async function (req, res) { + isFeatureEnabled(features.server, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const displayName = required(req.body, "displayName", res); + const serverConnectionAddress = required( + req.body, + "serverConnectionAddress", + res + ); + const position = required(req.body, "position", res); + + const serverCreatedLang = lang.server.serverCreated; + + try { + db.query( + ` INSERT INTO servers ( displayName, serverConnectionAddress, position - ) VALUES (?, ?, ?)`, [displayName, serverConnectionAddress, position], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "SUCCESS", "SERVER", `Created ${displayName} (${serverConnectionAddress})`, res); - - return res.send({ - success: true, - message: serverCreatedLang.replace("%NAME%", displayName) - }); - }); - - } catch (error) { + ) VALUES (?, ?, ?)`, + [displayName, serverConnectionAddress, position], + function (error, results, fields) { + if (error) { return res.send({ - success: false, - message: `${error}` + success: false, + message: `${error}`, }); + } + + generateLog( + actioningUser, + "SUCCESS", + "SERVER", + `Created ${displayName} (${serverConnectionAddress})`, + res + ); + + return res.send({ + success: true, + message: serverCreatedLang.replace("%NAME%", displayName), + }); } - - return res; - }); - - app.post(baseEndpoint + '/edit', async function(req, res) { - isFeatureEnabled(features.server, res, lang); - - const actioningUser = required(req.body, "actioningUser", res); - const serverId = required(req.body, "serverId", res); - const displayName = required(req.body, "displayName", res); - const serverConnectionAddress = required(req.body, "serverConnectionAddress", res); - const position = required(req.body, "position", res); - - try { - db.query(` + ); + } catch (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/edit", async function (req, res) { + isFeatureEnabled(features.server, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const serverId = required(req.body, "serverId", res); + const displayName = required(req.body, "displayName", res); + const serverConnectionAddress = required( + req.body, + "serverConnectionAddress", + res + ); + const position = required(req.body, "position", res); + + try { + db.query( + ` UPDATE servers SET @@ -114,68 +132,79 @@ export default function serverApiRoute(app, config, db, features, lang) { serverConnectionAddress=?, position=? WHERE - serverId=?`, - [ - displayName, - serverConnectionAddress, - position, - serverId - ], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "SUCCESS", "SERVER", `Edited ${displayName} (${serverConnectionAddress})`, res); - - return res.send({ - success: true, - message: lang.server.serverEdited - }); - }); - - } catch (error) { + serverId=?`, + [displayName, serverConnectionAddress, position, serverId], + function (error, results, fields) { + if (error) { return res.send({ - success: false, - message: `${error}` + success: false, + message: `${error}`, }); + } + + generateLog( + actioningUser, + "SUCCESS", + "SERVER", + `Edited ${displayName} (${serverConnectionAddress})`, + res + ); + + return res.send({ + success: true, + message: lang.server.serverEdited, + }); } - - return res; - }); - - app.post(baseEndpoint + '/delete', async function(req, res) { - isFeatureEnabled(features.server, res, lang); - - const actioningUser = required(req.body, "actioningUser", res); - const serverId = required(req.body, "serverId", res); - - try { - db.query(`DELETE FROM servers WHERE serverId=?;`, [serverId], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - generateLog(actioningUser, "SUCCESS", "SERVER", `Deleted ${serverId}`, res); - - return res.send({ - success: true, - message: lang.server.serverDeleted - }); - }); - - } catch (error) { + ); + } catch (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/delete", async function (req, res) { + isFeatureEnabled(features.server, res, lang); + + const actioningUser = required(req.body, "actioningUser", res); + const serverId = required(req.body, "serverId", res); + + try { + db.query( + `DELETE FROM servers WHERE serverId=?;`, + [serverId], + function (error, results, fields) { + if (error) { return res.send({ - success: false, - message: `${error}` + success: false, + message: `${error}`, }); + } + + generateLog( + actioningUser, + "SUCCESS", + "SERVER", + `Deleted ${serverId}`, + res + ); + + return res.send({ + success: true, + message: lang.server.serverDeleted, + }); } - - return res; - }); -} \ No newline at end of file + ); + } catch (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); +} diff --git a/api/routes/session.js b/api/routes/session.js index f8ef3b44..e3301159 100644 --- a/api/routes/session.js +++ b/api/routes/session.js @@ -1,17 +1,18 @@ -import {required} from '../common' +import { required } from "../common"; export default function sessionApiRoute(app, config, db, features, lang) { - const baseEndpoint = '/api/session'; + const baseEndpoint = "/api/session"; - app.post(baseEndpoint + '/create', async function(req, res) { - const uuid = required(req.body, "uuid", res); - const ipAddress = required(req.body, "ipAddress", res); - - const newSessionCreatedLang = lang.session.newSessionCreated + app.post(baseEndpoint + "/create", async function (req, res) { + const uuid = required(req.body, "uuid", res); + const ipAddress = required(req.body, "ipAddress", res); - try { - // Insert newly started session into database - db.query(` + const newSessionCreatedLang = lang.session.newSessionCreated; + + try { + // Insert newly started session into database + db.query( + ` INSERT INTO gameSessions ( userId, @@ -19,109 +20,118 @@ export default function sessionApiRoute(app, config, db, features, lang) { ) VALUES ( (SELECT userId FROM users WHERE uuid=?), ? - )`, [uuid, ipAddress], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - return res.send({ - success: true, - message: newSessionCreatedLang.replace("%UUID%", uuid) - }); + )`, + [uuid, ipAddress], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, }); + } - } catch (error) { - res.send({ - success: false, - message: `${error}` - }); + return res.send({ + success: true, + message: newSessionCreatedLang.replace("%UUID%", uuid), + }); } - - return res; - }); - - app.post(baseEndpoint + '/destroy', async function(req, res) { - const uuid = required(req.body, "uuid", res); - - const sessionClosedLang = lang.session.allSessionsClosed - - try { - // Update any open sessions for the specified user to close them - // The 'AND gameSessions.sessionId > 0' line is necessary to bypass mySQL's "safe update" feature. - // If this is not there and there is somehow more than 1 open session, the query will fail. - db.query(` + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/destroy", async function (req, res) { + const uuid = required(req.body, "uuid", res); + + const sessionClosedLang = lang.session.allSessionsClosed; + + try { + // Update any open sessions for the specified user to close them + // The 'AND gameSessions.sessionId > 0' line is necessary to bypass mySQL's "safe update" feature. + // If this is not there and there is somehow more than 1 open session, the query will fail. + db.query( + ` UPDATE gameSessions, users SET gameSessions.sessionEnd = NOW() WHERE gameSessions.userId = users.userId AND users.uuid = ? AND gameSessions.sessionEnd IS NULL AND gameSessions.sessionId > 0 - `, [uuid], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - return res.send({ - success: true, - message: sessionClosedLang.replace("%UUID%", uuid) - }); + `, + [uuid], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, }); + } - } catch (error) { - res.send({ - success: false, - message: `${error}` - }); + return res.send({ + success: true, + message: sessionClosedLang.replace("%UUID%", uuid), + }); } - - return res; - }); - - app.post(baseEndpoint + '/switch', async function(req, res) { - const uuid = required(req.body, "uuid", res); - const server = required(req.body, "server", res); - - const sessionSwitchLang = lang.session.sessionSwitch - - try { - // Update any open sessions for the specified user to change to the specified server - // The 'AND gameSessions.sessionId > 0' line is necessary to bypass mySQL's "safe update" feature. - // If this is not there and there is somehow more than 1 open session, the query will fail. - db.query(` + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); + + app.post(baseEndpoint + "/switch", async function (req, res) { + const uuid = required(req.body, "uuid", res); + const server = required(req.body, "server", res); + + const sessionSwitchLang = lang.session.sessionSwitch; + + try { + // Update any open sessions for the specified user to change to the specified server + // The 'AND gameSessions.sessionId > 0' line is necessary to bypass mySQL's "safe update" feature. + // If this is not there and there is somehow more than 1 open session, the query will fail. + db.query( + ` UPDATE gameSessions, users, servers SET gameSessions.server = ? WHERE gameSessions.userId = users.userId AND users.uuid = ? AND gameSessions.sessionEnd IS NULL AND gameSessions.sessionId > 0 - `, [server, uuid], function(error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - - return res.send({ - success: true, - message: sessionSwitchLang.replace("%UUID%", uuid).replace("%SERVER%", server) - }); - }); - - } catch (error) { - res.send({ - success: false, - message: `${error}` + `, + [server, uuid], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, }); + } + + return res.send({ + success: true, + message: sessionSwitchLang + .replace("%UUID%", uuid) + .replace("%SERVER%", server), + }); } - - return res; - }); - -} \ No newline at end of file + ); + } catch (error) { + res.send({ + success: false, + message: `${error}`, + }); + } + + return res; + }); +} diff --git a/api/routes/user.js b/api/routes/user.js index ae439337..50d6ba15 100644 --- a/api/routes/user.js +++ b/api/routes/user.js @@ -1,113 +1,131 @@ -import {required, optional} from '../common' +import { required, optional } from "../common"; export default function userApiRoute(app, config, db, features, lang) { - const baseEndpoint = '/api/user'; + const baseEndpoint = "/api/user"; - app.post(baseEndpoint + '/create', async function(req, res) { - const uuid = required(req.body, "uuid", res); - const username = required(req.body, "username", res); + app.post(baseEndpoint + "/create", async function (req, res) { + const uuid = required(req.body, "uuid", res); + const username = required(req.body, "username", res); - const userCreatedLang = lang.api.userCreated + const userCreatedLang = lang.api.userCreated; - // shadowolf - // Check if user does not exist, we do this in case of testing we create multiple users on accident - db.query(`SELECT * FROM users WHERE uuid=?`, [uuid], function (error, results, fields) { - if (error) { - console.log(error); - } - - if (results[0]) { - // To ensure usernames are always accurate we set the username just in case the username changes. - db.query(`UPDATE users SET username=? WHERE uuid=?;`, [username, uuid], function (error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } - }); + // shadowolf + // Check if user does not exist, we do this in case of testing we create multiple users on accident + db.query( + `SELECT * FROM users WHERE uuid=?`, + [uuid], + function (error, results, fields) { + if (error) { + console.log(error); + } - // If the user already exists, we alert the console that the user wasn't created because it doesn't exist. + if (results[0]) { + // To ensure usernames are always accurate we set the username just in case the username changes. + db.query( + `UPDATE users SET username=? WHERE uuid=?;`, + [username, uuid], + function (error, results, fields) { + if (error) { return res.send({ - success: null, - message: `${lang.api.userAlreadyExists}` + success: false, + message: `${error}`, }); + } } + ); - // If user does not exist, create them - db.query(`INSERT INTO users (uuid, username) VALUES (?, ?)`, [uuid, username], function (error, results, fields) { - if (error) { - return res.send({ - success: false, - message: `${error}` - }); - } + // If the user already exists, we alert the console that the user wasn't created because it doesn't exist. + return res.send({ + success: null, + message: `${lang.api.userAlreadyExists}`, + }); + } - return res.send({ - success: true, - message: userCreatedLang.replace('%USERNAME%', username).replace('%UUID%', uuid) - }); + // If user does not exist, create them + db.query( + `INSERT INTO users (uuid, username) VALUES (?, ?)`, + [uuid, username], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } + + return res.send({ + success: true, + message: userCreatedLang + .replace("%USERNAME%", username) + .replace("%UUID%", uuid), }); - }); + } + ); + } + ); + + return res; + }); - return res; - }); - - // TODO: Update docs - app.get(baseEndpoint + '/get', async function(req, res) { - const username = optional(req.query, "username"); - - try { - if (username) { - db.query(`SELECT * FROM users WHERE username=?;`, [username], function (error, results, fields) { - if (error) { - return res.send({ - success: false, - message: error - }); - } - - if (!results || !results.length) { - return res.send({ - success: false, - message: lang.api.userDoesNotExist - }); - } - - res.send({ - success: true, - data: results - }); - }); - } else { - db.query(`SELECT * FROM users;`, function (error, results, fields) { - if (error) { - return res.send({ - success: false, - message: error - }); - } - - if (!results || !results.length) { - return res.send({ - success: false, - message: `No Users found` - }); - } - - res.send({ - success: true, - data: results - }); - }); + // TODO: Update docs + app.get(baseEndpoint + "/get", async function (req, res) { + const username = optional(req.query, "username"); + + try { + if (username) { + db.query( + `SELECT * FROM users WHERE username=?;`, + [username], + function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: error, + }); } - } catch (error) { - return res.send({ + + if (!results || !results.length) { + return res.send({ success: false, - message: `${error}` + message: lang.api.userDoesNotExist, + }); + } + + res.send({ + success: true, + data: results, }); - } + } + ); + } else { + db.query(`SELECT * FROM users;`, function (error, results, fields) { + if (error) { + return res.send({ + success: false, + message: error, + }); + } + + if (!results || !results.length) { + return res.send({ + success: false, + message: `No Users found`, + }); + } + + res.send({ + success: true, + data: results, + }); + }); + } + } catch (error) { + return res.send({ + success: false, + message: `${error}`, + }); + } - return res; - }); -} \ No newline at end of file + return res; + }); +} diff --git a/api/routes/verifyToken.js b/api/routes/verifyToken.js index ea6d42f5..b0767b24 100644 --- a/api/routes/verifyToken.js +++ b/api/routes/verifyToken.js @@ -1,25 +1,24 @@ -import lang from "../../lang.json" assert {type: "json"}; +import lang from "../../lang.json" assert { type: "json" }; export default function verifyToken(req, res, done) { - - var token = req.headers['x-access-token']; + var token = req.headers["x-access-token"]; - if (!token) { - // Token not included - return res.send({ - success: false, - message: lang.api.noToken - }); - } - - if (token === process.env.apiKey) { - // Passed - done(); - } else { - // Token was incorrect. - return res.send({ - success: false, - message: lang.api.invalidToken - }); - } -} \ No newline at end of file + if (!token) { + // Token not included + return res.send({ + success: false, + message: lang.api.noToken, + }); + } + + if (token === process.env.apiKey) { + // Passed + done(); + } else { + // Token was incorrect. + return res.send({ + success: false, + message: lang.api.invalidToken, + }); + } +} diff --git a/api/routes/web.js b/api/routes/web.js index 6c6854fb..12f6dc2b 100644 --- a/api/routes/web.js +++ b/api/routes/web.js @@ -1,171 +1,201 @@ -import bcrypt from 'bcrypt'; -import { doesPasswordMatch, hasEmailBeenUsed, hasUserJoinedBefore } from '../../controllers/userController'; -import {generateLog, hashEmail, isFeatureEnabled, required, setBannerCookie} from '../common' +import bcrypt from "bcrypt"; +import { + doesPasswordMatch, + hasEmailBeenUsed, + hasUserJoinedBefore, +} from "../../controllers/userController"; +import { + generateLog, + hashEmail, + isFeatureEnabled, + required, + setBannerCookie, +} from "../common"; export default async function webApiRoute(app, config, db, features, lang) { - const baseEndpoint = '/api/web'; + const baseEndpoint = "/api/web"; - app.post(baseEndpoint + '/register/create', async function(req, res) { - isFeatureEnabled(features.web.register, res, lang); + app.post(baseEndpoint + "/register/create", async function (req, res) { + isFeatureEnabled(features.web.register, res, lang); - const username = required(req.body, "username", res); - const email = required(req.body, "email", res); - const password = required(req.body, "password", res); - const confirmPassword = required(req.body, "confirmPassword", res); + const username = required(req.body, "username", res); + const email = required(req.body, "email", res); + const password = required(req.body, "password", res); + const confirmPassword = required(req.body, "confirmPassword", res); - const notLoggedInBeforeLang = lang.web.notLoggedInBefore + const notLoggedInBeforeLang = lang.web.notLoggedInBefore; - db.query(`select * from users where username=?; select * from users where email=?;`, [username, email], async function (err, results) { - if (err) { - throw err; - } + db.query( + `select * from users where username=?; select * from users where email=?;`, + [username, email], + async function (err, results) { + if (err) { + throw err; + } - // User has not logged in before. - let userJoinBefore = await hasUserJoinedBefore(username); - if (!userJoinBefore) { - setBannerCookie(`warning`, `This is a test`, res); - - return res.send({ - success: false, - alertType: "warning", - alertContent: notLoggedInBeforeLang.replace("%SITEADDRESS%", process.env.siteAddress) - }); - } + // User has not logged in before. + let userJoinBefore = await hasUserJoinedBefore(username); + if (!userJoinBefore) { + setBannerCookie(`warning`, `This is a test`, res); + + return res.send({ + success: false, + alertType: "warning", + alertContent: notLoggedInBeforeLang.replace( + "%SITEADDRESS%", + process.env.siteAddress + ), + }); + } - let emailBeenUsed = await hasEmailBeenUsed(email) - if (emailBeenUsed) { - return res.send({ - success: false, - alertType: "warning", - alertContent: lang.web.emailAlreadyInUse - }); - } + let emailBeenUsed = await hasEmailBeenUsed(email); + if (emailBeenUsed) { + return res.send({ + success: false, + alertType: "warning", + alertContent: lang.web.emailAlreadyInUse, + }); + } - // Check if passwords match - let passwordMatch = await doesPasswordMatch(password, confirmPassword); - if (!passwordMatch) { - return res.send({ - success: false, - alertType: "danger", - alertContent: lang.web.passwordDoesNotMatch - }); - } + // Check if passwords match + let passwordMatch = await doesPasswordMatch(password, confirmPassword); + if (!passwordMatch) { + return res.send({ + success: false, + alertType: "danger", + alertContent: lang.web.passwordDoesNotMatch, + }); + } - // Hash password and enter into the database. - try { - const salt = await bcrypt.genSalt(); - let hashpassword = await bcrypt.hash(password, salt); - - db.query(`UPDATE users SET password=?, email=?, emailHash=? WHERE username=?;`, [hashpassword, email, await hashEmail(email), username], async function (err, results) { - if (err) { - console.log(err); - - return res.send({ - success: false, - alertType: "danger", - alertContent: lang.web.registrationError - }); - } - - generateLog(null, "INFO", "WEB", `New website registration ${username}`, res); - - // Success, generating account now. - return res.send({ - success: true, - alertType: "success", - alertContent: lang.web.registrationSuccess - }); - }); + // Hash password and enter into the database. + try { + const salt = await bcrypt.genSalt(); + let hashpassword = await bcrypt.hash(password, salt); - } catch (error) { - console.log(error); + db.query( + `UPDATE users SET password=?, email=?, emailHash=? WHERE username=?;`, + [hashpassword, email, await hashEmail(email), username], + async function (err, results) { + if (err) { + console.log(err); return res.send({ - success: false, - alertType: "danger", - alertContent: lang.web.registrationError + success: false, + alertType: "danger", + alertContent: lang.web.registrationError, }); + } + + generateLog( + null, + "INFO", + "WEB", + `New website registration ${username}`, + res + ); + + // Success, generating account now. + return res.send({ + success: true, + alertType: "success", + alertContent: lang.web.registrationSuccess, + }); } - }); + ); + } catch (error) { + console.log(error); - return res; - }); + return res.send({ + success: false, + alertType: "danger", + alertContent: lang.web.registrationError, + }); + } + } + ); - app.get(baseEndpoint + '/configuration', async function(req, res) { - // There is no isFeatureEnabled() due to being a critical endpoint. + return res; + }); - return res.send({ - success: true, - data: { - "siteName": config.siteConfiguration.siteName, - "siteAddress": process.env.siteAddress - } - }); + app.get(baseEndpoint + "/configuration", async function (req, res) { + // There is no isFeatureEnabled() due to being a critical endpoint. + + return res.send({ + success: true, + data: { + siteName: config.siteConfiguration.siteName, + siteAddress: process.env.siteAddress, + }, }); + }); - app.get(baseEndpoint + '/statistics', async function (req, res) { - // There is no isFeatureEnabled() due to being a critical endpoint. + app.get(baseEndpoint + "/statistics", async function (req, res) { + // There is no isFeatureEnabled() due to being a critical endpoint. - db.query(` + db.query( + ` SELECT COUNT(*) AS communityMembers FROM users; SELECT HOUR(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(COALESCE(sessionEnd, NOW()), sessionStart))))) AS timePlayed FROM gameSessions; SELECT COUNT(DISTINCT(u.uuid)) totalStaff FROM userRanks ur JOIN ranks r ON ur.rankSlug = r.rankSlug JOIN users u ON u.uuid = ur.uuid WHERE r.isStaff = 1 AND u.disabled = 0; - `, async function (err, results) { - if (err) { - return console.log(err); - } + `, + async function (err, results) { + if (err) { + return console.log(err); + } - // General - let communityMembers = results[0][0].communityMembers; - let timePlayed = results[1][0].timePlayed; - let staffMembers = results[2][0].totalStaff; + // General + let communityMembers = results[0][0].communityMembers; + let timePlayed = results[1][0].timePlayed; + let staffMembers = results[2][0].totalStaff; - return res.send({ - success: true, - data: { - general: { - "communityMembers": communityMembers, - "timePlayed": timePlayed, - "staffMembers": staffMembers, - } - } - }); + return res.send({ + success: true, + data: { + general: { + communityMembers: communityMembers, + timePlayed: timePlayed, + staffMembers: staffMembers, + }, + }, }); - - return res; - }); - - app.get(baseEndpoint + '/logs/get', async function (req, res) { - try { - db.query(`SELECT logId, creatorId, (SELECT username FROM users WHERE userId=creatorId) AS 'actionedUsername', logFeature, logType, description, actionedDateTime FROM logs ORDER BY actionedDateTime DESC;`, function (error, results, fields) { - if (error) { - res.send({ - success: false, - message: `${error}` - }); - } - - if (!results.length) { - res.send({ - success: false, - message: `There are no logs` - }); - } - - res.send({ - success: true, - data: results - }); + } + ); + + return res; + }); + + app.get(baseEndpoint + "/logs/get", async function (req, res) { + try { + db.query( + `SELECT logId, creatorId, (SELECT username FROM users WHERE userId=creatorId) AS 'actionedUsername', logFeature, logType, description, actionedDateTime FROM logs ORDER BY actionedDateTime DESC;`, + function (error, results, fields) { + if (error) { + res.send({ + success: false, + message: `${error}`, }); + } - } catch (error) { + if (!results.length) { res.send({ - success: false, - message: error + success: false, + message: `There are no logs`, }); - } - - return res; - }); + } -} \ No newline at end of file + res.send({ + success: true, + data: results, + }); + } + ); + } catch (error) { + res.send({ + success: false, + message: error, + }); + } + + return res; + }); +} diff --git a/app.js b/app.js index a781efba..53d22be6 100644 --- a/app.js +++ b/app.js @@ -1,128 +1,142 @@ -import packageData from './package.json' assert {type: "json"}; -import moment from 'moment'; -import fetch from 'node-fetch'; -import dotenv from 'dotenv'; -dotenv.config() - -import fastify from 'fastify'; -import fastifySession from '@fastify/session'; -import fastifyCookie from '@fastify/cookie'; - -import config from './config.json' assert {type: "json"}; -import features from './features.json' assert {type: "json"}; -import lang from './lang.json' assert {type: "json"}; -import db from './controllers/databaseController'; -import { getWebAnnouncement } from './controllers/announcementController'; +import packageData from "./package.json" assert { type: "json" }; +import moment from "moment"; +import fetch from "node-fetch"; +import dotenv from "dotenv"; +dotenv.config(); + +import fastify from "fastify"; +import fastifySession from "@fastify/session"; +import fastifyCookie from "@fastify/cookie"; + +import config from "./config.json" assert { type: "json" }; +import features from "./features.json" assert { type: "json" }; +import lang from "./lang.json" assert { type: "json" }; +import db from "./controllers/databaseController"; +import { getWebAnnouncement } from "./controllers/announcementController"; // Paths -import path from 'path'; -import { fileURLToPath } from 'url'; +import path from "path"; +import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -import('./controllers/discordController.js'); +import("./controllers/discordController.js"); -// +// // Website Related // // Site Routes -import siteRoutes from './routes' -import apiRoutes from './api/routes' -import apiRedirectRoutes from './api/internal_redirect' +import siteRoutes from "./routes"; +import apiRoutes from "./api/routes"; +import apiRedirectRoutes from "./api/internal_redirect"; // API token authentication -import verifyToken from './api/routes/verifyToken' -import { getGlobalImage } from './api/common'; -import { client } from './controllers/discordController'; +import verifyToken from "./api/routes/verifyToken"; +import { getGlobalImage } from "./api/common"; +import { client } from "./controllers/discordController"; // // Application Boot // const buildApp = async () => { - - const app = fastify({ logger: config.debug }); - - // When app errors, render the error on a page, do not provide JSON - app.setErrorHandler(async function (error, req, res) { - res.view('session/error', { - "pageTitle": `Server Error`, - config: config, - error: error, - req: req, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement(), - }); - }); - - // EJS Rendering Engine - await app.register(await import("@fastify/view"), { - engine: { - ejs: await import("ejs"), - }, - root: path.join(__dirname, "views"), + const app = fastify({ logger: config.debug }); + + // When app errors, render the error on a page, do not provide JSON + app.setNotFoundHandler(async function (req, res) { + return res.view("session/notFound", { + pageTitle: `404 Not Found`, + config: config, + error: error, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); - - await app.register(await import('@fastify/static'), { - root: path.join(__dirname, 'assets'), - prefix: '/', - }) - - await app.register(await import ('@fastify/formbody')) - - await app.register((instance, options, next) => { - // API routes (Token authenticated) - instance.addHook('preValidation', verifyToken); - apiRoutes(instance, client, moment, config, db, features, lang); - next(); + }); + + // When app errors, render the error on a page, do not provide JSON + app.setErrorHandler(async function (error, req, res) { + res.view("session/error", { + pageTitle: `Server Error`, + config: config, + error: error, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); - - await app.register((instance, options, next) => { - // Don't authenticate the Redirect routes. These are - // protected by - apiRedirectRoutes(instance, config, lang); - next(); - }); - - // Sessions - await app.register(fastifyCookie, { - secret: process.env.sessionCookieSecret, // for cookies signature - }); - - await app.register(fastifySession, { - cookieName: 'sessionId', - secret: process.env.sessionCookieSecret, - cookie: { secure: false }, - expires: 1800000 - }); - - await app.register((instance, options, next) => { - // Routes - siteRoutes(instance, client, fetch, moment, config, db, features, lang); - next(); - }); - - app.addHook('preHandler', (req, res, next) => { - req.session.authenticated = false; - next(); + }); + + // EJS Rendering Engine + await app.register(await import("@fastify/view"), { + engine: { + ejs: await import("ejs"), + }, + root: path.join(__dirname, "views"), + }); + + await app.register(await import("@fastify/static"), { + root: path.join(__dirname, "assets"), + prefix: "/", + }); + + await app.register(await import("@fastify/formbody")); + + await app.register((instance, options, next) => { + // API routes (Token authenticated) + instance.addHook("preValidation", verifyToken); + apiRoutes(instance, client, moment, config, db, features, lang); + next(); + }); + + await app.register((instance, options, next) => { + // Don't authenticate the Redirect routes. These are + // protected by + apiRedirectRoutes(instance, config, lang); + next(); + }); + + // Sessions + await app.register(fastifyCookie, { + secret: process.env.sessionCookieSecret, // for cookies signature + }); + + await app.register(fastifySession, { + cookieName: "sessionId", + secret: process.env.sessionCookieSecret, + cookie: { secure: false }, + expires: 1800000, + }); + + await app.register((instance, options, next) => { + // Routes + siteRoutes(instance, client, fetch, moment, config, db, features, lang); + next(); + }); + + app.addHook("preHandler", (req, res, next) => { + req.session.authenticated = false; + next(); + }); + + try { + const port = process.env.PORT; + + app.listen({ port: port, host: "0.0.0.0" }, (err) => { + if (err) { + app.log.error(err); + process.exit(1); + } }); - try { - const port = process.env.PORT; - - app.listen({ port: port, host: '0.0.0.0' }, (err) => { - if (err) { - app.log.error(err); - process.exit(1); - } - }) - - console.log(`\n// ${packageData.name} v.${packageData.version}\nGitHub Repository: ${packageData.homepage}\nCreated By: ${packageData.author}`); - console.log(`Site and API is listening to the port ${process.env.PORT}`); - } catch (error) { - app.log.error(`Unable to start the server:\n${error}`); - } + console.log( + `\n// ${packageData.name} v.${packageData.version}\nGitHub Repository: ${packageData.homepage}\nCreated By: ${packageData.author}` + ); + console.log(`Site and API is listening to the port ${process.env.PORT}`); + } catch (error) { + app.log.error(`Unable to start the server:\n${error}`); + } }; -buildApp(); \ No newline at end of file +buildApp(); diff --git a/commands/legoflip.mjs b/commands/legoflip.mjs index a5bf5dd9..98b00974 100644 --- a/commands/legoflip.mjs +++ b/commands/legoflip.mjs @@ -1,6 +1,6 @@ -import { Command, RegisterBehavior } from '@sapphire/framework'; -import { EmbedBuilder } from 'discord.js'; -import features from '../features.json' assert {type: "json"}; +import { Command, RegisterBehavior } from "@sapphire/framework"; +import { EmbedBuilder } from "discord.js"; +import features from "../features.json" assert { type: "json" }; export class LegoFlipCommand extends Command { constructor(context, options) { @@ -9,33 +9,41 @@ export class LegoFlipCommand extends Command { registerApplicationCommands(registry) { registry.registerChatInputCommand((builder) => - builder.setName('legoflip').setDescription('A simple lego flip! (Coin flip)') + builder + .setName("legoflip") + .setDescription("A simple lego flip! (Coin flip)") ); } async chatInputRun(interaction) { if (features.discord.commands.legoFlip) { - if (Math.random() < 0.50) { + if (Math.random() < 0.5) { const embed = new EmbedBuilder() - .setTitle(`Lego Flip!`) - .setImage(`https://crafatar.com/avatars/2a881594693543c99c39ec31374d46fe?overlay`) - + .setTitle(`Lego Flip!`) + .setImage( + `https://crafatar.com/avatars/2a881594693543c99c39ec31374d46fe?overlay` + ); + interaction.reply({ embeds: [embed], - empheral: false + empheral: false, }); } else { const embed = new EmbedBuilder() - .setTitle(`Lego Flip!`) - .setImage(`https://crafatar.com/avatars/21a6469871f04578830a2ab0ac2f4d48?overlay`) - + .setTitle(`Lego Flip!`) + .setImage( + `https://crafatar.com/avatars/21a6469871f04578830a2ab0ac2f4d48?overlay` + ); + interaction.reply({ embeds: [embed], - empheral: false - }); + empheral: false, + }); } } else { - interaction.reply("This feature has been disabled by the System Administrator."); + interaction.reply( + "This feature has been disabled by the System Administrator." + ); } } -} \ No newline at end of file +} diff --git a/commands/play.mjs b/commands/play.mjs index 836c0bdd..20a1e34c 100644 --- a/commands/play.mjs +++ b/commands/play.mjs @@ -1,50 +1,56 @@ -import { Command, RegisterBehavior } from '@sapphire/framework'; -import { Colors, EmbedBuilder } from 'discord.js'; -import fetch from 'node-fetch'; +import { Command, RegisterBehavior } from "@sapphire/framework"; +import { Colors, EmbedBuilder } from "discord.js"; +import fetch from "node-fetch"; export class PlayCommand extends Command { - constructor(context, options) { - super(context, { ...options }); - } + constructor(context, options) { + super(context, { ...options }); + } - registerApplicationCommands(registry) { - registry.registerChatInputCommand((builder) => - builder.setName('play').setDescription('Display all Network servers to play on.') - ); - } + registerApplicationCommands(registry) { + registry.registerChatInputCommand((builder) => + builder + .setName("play") + .setDescription("Display all Network servers to play on.") + ); + } - async chatInputRun(interaction) { - const fetchURL = `${process.env.siteAddress}/api/server/get`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const apiData = await response.json(); + async chatInputRun(interaction) { + const fetchURL = `${process.env.siteAddress}/api/server/get`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, + }); + const apiData = await response.json(); - if (!apiData.data) { - const noServersEmbed = new EmbedBuilder() - .setTitle(`No Servers`) - .setDescription(apiData.message) - .setColor(Colors.Red) + if (!apiData.data) { + const noServersEmbed = new EmbedBuilder() + .setTitle(`No Servers`) + .setDescription(apiData.message) + .setColor(Colors.Red); - interaction.reply({ - embeds: [noServersEmbed], - empheral: false - }); - } else { - const embed = new EmbedBuilder() - .setTitle(`Network Servers`) - .setDescription(`Get started! Jump on and play with our community!`) - .setColor(Colors.DarkGold) + interaction.reply({ + embeds: [noServersEmbed], + empheral: false, + }); + } else { + const embed = new EmbedBuilder() + .setTitle(`Network Servers`) + .setDescription(`Get started! Jump on and play with our community!`) + .setColor(Colors.DarkGold); - // Loop through the server data and add them to the embed - apiData.data.forEach(server => { - embed.addFields({ name: server.displayName, value: server.serverConnectionAddress, inline: true }); - }); + // Loop through the server data and add them to the embed + apiData.data.forEach((server) => { + embed.addFields({ + name: server.displayName, + value: server.serverConnectionAddress, + inline: true, + }); + }); - interaction.reply({ - embeds: [embed], - empheral: false - }); - } + interaction.reply({ + embeds: [embed], + empheral: false, + }); } + } } diff --git a/commands/policy.mjs b/commands/policy.mjs index f34be4e7..4650253b 100644 --- a/commands/policy.mjs +++ b/commands/policy.mjs @@ -1,5 +1,5 @@ -import { Command, RegisterBehavior } from '@sapphire/framework'; -import pkg from 'discord.js'; +import { Command, RegisterBehavior } from "@sapphire/framework"; +import pkg from "discord.js"; const { EmbedBuilder } = pkg; export class PolicyCommand extends Command { @@ -9,25 +9,47 @@ export class PolicyCommand extends Command { registerApplicationCommands(registry) { registry.registerChatInputCommand((builder) => - builder.setName('policy').setDescription('Display Network policy (Rules, Terms, Privacy, and Refund)') + builder + .setName("policy") + .setDescription( + "Display Network policy (Rules, Terms, Privacy, and Refund)" + ) ); } async chatInputRun(interaction) { const embed = new EmbedBuilder() - .setTitle('Network Policy') + .setTitle("Network Policy") .setColor(Colors.DarkGold) - .setDescription('For user reference, here is a link to all Network policies.\nBy joining the Network and using our services you agree to all our policies.') + .setDescription( + "For user reference, here is a link to all Network policies.\nBy joining the Network and using our services you agree to all our policies." + ) .addFields( - { name: 'Rules', value: `${process.env.siteAddress}/rules`, inline: false }, - { name: 'Terms Of Service', value: `${process.env.siteAddress}/terms`, inline: false }, - { name: 'Privacy Policy', value: `${process.env.siteAddress}/privacy`, inline: false }, - { name: 'Refund Policy', value: `${process.env.siteAddress}/refund`, inline: false } + { + name: "Rules", + value: `${process.env.siteAddress}/rules`, + inline: false, + }, + { + name: "Terms Of Service", + value: `${process.env.siteAddress}/terms`, + inline: false, + }, + { + name: "Privacy Policy", + value: `${process.env.siteAddress}/privacy`, + inline: false, + }, + { + name: "Refund Policy", + value: `${process.env.siteAddress}/refund`, + inline: false, + } ); const messageContent = { embeds: [embed], - ephemeral: false + ephemeral: false, }; interaction.reply(messageContent); diff --git a/commands/poll.mjs b/commands/poll.mjs index 96fce5fa..28b85061 100644 --- a/commands/poll.mjs +++ b/commands/poll.mjs @@ -1,5 +1,5 @@ -import { Command, RegisterBehavior } from '@sapphire/framework'; -import { Colors, EmbedBuilder } from 'discord.js'; +import { Command, RegisterBehavior } from "@sapphire/framework"; +import { Colors, EmbedBuilder } from "discord.js"; export class PollCommand extends Command { constructor(context, options) { @@ -8,28 +8,33 @@ export class PollCommand extends Command { registerApplicationCommands(registry) { registry.registerChatInputCommand((builder) => - builder.setName('poll').setDescription('Ask everyone a question or something to vote on!') - .addStringOption((option) => - option // - .setName('question') - .setDescription('Question to ask in the poll.') - .setRequired(true) - ) + builder + .setName("poll") + .setDescription("Ask everyone a question or something to vote on!") + .addStringOption((option) => + option // + .setName("question") + .setDescription("Question to ask in the poll.") + .setRequired(true) + ) ); } async chatInputRun(interaction) { - const pollQuestion = interaction.options.getString('question'); + const pollQuestion = interaction.options.getString("question"); const embed = new EmbedBuilder() .setTitle(`Poll by \`${interaction.user.username}\``) .setDescription(`${pollQuestion}`) - .setFooter({ text: 'Vote using the reactions below to have your say!' }) - .setColor(Colors.Blue) + .setFooter({ text: "Vote using the reactions below to have your say!" }) + .setColor(Colors.Blue); - const message = await interaction.reply({ embeds: [embed], fetchReply: true }); + const message = await interaction.reply({ + embeds: [embed], + fetchReply: true, + }); - await message.react('⬆️'); - await message.react('⬇️'); + await message.react("⬆️"); + await message.react("⬇️"); } -} \ No newline at end of file +} diff --git a/commands/rules.mjs b/commands/rules.mjs index 23cc5347..c07b7acd 100644 --- a/commands/rules.mjs +++ b/commands/rules.mjs @@ -1,5 +1,5 @@ -import { Command, RegisterBehavior } from '@sapphire/framework'; -import { EmbedBuilder } from 'discord.js'; +import { Command, RegisterBehavior } from "@sapphire/framework"; +import { EmbedBuilder } from "discord.js"; export class RulesCommand extends Command { constructor(context, options) { @@ -8,19 +8,23 @@ export class RulesCommand extends Command { registerApplicationCommands(registry) { registry.registerChatInputCommand((builder) => - builder.setName('rules').setDescription('Display link to the Network Rules') + builder + .setName("rules") + .setDescription("Display link to the Network Rules") ); } async chatInputRun(interaction) { const embed = new EmbedBuilder() .setTitle(`Network Rules`) - .setDescription(`Please ensure you follow and abide by the rules which you can read here: ${process.env.siteAddress}/rules`) - .setColor(Colors.DarkGold) + .setDescription( + `Please ensure you follow and abide by the rules which you can read here: ${process.env.siteAddress}/rules` + ) + .setColor(Colors.DarkGold); - interaction.reply({ - embeds: [embed], - empheral: false - }); + interaction.reply({ + embeds: [embed], + empheral: false, + }); } -} \ No newline at end of file +} diff --git a/commands/staffhelp.mjs b/commands/staffhelp.mjs index be0c5d7b..1cf020b7 100644 --- a/commands/staffhelp.mjs +++ b/commands/staffhelp.mjs @@ -1,6 +1,6 @@ -import { Command, RegisterBehavior } from '@sapphire/framework'; -import { Colors, EmbedBuilder } from 'discord.js'; -import config from '../config.json' assert {type: "json"}; +import { Command, RegisterBehavior } from "@sapphire/framework"; +import { Colors, EmbedBuilder } from "discord.js"; +import config from "../config.json" assert { type: "json" }; export class StaffHelpCommand extends Command { constructor(context, options) { @@ -10,40 +10,44 @@ export class StaffHelpCommand extends Command { registerApplicationCommands(registry) { registry.registerChatInputCommand((builder) => builder - .setName('staffhelp') - .setDescription('Sends a message to our Staff for help or assistance.') + .setName("staffhelp") + .setDescription("Sends a message to our Staff for help or assistance.") .addStringOption((option) => option // - .setName('query') - .setDescription('Question to ask in the poll.') + .setName("query") + .setDescription("Question to ask in the poll.") .setRequired(true) ) ); } async chatInputRun(interaction) { - const userQuery = interaction.options.getString('query'); + const userQuery = interaction.options.getString("query"); const staffAssistanceEmbed = new EmbedBuilder() - .setTitle(`Staff Assistance Requested by \`${interaction.user.username}\``) + .setTitle( + `Staff Assistance Requested by \`${interaction.user.username}\`` + ) .setDescription(`**Request:** ${userQuery}`) .setColor(Colors.Gold); - + const staffAssistanceConfirmed = new EmbedBuilder() .setTitle(`Staff Assistance Requested`) .setDescription(`Assistance request has been sent.`) .setColor(Colors.Green); const guild = interaction.guild; - const channel = guild.channels.cache.get(config.discord.channels.staffChannel); + const channel = guild.channels.cache.get( + config.discord.channels.staffChannel + ); channel.send({ - embeds: [staffAssistanceEmbed] + embeds: [staffAssistanceEmbed], }); interaction.reply({ embeds: [staffAssistanceConfirmed], - ephemeral: true + ephemeral: true, }); } -} \ No newline at end of file +} diff --git a/commands/website.mjs b/commands/website.mjs index f56d0351..6712a45b 100644 --- a/commands/website.mjs +++ b/commands/website.mjs @@ -1,5 +1,5 @@ -import { Command, RegisterBehavior } from '@sapphire/framework'; -import { EmbedBuilder } from 'discord.js'; +import { Command, RegisterBehavior } from "@sapphire/framework"; +import { EmbedBuilder } from "discord.js"; export class WebsiteCommand extends Command { constructor(context, options) { @@ -8,19 +8,23 @@ export class WebsiteCommand extends Command { registerApplicationCommands(registry) { registry.registerChatInputCommand((builder) => - builder.setName('website').setDescription('Display link to the Network Website') + builder + .setName("website") + .setDescription("Display link to the Network Website") ); } async chatInputRun(interaction) { const embed = new EmbedBuilder() .setTitle(`Network Website`) - .setDescription(`For more info and to get involved with the community, jump on our website ${process.env.siteAddress}`) - .setColor(Colors.DarkGold) + .setDescription( + `For more info and to get involved with the community, jump on our website ${process.env.siteAddress}` + ) + .setColor(Colors.DarkGold); - interaction.reply({ - embeds: [embed], - empheral: false - }); + interaction.reply({ + embeds: [embed], + empheral: false, + }); } -} \ No newline at end of file +} diff --git a/config.json b/config.json index aca9e2dc..1c59fbb3 100644 --- a/config.json +++ b/config.json @@ -1,39 +1,39 @@ { - "debug": true, - "siteConfiguration": { - "siteName": "Crafting For Christ", - "tagline": "Crafting A Christ Centred Gaming Community", - "keywords": "Christian, Minecraft, Faith, Gaming, Ministry, Community, Believers, Experience, Crafting, Creativity, Worship, Scripture, Fellowship, Gameplay, Builds, Christian Minecraft Server, Faith-based Gaming Community, Minecraft for Christians, Christ-Centered Gameplay, Bible-inspired Builds, Virtual Fellowship, Gaming Ministry, Christian Gaming Experience, Building Faith in Minecraft, Community of Faithful Gamers, Gaming and Worship, Scripture-based Creativity, Christian Fellowship in Minecraft", - "email": "support@craftingforchrist.net", - "policy": { - "termsOfService": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/terms.md", - "rules": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/rules.md", - "privacy": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/privacy.md", - "refund": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/refund.md" - }, - "platforms": { - "webstore": "https://crafting-for-christ.tebex.io/", - "discord": "https://discord.com/", - "facebook": "https://www.facebook.com/craft4christ/", - "twitter": "https://twitter.com/craft4christmc", - "instagram": "https://instagram.com/craftingforchrist", - "reddit": "https://www.reddit.com/r/craftingforchrist/", - "twitch": "https://www.twitch.tv/craftingforchrist", - "youtube": "https://www.youtube.com/channel/UCeijz6MNnya85LprMjPmYag", - "linkedin": "https://www.linkedin.com/company/68885022/", - "tiktok": "https://www.tiktok.com/@craftingforchrist" - } + "debug": true, + "siteConfiguration": { + "siteName": "Crafting For Christ", + "tagline": "Crafting A Christ Centred Gaming Community", + "keywords": "Christian, Minecraft, Faith, Gaming, Ministry, Community, Believers, Experience, Crafting, Creativity, Worship, Scripture, Fellowship, Gameplay, Builds, Christian Minecraft Server, Faith-based Gaming Community, Minecraft for Christians, Christ-Centered Gameplay, Bible-inspired Builds, Virtual Fellowship, Gaming Ministry, Christian Gaming Experience, Building Faith in Minecraft, Community of Faithful Gamers, Gaming and Worship, Scripture-based Creativity, Christian Fellowship in Minecraft", + "email": "support@craftingforchrist.net", + "policy": { + "termsOfService": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/terms.md", + "rules": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/rules.md", + "privacy": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/privacy.md", + "refund": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/refund.md" }, - "discord": { - "guildId": "899441191416901632", - "channels": { - "welcome": "926380663953821736", - "networkChatLog": "925702393423859724", - "adminLog": "926380052155867146", - "staffChannel": "926380052155867146" - }, - "roles": { - "verified": "926259482319794246" - } + "platforms": { + "webstore": "https://crafting-for-christ.tebex.io/", + "discord": "https://discord.com/", + "facebook": "https://www.facebook.com/craft4christ/", + "twitter": "https://twitter.com/craft4christmc", + "instagram": "https://instagram.com/craftingforchrist", + "reddit": "https://www.reddit.com/r/craftingforchrist/", + "twitch": "https://www.twitch.tv/craftingforchrist", + "youtube": "https://www.youtube.com/channel/UCeijz6MNnya85LprMjPmYag", + "linkedin": "https://www.linkedin.com/company/68885022/", + "tiktok": "https://www.tiktok.com/@craftingforchrist" } -} \ No newline at end of file + }, + "discord": { + "guildId": "899441191416901632", + "channels": { + "welcome": "926380663953821736", + "networkChatLog": "925702393423859724", + "adminLog": "926380052155867146", + "staffChannel": "926380052155867146" + }, + "roles": { + "verified": "926259482319794246" + } + } +} diff --git a/controllers/announcementController.js b/controllers/announcementController.js index 0d872435..5513d0d2 100644 --- a/controllers/announcementController.js +++ b/controllers/announcementController.js @@ -4,28 +4,30 @@ import fetch from "node-fetch"; */ export async function getWebAnnouncement() { - const fetchURL = `${process.env.siteAddress}/api/announcement/get?announcementType=web`; - try { - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); + const fetchURL = `${process.env.siteAddress}/api/announcement/get?announcementType=web`; + try { + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, + }); - if (!response.ok) { - // Handle the case where the API request is not successful, e.g., non-2xx status code. - throw new Error(`Failed to fetch announcement data. Status: ${response.status}`); - } + if (!response.ok) { + // Handle the case where the API request is not successful, e.g., non-2xx status code. + throw new Error( + `Failed to fetch announcement data. Status: ${response.status}` + ); + } - const apiData = await response.json(); + const apiData = await response.json(); - if (apiData.data && apiData.data.length > 0) { - return apiData.data[0]; - } else { - // Handle the case where there are no announcements. - return null; // or return a default value as needed - } - } catch (error) { - // Handle other potential errors such as network issues or JSON parsing errors. - console.error("Error fetching announcement:", error); - return null; // or throw an error, or handle it differently as needed + if (apiData.data && apiData.data.length > 0) { + return apiData.data[0]; + } else { + // Handle the case where there are no announcements. + return null; // or return a default value as needed } -} \ No newline at end of file + } catch (error) { + // Handle other potential errors such as network issues or JSON parsing errors. + console.error("Error fetching announcement:", error); + return null; // or throw an error, or handle it differently as needed + } +} diff --git a/controllers/databaseController.js b/controllers/databaseController.js index b5c7a897..e5061682 100644 --- a/controllers/databaseController.js +++ b/controllers/databaseController.js @@ -1,6 +1,6 @@ -import mysql from 'mysql'; -import dotenv from 'dotenv'; -dotenv.config() +import mysql from "mysql"; +import dotenv from "dotenv"; +dotenv.config(); var pool = mysql.createPool({ connectionLimit: 10, @@ -9,10 +9,10 @@ var pool = mysql.createPool({ user: process.env.databaseUser, password: process.env.databasePassword, database: process.env.databaseName, - multipleStatements: true + multipleStatements: true, }); -pool.getConnection(function(err) { +pool.getConnection(function (err) { if (err) { console.error(`[ERROR] [DB] There was an error connecting:\n ${err.stack}`); pool.connect(); diff --git a/controllers/discordController.js b/controllers/discordController.js index bfce358d..6ba494af 100644 --- a/controllers/discordController.js +++ b/controllers/discordController.js @@ -1,24 +1,26 @@ -import { SapphireClient } from '@sapphire/framework'; -import { GatewayIntentBits } from 'discord.js'; +import { SapphireClient } from "@sapphire/framework"; +import { GatewayIntentBits } from "discord.js"; -// +// // Discord // export const client = new SapphireClient({ - intents: [ - GatewayIntentBits.Guilds, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.GuildMembers, - GatewayIntentBits.GuildVoiceStates, - GatewayIntentBits.MessageContent, + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildVoiceStates, + GatewayIntentBits.MessageContent, + ], + presence: { + status: "online", + activities: [ + { + name: process.env.siteAddress, + type: "PLAYING", + }, ], - presence: { - status: "online", - activities: [{ - name: process.env.siteAddress, - type: 'PLAYING' - }] - } + }, }); client.login(process.env.discordAPIKey); @@ -29,9 +31,9 @@ client.login(process.env.discordAPIKey); @param username The username of the user. */ export async function isBot() { - const user = client.users.cache.get(userId); - if (user) { - return user.bot; - } - return false; -} \ No newline at end of file + const user = client.users.cache.get(userId); + if (user) { + return user.bot; + } + return false; +} diff --git a/controllers/userController.js b/controllers/userController.js index 892a4476..70cff039 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -1,4 +1,4 @@ -import db from './databaseController'; +import db from "./databaseController"; /* Returns a Promise which checks if a user with a given username has joined @@ -10,19 +10,23 @@ import db from './databaseController'; @param username The username of the user */ export async function hasUserJoinedBefore(username) { - return new Promise((resolve, reject) => { - db.query(`select * from users where username=?;`, [username], function (error, results, fields) { - if (error) { - reject(error); - } + return new Promise((resolve, reject) => { + db.query( + `select * from users where username=?;`, + [username], + function (error, results, fields) { + if (error) { + reject(error); + } - if (!results || !results.length) { - resolve(false); - } + if (!results || !results.length) { + resolve(false); + } - resolve(true); - }); - }); + resolve(true); + } + ); + }); } /* @@ -35,19 +39,23 @@ export async function hasUserJoinedBefore(username) { @param email The email to specify */ export async function hasEmailBeenUsed(email) { - return new Promise((resolve, reject) => { - db.query(`select * from users where email=?;`, [email], function (error, results, fields) { - if (error) { - reject(error); - } + return new Promise((resolve, reject) => { + db.query( + `select * from users where email=?;`, + [email], + function (error, results, fields) { + if (error) { + reject(error); + } - if (!results || !results.length) { - resolve(false); - } + if (!results || !results.length) { + resolve(false); + } - resolve(true); - }); - }); + resolve(true); + } + ); + }); } /* @@ -57,13 +65,13 @@ export async function hasEmailBeenUsed(email) { @param confirmPassword The password to validate against password */ export async function doesPasswordMatch(password, confirmPassword) { - return new Promise((resolve, reject) => { - if (password === confirmPassword) { - resolve(true); - } + return new Promise((resolve, reject) => { + if (password === confirmPassword) { + resolve(true); + } - resolve(false); - }); + resolve(false); + }); } /* @@ -72,18 +80,24 @@ export async function doesPasswordMatch(password, confirmPassword) { @param username The username of the user. */ export async function getProfilePicture(username) { - return new Promise((resolve, reject) => { - db.query(`SELECT * FROM users WHERE username=?;`, [username], function (error, results, fields) { - if (error) { - reject(error); - } + return new Promise((resolve, reject) => { + db.query( + `SELECT * FROM users WHERE username=?;`, + [username], + function (error, results, fields) { + if (error) { + reject(error); + } - let profilePictureType = results[0].profilePictureType; - let craftUUID = results[0].uuid; - let emailHash = results[0].emailHash; + let profilePictureType = results[0].profilePictureType; + let craftUUID = results[0].uuid; + let emailHash = results[0].emailHash; - if (profilePictureType == "CRAFTATAR") return resolve(`https://crafatar.com/avatars/${craftUUID}?helm`); - if (profilePictureType == "GRAVATAR") return resolve(`https://www.gravatar.com/avatar/${emailHash}?s=300`); - }); - }); -} \ No newline at end of file + if (profilePictureType == "CRAFTATAR") + return resolve(`https://crafatar.com/avatars/${craftUUID}?helm`); + if (profilePictureType == "GRAVATAR") + return resolve(`https://www.gravatar.com/avatar/${emailHash}?s=300`); + } + ); + }); +} diff --git a/features.json b/features.json index 32d62640..5461269d 100644 --- a/features.json +++ b/features.json @@ -1,33 +1,33 @@ { - "announcements": true, - "applications": true, - "discord": { - "commands": { - "legoFlip": true - }, - "events": { - "generalKenobi": true, - "guildMemberBoost": true, - "guildMemberVerify": true - } + "announcements": true, + "applications": true, + "discord": { + "commands": { + "legoFlip": true }, - "server": true, - "filter": { - "link": true, - "phrase": true - }, - "web": { - "login": true, - "register": true - }, - - "smDiscord": true, - "smFacebook": true, - "smTwitter": true, - "smInstagram": true, - "smReddit": false, - "smTwitch": true, - "smYouTube": true, - "smLinkedIn": true, - "smTikTok": true -} \ No newline at end of file + "events": { + "generalKenobi": true, + "guildMemberBoost": true, + "guildMemberVerify": true + } + }, + "server": true, + "filter": { + "link": true, + "phrase": true + }, + "web": { + "login": true, + "register": true + }, + + "smDiscord": true, + "smFacebook": true, + "smTwitter": true, + "smInstagram": true, + "smReddit": false, + "smTwitch": true, + "smYouTube": true, + "smLinkedIn": true, + "smTikTok": true +} diff --git a/filter.json b/filter.json index 90e47fdf..cbb74332 100644 --- a/filter.json +++ b/filter.json @@ -1,40 +1,33 @@ { - "phrases": [ - "shit", - "fuck", - "fish" - ], - "links": [ - "discord.gg", - "pornhub.com" - ], - "__alias_comment": "Below is derived from https://raw.githubusercontent.com/codebox/homoglyph/master/raw_data/chars.txt", - "alias": { - "a": "4@@AΑАᎪᗅᴀꓮꭺA𐊠aɑαа⍺a𝐚𝑎𝒂𝒶𝓪𝔞𝕒𝖆𝖺𝗮𝘢𝙖𝚊𝛂𝛼𝜶𝝰𝞪", - "b": "8BʙΒВвᏴᏼᗷᛒℬꓐꞴB𐊂𐊡𐌁𝐁𝐵𝑩𝓑𝔅𝔹𝕭𝖡𝗕𝘉𝘽𝙱𝚩𝛣𝜝𝝗𝞑bƄЬᏏᑲᖯb𝐛𝑏𝒃𝒷𝓫𝔟𝕓𝖇𝖻𝗯𝘣𝙗𝚋", - "c": "<˂ᐸᚲ‹❮<\\[(❨❲〔﴾([CϹСᏟᑕℂℭⅭ⊂Ⲥ⸦ꓚC𐊢𐌂𐐕cϲсᴄⅽⲥꮯc𐐽𝐜𝑐𝒄𝒸𝓬𝔠𝕔𝖈𝖼𝗰𝘤𝙘𝚌", - "d": "DᎠᗞᗪᴅⅅⅮꓓꭰD𝐃𝐷𝑫𝒟𝓓𝔇𝔻𝕯𝖣𝗗𝘋𝘿𝙳dԁᏧᑯⅆⅾꓒd𝐝𝑑𝒅𝒹𝓭𝔡𝕕𝖉𝖽𝗱𝘥𝙙𝚍", - "e": "3EΕЕᎬᴇℰ⋿ⴹꓰꭼE𐊆eеҽ℮ℯⅇꬲe𝐞𝑒𝒆𝓮𝔢𝕖𝖊𝖾𝗲𝘦𝙚𝚎", - "f": "FϜᖴℱꓝꞘF𐊇𐊥fſϝքẝꞙꬵf𝐟𝑓𝒇𝒻𝓯𝔣𝕗𝖋𝖿𝗳𝘧𝙛𝚏𝟋", - "g": "9GɢԌԍᏀᏳᏻꓖꮐG𝐆𝐺𝑮𝒢𝓖𝔊𝔾𝕲𝖦𝗚𝘎𝙂𝙶gƍɡցᶃℊg𝐠𝑔𝒈𝓰𝔤𝕘𝖌𝗀𝗴𝘨𝙜𝚐", - "h": "4HʜΗНнᎻᕼℋℌℍⲎꓧꮋH𐋏𝐇𝐻𝑯𝓗𝕳𝖧𝗛𝘏𝙃𝙷𝚮𝛨𝜢𝝜𝞖hһհᏂℎh𝐡𝒉𝒽𝓱𝔥𝕙𝖍𝗁𝗵𝘩𝙝𝚑", - "i": "iıɩɪ˛ͺιіӏᎥιℹⅈⅰ⍳ꙇꭵi1Il|ƖǀΙІӀ׀וןا١۱ߊᛁℐℑℓⅠⅼ∣Ⲓⵏꓲﺍﺎ1Il│𐊊𐌉𐌠", - "j": "JͿЈᎫᒍᴊꓙꞲꭻJ𝐉𝐽𝑱𝒥𝓙𝔍𝕁𝕵𝖩𝗝𝘑𝙅𝙹jϳјⅉj𝐣𝑗𝒋𝒿𝓳𝔧𝕛𝖏𝗃𝗷𝘫𝙟𝚓", - "k": "KΚКᏦᛕKⲔꓗKkk𝐤𝑘𝒌𝓀𝓴𝔨𝕜𝖐𝗄𝗸𝘬𝙠𝚔", - "l": "1Il|ƖǀΙІӀ׀וןا١۱ߊᛁℐℑℓⅠⅼ∣⏽Ⲓⵏꓲﺍﺎ1Il│𐊊𐌉𐌠", - "m": "MΜϺМᎷᗰᛖℳⅯⲘꓟM𐊰𐌑𝐌𝑀𝑴𝓜𝔐𝕄𝕸𝖬𝗠𝘔𝙈𝙼𝚳𝛭𝜧𝝡𝞛mm", - "o": "0OoΟοσОоՕօסه٥ھہە۵߀०০੦૦ଠ୦௦ం౦ಂ೦ംഠ൦ං๐໐ဝ၀ჿዐᴏᴑℴⲞⲟⵔ〇ꓳꬽﮦﮧﮨﮩﮪﮫﮬﮭﻩﻪﻫﻬ0Oo𐊒𐊫𐐄𐐬𐓂𐓪", - "p": "PΡРᏢᑭᴘᴩℙⲢꓑꮲP𐊕𝐏𝑃𝑷𝒫𝓟𝔓𝕻𝖯𝗣𝘗𝙋𝙿𝚸𝛲𝜬𝝦𝞠pρϱр⍴ⲣp𝐩𝑝𝒑𝓅𝓹𝔭𝕡𝖕𝗉𝗽𝘱𝙥𝚙𝛒𝛠𝜌𝜚𝝆𝝔𝞀𝞎𝞺𝟈", - "q": "QℚⵕQ𝐐𝑄𝑸𝒬𝓠𝔔𝕼𝖰𝗤𝘘𝙌𝚀qԛգզq𝐪𝑞𝒒𝓆𝓺𝔮𝕢𝖖𝗊𝗾𝘲𝙦𝚚", - "r": "RƦʀᎡᏒᖇᚱℛℜℝꓣꭱꮢR𐒴rгᴦⲅꭇꭈꮁr𝐫𝑟𝒓𝓇𝓻𝔯𝕣𝖗𝗋𝗿𝘳𝙧𝚛", - "s": "5SЅՏᏕᏚꓢS𐊖𐐠sƽѕꜱꮪs𐑈", - "t": "TΤτТтᎢᴛ⊤⟙ⲦꓔꭲT𐊗𐊱𐌕tt𝐭𝑡𝒕𝓉𝓽𝔱𝕥𝖙𝗍𝘁𝘵𝙩𝚝", - "u": "UՍሀᑌ∪⋃ꓴU𐓎uʋυսᴜꞟꭎꭒu𐓶VѴ٧۷ᏙᐯⅤⴸꓦꛟVvνѵטᴠⅴ∨⋁ꮩv", - "v": "UՍሀᑌ∪⋃ꓴU𐓎uʋυսᴜꞟꭎꭒu𐓶VѴ٧۷ᏙᐯⅤⴸꓦꛟVvνѵטᴠⅴ∨⋁ꮩv", - "w": "WԜᎳᏔꓪWwɯѡԝաᴡꮃw", - "x": "XΧХ᙭ᚷⅩ╳ⲬⵝꓫꞳX𐊐𐊴𐌗𐌢x×хᕁᕽ᙮ⅹ⤫⤬⨯x𝐱𝑥𝒙𝓍𝔁𝔵𝕩𝖝𝗑𝘅𝘹𝙭𝚡", - "y": "YΥϒУҮᎩᎽⲨꓬY𐊲yɣʏγуүყᶌỿℽꭚy", - "z": "ZΖᏃℤℨꓜZzᴢꮓz", - ".": "\\.,:'\"-=+<>`~?\\*" - } -} \ No newline at end of file + "phrases": ["shit", "fuck", "fish"], + "links": ["discord.gg", "pornhub.com"], + "__alias_comment": "Below is derived from https://raw.githubusercontent.com/codebox/homoglyph/master/raw_data/chars.txt", + "alias": { + "a": "4@@AΑАᎪᗅᴀꓮꭺA𐊠aɑαа⍺a𝐚𝑎𝒂𝒶𝓪𝔞𝕒𝖆𝖺𝗮𝘢𝙖𝚊𝛂𝛼𝜶𝝰𝞪", + "b": "8BʙΒВвᏴᏼᗷᛒℬꓐꞴB𐊂𐊡𐌁𝐁𝐵𝑩𝓑𝔅𝔹𝕭𝖡𝗕𝘉𝘽𝙱𝚩𝛣𝜝𝝗𝞑bƄЬᏏᑲᖯb𝐛𝑏𝒃𝒷𝓫𝔟𝕓𝖇𝖻𝗯𝘣𝙗𝚋", + "c": "<˂ᐸᚲ‹❮<\\[(❨❲〔﴾([CϹСᏟᑕℂℭⅭ⊂Ⲥ⸦ꓚC𐊢𐌂𐐕cϲсᴄⅽⲥꮯc𐐽𝐜𝑐𝒄𝒸𝓬𝔠𝕔𝖈𝖼𝗰𝘤𝙘𝚌", + "d": "DᎠᗞᗪᴅⅅⅮꓓꭰD𝐃𝐷𝑫𝒟𝓓𝔇𝔻𝕯𝖣𝗗𝘋𝘿𝙳dԁᏧᑯⅆⅾꓒd𝐝𝑑𝒅𝒹𝓭𝔡𝕕𝖉𝖽𝗱𝘥𝙙𝚍", + "e": "3EΕЕᎬᴇℰ⋿ⴹꓰꭼE𐊆eеҽ℮ℯⅇꬲe𝐞𝑒𝒆𝓮𝔢𝕖𝖊𝖾𝗲𝘦𝙚𝚎", + "f": "FϜᖴℱꓝꞘF𐊇𐊥fſϝքẝꞙꬵf𝐟𝑓𝒇𝒻𝓯𝔣𝕗𝖋𝖿𝗳𝘧𝙛𝚏𝟋", + "g": "9GɢԌԍᏀᏳᏻꓖꮐG𝐆𝐺𝑮𝒢𝓖𝔊𝔾𝕲𝖦𝗚𝘎𝙂𝙶gƍɡցᶃℊg𝐠𝑔𝒈𝓰𝔤𝕘𝖌𝗀𝗴𝘨𝙜𝚐", + "h": "4HʜΗНнᎻᕼℋℌℍⲎꓧꮋH𐋏𝐇𝐻𝑯𝓗𝕳𝖧𝗛𝘏𝙃𝙷𝚮𝛨𝜢𝝜𝞖hһհᏂℎh𝐡𝒉𝒽𝓱𝔥𝕙𝖍𝗁𝗵𝘩𝙝𝚑", + "i": "iıɩɪ˛ͺιіӏᎥιℹⅈⅰ⍳ꙇꭵi1Il|ƖǀΙІӀ׀וןا١۱ߊᛁℐℑℓⅠⅼ∣Ⲓⵏꓲﺍﺎ1Il│𐊊𐌉𐌠", + "j": "JͿЈᎫᒍᴊꓙꞲꭻJ𝐉𝐽𝑱𝒥𝓙𝔍𝕁𝕵𝖩𝗝𝘑𝙅𝙹jϳјⅉj𝐣𝑗𝒋𝒿𝓳𝔧𝕛𝖏𝗃𝗷𝘫𝙟𝚓", + "k": "KΚКᏦᛕKⲔꓗKkk𝐤𝑘𝒌𝓀𝓴𝔨𝕜𝖐𝗄𝗸𝘬𝙠𝚔", + "l": "1Il|ƖǀΙІӀ׀וןا١۱ߊᛁℐℑℓⅠⅼ∣⏽Ⲓⵏꓲﺍﺎ1Il│𐊊𐌉𐌠", + "m": "MΜϺМᎷᗰᛖℳⅯⲘꓟM𐊰𐌑𝐌𝑀𝑴𝓜𝔐𝕄𝕸𝖬𝗠𝘔𝙈𝙼𝚳𝛭𝜧𝝡𝞛mm", + "o": "0OoΟοσОоՕօסه٥ھہە۵߀०০੦૦ଠ୦௦ం౦ಂ೦ംഠ൦ං๐໐ဝ၀ჿዐᴏᴑℴⲞⲟⵔ〇ꓳꬽﮦﮧﮨﮩﮪﮫﮬﮭﻩﻪﻫﻬ0Oo𐊒𐊫𐐄𐐬𐓂𐓪", + "p": "PΡРᏢᑭᴘᴩℙⲢꓑꮲP𐊕𝐏𝑃𝑷𝒫𝓟𝔓𝕻𝖯𝗣𝘗𝙋𝙿𝚸𝛲𝜬𝝦𝞠pρϱр⍴ⲣp𝐩𝑝𝒑𝓅𝓹𝔭𝕡𝖕𝗉𝗽𝘱𝙥𝚙𝛒𝛠𝜌𝜚𝝆𝝔𝞀𝞎𝞺𝟈", + "q": "QℚⵕQ𝐐𝑄𝑸𝒬𝓠𝔔𝕼𝖰𝗤𝘘𝙌𝚀qԛգզq𝐪𝑞𝒒𝓆𝓺𝔮𝕢𝖖𝗊𝗾𝘲𝙦𝚚", + "r": "RƦʀᎡᏒᖇᚱℛℜℝꓣꭱꮢR𐒴rгᴦⲅꭇꭈꮁr𝐫𝑟𝒓𝓇𝓻𝔯𝕣𝖗𝗋𝗿𝘳𝙧𝚛", + "s": "5SЅՏᏕᏚꓢS𐊖𐐠sƽѕꜱꮪs𐑈", + "t": "TΤτТтᎢᴛ⊤⟙ⲦꓔꭲT𐊗𐊱𐌕tt𝐭𝑡𝒕𝓉𝓽𝔱𝕥𝖙𝗍𝘁𝘵𝙩𝚝", + "u": "UՍሀᑌ∪⋃ꓴU𐓎uʋυսᴜꞟꭎꭒu𐓶VѴ٧۷ᏙᐯⅤⴸꓦꛟVvνѵטᴠⅴ∨⋁ꮩv", + "v": "UՍሀᑌ∪⋃ꓴU𐓎uʋυսᴜꞟꭎꭒu𐓶VѴ٧۷ᏙᐯⅤⴸꓦꛟVvνѵטᴠⅴ∨⋁ꮩv", + "w": "WԜᎳᏔꓪWwɯѡԝաᴡꮃw", + "x": "XΧХ᙭ᚷⅩ╳ⲬⵝꓫꞳX𐊐𐊴𐌗𐌢x×хᕁᕽ᙮ⅹ⤫⤬⨯x𝐱𝑥𝒙𝓍𝔁𝔵𝕩𝖝𝗑𝘅𝘹𝙭𝚡", + "y": "YΥϒУҮᎩᎽⲨꓬY𐊲yɣʏγуүყᶌỿℽꭚy", + "z": "ZΖᏃℤℨꓜZzᴢꮓz", + ".": "\\.,:'\"-=+<>`~?\\*" + } +} diff --git a/joinMessages.json b/joinMessages.json index fcbd153b..16732c4d 100644 --- a/joinMessages.json +++ b/joinMessages.json @@ -1,20 +1,20 @@ [ - "Yo! %USERNAME% just rocked up! Give them a warm welcome!", - "Start celebrating :tada: %USERNAME% has joined the party!", - "All your base belongs to %USERNAME%!!!", - "Welcome %USERNAME%, don't get supply blocked.", - "Hello there! General %USERNAME%!", - "%USERNAME% joined. You must construct additional pylons.", - "Woah! %USERNAME% just rocked up, Welcome!", - "%USERNAME% just rocked up with Diamonds!", - "%USERNAME% was blown up by a Creeper.. sad times.", - "%USERNAME% was slain by a Zombie.. BRUH.", - "%USERNAME% forgot how to use ladders.. oof.", - "%USERNAME% we were expecting you ( ͡° ͜ʖ ͡°)", - "Welcome %USERNAME% we hope you brought cake.", - "Welcome %USERNAME% leave the swords and armour at the door.", - "Swoooosh. %USERNAME% landed safely", - "%USERNAME% just joined. Hide your Diamonds.", - "%USERNAME% has joined the game.", - "%USERNAME% just showed up. Hold my milk." -] \ No newline at end of file + "Yo! %USERNAME% just rocked up! Give them a warm welcome!", + "Start celebrating :tada: %USERNAME% has joined the party!", + "All your base belongs to %USERNAME%!!!", + "Welcome %USERNAME%, don't get supply blocked.", + "Hello there! General %USERNAME%!", + "%USERNAME% joined. You must construct additional pylons.", + "Woah! %USERNAME% just rocked up, Welcome!", + "%USERNAME% just rocked up with Diamonds!", + "%USERNAME% was blown up by a Creeper.. sad times.", + "%USERNAME% was slain by a Zombie.. BRUH.", + "%USERNAME% forgot how to use ladders.. oof.", + "%USERNAME% we were expecting you ( ͡° ͜ʖ ͡°)", + "Welcome %USERNAME% we hope you brought cake.", + "Welcome %USERNAME% leave the swords and armour at the door.", + "Swoooosh. %USERNAME% landed safely", + "%USERNAME% just joined. Hide your Diamonds.", + "%USERNAME% has joined the game.", + "%USERNAME% just showed up. Hold my milk." +] diff --git a/lang.json b/lang.json index f6b96fb5..abbd08c6 100644 --- a/lang.json +++ b/lang.json @@ -1,54 +1,54 @@ { - "api": { - "noToken": "There was no token included in this request.", - "invalidToken": "The token that was provided is not valid or incorrect.", - "featureDisabled": "This action could not be completed because the feature has been disabled by the System Administrator.", - "userCreated": "The user %USERNAME% with the unique identifier of %UUID% is new, profile created.", - "userAlreadyExists": "The requested user already exists in the database, the user creation is being terminated.", - "userDoesNotExist": "The requested user does not exist.", - "noNotifications": "You do not have any notifications, good day!", - "databaseError": "A database error has occured trying to process this request. Please try again later." - }, - "error": { - "noReportServers": "The report feature could not be loaded because no public servers are avaliable. Consider asking your System Administrator to add one." - }, - "web": { - "notLoggedInBefore": "You have not logged in before. You are required to login before becoming a community site member. You can jump on and play here: %SITEADDRESS%/play", - "emailAlreadyInUse": "The email you have provided is already in use, please enter another email and try again.", - "passwordDoesNotMatch": "The password you have provided does not match. Please try again.", - "registrationError": "There was an error in registration, please try again later.", - "registrationSuccess": "You are now successfully registered. Please go back and login to get started!" - }, - "applications": { - "noApplicationsFound": "No applications could be found at this time.", - "applicationCreated": "The application has been created.", - "applicationEdited": "The application has been updated.", - "applicationDeleted": "The application has been deleted." - }, - "server": { - "noServers": "There are currently no Servers that can be displayed at this time.", - "serverCreated": "The Server has been successfully created!", - "serverEdited": "The Server record has been edited successfully.", - "serverDeleted": "This Server has now been deleted." - }, - "session": { - "newSessionCreated": "A new session has been created for %UUID%", - "allSessionsClosed": "All sessions for %UUID% have now been closed.", - "sessionSwitch": "%UUID% has switched to %SERVER%", - "userSuccessLogin": "Sign in successful, welcome.", - "userFailedLogin": "The username or password you have entered is incorrect, please try again.", - "userLogout": "You have been successfully logged out." - }, - "announcement": { - "announcementCreated": "Announcement has been created.", - "noAnnouncements": "There are currently no announcements set.", - "announcementEdited": "Announcement has been successfully edited", - "announcementDeleted": "Announcement has been successfully deleted.", - "announcementEnabled": "Announcement has been enabled.", - "announcementDisabled": "Announcement has been disabled." - }, - "filter": { - "phraseCaught": "This message was blocked due to the usage of blocked words/phrases.", - "linkCaught": "This message was blocked due to the usage of blocked links/sites." - } -} \ No newline at end of file + "api": { + "noToken": "There was no token included in this request.", + "invalidToken": "The token that was provided is not valid or incorrect.", + "featureDisabled": "This action could not be completed because the feature has been disabled by the System Administrator.", + "userCreated": "The user %USERNAME% with the unique identifier of %UUID% is new, profile created.", + "userAlreadyExists": "The requested user already exists in the database, the user creation is being terminated.", + "userDoesNotExist": "The requested user does not exist.", + "noNotifications": "You do not have any notifications, good day!", + "databaseError": "A database error has occured trying to process this request. Please try again later." + }, + "error": { + "noReportServers": "The report feature could not be loaded because no public servers are avaliable. Consider asking your System Administrator to add one." + }, + "web": { + "notLoggedInBefore": "You have not logged in before. You are required to login before becoming a community site member. You can jump on and play here: %SITEADDRESS%/play", + "emailAlreadyInUse": "The email you have provided is already in use, please enter another email and try again.", + "passwordDoesNotMatch": "The password you have provided does not match. Please try again.", + "registrationError": "There was an error in registration, please try again later.", + "registrationSuccess": "You are now successfully registered. Please go back and login to get started!" + }, + "applications": { + "noApplicationsFound": "No applications could be found at this time.", + "applicationCreated": "The application has been created.", + "applicationEdited": "The application has been updated.", + "applicationDeleted": "The application has been deleted." + }, + "server": { + "noServers": "There are currently no Servers that can be displayed at this time.", + "serverCreated": "The Server has been successfully created!", + "serverEdited": "The Server record has been edited successfully.", + "serverDeleted": "This Server has now been deleted." + }, + "session": { + "newSessionCreated": "A new session has been created for %UUID%", + "allSessionsClosed": "All sessions for %UUID% have now been closed.", + "sessionSwitch": "%UUID% has switched to %SERVER%", + "userSuccessLogin": "Sign in successful, welcome.", + "userFailedLogin": "The username or password you have entered is incorrect, please try again.", + "userLogout": "You have been successfully logged out." + }, + "announcement": { + "announcementCreated": "Announcement has been created.", + "noAnnouncements": "There are currently no announcements set.", + "announcementEdited": "Announcement has been successfully edited", + "announcementDeleted": "Announcement has been successfully deleted.", + "announcementEnabled": "Announcement has been enabled.", + "announcementDisabled": "Announcement has been disabled." + }, + "filter": { + "phraseCaught": "This message was blocked due to the usage of blocked words/phrases.", + "linkCaught": "This message was blocked due to the usage of blocked links/sites." + } +} diff --git a/listeners/filter.js b/listeners/filter.js index 6e5245e0..a1295937 100644 --- a/listeners/filter.js +++ b/listeners/filter.js @@ -1,14 +1,14 @@ -import { Listener } from '@sapphire/framework'; -import { EmbedBuilder } from 'discord.js'; -import fetch from 'node-fetch'; -import features from '../features.json' assert {type: "json"}; +import { Listener } from "@sapphire/framework"; +import { EmbedBuilder } from "discord.js"; +import fetch from "node-fetch"; +import features from "../features.json" assert { type: "json" }; export class GuildMessageListener extends Listener { constructor(context, options) { super(context, { ...options, once: false, - event: 'messageCreate' + event: "messageCreate", }); } @@ -22,33 +22,34 @@ export class GuildMessageListener extends Listener { const bodyJSON = { content: message.content }; const response = await fetch(filterURL, { - method: 'POST', + method: "POST", body: JSON.stringify(bodyJSON), headers: { - 'Content-Type': 'application/json', - 'x-access-token': process.env.apiKey - } - }) + "Content-Type": "application/json", + "x-access-token": process.env.apiKey, + }, + }); const dataResponse = await response.json(); console.log(dataResponse); - if (message.author.isbot) return + if (message.author.isbot) return; if (dataResponse.success == false) { message.delete(); // Delete the message let embed = new EmbedBuilder() .setTitle(`Prohibited content has been detected!`) - .setDescription(`\`${message.author.username}\` please don't advertise or say prohibited content/phrases. If you continue, you will be punished.`) - .setColor(`#ff3333`) + .setDescription( + `\`${message.author.username}\` please don't advertise or say prohibited content/phrases. If you continue, you will be punished.` + ) + .setColor(`#ff3333`); message.reply({ embeds: [embed] }); } - } catch (error) { console.log(error); - return + return; } } } -} \ No newline at end of file +} diff --git a/listeners/generalKenobi.js b/listeners/generalKenobi.js index b4e52377..bcd18764 100644 --- a/listeners/generalKenobi.js +++ b/listeners/generalKenobi.js @@ -1,23 +1,23 @@ -import { Listener } from '@sapphire/framework'; -import features from '../features.json' assert {type: "json"}; +import { Listener } from "@sapphire/framework"; +import features from "../features.json" assert { type: "json" }; export class GuildMessageListener extends Listener { constructor(context, options) { super(context, { ...options, once: false, - event: 'messageCreate' + event: "messageCreate", }); } run(message) { - if (message.author.isbot) return - + if (message.author.isbot) return; + if (features.discord.events.generalKenobi) { if (message.content.toLowerCase().includes("hello there")) { - message.channel.send('General Kenobi'); + message.channel.send("General Kenobi"); return; - }; + } } } -} \ No newline at end of file +} diff --git a/listeners/guildMemberBoostUpdate.js b/listeners/guildMemberBoostUpdate.js index ff33e7a0..d384b0da 100644 --- a/listeners/guildMemberBoostUpdate.js +++ b/listeners/guildMemberBoostUpdate.js @@ -1,14 +1,14 @@ -import { Listener } from '@sapphire/framework'; -import config from '../config.json' assert {type: "json"}; -import { Colors, EmbedBuilder } from 'discord.js'; -import features from '../features.json' assert {type: "json"}; +import { Listener } from "@sapphire/framework"; +import config from "../config.json" assert { type: "json" }; +import { Colors, EmbedBuilder } from "discord.js"; +import features from "../features.json" assert { type: "json" }; export class GuildMemberBoostUpdateListener extends Listener { constructor(context, options) { super(context, { ...options, once: false, - event: 'guildMemberUpdate' + event: "guildMemberUpdate", }); } @@ -20,16 +20,20 @@ export class GuildMemberBoostUpdateListener extends Listener { const oldStatus = oldMember.premiumSince; const newStatus = newMember.premiumSince; - let welcomechannel = newMember.guild.channels.cache.find(c => c.id === config.discord.channels.welcome); + let welcomechannel = newMember.guild.channels.cache.find( + (c) => c.id === config.discord.channels.welcome + ); if (!welcomechannel) return; if (!oldStatus && newStatus) { let embed = new EmbedBuilder() - .setTitle(`\`${newMember.user.username}\` has boosted the Server! :tada:`) - .setColor(Colors.DarkVividPink) - welcomechannel.send({embeds: [embed]}); + .setTitle( + `\`${newMember.user.username}\` has boosted the Server! :tada:` + ) + .setColor(Colors.DarkVividPink); + welcomechannel.send({ embeds: [embed] }); } return; } } -} \ No newline at end of file +} diff --git a/listeners/guildMemberUpdate.js b/listeners/guildMemberUpdate.js index b705e79d..ca8be997 100644 --- a/listeners/guildMemberUpdate.js +++ b/listeners/guildMemberUpdate.js @@ -1,15 +1,15 @@ -import { Listener } from '@sapphire/framework'; -import joinMessages from '../joinMessages.json' assert {type: "json"}; -import config from '../config.json' assert {type: "json"}; -import { EmbedBuilder } from 'discord.js'; -import features from '../features.json' assert {type: "json"}; +import { Listener } from "@sapphire/framework"; +import joinMessages from "../joinMessages.json" assert { type: "json" }; +import config from "../config.json" assert { type: "json" }; +import { EmbedBuilder } from "discord.js"; +import features from "../features.json" assert { type: "json" }; export class GuildMemberUpdateListener extends Listener { constructor(context, options) { super(context, { ...options, once: false, - event: 'guildMemberUpdate' + event: "guildMemberUpdate", }); } @@ -17,26 +17,31 @@ export class GuildMemberUpdateListener extends Listener { if (features.discord.events.guildMemberVerify) { if (!newMember.guild) return; if (newMember.user.bot) return; - + const oldRole = oldMember.roles.cache.has(config.discord.roles.verified); const newRole = newMember.roles.cache.has(config.discord.roles.verified); - let welcomechannel = newMember.guild.channels.cache.find(channel => channel.id === config.discord.channels.welcome); + let welcomechannel = newMember.guild.channels.cache.find( + (channel) => channel.id === config.discord.channels.welcome + ); if (!welcomechannel) return; // Grab random letters and numbers to get a HEX Colour. - const randomColor = Math.floor(Math.random()*16777215).toString(16); + const randomColor = Math.floor(Math.random() * 16777215).toString(16); // Select a random join message from joinMessages.json - const randomJoinMessage = joinMessages[Math.floor(Math.random() * joinMessages.length)]; + const randomJoinMessage = + joinMessages[Math.floor(Math.random() * joinMessages.length)]; if (!oldRole && newRole) { let embed = new EmbedBuilder() - .setTitle(randomJoinMessage.replace("%USERNAME%", newMember.user.username)) - .setColor(`#${randomColor}`) - welcomechannel.send({embeds: [embed]}); + .setTitle( + randomJoinMessage.replace("%USERNAME%", newMember.user.username) + ) + .setColor(`#${randomColor}`); + welcomechannel.send({ embeds: [embed] }); } - return; + return; } } -} \ No newline at end of file +} diff --git a/listeners/messageDelete.js b/listeners/messageDelete.js index a0d266d5..5d42d0e7 100644 --- a/listeners/messageDelete.js +++ b/listeners/messageDelete.js @@ -1,13 +1,13 @@ -import { Listener } from '@sapphire/framework'; -import config from '../config.json' assert { type: 'json' }; -import { Colors, EmbedBuilder } from 'discord.js'; +import { Listener } from "@sapphire/framework"; +import config from "../config.json" assert { type: "json" }; +import { Colors, EmbedBuilder } from "discord.js"; export class GuildMessageDeleteListener extends Listener { constructor(context, options) { super(context, { ...options, once: false, - event: 'messageDelete', + event: "messageDelete", }); } @@ -15,17 +15,23 @@ export class GuildMessageDeleteListener extends Listener { // Check if the author of the deleted message is a bot and stop if true. if (message.author.bot) return; - let adminLogChannel = message.guild.channels.cache.find(c => c.id === config.discord.channels.adminLog); + let adminLogChannel = message.guild.channels.cache.find( + (c) => c.id === config.discord.channels.adminLog + ); if (!adminLogChannel) return; const embed = new EmbedBuilder() - .setTitle('Message Delete') + .setTitle("Message Delete") .setColor(Colors.Red) - .setDescription(`Message deleted from \`${message.author.username}\` in \`#${message.channel.name}\``) - .addFields( - { name: 'Deleted Message', value: `${message.content}`, inline: false } - ); + .setDescription( + `Message deleted from \`${message.author.username}\` in \`#${message.channel.name}\`` + ) + .addFields({ + name: "Deleted Message", + value: `${message.content}`, + inline: false, + }); adminLogChannel.send({ embeds: [embed] }); } -} \ No newline at end of file +} diff --git a/listeners/messageUpdate.js b/listeners/messageUpdate.js index b1bd3b91..a8346fda 100644 --- a/listeners/messageUpdate.js +++ b/listeners/messageUpdate.js @@ -1,13 +1,13 @@ -import { Listener } from '@sapphire/framework'; -import config from '../config.json' assert {type: "json"}; -import { Colors, EmbedBuilder } from 'discord.js'; +import { Listener } from "@sapphire/framework"; +import config from "../config.json" assert { type: "json" }; +import { Colors, EmbedBuilder } from "discord.js"; export class GuildMessageUpdateListener extends Listener { constructor(context, options) { super(context, { ...options, once: false, - event: 'messageUpdate' + event: "messageUpdate", }); } @@ -15,16 +15,24 @@ export class GuildMessageUpdateListener extends Listener { // Check if the author is a bot and stop if true. if (newMessage.author.bot) return; - let adminLogChannel = oldMessage.guild.channels.cache.find(c => c.id === config.discord.channels.adminLog); + let adminLogChannel = oldMessage.guild.channels.cache.find( + (c) => c.id === config.discord.channels.adminLog + ); if (!adminLogChannel) return; const embed = new EmbedBuilder() - .setTitle('Message Edit') + .setTitle("Message Edit") .setColor(Colors.Yellow) - .setDescription(`Message edit from \`${oldMessage.author.username}\` in \`#${oldMessage.channel.name}\``) + .setDescription( + `Message edit from \`${oldMessage.author.username}\` in \`#${oldMessage.channel.name}\`` + ) .addFields( - { name: 'Old Message', value: `${oldMessage.content}`, inline: false }, - { name: 'Edited Message', value: `${newMessage.content}`, inline: false } + { name: "Old Message", value: `${oldMessage.content}`, inline: false }, + { + name: "Edited Message", + value: `${newMessage.content}`, + inline: false, + } ); adminLogChannel.send({ embeds: [embed] }); diff --git a/listeners/ready.js b/listeners/ready.js index 8f26940a..86997604 100644 --- a/listeners/ready.js +++ b/listeners/ready.js @@ -1,8 +1,10 @@ -import { Listener } from '@sapphire/framework'; +import { Listener } from "@sapphire/framework"; export class ReadyListener extends Listener { run(client) { const { username, id } = client.user; - this.container.logger.info(`[CONSOLE] [DISCORD] Successfully logged in as ${username} (${id})`); + this.container.logger.info( + `[CONSOLE] [DISCORD] Successfully logged in as ${username} (${id})` + ); } -} \ No newline at end of file +} diff --git a/routes/dashboard/announcement.js b/routes/dashboard/announcement.js index 55352c13..0be50fe2 100644 --- a/routes/dashboard/announcement.js +++ b/routes/dashboard/announcement.js @@ -1,82 +1,89 @@ -import { getGlobalImage, hasPermission, isFeatureWebRouteEnabled } from "../../api/common"; +import { + getGlobalImage, + hasPermission, + isFeatureWebRouteEnabled, +} from "../../api/common"; import { getWebAnnouncement } from "../../controllers/announcementController"; -export default function dashboardAnnouncementSiteRoute(app, fetch, config, db, features, lang) { - // - // Servers - // - app.get('/dashboard/announcements', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.announcements, req, res, features)) - return; - - if (!hasPermission('zander.web.announcements', req, res, features)) - return; +export default function dashboardAnnouncementSiteRoute( + app, + fetch, + config, + db, + features, + lang +) { + // + // Servers + // + app.get("/dashboard/announcements", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.announcements, req, res, features)) + return; - const fetchURL = `${process.env.siteAddress}/api/announcement/get`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const apiData = await response.json(); - - res.view('dashboard/announcements/announcements-list', { - "pageTitle": `Dashboard - Announcements`, - config: config, - apiData: apiData, - features: features, - req: req, - globalImage: getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + if (!hasPermission("zander.web.announcements", req, res, features)) return; - return res; + const fetchURL = `${process.env.siteAddress}/api/announcement/get`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, }); + const apiData = await response.json(); - app.get('/dashboard/announcements/create', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.announcements, req, res, features)) - return; - - if (!hasPermission('zander.web.announcements', req, res, features)) - return; - - res.view('dashboard/announcements/announcements-editor', { - "pageTitle": `Dashboard - Announcement Creator`, - config: config, - type: "create", - features: features, - req: req, - globalImage: getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + res.view("dashboard/announcements/announcements-list", { + pageTitle: `Dashboard - Announcements`, + config: config, + apiData: apiData, + features: features, + req: req, + globalImage: getGlobalImage(), + announcementWeb: await getWebAnnouncement(), + }); + + return res; + }); + + app.get("/dashboard/announcements/create", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.announcements, req, res, features)) + return; + + if (!hasPermission("zander.web.announcements", req, res, features)) return; - return res; + res.view("dashboard/announcements/announcements-editor", { + pageTitle: `Dashboard - Announcement Creator`, + config: config, + type: "create", + features: features, + req: req, + globalImage: getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); - app.get('/dashboard/announcements/edit', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.announcements, req, res, features)) - return; - - if (!hasPermission('zander.web.announcements', req, res, features)) - return; - - const announcementSlug = req.query.announcementSlug; - const fetchURL = `${process.env.siteAddress}/api/announcement/get?announcementSlug=${announcementSlug}`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const announcementApiData = await response.json(); + return res; + }); - res.view('dashboard/announcements/announcements-editor', { - "pageTitle": `Dashboard - Announcement Editor`, - config: config, - announcementApiData: announcementApiData.data[0], - type: "edit", - features: features, - req: req, - globalImage: getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + app.get("/dashboard/announcements/edit", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.announcements, req, res, features)) + return; + + if (!hasPermission("zander.web.announcements", req, res, features)) return; + + const announcementSlug = req.query.announcementSlug; + const fetchURL = `${process.env.siteAddress}/api/announcement/get?announcementSlug=${announcementSlug}`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, + }); + const announcementApiData = await response.json(); - return res; + res.view("dashboard/announcements/announcements-editor", { + pageTitle: `Dashboard - Announcement Editor`, + config: config, + announcementApiData: announcementApiData.data[0], + type: "edit", + features: features, + req: req, + globalImage: getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); -} \ No newline at end of file + return res; + }); +} diff --git a/routes/dashboard/applications.js b/routes/dashboard/applications.js index 4921d083..8d219e29 100644 --- a/routes/dashboard/applications.js +++ b/routes/dashboard/applications.js @@ -1,77 +1,83 @@ -import { getGlobalImage, hasPermission, isFeatureWebRouteEnabled } from "../../api/common"; +import { + getGlobalImage, + hasPermission, + isFeatureWebRouteEnabled, +} from "../../api/common"; import { getWebAnnouncement } from "../../controllers/announcementController"; -export default function dashboardApplicationsSiteRoute(app, fetch, config, db, features, lang) { +export default function dashboardApplicationsSiteRoute( + app, + fetch, + config, + db, + features, + lang +) { + // + // Applications + // + app.get("/dashboard/applications", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.applications, req, res, features)) + return; - // - // Applications - // - app.get('/dashboard/applications', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.applications, req, res, features)) - return; - - if (!hasPermission('zander.web.application', req, res, features)) - return; + if (!hasPermission("zander.web.application", req, res, features)) return; - const fetchURL = `${process.env.siteAddress}/api/application/get`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const apiData = await response.json(); + const fetchURL = `${process.env.siteAddress}/api/application/get`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, + }); + const apiData = await response.json(); - return res.view('dashboard/applications/application-list', { - "pageTitle": `Dashboard - Applications`, - config: config, - apiData: apiData, - features: features, - req: req, - globalImage: getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + return res.view("dashboard/applications/application-list", { + pageTitle: `Dashboard - Applications`, + config: config, + apiData: apiData, + features: features, + req: req, + globalImage: getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); + }); - app.get('/dashboard/applications/create', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.applications, req, res, features)) - return; + app.get("/dashboard/applications/create", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.applications, req, res, features)) + return; - if (!hasPermission('zander.web.application', req, res, features)) - return; + if (!hasPermission("zander.web.application", req, res, features)) return; - return res.view('dashboard/applications/application-editor', { - "pageTitle": `Dashboard - Application Creator`, - config: config, - type: "create", - features: features, - req: req, - globalImage: getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + return res.view("dashboard/applications/application-editor", { + pageTitle: `Dashboard - Application Creator`, + config: config, + type: "create", + features: features, + req: req, + globalImage: getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); + }); - app.get('/dashboard/applications/edit', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.applications, req, res, features)) - return; - - if (!hasPermission('zander.web.application', req, res, features)) - return; + app.get("/dashboard/applications/edit", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.applications, req, res, features)) + return; - const applicationId = req.query.applicationId; - const fetchURL = `${process.env.siteAddress}/api/application/get?id=${applicationId}`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const applicationApiData = await response.json(); + if (!hasPermission("zander.web.application", req, res, features)) return; - return res.view('dashboard/applications/application-editor', { - "pageTitle": `Dashboard - Application Editor`, - config: config, - applicationApiData: applicationApiData.data[0], - type: "edit", - features: features, - req: req, - globalImage: getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + const applicationId = req.query.applicationId; + const fetchURL = `${process.env.siteAddress}/api/application/get?id=${applicationId}`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, }); + const applicationApiData = await response.json(); -} \ No newline at end of file + return res.view("dashboard/applications/application-editor", { + pageTitle: `Dashboard - Application Editor`, + config: config, + applicationApiData: applicationApiData.data[0], + type: "edit", + features: features, + req: req, + globalImage: getGlobalImage(), + announcementWeb: await getWebAnnouncement(), + }); + }); +} diff --git a/routes/dashboard/dashboard.js b/routes/dashboard/dashboard.js index c02fc52b..31490934 100644 --- a/routes/dashboard/dashboard.js +++ b/routes/dashboard/dashboard.js @@ -4,49 +4,51 @@ import { getGlobalImage, hasPermission } from "../../api/common"; import { getWebAnnouncement } from "../../controllers/announcementController"; export default function dashbordSiteRoute(app, config, features, lang) { + // + // Dashboard + // + app.get("/dashboard", async function (req, res) { + const permissionBoolean = await hasPermission( + "zander.web.dashboard", + req, + res, + features + ); + if (!permissionBoolean) return; - // - // Dashboard - // - app.get('/dashboard', async function (req, res) { - const permissionBoolean = await hasPermission('zander.web.dashboard', req, res, features) - if (!permissionBoolean) - return; - - return res.view('dashboard/dashboard-index', { - "pageTitle": `Dashboard`, - config: config, - features: features, - req: req, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + return res.view("dashboard/dashboard-index", { + pageTitle: `Dashboard`, + config: config, + features: features, + req: req, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); + }); - // - // Logs - // - app.get('/dashboard/logs', async function (req, res) { - if (!hasPermission('zander.web.logs', req, res, features)) - return; - - const fetchURL = `${process.env.siteAddress}/api/web/logs/get`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const apiData = await response.json(); + // + // Logs + // + app.get("/dashboard/logs", async function (req, res) { + if (!hasPermission("zander.web.logs", req, res, features)) return; - res.view('dashboard/logs', { - "pageTitle": `Dashboard - Logs`, - config: config, - apiData: apiData, - features: features, - req: req, - globalImage: getGlobalImage(), - moment: moment, - announcementWeb: await getWebAnnouncement() - }); + const fetchURL = `${process.env.siteAddress}/api/web/logs/get`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, + }); + const apiData = await response.json(); - return res; + res.view("dashboard/logs", { + pageTitle: `Dashboard - Logs`, + config: config, + apiData: apiData, + features: features, + req: req, + globalImage: getGlobalImage(), + moment: moment, + announcementWeb: await getWebAnnouncement(), }); -} \ No newline at end of file + + return res; + }); +} diff --git a/routes/dashboard/index.js b/routes/dashboard/index.js index dc026d28..f42e843a 100644 --- a/routes/dashboard/index.js +++ b/routes/dashboard/index.js @@ -1,12 +1,20 @@ -import dashboardSiteRoute from './dashboard' -import dashboardServersSiteRoute from './servers' -import dashboardApplicationsSiteRoute from './applications' -import dashboardAnnouncementSiteRoute from './announcement' +import dashboardSiteRoute from "./dashboard"; +import dashboardServersSiteRoute from "./servers"; +import dashboardApplicationsSiteRoute from "./applications"; +import dashboardAnnouncementSiteRoute from "./announcement"; -export default function dashbordSiteRoutes(app, client, fetch, moment, config, db, features, lang) { - - dashboardSiteRoute(app, config, features, lang); - dashboardServersSiteRoute(app, fetch, config, db, features, lang); - dashboardAnnouncementSiteRoute(app, fetch, config, db, features, lang); - dashboardApplicationsSiteRoute(app, fetch, config, db, features, lang); -} \ No newline at end of file +export default function dashbordSiteRoutes( + app, + client, + fetch, + moment, + config, + db, + features, + lang +) { + dashboardSiteRoute(app, config, features, lang); + dashboardServersSiteRoute(app, fetch, config, db, features, lang); + dashboardAnnouncementSiteRoute(app, fetch, config, db, features, lang); + dashboardApplicationsSiteRoute(app, fetch, config, db, features, lang); +} diff --git a/routes/dashboard/servers.js b/routes/dashboard/servers.js index 9777ba31..85744385 100644 --- a/routes/dashboard/servers.js +++ b/routes/dashboard/servers.js @@ -1,82 +1,86 @@ -import { getGlobalImage, hasPermission, isFeatureWebRouteEnabled } from "../../api/common"; +import { + getGlobalImage, + hasPermission, + isFeatureWebRouteEnabled, +} from "../../api/common"; import { getWebAnnouncement } from "../../controllers/announcementController"; -export default function dashboardServersSiteRoute(app, fetch, config, db, features, lang) { - // - // Servers - // - app.get('/dashboard/servers', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.server, req, res, features)) - return; - - if (!hasPermission('zander.web.server', req, res, features)) - return; +export default function dashboardServersSiteRoute( + app, + fetch, + config, + db, + features, + lang +) { + // + // Servers + // + app.get("/dashboard/servers", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.server, req, res, features)) return; - const fetchURL = `${process.env.siteAddress}/api/server/get`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const apiData = await response.json(); + if (!hasPermission("zander.web.server", req, res, features)) return; - res.view('dashboard/servers/server-list', { - "pageTitle": `Dashboard - Servers`, - config: config, - apiData: apiData, - features: features, - req: req, - globalImage: getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + const fetchURL = `${process.env.siteAddress}/api/server/get`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, + }); + const apiData = await response.json(); - return res; + res.view("dashboard/servers/server-list", { + pageTitle: `Dashboard - Servers`, + config: config, + apiData: apiData, + features: features, + req: req, + globalImage: getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); - app.get('/dashboard/servers/create', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.server, req, res, features)) - return; - - if (!hasPermission('zander.web.server', req, res, features)) - return; - - res.view('dashboard/servers/server-editor', { - "pageTitle": `Dashboard - Server Creator`, - config: config, - type: "create", - features: features, - globalImage: getGlobalImage(), - req: req, - announcementWeb: await getWebAnnouncement() - }); + return res; + }); + + app.get("/dashboard/servers/create", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.server, req, res, features)) return; + + if (!hasPermission("zander.web.server", req, res, features)) return; - return res; + res.view("dashboard/servers/server-editor", { + pageTitle: `Dashboard - Server Creator`, + config: config, + type: "create", + features: features, + globalImage: getGlobalImage(), + req: req, + announcementWeb: await getWebAnnouncement(), }); - app.get('/dashboard/servers/edit', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.server, req, res, features)) - return; - - if (!hasPermission('zander.web.server', req, res, features)) - return; - - const id = req.query.id; - const fetchURL = `${process.env.siteAddress}/api/server/get?id=${id}`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const serverApiData = await response.json(); + return res; + }); - res.view('dashboard/servers/server-editor', { - "pageTitle": `Dashboard - Server Editor`, - config: config, - serverApiData: serverApiData.data[0], - type: "edit", - features: features, - globalImage: getGlobalImage(), - req: req, - announcementWeb: await getWebAnnouncement() - }); + app.get("/dashboard/servers/edit", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.server, req, res, features)) return; + + if (!hasPermission("zander.web.server", req, res, features)) return; + + const id = req.query.id; + const fetchURL = `${process.env.siteAddress}/api/server/get?id=${id}`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, + }); + const serverApiData = await response.json(); - return res; + res.view("dashboard/servers/server-editor", { + pageTitle: `Dashboard - Server Editor`, + config: config, + serverApiData: serverApiData.data[0], + type: "edit", + features: features, + globalImage: getGlobalImage(), + req: req, + announcementWeb: await getWebAnnouncement(), }); -} \ No newline at end of file + return res; + }); +} diff --git a/routes/index.js b/routes/index.js index 38a12f52..b6e180ff 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,98 +1,105 @@ -import dashboardSiteRoutes from './dashboard' -import policySiteRoutes from './policyRoutes' -import sessionRoutes from './sessionRoutes' +import dashboardSiteRoutes from "./dashboard"; +import policySiteRoutes from "./policyRoutes"; +import sessionRoutes from "./sessionRoutes"; import { isFeatureWebRouteEnabled, getGlobalImage } from "../api/common"; -import { getWebAnnouncement } from '../controllers/announcementController'; +import { getWebAnnouncement } from "../controllers/announcementController"; -export default function applicationSiteRoutes(app, client, fetch, moment, config, db, features, lang) { +export default function applicationSiteRoutes( + app, + client, + fetch, + moment, + config, + db, + features, + lang +) { + dashboardSiteRoutes(app, client, fetch, moment, config, db, features, lang); + sessionRoutes(app, client, fetch, moment, config, db, features, lang); + policySiteRoutes(app, config, features); - dashboardSiteRoutes(app, client, fetch, moment, config, db, features, lang); - sessionRoutes(app, client, fetch, moment, config, db, features, lang); - policySiteRoutes(app, config, features); - - app.get('/', async function (req, res) { - const fetchURL = `${process.env.siteAddress}/api/web/statistics`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const statApiData = await response.json(); - - return res.view("modules/index/index", { - "pageTitle": `${config.siteConfiguration.siteName}`, - config: config, - req: req, - features: features, - globalImage: await getGlobalImage(), - statApiData: statApiData, - announcementWeb: await getWebAnnouncement() - }); + app.get("/", async function (req, res) { + const fetchURL = `${process.env.siteAddress}/api/web/statistics`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, }); + const statApiData = await response.json(); - // - // Play - // - app.get('/play', async function (req, res) { - isFeatureWebRouteEnabled(features.server, req, res, features); + return res.view("modules/index/index", { + pageTitle: `${config.siteConfiguration.siteName}`, + config: config, + req: req, + features: features, + globalImage: await getGlobalImage(), + statApiData: statApiData, + announcementWeb: await getWebAnnouncement(), + }); + }); - const fetchURL = `${process.env.siteAddress}/api/server/get?visible=true`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const apiData = await response.json(); + // + // Play + // + app.get("/play", async function (req, res) { + isFeatureWebRouteEnabled(features.server, req, res, features); - return res.view('modules/play/play', { - "pageTitle": `Play`, - config: config, - req: req, - apiData: apiData, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + const fetchURL = `${process.env.siteAddress}/api/server/get?visible=true`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, }); + const apiData = await response.json(); - // - // Apply - // - app.get('/apply', async function (req, res) { - isFeatureWebRouteEnabled(features.applications, req, res, features); + return res.view("modules/play/play", { + pageTitle: `Play`, + config: config, + req: req, + apiData: apiData, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), + }); + }); - const fetchURL = `${process.env.siteAddress}/api/application/get`; - const response = await fetch(fetchURL, { - headers: { 'x-access-token': process.env.apiKey } - }); - const apiData = await response.json(); + // + // Apply + // + app.get("/apply", async function (req, res) { + isFeatureWebRouteEnabled(features.applications, req, res, features); - return res.view('apply', { - "pageTitle": `Apply`, - config: config, - req: req, - apiData: apiData, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + const fetchURL = `${process.env.siteAddress}/api/application/get`; + const response = await fetch(fetchURL, { + headers: { "x-access-token": process.env.apiKey }, }); + const apiData = await response.json(); - // - // Discord Redirect - // - app.get('/discord', async function (req, res) { - return res.redirect(config.siteConfiguration.platforms.discord); + return res.view("apply", { + pageTitle: `Apply`, + config: config, + req: req, + apiData: apiData, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); + }); - // - // Webstore Redirect - // - app.get('/webstore', async function (req, res) { - return res.redirect(config.siteConfiguration.platforms.webstore); - }); + // + // Discord Redirect + // + app.get("/discord", async function (req, res) { + return res.redirect(config.siteConfiguration.platforms.discord); + }); - // - // Guides Redirect - // - app.get('/knowledgebase', async function (req, res) { - return res.redirect(`https://guides.craftingforchrist.net/`); - }); + // + // Webstore Redirect + // + app.get("/webstore", async function (req, res) { + return res.redirect(config.siteConfiguration.platforms.webstore); + }); -} \ No newline at end of file + // + // Guides Redirect + // + app.get("/knowledgebase", async function (req, res) { + return res.redirect(`https://guides.craftingforchrist.net/`); + }); +} diff --git a/routes/policyRoutes.js b/routes/policyRoutes.js index 6ec03c48..f3444e45 100644 --- a/routes/policyRoutes.js +++ b/routes/policyRoutes.js @@ -2,49 +2,47 @@ import { getGlobalImage } from "../api/common"; import { getWebAnnouncement } from "../controllers/announcementController"; export default function policySiteRoute(app, config, features) { - - app.get('/terms', async function (req, res) { - return res.view('policy/termsOfService', { - "pageTitle": `Network Terms Of Service`, - config: config, - req: req, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + app.get("/terms", async function (req, res) { + return res.view("policy/termsOfService", { + pageTitle: `Network Terms Of Service`, + config: config, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); + }); - app.get('/rules', async function (req, res) { - return res.view('policy/rules', { - "pageTitle": `Network Rules`, - config: config, - req: req, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + app.get("/rules", async function (req, res) { + return res.view("policy/rules", { + pageTitle: `Network Rules`, + config: config, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); + }); - app.get('/privacy', async function (req, res) { - return res.view('policy/privacy', { - "pageTitle": `Network Privacy Policy`, - config: config, - req: req, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + app.get("/privacy", async function (req, res) { + return res.view("policy/privacy", { + pageTitle: `Network Privacy Policy`, + config: config, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); + }); - app.get('/refund', async function (req, res) { - return res.view('policy/refund', { - "pageTitle": `Network Refund Policy`, - config: config, - req: req, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + app.get("/refund", async function (req, res) { + return res.view("policy/refund", { + pageTitle: `Network Refund Policy`, + config: config, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); - -} \ No newline at end of file + }); +} diff --git a/routes/sessionRoutes.js b/routes/sessionRoutes.js index 4f437f3c..41a3d3ab 100644 --- a/routes/sessionRoutes.js +++ b/routes/sessionRoutes.js @@ -1,198 +1,242 @@ -import bcrypt from 'bcrypt'; -import { isFeatureWebRouteEnabled, setBannerCookie, getGlobalImage } from "../api/common"; -import { getProfilePicture } from '../controllers/userController'; -import { getWebAnnouncement } from '../controllers/announcementController'; - -export default function sessionSiteRoute(app, client, fetch, moment, config, db, features, lang) { - - // - // Session - // - app.get('/login', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.web.login, req, res, features)) - return; - - res.view('session/login', { - "pageTitle": `Login`, - config: config, - req: req, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); - - return res; +import bcrypt from "bcrypt"; +import { + isFeatureWebRouteEnabled, + setBannerCookie, + getGlobalImage, +} from "../api/common"; +import { getProfilePicture } from "../controllers/userController"; +import { getWebAnnouncement } from "../controllers/announcementController"; + +export default function sessionSiteRoute( + app, + client, + fetch, + moment, + config, + db, + features, + lang +) { + // + // Session + // + app.get("/login", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.web.login, req, res, features)) + return; + + res.view("session/login", { + pageTitle: `Login`, + config: config, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); - app.get('/register', async function (req, res) { - if (!isFeatureWebRouteEnabled(features.web.register, req, res, features)) - return; - - res.view('session/register', { - "pageTitle": `Register`, - config: config, - req: req, - features: features, - globalImage: await getGlobalImage(), - announcementWeb: await getWebAnnouncement() - }); + return res; + }); - return res; + app.get("/register", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.web.register, req, res, features)) + return; + + res.view("session/register", { + pageTitle: `Register`, + config: config, + req: req, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), }); - app.post('/login', async function(req, res) { - if (!isFeatureWebRouteEnabled(features.web.login, req, res, features)) - return; - - const username = req.body.username; - const email = req.body.email; - const password = req.body.password; - - - async function getUserRanks(userData, userRanks = null) { - return new Promise((resolve) => { - // Call with just userData only get directly assigned Ranks - if (userRanks === null) { - db.query(`SELECT rankSlug, title FROM userRanks WHERE userId = ?`, [userData.userId], async function (err, results) { - if (err) { - throw err; - } - - let userRanks = results.map(a => ({['rankSlug']:a.rankSlug, ['title']:a.title})); - resolve(userRanks); - }); - // Ranks were passed in meaning we are looking for nested ranks - } else { - db.query(`SELECT rankSlug FROM rankRanks WHERE FIND_IN_SET(parentRankSlug, ?)`, [userRanks.join()], async function (err, results) { - if (err) { - throw err; - } - - let childRanks = results.map(a => a.rankSlug); - let allRanks = userRanks.concat(childRanks); - //Using a set of the array removes duplicates and prevents infinite loops - let removeDuplicates = [...new Set(allRanks)]; - - //If after removing duplicates the length of the new list is not longer than the old list we are done simply resolve - if(userRanks.length <= removeDuplicates.length) { - resolve(removeDuplicates); - } else { - resolve(getUserRanks(userData, removeDuplicates)); - } - }); - } - }); - } - - async function getRankPermissions (allRanks) { - return new Promise((resolve) => { - db.query(`SELECT DISTINCT permission FROM rankPermissions WHERE FIND_IN_SET(rankSlug, ?)`, [allRanks.join()], async function (err, results) { - if (err) { - throw err; - } - - let rankPermissions = results.map(a => a.permission); - resolve(rankPermissions); - }); - }); - } - - async function getUserPermissions(userData) { - return new Promise((resolve) => { - //Get permissions assigned directly to user - db.query(`SELECT DISTINCT permission FROM userPermissions WHERE userId = ?`, [userData.userId], async function (err, results) { - if (err) { - throw err; - } - - let userPermissions = results.map(a => a.permission); - resolve(userPermissions); - }); - }); - } - - async function getPermissions(userData) { - //Get directly assigned User Ranks - userData.userRanks = await getUserRanks(userData); - //get all the ranks including children - let allRanks = await getUserRanks(userData, userData.userRanks.map(a => a.rankSlug)); - //get permissions assigned to all the ranks - let rankPermissions = await getRankPermissions(allRanks); - //Get permissions assigned directly to user - let userPermissions = await getUserPermissions(userData); - //Combine into 1 permissions array - let permissions = rankPermissions.concat(userPermissions); - //Using a set of the array removes duplicates and prevents infinite loops - userData.permissions = [...new Set(permissions)]; - return userData; - } - - db.query(`select * from users where username=?`, [username], async function (err, results) { - if (err) { - throw err; - } - - let hashedPassword = null; - - let loginFailed = false; - if (!results.length) { - loginFailed = true; - } else { - hashedPassword = results[0].password; - } - - // User has not logged in before. - if (loginFailed || hashedPassword == null) { - let notLoggedInBeforeLang = lang.web.notLoggedInBefore; - - setBannerCookie("warning", notLoggedInBeforeLang.replace("%SITEADDRESS%", process.env.siteAddress), res); - return res.redirect(`${process.env.siteAddress}/login`); - } - - // Check if passwords match - const salt = await bcrypt.genSalt(); - - bcrypt.compare(password, hashedPassword, async function(err, result) { - if (err) { - throw err; - } - - if (result) { - req.session.authenticated = true; - let userData = await getPermissions(results[0]); - let profilePicture = await getProfilePicture(userData.username); - - req.session.user = { - userId: userData.userId, - username: userData.username, - profilePicture: profilePicture, - discordID: userData.discordID, - uuid: userData.uuid, - ranks: userData.userRanks, - permissions: userData.permissions - }; - - setBannerCookie("success", lang.session.userSuccessLogin, res); - return res.redirect(`${process.env.siteAddress}/`); - } else { - setBannerCookie("warning", lang.session.userFailedLogin, res); - return res.redirect(`${process.env.siteAddress}/login`); - } - }); + return res; + }); + + app.post("/login", async function (req, res) { + if (!isFeatureWebRouteEnabled(features.web.login, req, res, features)) + return; + + const username = req.body.username; + const email = req.body.email; + const password = req.body.password; + + async function getUserRanks(userData, userRanks = null) { + return new Promise((resolve) => { + // Call with just userData only get directly assigned Ranks + if (userRanks === null) { + db.query( + `SELECT rankSlug, title FROM userRanks WHERE userId = ?`, + [userData.userId], + async function (err, results) { + if (err) { + throw err; + } + + let userRanks = results.map((a) => ({ + ["rankSlug"]: a.rankSlug, + ["title"]: a.title, + })); + resolve(userRanks); + } + ); + // Ranks were passed in meaning we are looking for nested ranks + } else { + db.query( + `SELECT rankSlug FROM rankRanks WHERE FIND_IN_SET(parentRankSlug, ?)`, + [userRanks.join()], + async function (err, results) { + if (err) { + throw err; + } + + let childRanks = results.map((a) => a.rankSlug); + let allRanks = userRanks.concat(childRanks); + //Using a set of the array removes duplicates and prevents infinite loops + let removeDuplicates = [...new Set(allRanks)]; + + //If after removing duplicates the length of the new list is not longer than the old list we are done simply resolve + if (userRanks.length <= removeDuplicates.length) { + resolve(removeDuplicates); + } else { + resolve(getUserRanks(userData, removeDuplicates)); + } + } + ); + } + }); + } + + async function getRankPermissions(allRanks) { + return new Promise((resolve) => { + db.query( + `SELECT DISTINCT permission FROM rankPermissions WHERE FIND_IN_SET(rankSlug, ?)`, + [allRanks.join()], + async function (err, results) { + if (err) { + throw err; + } + + let rankPermissions = results.map((a) => a.permission); + resolve(rankPermissions); + } + ); + }); + } + + async function getUserPermissions(userData) { + return new Promise((resolve) => { + //Get permissions assigned directly to user + db.query( + `SELECT DISTINCT permission FROM userPermissions WHERE userId = ?`, + [userData.userId], + async function (err, results) { + if (err) { + throw err; + } + + let userPermissions = results.map((a) => a.permission); + resolve(userPermissions); + } + ); }); + } + + async function getPermissions(userData) { + //Get directly assigned User Ranks + userData.userRanks = await getUserRanks(userData); + //get all the ranks including children + let allRanks = await getUserRanks( + userData, + userData.userRanks.map((a) => a.rankSlug) + ); + //get permissions assigned to all the ranks + let rankPermissions = await getRankPermissions(allRanks); + //Get permissions assigned directly to user + let userPermissions = await getUserPermissions(userData); + //Combine into 1 permissions array + let permissions = rankPermissions.concat(userPermissions); + //Using a set of the array removes duplicates and prevents infinite loops + userData.permissions = [...new Set(permissions)]; + return userData; + } + + db.query( + `select * from users where username=?`, + [username], + async function (err, results) { + if (err) { + throw err; + } + + let hashedPassword = null; + + let loginFailed = false; + if (!results.length) { + loginFailed = true; + } else { + hashedPassword = results[0].password; + } + + // User has not logged in before. + if (loginFailed || hashedPassword == null) { + let notLoggedInBeforeLang = lang.web.notLoggedInBefore; + + setBannerCookie( + "warning", + notLoggedInBeforeLang.replace( + "%SITEADDRESS%", + process.env.siteAddress + ), + res + ); + return res.redirect(`${process.env.siteAddress}/login`); + } + + // Check if passwords match + const salt = await bcrypt.genSalt(); + + bcrypt.compare(password, hashedPassword, async function (err, result) { + if (err) { + throw err; + } + + if (result) { + req.session.authenticated = true; + let userData = await getPermissions(results[0]); + let profilePicture = await getProfilePicture(userData.username); + + req.session.user = { + userId: userData.userId, + username: userData.username, + profilePicture: profilePicture, + discordID: userData.discordID, + uuid: userData.uuid, + ranks: userData.userRanks, + permissions: userData.permissions, + }; + + setBannerCookie("success", lang.session.userSuccessLogin, res); + return res.redirect(`${process.env.siteAddress}/`); + } else { + setBannerCookie("warning", lang.session.userFailedLogin, res); + return res.redirect(`${process.env.siteAddress}/login`); + } + }); + } + ); - return res; + return res; }); - app.get('/logout', async function(req, res) { - req.destroySession((err) => { - if (err) { - console.log(err); - throw err; - } else { - setBannerCookie("success", lang.session.userLogout, res); - return res.redirect(`${process.env.siteAddress}/`); - } - }) + app.get("/logout", async function (req, res) { + req.destroySession((err) => { + if (err) { + console.log(err); + throw err; + } else { + setBannerCookie("success", lang.session.userLogout, res); + return res.redirect(`${process.env.siteAddress}/`); + } + }); }); -} \ No newline at end of file +} From 726cf143717e52ae6465a462fe57400d703bf8bf Mon Sep 17 00:00:00 2001 From: benrobson Date: Mon, 20 Nov 2023 22:30:09 +1100 Subject: [PATCH 17/27] Resolve issue with logout crashing. --- routes/sessionRoutes.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/routes/sessionRoutes.js b/routes/sessionRoutes.js index 41a3d3ab..7f823ef0 100644 --- a/routes/sessionRoutes.js +++ b/routes/sessionRoutes.js @@ -228,15 +228,14 @@ export default function sessionSiteRoute( return res; }); - app.get("/logout", async function (req, res) { - req.destroySession((err) => { - if (err) { - console.log(err); - throw err; - } else { - setBannerCookie("success", lang.session.userLogout, res); - return res.redirect(`${process.env.siteAddress}/`); - } - }); + app.get("/logout", async function (req, reply) { + try { + await req.session.destroy(); + setBannerCookie("success", lang.session.userLogout, reply.res); + reply.redirect(`${process.env.siteAddress}/`); + } catch (err) { + console.log(err); + throw err; + } }); } From f61ffa5102faa767f74df64275b373df59deea7f Mon Sep 17 00:00:00 2001 From: benrobson Date: Tue, 21 Nov 2023 21:59:41 +1100 Subject: [PATCH 18/27] Commence work on /ranks page and Tebex integration. --- assets/css/style.css | 11 +++++ config.json | 2 +- features.json | 1 + ranks.json | 86 +++++++++++++++++++++++++++++++++ routes/index.js | 27 +++++++++++ views/modules/footer.ejs | 3 ++ views/modules/navigationBar.ejs | 3 ++ views/ranks.ejs | 47 ++++++++++++++++++ 8 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 ranks.json create mode 100644 views/ranks.ejs diff --git a/assets/css/style.css b/assets/css/style.css index 0bb1e59f..c49e0177 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1551,4 +1551,15 @@ a:focus { .dashboard-sidebar { display: block !important; } +} + +@media (max-width: 767px) { + .button-group { + display: flex; + justify-content: center; + } + + .button-group a { + margin-right: 10px; + } } \ No newline at end of file diff --git a/config.json b/config.json index 1c59fbb3..eb9df35c 100644 --- a/config.json +++ b/config.json @@ -12,7 +12,7 @@ "refund": "https://raw.githubusercontent.com/craftingforchrist/Legal/master/refund.md" }, "platforms": { - "webstore": "https://crafting-for-christ.tebex.io/", + "webstore": "https://crafting-for-christ.tebex.io", "discord": "https://discord.com/", "facebook": "https://www.facebook.com/craft4christ/", "twitter": "https://twitter.com/craft4christmc", diff --git a/features.json b/features.json index 5461269d..1349aca3 100644 --- a/features.json +++ b/features.json @@ -12,6 +12,7 @@ } }, "server": true, + "ranks": true, "filter": { "link": true, "phrase": true diff --git a/ranks.json b/ranks.json new file mode 100644 index 00000000..a28aca66 --- /dev/null +++ b/ranks.json @@ -0,0 +1,86 @@ +{ + "currency": "AUD", + "ranks": [ + { + "name": "Iron", + "image": "images/ranks/iron.png", + "priceMonthly": 1, + "monthlyRedirectUrl": "https://crafting-for-christ.tebex.io/package/4028832", + "globalPerks": ["Iron tag on Server and Discord"], + "networkPerks": ["Ability to join full games during Events on Mixed"], + "hubPerks": [ + "Player statue in the Hall of Patrons", + "Access to /fly :elytra: in the Hub" + ], + "survivalPerks": ["Access to /sethome :homes:, maximum of 2"], + "discordPerks": [ + "Access to exclusive Donator channels", + "Access to using the Discord Music Bot" + ] + }, + { + "name": "Gold", + "image": "images/ranks/gold.png", + "priceMonthly": 5, + "priceOneTime": 25, + "monthlyRedirectUrl": "https://crafting-for-christ.tebex.io/package/4028834", + "oneTimeRedirectUrl": "https://crafting-for-christ.tebex.io/package/4028835", + "inherits": "Iron", + "globalPerks": ["Gold tag on Server and Discord"], + "survivalPerks": [ + "Access to /hat :womans_hat:", + "Ability to customize armor stands using armour statues (https://www.youtube.com/watch?v=A25hSBnM7dM)", + "Access to /sethome, maximum of 3" + ] + }, + { + "name": "Diamond", + "image": "images/ranks/diamond.png", + "priceMonthly": 10, + "priceOneTime": 50, + "monthlyRedirectUrl": "https://crafting-for-christ.tebex.io/package/4028837", + "oneTimeRedirectUrl": "https://crafting-for-christ.tebex.io/package/4028840", + "inherits": "Gold", + "globalPerks": ["Diamond tag on Server and Discord"], + "survivalPerks": ["Access to /sethome, maximum of 4"] + } + ], + "additionalItems": [ + { + "name": "$10 Donation", + "image": "images/ranks/donate.png", + "price": 10, + "redirectUrl": "https://crafting-for-christ.tebex.io/package/4028841" + }, + { + "name": "$20 Donation", + "image": "images/ranks/donate.png", + "price": 20, + "redirectUrl": "https://crafting-for-christ.tebex.io/package/4028842" + }, + { + "name": "$30 Donation", + "image": "images/ranks/donate.png", + "price": 30, + "redirectUrl": "https://crafting-for-christ.tebex.io/package/4028843" + }, + { + "name": "$40 Donation", + "image": "images/ranks/donate.png", + "price": 40, + "redirectUrl": "https://crafting-for-christ.tebex.io/package/4028844" + }, + { + "name": "$50 Donation", + "image": "images/ranks/donate.png", + "price": 50, + "redirectUrl": "https://crafting-for-christ.tebex.io/package/4028845" + }, + { + "name": "$100 Donation", + "image": "images/ranks/donate.png", + "price": 100, + "redirectUrl": "https://crafting-for-christ.tebex.io/package/4028846" + } + ] +} diff --git a/routes/index.js b/routes/index.js index b6e180ff..fb87a8e5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -3,6 +3,7 @@ import policySiteRoutes from "./policyRoutes"; import sessionRoutes from "./sessionRoutes"; import { isFeatureWebRouteEnabled, getGlobalImage } from "../api/common"; import { getWebAnnouncement } from "../controllers/announcementController"; +import rankData from "../ranks.json" assert { type: "json" }; export default function applicationSiteRoutes( app, @@ -82,6 +83,32 @@ export default function applicationSiteRoutes( }); }); + // + // Ranks + // + app.get("/ranks", async function (req, res) { + isFeatureWebRouteEnabled(features.ranks, req, res, features); + + const fetchURL = `https://plugin.tebex.io/listing`; + const response = await fetch(fetchURL, { + headers: { "X-Tebex-Secret": process.env.tebexSecretKey }, + }); + const tebexPackageData = await response.json(); + + console.log(tebexPackageData.categories); + + return res.view("ranks", { + pageTitle: `Ranks`, + config: config, + req: req, + rankData: rankData, + tebexPackageData: tebexPackageData.categories, + features: features, + globalImage: await getGlobalImage(), + announcementWeb: await getWebAnnouncement(), + }); + }); + // // Discord Redirect // diff --git a/views/modules/footer.ejs b/views/modules/footer.ejs index ee1c0605..d92cef9e 100644 --- a/views/modules/footer.ejs +++ b/views/modules/footer.ejs @@ -51,6 +51,9 @@
  • Apply
  • <% } %>
  • Knowledgebase
  • + <% if (features.ranks) { %> +
  • Ranks
  • + <% } %>
    diff --git a/views/modules/navigationBar.ejs b/views/modules/navigationBar.ejs index d85db92b..7229681a 100644 --- a/views/modules/navigationBar.ejs +++ b/views/modules/navigationBar.ejs @@ -28,6 +28,9 @@ <% if (features.applications) { %> <% } %> + <% if (features.ranks) { %> + + <% } %> <% if (req.session?.user) { %>