This commit is contained in:
Jonny_Bro (Nikita) 2023-06-22 19:36:52 +05:00
parent f61dc139f6
commit 849a93887a
96 changed files with 10351 additions and 10825 deletions

585
.d.ts vendored
View file

@ -1,342 +1,337 @@
declare module "discord-dashboard" { declare module "discord-dashboard" {
let Dashboard: any let Dashboard: any
const formTypes: formTypes const formTypes: formTypes
const customPagesTypes: customPagesTypes const customPagesTypes: customPagesTypes
const DISCORD_FLAGS: {
Permissions: Permissions
}
const version: string const version: string
} }
interface RateLimitSettingsObject { interface RateLimitSettingsObject {
windowMs: Number windowMs: Number
max: Number max: Number
message: String message: String
store?: any store?: any
} }
interface Dashboard { interface Dashboard {
new (config: { new(config: {
port: number port: number
client: { client: {
id: string id: string
secret: string secret: string
} }
redirectUri: string redirectUri: string
domain: string domain: string
bot: any bot: any
theme: any theme: any
settings: category[] settings: category[]
requiredPermissions?: object, ownerIDs: array,
ownerIDs: array, useTheme404: boolean,
useTheme404: boolean, useThemeMaintenance: boolean,
useThemeMaintenance: boolean, noCreateServer?: boolean
acceptPrivacyPolicy?: boolean SSL?: {
noCreateServer?: boolean enabled: boolean
SSL?: { key: string
enabled: boolean cert: string
key: string }
cert: string minimizedConsoleLogs?: boolean
} rateLimits?: {
minimizedConsoleLogs?: boolean manage?: RateLimitSettingsObject
rateLimits?: { guildPage?: RateLimitSettingsObject
manage?: RateLimitSettingsObject settingsUpdatePostAPI?: RateLimitSettingsObject
guildPage?: RateLimitSettingsObject discordOAuth2?: RateLimitSettingsObject
settingsUpdatePostAPI?: RateLimitSettingsObject }
discordOAuth2?: RateLimitSettingsObject invite?: {
} clientId: string
invite?: { scopes: object
clientId: string permissions: string
scopes: object redirectUri: string
permissions: string otherParams: string
redirectUri: string }
otherParams: string supportServer?: {
} slash: string
supportServer?: { inviteUrl: string
slash: string }
inviteUrl: string guildAfterAuthorization?: {
} use: boolean
guildAfterAuthorization?: { guildId: string
use: boolean options?: {
guildId: string nickname?: string
options?: { roles?: [string]
nickname?: string mute?: boolean
roles?: [string] deaf?: boolean
mute?: boolean }
deaf?: boolean }
} reportError?: (where: string, what: any) => any
} assistantsSecureStorageKey?: string
reportError?: (where: string, what: any) => any }): any
assistantsSecureStorageKey?: string DBDEvents: () => any
}): any init: () => Promise<any>
DBDEvents: () => any getApp: () => any
init: () => Promise<any> useThirdPartyModule: (module: any) => any
getApp: () => any
useThirdPartyModule: (module: any) => any
} }
interface category { interface category {
categoryId: string categoryId: string
categoryName: string categoryName: string
categoryDescription: string categoryDescription: string
categoryOptionsList: option[] categoryOptionsList: option[]
} }
interface option { interface option {
optionId?: string optionId?: string
optionName?: string optionName?: string
optionDescription?: string optionDescription?: string
title?: string title?: string
description?: string description?: string
optionType: optionType:
| { | {
type: string type: string
data?: string | null data?: string | null
function?: any function?: any
min?: number | null min?: number | null
max?: number | null max?: number | null
disabled?: boolean | null disabled?: boolean | null
required?: boolean | null required?: boolean | null
themeOptions?: object | null themeOptions?: object | null
} }
| string | string
getActualSet?: (options: optionOptions) => Promise<any> getActualSet?: (options: optionOptions) => Promise<any>
setNew?: (options: optionOptions) => Promise<any> setNew?: (options: optionOptions) => Promise<any>
allowedCheck?: (options: allowedCheckOption) => Promise<any> allowedCheck?: (options: allowedCheckOption) => Promise<any>
themeOptions?: Object themeOptions?: Object
} }
interface optionOptions { interface optionOptions {
guild: { id: string } guild: { id: string }
user: { id: string } user: { id: string }
newData: any newData: any
} }
interface allowedCheckOption { interface allowedCheckOption {
guild: { id: string } guild: { id: string }
user: { id: string } user: { id: string }
} }
interface formTypes { interface formTypes {
select: ( select: (
list: object, list: object,
disabled?: boolean, disabled?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
data: { data: {
keys: object keys: object
values: object values: object
} }
disabled: boolean disabled: boolean
themeOptions: object themeOptions: object
} }
multiSelect: ( multiSelect: (
list: object, list: object,
disabled?: boolean, disabled?: boolean,
required?: boolean, required?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
data: { data: {
keys: object keys: object
values: object values: object
} }
disabled: boolean | null disabled: boolean | null
required: boolean | null required: boolean | null
themeOptions: object themeOptions: object
} }
input: ( input: (
placeholder?: string, placeholder?: string,
min?: number, min?: number,
max?: number, max?: number,
disabled?: boolean, disabled?: boolean,
required?: boolean, required?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
data: string | null data: string | null
min: number | null min: number | null
max: number | null max: number | null
disabled: boolean | null disabled: boolean | null
required: boolean | null required: boolean | null
themeOptions: object | null themeOptions: object | null
} }
textarea: ( textarea: (
placeholder?: string, placeholder?: string,
min?: number, min?: number,
max?: number, max?: number,
disabled?: boolean, disabled?: boolean,
required?: boolean, required?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
data: string | null data: string | null
min: number | null min: number | null
max: number | null max: number | null
disabled: boolean | null disabled: boolean | null
required: boolean | null required: boolean | null
themeOptions: object | null themeOptions: object | null
} }
switch: ( switch: (
disabled?: boolean, disabled?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
disabled: boolean disabled: boolean
themeOptions: object themeOptions: object
} }
checkbox: ( checkbox: (
disabled?: boolean, disabled?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
disabled: boolean disabled: boolean
themeOptions: object themeOptions: object
} }
channelsSelect: ( channelsSelect: (
disabled?: boolean, disabled?: boolean,
channelTypes?: string[], channelTypes?: string[],
hideNSFW?: boolean, hideNSFW?: boolean,
onlyNSFW?: boolean, onlyNSFW?: boolean,
hideNoAccess?: boolean, hideNoAccess?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
function: (client: string, guildid: string) => any function: (client: string, guildid: string) => any
disabled: boolean disabled: boolean
themeOptions: object themeOptions: object
} }
channelsMultiSelect: ( channelsMultiSelect: (
disabled?: boolean, disabled?: boolean,
required?: boolean, required?: boolean,
channelTypes?: string[], channelTypes?: string[],
hideNSFW?: boolean, hideNSFW?: boolean,
onlyNSFW?: boolean, onlyNSFW?: boolean,
hideNoAccess?: boolean, hideNoAccess?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
function: (client: string, guildid: string) => any function: (client: string, guildid: string) => any
disabled: boolean disabled: boolean
required: boolean required: boolean
themeOptions: object themeOptions: object
} }
rolesSelect: ( rolesSelect: (
includeBots: boolean, includeBots: boolean,
disabled?: boolean, disabled?: boolean,
hideHigherRoles?: boolean, hideHigherRoles?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
function: (client: string, guildid: string) => any function: (client: string, guildid: string) => any
disabled: boolean disabled: boolean
themeOptions: object themeOptions: object
} }
rolesMultiSelect: ( rolesMultiSelect: (
includeBots: boolean, includeBots: boolean,
disabled?: boolean, disabled?: boolean,
required?: boolean, required?: boolean,
hideHigherRoles?: boolean, hideHigherRoles?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
function: (client: string, guildid: string) => any function: (client: string, guildid: string) => any
disabled: boolean disabled: boolean
required: boolean required: boolean
themeOptions: object themeOptions: object
} }
colorSelect: ( colorSelect: (
defaultState: string, defaultState: string,
disabled?: boolean, disabled?: boolean,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
data: string data: string
disabled: boolean disabled: boolean
themeOptions: object themeOptions: object
} }
embedBuilder: ( embedBuilder: (
defaultSettings: object, defaultSettings: object,
themeOptions?: object themeOptions?: object
) => { ) => {
type: string type: string
data: object data: object
themeOptions: object themeOptions: object
} }
} }
interface EmbedBuilder { interface EmbedBuilder {
content?: string content?: string
embed: { embed: {
title?: string title?: string
description: string description: string
color?: string | number color?: string | number
timestamp?: any timestamp?: any
url?: string url?: string
author?: { author?: {
name?: string name?: string
url?: string url?: string
icon_url?: string icon_url?: string
} }
thumbnail?: { thumbnail?: {
url?: string url?: string
} }
image?: { image?: {
url?: string url?: string
} }
footer?: { footer?: {
text?: string text?: string
icon_url?: string icon_url?: string
} }
fields?: EmbedBuilderField[] fields?: EmbedBuilderField[]
} }
} }
interface EmbedBuilderField { interface EmbedBuilderField {
name?: string name?: string
value?: string value?: string
inline?: boolean inline?: boolean
} }
interface customPagesTypes { interface customPagesTypes {
redirectToUrl: ( redirectToUrl: (
endpoint: string, endpoint: string,
getDataFunction: any getDataFunction: any
) => { ) => {
type: string type: string
endpoint: string endpoint: string
getEndpoint: any getEndpoint: any
} }
renderHtml: ( renderHtml: (
endpoint: string, endpoint: string,
getDataFunction: any getDataFunction: any
) => { ) => {
type: string type: string
endpoint: string endpoint: string
getHtml: any getHtml: any
} }
sendJson: ( sendJson: (
endpoint: string, endpoint: string,
getDataFunction: any getDataFunction: any
) => { ) => {
type: string type: string
endpoint: string endpoint: string
getJson: any getJson: any
} }
} }

35
.gitignore vendored
View file

@ -1,33 +1,2 @@
./node_modules/ node_modules
node_modules/ package-lock.json
test/
/test
./test/
./test/
./.idea
discord-dashboard-pp
./discord-dashboard-pp
.idea
.devChannel
./.devChannel
./ExternalStatistics/index_unobfuscated.js
ExternalStatistics/index_unobfuscated.js
./dev_project.json
dev_project.json
altometra-dashboard
./altometra-dashboard
index_unobf.js
./index_unobf.js
/altometra-dashoard
altometra-dashboard/
./altometra-dashboard/
/altometra-dashoard/
./licensedDashboardClass_unobfuscated.js
./npmPublish.js
licensedDashboardClass_unobfuscated.js
npmPublish.js
updateObfuscatedIndex.js
./updateObfuscatedIndex.js
.idea
.idea
yarn-error.log

View file

@ -28,5 +28,4 @@ module.exports = (websiteTitle) => `<!DOCTYPE html>
</body> </body>
</html> </html>`;
`

View file

@ -1,36 +1,26 @@
const prefix = "[DBD-Storage-Handler]" const prefix = "[DBD-Storage-Handler]";
const colors = require("colors") const Keyv = require("keyv");
const Keyv = require("keyv") const { join } = require("path");
const { join } = require("path")
const err = (text) => {
return `🐧${text} Do you need help? Join our Discord server: ${"https://discord.gg/CzfMGtrdaA".blue
}`
}
class Handler { class Handler {
constructor(keyvAdapter) { constructor(keyvAdapter) {
this.db = new Keyv( this.db = new Keyv(keyvAdapter || `sqlite://${join(__dirname, "/database.sqlite")}`);
keyvAdapter || `sqlite://${join(__dirname, "/database.sqlite")}`
)
this.db.on("error", (err) => this.db.on("error", (err) => console.error(`${prefix} ${`Keyv connection error: ${err}`.red}`));
console.error(`${prefix} ${`Keyv connection error: ${err}`.red}`)
)
this.Category = require(`${__dirname}/structures/Category`)(this.db) this.Category = require(`${__dirname}/structures/Category`)(this.db);
this.Option = require(`${__dirname}/structures/Option`)(this.db) this.Option = require(`${__dirname}/structures/Option`)(this.db);
console.log(`${prefix} Database successfully initialized!`) console.log(`${prefix} Database successfully initialized!`);
} }
async fetch(guildId, optionId) { async fetch(guildId, optionId) {
return await this.db.get(`${guildId}.options.${optionId}`) return await this.db.get(`${guildId}.options.${optionId}`);
} }
db() { db() {
return this.db return this.db;
} }
} }
module.exports = Handler module.exports = Handler;

View file

@ -1,104 +1,103 @@
module.exports = (db) => { module.exports = db => {
return class Category { return class Category {
constructor( constructor(
options = { categoryId: "", categoryName: "", categoryDescription: "" } options = {
) { categoryId: "",
this.categoryId = options.categoryId categoryName: "",
this.categoryName = options.categoryName categoryDescription: "",
this.categoryDescription = options.categoryDescription },
this.categoryOptionsList = [] ) {
this.categoryId = options.categoryId;
this.categoryName = options.categoryName;
this.categoryDescription = options.categoryDescription;
this.categoryOptionsList = [];
// const db = Handler.getDB() // const db = Handler.getDB()
this.db = db this.db = db;
} }
/** /**
* *
* @param {string} id - The id of the category, must be unique * @param {string} id - The id of the category, must be unique
* @returns * @returns
*/ */
setId(id) { setId(id) {
this.categoryId = id this.categoryId = id;
return this return this;
} }
/** /**
* *
* @param {string} name - The name of the category displayed in the dashboard * @param {string} name - The name of the category displayed in the dashboard
* @returns * @returns
*/ */
setName(name) { setName(name) {
this.categoryName = name this.categoryName = name;
return this return this;
} }
/** /**
* *
* @param {string} description - The description of the category displayed in the dashboard * @param {string} description - The description of the category displayed in the dashboard
* @returns * @returns
*/ */
setDescription(description) { setDescription(description) {
this.categoryDescription = description this.categoryDescription = description;
return this return this;
} }
/** /**
* *
* @param {string} image - Set the image for a Soft UI category, must be a link * @param {string} image - Set the image for a Soft UI category, must be a link
* @returns * @returns
*/ */
setImage(image) { setImage(image) {
this.categoryImageURL = image this.categoryImageURL = image;
return this return this;
} }
/** /**
* *
* @param {boolean} toggleable - Allows Soft UI category to be toggleable * @param {boolean} toggleable - Allows Soft UI category to be toggleable
* @returns * @returns
*/ */
setToggleable(toggleable) { setToggleable(toggleable) {
this.toggleable = toggleable this.toggleable = toggleable;
this.getActualSet = async ({ guild }) => { this.getActualSet = async ({ guild }) => {
return await this.db.get( return await this.db.get(`${guild.id}.categories.${this.categoryId}.toggle`);
`${guild.id}.categories.${this.categoryId}.toggle` };
)
}
this.setNew = async ({ guild, newData }) => { this.setNew = async ({ guild, newData }) => {
await this.db.set( await this.db.set(`${guild.id}.categories.${this.categoryId}.toggle`, newData);
`${guild.id}.categories.${this.categoryId}.toggle`, };
newData
)
}
return this return this;
} }
/** /**
* @param {import('./Option')[]} options - The options of the category * @param {import('./Option')[]} options - The options of the category
* @example * @example
* new Category() * new Category()
* .setId('setup') * .setId('setup')
* .setName("Setup") * .setName("Setup")
* .setDescription("Setup your bot with default settings!") * .setDescription("Setup your bot with default settings!")
* .addOptions( * .addOptions(
* new Option() * new Option()
* .setId('lang') * .setId('lang')
* .setName("Language") * .setName("Language")
* .setDescription("Change bot's language easily") * .setDescription("Change bot's language easily")
* .setType(dbd.formTypes.select({"Polish": 'pl', "English": 'en', "French": 'fr'})) * .setType(dbd.formTypes.select({"Polish": 'pl', "English": 'en', "French": 'fr'}))
* ) * )
*/ */
addOptions() { addOptions() {
this.categoryOptionsList.push(...arguments) this.categoryOptionsList.push(...arguments);
return this return this;
} }
} };
} };

View file

@ -1,95 +1,88 @@
const { formTypes } = require("discord-dashboard") const { formTypes } = require("../../ModuleExportsFunctions/formTypes");
const ids = [] const ids = [];
const err = (text) => {
return `🐧${text} Do you need help? Join our Discord server: ${
"https://discord.gg/CzfMGtrdaA".blue
}`
}
module.exports = (db) => { module.exports = (db) => {
return class Option { return class Option {
constructor( constructor(
options = { options = {
optionId: "", optionId: "",
optionName: "", optionName: "",
optionDescription: "", optionDescription: "",
optionType: formTypes, optionType: formTypes,
} },
) { ) {
// //
this.optionId = options.optionId this.optionId = options.optionId;
this.optionName = options.optionName this.optionName = options.optionName;
this.optionDescription = options.optionDescription this.optionDescription = options.optionDescription;
this.optionType = options.optionType this.optionType = options.optionType;
this.categoryId = "default" this.categoryId = "default";
this.setNew = async ({ guild, newData }) => { this.setNew = async ({ guild, newData }) => {
await db.set(`${guild.id}.options.${this.optionId}`, newData) await db.set(`${guild.id}.options.${this.optionId}`, newData);
} };
this.getActualSet = async ({ guild }) => { this.getActualSet = async ({ guild }) => {
return await db.get(`${guild.id}.options.${this.optionId}`) return await db.get(`${guild.id}.options.${this.optionId}`);
} };
} }
/** /**
* *
* @param {string} id - The id of the option, must be unique * @param {string} id - The id of the option, must be unique
* @returns * @returns
*/ */
setId(id) { setId(id) {
this.optionId = id this.optionId = id;
if (ids.includes(id)) if (ids.includes(id)) throw new Error(`Option id ${id} already exists`);
throw new Error(err(`Option id ${id} already exists`)) else ids.push(this.optionId);
else ids.push(this.optionId)
return this return this;
} }
/** /**
* *
* @param {string} name - The name of the option displayed in the dashboard * @param {string} name - The name of the option displayed in the dashboard
* @returns * @returns
*/ */
setName(name) { setName(name) {
this.optionName = name this.optionName = name;
return this return this;
} }
/** /**
* *
* @param {string} description - The description of the option displayed in the dashboard * @param {string} description - The description of the option displayed in the dashboard
* @returns * @returns
*/ */
setDescription(description) { setDescription(description) {
this.optionDescription = description this.optionDescription = description;
return this return this;
} }
/** /**
* *
* @param {object} options - Set custom options for the formType * @param {object} options - Set custom options for the formType
* @returns * @returns
*/ */
setOptions(options) { setOptions(options) {
this.themeOptions = options this.themeOptions = options;
} }
/** /**
* *
* @param {formTypes} type - The type of the option * @param {formTypes} type - The type of the option
* @returns * @returns
*/ */
setType(type) { setType(type) {
this.optionType = type this.optionType = type;
return this return this;
} }
} };
} };

View file

@ -1,109 +1,51 @@
const https = require("https") const https = require("https");
const http = require("http") const http = require("http");
const { Server: SocketServer } = require("socket.io") const { Server: SocketServer } = require("socket.io");
const err = (text) => {
return (
text +
` Do you need help? Join our Discord server: ${
"https://discord.gg/CzfMGtrdaA".blue
}`
)
}
module.exports = (app, config, themeConfig, modules) => { module.exports = (app, config, themeConfig, modules) => {
if (config.noCreateServer) return { io: null, server: null } if (config.noCreateServer) return { io: null, server: null };
let server
if (!config.SSL) config.SSL = {} let server;
if (config.SSL.enabled) {
if (!config.SSL.key || !config.SSL.cert)
console.log(
err(
`${
"discord-dashboard issue:".red
} The SSL preference for Dashboard is selected (config.SSL.enabled), but config does not include key or cert (config.SSL.key, config.SSL.cert).`
)
)
let options = {
key: config.SSL.key || "",
cert: config.SSL.cert || "",
}
try {
const https = require("https")
server = https.createServer(options, app)
} catch (e) {
console.log(
err(
`${
"discord-dashboard issue:".red
} There's a problem while creating server, check if the port specified is already on use.`
)
)
}
} else {
const http = require("http")
server = http.createServer(app)
}
let pport = "" if (!config.SSL) config.SSL = {};
if (config.port !== 80 && config.port !== 443) { if (config.SSL.enabled) {
pport = `:${config.port}` if (!config.SSL.key || !config.SSL.cert) console.log(`${"discord-dashboard issue:".red} The SSL preference for Dashboard is selected (config.SSL.enabled), but config does not include key or cert (config.SSL.key, config.SSL.cert).`);
}
if (!config.minimizedConsoleLogs) { const options = {
console.log( key: config.SSL.key || "",
` cert: config.SSL.cert || "",
};
Discord Bot Dashboard
`.rainbow +
`
Thanks for using ${
"discord-dashboard".rainbow
} module! The server is up and running, so head over to the ${
`${(config.domain || "domain.com") + pport}`.blue
} website and start your fun.
Remember that there are ${ try {
"themes".rainbow server = https.createServer(options, app);
} available to make the Dashboard look better: ${ } catch (e) {
"https://dbd-docs.assistantscenter.com/#/?id=themes".blue console.log(`${"discord-dashboard issue:".red} There's a problem while creating server, check if the port specified is already on use.`);
} }
} else {
server = http.createServer(app);
}
If you need help with something or you don't understand something, please visit our ${ let pport = "";
"Discord Support Server".rainbow if (config.port != 80 && config.port != 443) pport = `:${config.port}`;
}: ${"https://discord.gg/CzfMGtrdaA".blue}
`
)
} else {
console.log(
`DBD Dashboard running on ${
`${(config.domain || "domain.com") + pport}`.blue
} !`
)
}
const SocketServer = require("socket.io").Server console.log(`DBD Dashboard running on ${`${(config.domain || "domain.com") + pport}`.blue} !`);
const io = new SocketServer(server, {
cors: {
origin: "*",
},
})
modules.forEach((module) => { const io = new SocketServer(server, {
module.server({ cors: {
io: io, origin: "*",
server: server, },
config: config, });
themeConfig: themeConfig,
})
})
server.listen(config.port) modules.forEach((module) => {
return { server, io } module.server({
} io: io,
server: server,
config: config,
themeConfig: themeConfig,
});
});
server.listen(config.port);
return { server, io };
};

View file

@ -1,23 +1,23 @@
module.exports = { module.exports = {
redirectToUrl: (endpoint, getDataFunction) => { redirectToUrl: (endpoint, getDataFunction) => {
return { return {
type: "redirect", type: "redirect",
endpoint: endpoint, endpoint: endpoint,
getEndpoint: getDataFunction, getEndpoint: getDataFunction,
} };
}, },
renderHtml: (endpoint, getDataFunction) => { renderHtml: (endpoint, getDataFunction) => {
return { return {
type: "html", type: "html",
endpoint: endpoint, endpoint: endpoint,
getHtml: getDataFunction, getHtml: getDataFunction,
} };
}, },
sendJson: (endpoint, getDataFunction) => { sendJson: (endpoint, getDataFunction) => {
return { return {
type: "json", type: "json",
endpoint: endpoint, endpoint: endpoint,
getJson: getDataFunction, getJson: getDataFunction,
} };
}, },
} };

View file

@ -1,43 +0,0 @@
module.exports = {
CREATE_INSTANT_INVITE: ["CREATE_INSTANT_INVITE", 0x1],
KICK_MEMBERS: ["KICK_MEMBERS", 0x2],
BAN_MEMBERS: ["BAN_MEMBERS", 0x4],
ADMINISTRATOR: ["ADMINISTRATOR", 0x8],
MANAGE_CHANNELS: ["MANAGE_CHANNELS", 0x10],
MANAGE_GUILD: ["MANAGE_GUILD", 0x20],
ADD_REACTIONS: ["ADD_REACTIONS", 0x40],
VIEW_AUDIT_LOG: ["VIEW_AUDIT_LOG", 0x80],
PRIORITY_SPEAKER: ["PRIORITY_SPEAKER", 0x100],
STREAM: ["STREAM", 0x200],
VIEW_CHANNEL: ["VIEW_CHANNEL", 0x400],
SEND_MESSAGES: ["SEND_MESSAGES", 0x800],
SEND_TTS_MESSAGES: ["SEND_TTS_MESSAGES", 0x1000],
MANAGE_MESSAGES: ["MANAGE_MESSAGES", 0x2000],
EMBED_LINKS: ["EMBED_LINKS", 0x4000],
ATTACH_FILES: ["ATTACH_FILES", 0x8000],
READ_MESSAGE_HISTORY: ["READ_MESSAGE_HISTORY", 0x10000],
MENTION_EVERYONE: ["MENTION_EVERYONE", 0x20000],
USE_EXTERNAL_EMOJIS: ["USE_EXTERNAL_EMOJIS", 0x40000],
VIEW_GUILD_INSIGHTS: ["VIEW_GUILD_INSIGHTS", 0x80000],
CONNECT: ["CONNECT", 0x100000],
SPEAK: ["SPEAK", 0x200000],
MUTE_MEMBERS: ["MUTE_MEMBERS", 0x400000],
DEAFEN_MEMBERS: ["DEAFEN_MEMBERS", 0x800000],
MOVE_MEMBERS: ["MOVE_MEMBERS", 0x1000000],
USE_VAD: ["USE_VAD", 0x2000000],
CHANGE_NICKNAME: ["CHANGE_NICKNAME", 0x4000000],
MANAGE_NICKNAMES: ["MANAGE_NICKNAMES", 0x8000000],
MANAGE_ROLES: ["MANAGE_ROLES", 0x10000000],
MANAGE_WEBHOOKS: ["MANAGE_WEBHOOKS", 0x20000000],
MANAGE_EMOJIS_AND_STICKERS: ["MANAGE_EMOJIS_AND_STICKERS", 0x40000000],
USE_APPLICATION_COMMANDS: ["USE_APPLICATION_COMMANDS", 0x80000000],
REQUEST_TO_SPEAK: ["REQUEST_TO_SPEAK", 0x100000000],
MANAGE_EVENTS: ["MANAGE_EVENTS", 0x200000000],
MANAGE_THREADS: ["MANAGE_THREADS", 0x400000000],
CREATE_PUBLIC_THREADS: ["CREATE_PUBLIC_THREADS", 0x800000000],
CREATE_PRIVATE_THREADS: ["CREATE_PRIVATE_THREADS", 0x1000000000],
USE_EXTERNAL_STICKERS: ["USE_EXTERNAL_STICKERS", 0x2000000000],
SEND_MESSAGES_IN_THREADS: ["SEND_MESSAGES_IN_THREADS", 0x4000000000],
START_EMBEDDED_ACTIVITIES: ["START_EMBEDDED_ACTIVITIES", 0x8000000000],
MODERATE_MEMBERS: ["MODERATE_MEMBERS", 0x10000000000],
}

View file

@ -1,346 +1,294 @@
const discordPermissions = require("./discordPermissions") const { Permissions } = require("discord.js");
module.exports = { module.exports = {
select: (list, disabled, themeOptions = {}) => { select: (list, disabled, themeOptions = {}) => {
if (!list) if (!list) throw new Error(console.log("List in the 'select' form type cannot be empty."));
throw new Error( if (typeof list != "object") throw new Error(console.log("List in the 'select' form type should be an JSON object."));
err("List in the 'select' form type cannot be empty.")
)
if (typeof list != "object")
throw new Error(
err("List in the 'select' form type should be an JSON object.")
)
let keys = Object.keys(list)
let values = Object.values(list)
return {
type: "select",
data: {
keys,
values,
},
disabled: disabled || false,
themeOptions,
}
},
multiSelect: (list, disabled, required, themeOptions = {}) => {
if (!list)
throw new Error(
err("List in the 'select' form type cannot be empty.")
)
if (typeof list != "object")
throw new Error(
err("List in the 'select' form type should be an JSON object.")
)
let keys = Object.keys(list)
let values = Object.values(list)
return {
type: "multiSelect",
data: {
keys,
values,
},
disabled: disabled || false,
required: required || false,
themeOptions,
}
},
input: (placeholder, min, max, disabled, required, themeOptions = {}) => {
if (min) {
if (isNaN(min))
throw new Error(
err("'min' in the 'input' form type should be an number.")
)
}
if (max) {
if (isNaN(max))
throw new Error(
err("'max' in the 'input' form type should be an number.")
)
}
if (min && max) {
if (min > max)
throw new Error(
err(
"'min' in the 'input' form type cannot be higher than 'max'."
)
)
}
return {
type: "input",
data: placeholder,
min: min || null,
max: max || null,
disabled: disabled || false,
required: required || false,
themeOptions,
}
},
textarea: (
placeholder,
min,
max,
disabled,
required,
themeOptions = {}
) => {
if (min) {
if (isNaN(min))
throw new Error(
err("'min' in the 'input' form type should be an number.")
)
}
if (max) {
if (isNaN(max))
throw new Error(
err("'max' in the 'input' form type should be an number.")
)
}
if (min && max) {
if (min > max)
throw new Error(
err(
"'min' in the 'input' form type cannot be higher than 'max'."
)
)
}
return {
type: "textarea",
data: placeholder,
min: min || null,
max: max || null,
disabled: disabled || false,
required: required || false,
themeOptions,
}
},
switch: (disabled, themeOptions = {}) => {
return {
type: "switch",
disabled: disabled,
themeOptions,
}
},
checkbox: (disabled, themeOptions = {}) => {
return {
type: "checkbox",
disabled: disabled,
themeOptions,
}
},
channelsSelect: (
disabled,
channelTypes = ["GUILD_TEXT"],
hideNSFW,
onlyNSFW,
hideNoAccess,
themeOptions = {}
) => {
return {
type: "channelsSelect",
function: (client, guildid, userid) => {
let listCount = {}
let list = {
"-": "",
}
const guild = client.guilds.cache.get(guildid)
const user = guild.members.cache.get(userid)
const bot = guild.members.cache.get(client.user.id)
client.guilds.cache
.get(guildid)
.channels.cache.forEach((channel) => {
if (!channelTypes.includes(channel.type)) return
if (hideNSFW && channel.nsfw) return
if (onlyNSFW && !channel.nsfw) return
if (hideNoAccess) {
if (!user.permissionsIn(channel).has('0x800') || !user.permissionsIn(channel).has('0x400')) return
if (!bot.permissionsIn(channel).has('0x800') || !bot.permissionsIn(channel).has('0x800')) return
}
listCount[channel.name]
? (listCount[channel.name] =
listCount[channel.name] + 1)
: (listCount[channel.name] = 1)
if (list[channel.name])
list[
`${channel.name} (${listCount[channel.name]})`
] = channel.id
else list[channel.name] = channel.id
})
let myObj = list const keys = Object.keys(list);
let keys = Object.keys(myObj), const values = Object.values(list);
i = null,
len = keys.length
keys.sort() return {
list = {} type: "select",
data: {
keys,
values,
},
disabled: disabled || false,
themeOptions,
};
},
multiSelect: (list, disabled, required, themeOptions = {}) => {
if (!list) throw new Error(console.log("List in the 'select' form type cannot be empty."));
if (typeof list != "object") throw new Error(console.log("List in the 'select' form type should be an JSON object."));
for (i = 0; i < len; i++) { const keys = Object.keys(list);
k = keys[i] const values = Object.values(list);
list[k] = myObj[k]
}
return { return {
values: Object.values(list), type: "multiSelect",
keys: Object.keys(list), data: {
} keys,
}, values,
disabled, },
themeOptions, disabled: disabled || false,
} required: required || false,
}, themeOptions,
channelsMultiSelect: ( };
disabled, },
required, input: (placeholder, min, max, disabled, required, themeOptions = {}) => {
channelTypes = ["GUILD_TEXT"], if (min && isNaN(min)) throw new Error(console.log("'min' in the 'input' form type should be an number."));
hideNSFW, if (max && isNaN(max)) throw new Error(console.log("'max' in the 'input' form type should be an number."));
onlyNSFW, if ((min && max) && (min > max)) throw new Error(console.log("'min' in the 'input' form type cannot be higher than 'max'."));
hideNoAccess,
themeOptions = {}
) => {
return {
type: "channelsMultiSelect",
function: (client, guildid, userid) => {
let listCount = {}
let list = {}
const guild = client.guilds.cache.get(guildid)
const user = guild.members.cache.get(userid)
const bot = guild.members.cache.get(client.user.id)
client.guilds.cache
.get(guildid)
.channels.cache.forEach((channel) => {
if (!channelTypes.includes(channel.type)) return
if (hideNSFW && channel.nsfw) return
if (onlyNSFW && !channel.nsfw) return
if (hideNoAccess) {
if (!user.permissionsIn(channel).has('0x800') || !user.permissionsIn(channel).has('0x400')) return
if (!bot.permissionsIn(channel).has('0x800') || !bot.permissionsIn(channel).has('0x800')) return
}
listCount[channel.name]
? (listCount[channel.name] =
listCount[channel.name] + 1)
: (listCount[channel.name] = 1)
if (list[channel.name])
list[
`${channel.name} (${listCount[channel.name]})`
] = channel.id
else list[channel.name] = channel.id
})
let myObj = list return {
let keys = Object.keys(myObj), type: "input",
i = null, data: placeholder,
len = keys.length min: min || null,
max: max || null,
disabled: disabled || false,
required: required || false,
themeOptions,
};
},
textarea: (placeholder, min, max, disabled, required, themeOptions = {}) => {
if (min && isNaN(min)) throw new Error(console.log("'min' in the 'input' form type should be an number."));
if (max && isNaN(max)) throw new Error(console.log("'max' in the 'input' form type should be an number."));
if ((min && max) && (min > max)) throw new Error(console.log("'min' in the 'input' form type cannot be higher than 'max'."));
keys.sort() return {
list = {} type: "textarea",
data: placeholder,
min: min || null,
max: max || null,
disabled: disabled || false,
required: required || false,
themeOptions,
};
},
switch: (disabled, themeOptions = {}) => {
return {
type: "switch",
disabled: disabled,
themeOptions,
};
},
checkbox: (disabled, themeOptions = {}) => {
return {
type: "checkbox",
disabled: disabled,
themeOptions,
};
},
channelsSelect: (disabled, channelTypes = ["GUILD_TEXT"], hideNSFW, onlyNSFW, hideNoAccess, themeOptions = {}) => {
return {
type: "channelsSelect",
function: (client, guildid, userid) => {
const listCount = {};
let list = {
"-": "",
};
for (i = 0; i < len; i++) { const guild = client.guilds.cache.get(guildid),
k = keys[i] user = guild.members.cache.get(userid),
list[k] = myObj[k] bot = guild.members.cache.get(client.user.id);
}
return { client.guilds.cache.get(guildid).channels.cache.forEach((channel) => {
values: Object.values(list), if (!channelTypes.includes(channel.type)) return;
keys: Object.keys(list), if (hideNSFW && channel.nsfw) return;
} if (onlyNSFW && !channel.nsfw) return;
}, if (hideNoAccess) {
disabled, if (!user.permissionsIn(channel).has(Permissions.FLAGS.SEND_MESSAGES) || !user.permissionsIn(channel).has(Permissions.FLAGS.VIEW_CHANNEL)) return;
required, if (!bot.permissionsIn(channel).has(Permissions.FLAGS.SEND_MESSAGES) || !bot.permissionsIn(channel).has(Permissions.FLAGS.SEND_MESSAGES)) return;
themeOptions, }
}
},
rolesMultiSelect: (disabled, required, includeBots, hideHigherRoles, themeOptions = {}) => {
return {
type: "rolesMultiSelect",
function: (client, guildid, userid) => {
let listCount = {}
const list = []
const guild = client.guilds.cache.get(guildid)
const user = guild.members.cache.get(userid)
const bot = guild.members.cache.get(client.user.id)
client.guilds.cache.get(guildid).roles.cache.forEach((role) => { listCount[channel.name] ? (listCount[channel.name] = listCount[channel.name] + 1) : (listCount[channel.name] = 1);
if (role.managed && !includeBots) return
if (role.id === guildid) return // @everyone role
if (hideHigherRoles) {
if (role.position >= user.roles.highest.position) return
if (role.position >= bot.roles.highest.position) return
}
listCount[role.name]
? (listCount[role.name] = listCount[role.name] + 1)
: (listCount[role.name] = 1)
if (listCount[role.name] > 1)
list.push({ key: `${role.name} (${listCount[role.name]})`, value: role.id, position: role.position })
else list.push({ key: role.name, value: role.id, position: role.position })
})
list.sort((a, b) => b.position - a.position) if (list[channel.name]) list[`${channel.name} (${listCount[channel.name]})`] = channel.id;
else list[channel.name] = channel.id;
});
const sortedList = {} const myObj = list;
list.forEach(({ key, value }) => (sortedList[key] = value)) let i = null;
const keys = Object.keys(myObj),
len = keys.length;
return { keys.sort();
values: Object.values(sortedList), list = {};
keys: Object.keys(sortedList),
}
},
disabled,
required,
themeOptions,
}
},
rolesSelect: (disabled, includeBots, hideHigherRoles, themeOptions = {}) => {
return {
type: "rolesSelect",
function: (client, guildid, userid) => {
let listCount = {}
const list = [{ key: '-', value: '' }]
const guild = client.guilds.cache.get(guildid)
const user = guild.members.cache.get(userid)
const bot = guild.members.cache.get(client.user.id)
client.guilds.cache.get(guildid).roles.cache.forEach((role) => {
if (role.managed && !includeBots) return
if (role.id === guildid) return // @everyone role
if (hideHigherRoles) {
if (role.position >= user.roles.highest.position) return
if (role.position >= bot.roles.highest.position) return
}
listCount[role.name]
? (listCount[role.name] = listCount[role.name] + 1)
: (listCount[role.name] = 1)
if (listCount[role.name] > 1)
list.push({ key: `${role.name} (${listCount[role.name]})`, value: role.id, position: role.position })
else list.push({ key: role.name, value: role.id, position: role.position })
})
list.sort((a, b) => b.position - a.position) for (i = 0; i < len; i++) {
const k = keys[i];
list[k] = myObj[k];
}
const sortedList = {} return {
list.forEach(({ key, value }) => (sortedList[key] = value)) values: Object.values(list),
keys: Object.keys(list),
};
},
disabled,
themeOptions,
};
},
channelsMultiSelect: (disabled, required, channelTypes = ["GUILD_TEXT"], hideNSFW, onlyNSFW, hideNoAccess, themeOptions = {}) => {
return {
type: "channelsMultiSelect",
function: (client, guildid, userid) => {
const listCount = {};
let list = {};
const guild = client.guilds.cache.get(guildid);
const user = guild.members.cache.get(userid);
const bot = guild.members.cache.get(client.user.id);
return { client.guilds.cache.get(guildid).channels.cache.forEach(channel => {
values: Object.values(sortedList), if (!channelTypes.includes(channel.type)) return;
keys: Object.keys(sortedList), if (hideNSFW && channel.nsfw) return;
} if (onlyNSFW && !channel.nsfw) return;
}, if (hideNoAccess) {
disabled, if (!user.permissionsIn(channel).has(Permissions.FLAGS.SEND_MESSAGES) || !user.permissionsIn(channel).has(Permissions.FLAGS.VIEW_CHANNEL)) return;
themeOptions, if (!bot.permissionsIn(channel).has(Permissions.FLAGS.SEND_MESSAGES) || !bot.permissionsIn(channel).has(Permissions.FLAGS.SEND_MESSAGES)) return;
} }
}, listCount[channel.name] ? (listCount[channel.name] = listCount[channel.name] + 1) : (listCount[channel.name] = 1);
colorSelect: (defaultState, disabled, themeOptions = {}) => {
return { if (list[channel.name]) list[`${channel.name} (${listCount[channel.name]})`] = channel.id;
type: "colorSelect", else list[channel.name] = channel.id;
data: defaultState, });
disabled,
themeOptions, const myObj = list;
} let i = null;
}, const keys = Object.keys(myObj),
embedBuilder: (defaultSettings, disabled, themeOptions = {}) => { len = keys.length;
return {
type: "embedBuilder", keys.sort();
data: defaultSettings, list = {};
disabled,
themeOptions, for (i = 0; i < len; i++) {
} const k = keys[i];
}, list[k] = myObj[k];
} }
return {
values: Object.values(list),
keys: Object.keys(list),
};
},
disabled,
required,
themeOptions,
};
},
rolesMultiSelect: (disabled, required, includeBots, hideHigherRoles, themeOptions = {}) => {
return {
type: "rolesMultiSelect",
function: (client, guildid, userid) => {
const listCount = {};
const list = [];
const guild = client.guilds.cache.get(guildid);
const user = guild.members.cache.get(userid);
const bot = guild.members.cache.get(client.user.id);
client.guilds.cache.get(guildid).roles.cache.forEach((role) => {
if (role.managed && !includeBots) return;
if (role.id === guildid) return; // @everyone role
if (hideHigherRoles) {
if (role.position >= user.roles.highest.position) return;
if (role.position >= bot.roles.highest.position) return;
}
listCount[role.name] ? (listCount[role.name] = listCount[role.name] + 1) : (listCount[role.name] = 1);
if (listCount[role.name] > 1)
list.push({
key: `${role.name} (${listCount[role.name]})`,
value: role.id,
position: role.position,
});
else list.push({
key: role.name,
value: role.id,
position: role.position,
});
});
list.sort((a, b) => b.position - a.position);
const sortedList = {};
list.forEach(({ key, value }) => (sortedList[key] = value));
return {
values: Object.values(sortedList),
keys: Object.keys(sortedList),
};
},
disabled,
required,
themeOptions,
};
},
rolesSelect: (disabled, includeBots, hideHigherRoles, themeOptions = {}) => {
return {
type: "rolesSelect",
function: (client, guildid, userid) => {
const listCount = {};
const list = [{
key: "-",
value: "",
}];
const guild = client.guilds.cache.get(guildid);
const user = guild.members.cache.get(userid);
const bot = guild.members.cache.get(client.user.id);
client.guilds.cache.get(guildid).roles.cache.forEach((role) => {
if (role.managed && !includeBots) return;
if (role.id === guildid) return; // @everyone role
if (hideHigherRoles) {
if (role.position >= user.roles.highest.position) return;
if (role.position >= bot.roles.highest.position) return;
}
listCount[role.name] ? (listCount[role.name] = listCount[role.name] + 1) : (listCount[role.name] = 1);
if (listCount[role.name] > 1)
list.push({
key: `${role.name} (${listCount[role.name]})`,
value: role.id,
position: role.position,
});
else list.push({
key: role.name,
value: role.id,
position: role.position,
});
});
list.sort((a, b) => b.position - a.position);
const sortedList = {};
list.forEach(({ key, value }) => (sortedList[key] = value));
return {
values: Object.values(sortedList),
keys: Object.keys(sortedList),
};
},
disabled,
themeOptions,
};
},
colorSelect: (defaultState, disabled, themeOptions = {}) => {
return {
type: "colorSelect",
data: defaultState,
disabled,
themeOptions,
};
},
embedBuilder: (defaultSettings, disabled, themeOptions = {}) => {
return {
type: "embedBuilder",
data: defaultSettings,
disabled,
themeOptions,
};
},
};

File diff suppressed because it is too large Load diff

View file

@ -1,416 +1,397 @@
const router = require("express").Router() const router = require("express").Router();
const fetch = require("node-fetch") const RL = require("express-rate-limit");
const safeStorage = require("assistants-safe-storage");
const DiscordOauth2 = require("discord-oauth2") const DiscordOauth2 = require("discord-oauth2");
const oauth = new DiscordOauth2() const oauth = new DiscordOauth2();
module.exports = (app, config, themeConfig) => { module.exports = (app, config, themeConfig) => {
const scopes = config.guildAfterAuthorization?.use const storage = new safeStorage(config.bot.config.token);
? ["identify", "guilds", "guilds.join"] const scopes = config.guildAfterAuthorization?.use ? ["identify", "guilds", "guilds.join"] : ["identify", "guilds"];
: ["identify", "guilds"]
const RL = require("express-rate-limit")
const RateLimits = config.rateLimits || {}
let RateFunctions = {}
const NoRL = (req, res, next) => next() const RateLimits = config.rateLimits || {};
const RateFunctions = {};
if (RateLimits.discordOAuth2) { const NoRL = (req, res, next) => next();
RateFunctions.discordOAuth2 = RL.rateLimit({
windowMs: RateLimits.discordOAuth2.windowMs,
max: RateLimits.discordOAuth2.max,
message: RateLimits.discordOAuth2.message,
store: RateLimits.discordOAuth2.store || new RL.MemoryStore(),
})
}
router.get("/", (req, res) => { if (RateLimits.discordOAuth2) {
const clientId = req.client.id RateFunctions.discordOAuth2 = RL.rateLimit({
const redirectUri = req.redirectUri windowMs: RateLimits.discordOAuth2.windowMs,
max: RateLimits.discordOAuth2.max,
message: RateLimits.discordOAuth2.message,
store: RateLimits.discordOAuth2.store || new RL.MemoryStore(),
});
}
let newPage = "/" router.get("/", (req, res) => {
if (themeConfig.landingPage?.enabled) newPage = "/dash" const clientId = req.client.id;
req.session.r = req.query.r || newPage const redirectUri = req.redirectUri;
const authorizeUrl = `https://discord.com/api/oauth2/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent( let newPage = "/";
redirectUri if (themeConfig.landingPage?.enabled) newPage = "/dash";
)}&response_type=code&scope=${scopes.join("%20")}`
res.redirect(authorizeUrl)
})
router.get("/status", async (req, res) => { req.session.r = req.query.r || newPage;
res.send(req.session?.discordAuthStatus)
})
router.get( const authorizeUrl = `https://discord.com/api/oauth2/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&scope=${scopes.join("%20")}`;
"/callback",
RateFunctions.discordOAuth2 ? RateFunctions.discordOAuth2 : NoRL,
async (req, res) => {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: null,
},
}
const clientId = req.client.id
const clientSecret = req.client.secret
const redirectUri = req.redirectUri
const accessCode = req.query.code res.redirect(authorizeUrl);
if (!accessCode) });
return res.redirect("/?error=NoAccessCodeReturnedFromDiscord")
res.redirect("/loading") router.get("/status", async (req, res) => {
res.send(req.session?.discordAuthStatus);
});
let OAuth2Response router.get("/callback", RateFunctions.discordOAuth2 ? RateFunctions.discordOAuth2 : NoRL, async (req, res) => {
let OAuth2UserResponse req.session.discordAuthStatus = {
let OAuth2GuildsResponse loading: true,
success: null,
state: {
error: null,
data: null,
},
};
/* const clientId = req.client.id;
Get Discord OAuth2 API Response with Access Code gained const clientSecret = req.client.secret;
*/ const redirectUri = req.redirectUri;
try {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Requesting token...",
},
}
req.session.save(function (err) {})
OAuth2Response = await oauth.tokenRequest({
clientId,
clientSecret,
code: accessCode, const accessCode = req.query.code;
scope: scopes.join(" "), if (!accessCode) return res.redirect("/?error=NoAccessCodeReturnedFromDiscord");
grantType: "authorization_code",
redirectUri, res.redirect("/loading");
})
} catch (err) {
req.config.reportError(
"Discord.js Route - OAuth2Response (line 86)",
err
)
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
}
req.session.save(function (err) {})
return
}
/* let OAuth2Response;
Get User from Discord OAuth2 API using gained access_token and update its values with tag and avatarURL let OAuth2UserResponse;
*/ let OAuth2GuildsResponse;
try { try {
req.session.discordAuthStatus = { req.session.discordAuthStatus = {
loading: true, loading: true,
success: null, success: null,
state: { state: {
error: null, error: null,
data: "Getting User...", data: "Requesting token...",
}, },
} };
req.session.save(function (err) {})
OAuth2UserResponse = await oauth.getUser(
OAuth2Response.access_token
)
} catch (err) {
req.config.reportError(
"Discord.js Route - OAuth2UserResponse (line 118)",
err
)
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
}
req.session.save(function (err) {})
return
}
OAuth2UserResponse.tag = `${OAuth2UserResponse.username}#${OAuth2UserResponse.discriminator}`
OAuth2UserResponse.avatarURL = OAuth2UserResponse.avatar
? `https://cdn.discordapp.com/avatars/${OAuth2UserResponse.id}/${OAuth2UserResponse.avatar}.png?size=1024`
: null
/* req.session.save(function () {});
Save user token in Assistants Secure Storage
*/
try { OAuth2Response = await oauth.tokenRequest({
req.AssistantsSecureStorage.SaveUser( clientId,
OAuth2UserResponse.id, clientSecret,
OAuth2Response.access_token
)
} catch (err) {
req.config.reportError(
"Discord.js Route - Assistants Secure Storage (line 141)",
err
)
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
}
req.session.save(function (err) {})
return
}
/* code: accessCode,
Save user in session scope: scopes.join(" "),
*/ grantType: "authorization_code",
req.session.user = OAuth2UserResponse redirectUri,
req.session.loggedInLastTime = true });
} catch (err) {
console.log("Discord.js Route - OAuth2Response (line 88)\n" + err);
/* req.session.discordAuthStatus = {
Register user to DBD Stats and emit userLoggedIn event loading: false,
*/ success: false,
state: {
error: err,
data: null,
},
};
try { req.session.save(function () {});
req.DBDEvents.emit("userLoggedIn", OAuth2UserResponse)
} catch (err) {
req.config.reportError("Discord.js Route - Register and DBDEvents emit userLoggedIn (line 170)", err)
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
}
req.session.save(function (err) {})
return
}
/* return;
Gain and update session with user guilds }
*/
try { /*
req.session.discordAuthStatus = { Get User from Discord OAuth2 API using gained access_token and update its values with tag and avatarURL
loading: true, */
success: null, try {
state: { req.session.discordAuthStatus = {
error: null, loading: true,
data: "Getting List of User Guilds...", success: null,
}, state: {
} error: null,
req.session.save(function (err) {}) data: "Getting User...",
OAuth2GuildsResponse = await oauth.getUserGuilds( },
OAuth2Response.access_token };
)
} catch (err) {
req.config.reportError(
"Discord.js Route - OAuth2GuildsResponse (line 201)",
err
)
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
}
req.session.save(function (err) {})
return
}
req.session.guilds = OAuth2GuildsResponse || []
/* req.session.save(function () {});
Loop and fetch each guild into bots cache
*/
if (!req.config.disableResolvingGuildCache) { OAuth2UserResponse = await oauth.getUser(OAuth2Response.access_token);
try { } catch (err) {
req.session.discordAuthStatus = { console.log("Discord.js Route - OAuth2UserResponse (line 122)\n" + err);
loading: true,
success: null,
state: {
error: null,
data: "Resolving guilds cache...",
},
}
req.session.save(function (err) {})
for (let g of OAuth2GuildsResponse) {
try {
await req.bot.guilds.fetch(g.id)
} catch (err) {}
}
} catch (err) {
req.config.reportError(
"Discord.js Route - OAuth2GuildsResponse Whole Loop (line 239)",
err
)
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
}
req.session.save(function (err) {})
return
}
}
/* req.session.discordAuthStatus = {
If joining specific guild after authorization is enabled, do it loading: false,
*/ success: false,
state: {
error: err,
data: null,
},
};
if (req.guildAfterAuthorization.use == true) { req.session.save(function () {});
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Authorizing user with guild...",
},
}
req.session.save(function (err) {})
try {
await oauth.addMember({
accessToken: OAuth2Response.access_token,
botToken: req.botToken,
guildId: req.guildAfterAuthorization.guildId,
userId: OAuth2UserResponse.id,
...(req.guildAfterAuthorization.options || {}), return;
/* }
options?: { OAuth2UserResponse.tag = `${OAuth2UserResponse.username}#${OAuth2UserResponse.discriminator}`;
nickname?: string, OAuth2UserResponse.avatarURL = OAuth2UserResponse.avatar ? `https://cdn.discordapp.com/avatars/${OAuth2UserResponse.id}/${OAuth2UserResponse.avatar}.png?size=1024` : null;
roles?: [string],
mute?: boolean,
deaf?: boolean,
}
*/
})
} catch (err) {
req.config.reportError(
"Discord.js Route - guildAfterAuthorization (line 287)",
err
)
}
}
req.session.discordAuthStatus = { /*
loading: false, Save user token in Assistants Secure Storage
success: true, */
state: { try {
error: null, storage.SaveUser(OAuth2UserResponse.id, OAuth2Response.access_token);
data: null, } catch (err) {
}, console.log("Discord.js Route - Assistants Secure Storage (line 147)\n" + err);
}
req.session.save(function (err) {})
return req.session.discordAuthStatus = {
} loading: false,
) success: false,
state: {
error: err,
data: null,
},
};
router.get("/logout", (req, res) => { req.session.save(function () {});
let r = req.query.r || "/"
req.session.destroy()
res.redirect(r)
})
router.get("/guilds/reload", async (req, res) => { return;
if (!req.session.user) return res.redirect("/discord") }
/* /*
Fetch user token Save user in session
*/ */
req.session.user = OAuth2UserResponse;
req.session.loggedInLastTime = true;
const access_token = req.AssistantsSecureStorage.GetUser( /*
req.session.user.id Register user to DBD Stats and emit userLoggedIn event
) */
if (!access_token) try {
return res.send({ req.DBDEvents.emit("userLoggedIn", OAuth2UserResponse);
error: true, } catch (err) {
message: "You don't have any access_token saved.", console.log("Discord.js Route - DBDStats register and DBDEvent emit userLoggedIn (line 173)\n" + err);
login_again_text: true,
})
/* req.session.discordAuthStatus = {
Gain and update session with user guilds loading: false,
*/ success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
let OAuth2GuildsResponse return;
}
try { /*
OAuth2GuildsResponse = await oauth.getUserGuilds(access_token) Gain and update session with user guilds
} catch (err) { */
req.config.reportError( try {
"Discord.js Route - OAuth2GuildsResponse for ReloadGuilds (line 335)", req.session.discordAuthStatus = {
err loading: true,
) success: null,
return res.send({ state: {
error: true, error: null,
message: data: "Getting List of User Guilds...",
"An error occured. Access_token is wrong or you're being rate limited.", },
login_again_text: true, };
})
}
req.session.guilds = OAuth2GuildsResponse || []
/* req.session.save(function () {});
Loop and fetch each guild into bots cache
*/
try { OAuth2GuildsResponse = await oauth.getUserGuilds(OAuth2Response.access_token);
const Promises = [] } catch (err) {
for (let g of OAuth2GuildsResponse) { req.config.reportError("Discord.js Route - OAuth2GuildsResponse (line 205)\n" + err);
Promises.push(
new Promise(async (resolve, reject) => {
try {
await req.bot.guilds.fetch(g.id)
} catch (err) {}
resolve(1)
})
)
try {
await Promises.all(Promises)
} catch (err) {}
}
} catch (err) {
req.config.reportError(
"Discord.js Route - OAuth2GuildsResponse Whole Loop for ReloadGuilds (line 363)",
err
)
return res.send({
error: true,
message:
"An error occured. Access_token is wrong or you're being rate limited.",
login_again_text: true,
})
}
/* req.session.discordAuthStatus = {
Success loading: false,
*/ success: false,
state: {
error: err,
data: null,
},
};
return res.send({ req.session.save(function () {});
error: false,
message: null,
login_again_text: false,
})
})
return router return;
} }
req.session.guilds = OAuth2GuildsResponse || [];
/*
Loop and fetch each guild into bots cache
*/
if (!req.config.disableResolvingGuildCache) {
try {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Resolving guilds cache...",
},
};
req.session.save(function () {});
for (const g of OAuth2GuildsResponse) {
try {
await req.bot.guilds.fetch(g.id);
} catch (e) { /* ... */ }
}
} catch (err) {
console.log("Discord.js Route - OAuth2GuildsResponse Whole Loop (line 244)" + err);
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
return;
}
}
/*
If joining specific guild after authorization is enabled, do it
*/
if (req.guildAfterAuthorization.use == true) {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Authorizing user with guild...",
},
};
req.session.save(function () {});
try {
await oauth.addMember({
accessToken: OAuth2Response.access_token,
botToken: req.botToken,
guildId: req.guildAfterAuthorization.guildId,
userId: OAuth2UserResponse.id,
...(req.guildAfterAuthorization.options || {}),
/*
options?: {
nickname?: string,
roles?: [string],
mute?: boolean,
deaf?: boolean,
}
*/
});
} catch (err) {
req.config.reportError("Discord.js Route - guildAfterAuthorization (line 295)" + err);
}
}
req.session.discordAuthStatus = {
loading: false,
success: true,
state: {
error: null,
data: null,
},
};
req.session.save(function () {});
return;
});
router.get("/logout", (req, res) => {
const r = req.query.r || "/";
req.session.destroy();
res.redirect(r);
});
router.get("/guilds/reload", async (req, res) => {
if (!req.session.user) return res.redirect("/discord");
/*
Fetch user token
*/
const access_token = storage.GetUser(req.session.user.id);
if (!access_token)
return res.send({
error: true,
message: "You don't have any access_token saved.",
login_again_text: true,
});
/*
Gain and update session with user guilds
*/
let OAuth2GuildsResponse;
try {
OAuth2GuildsResponse = await oauth.getUserGuilds(access_token);
} catch (err) {
req.config.reportError("Discord.js Route - OAuth2GuildsResponse for ReloadGuilds (line 342)" + err);
return res.send({
error: true,
message: "An error occured. Access_token is wrong or you're being rate limited.",
login_again_text: true,
});
}
req.session.guilds = OAuth2GuildsResponse || [];
/*
Loop and fetch each guild into bots cache
*/
try {
const Promises = [];
for (const g of OAuth2GuildsResponse) {
Promises.push(
// eslint-disable-next-line no-unused-vars, no-async-promise-executor
new Promise(async (resolve, reject) => {
try {
await req.bot.guilds.fetch(g.id);
} catch (e) { /* ... */ }
resolve(1);
}),
);
try {
await Promises.all(Promises);
} catch (e) { /* ... */ }
}
} catch (err) {
console.log("Discord.js Route - OAuth2GuildsResponse Whole Loop for ReloadGuilds (line 375)" + err);
return res.send({
error: true,
message: "An error occured. Access_token is wrong or you're being rate limited.",
login_again_text: true,
});
}
/*
Success
*/
return res.send({
error: false,
message: null,
login_again_text: false,
});
});
return router;
};

View file

@ -1,122 +1,91 @@
const Discord = require("discord.js") const router = require("express").Router();
const router = require("express").Router()
// eslint-disable-next-line no-unused-vars
module.exports = (app, config, themeConfig, modules) => { module.exports = (app, config, themeConfig, modules) => {
router.get( router.get(themeConfig.landingPage?.enabled ? "/dash" : "/", async (req, res) => {
themeConfig.landingPage?.enabled ? "/dash" : "/", let customThemeOptions;
async (req, res) => {
let customThemeOptions
if (themeConfig?.customThemeOptions?.index) {
customThemeOptions = await themeConfig.customThemeOptions.index(
{ req: req, res: res, config: config }
)
}
res.render("index", {
req: req,
themeConfig: req.themeConfig,
bot: config.bot,
customThemeOptions: customThemeOptions || {},
config,
require,
})
}
)
if (themeConfig.landingPage?.enabled) if (themeConfig?.customThemeOptions?.index) {
router.get("/", async (req, res) => { customThemeOptions = await themeConfig.customThemeOptions.index({
res.setHeader("Content-Type", "text/html") req: req,
res.send(await themeConfig.landingPage.getLandingPage(req, res)) res: res,
}) config: config,
});
}
router.get("/loading", async (req, res) => { res.render("index", {
if (!req.session?.discordAuthStatus?.loading) req: req,
return res.redirect("/manage") themeConfig: req.themeConfig,
bot: config.bot,
customThemeOptions: customThemeOptions || {},
config,
require,
});
});
res.render("loading", { req, themeConfig, bot: config.bot }) if (themeConfig.landingPage?.enabled)
}) router.get("/", async (req, res) => {
res.setHeader("Content-Type", "text/html");
res.send(await themeConfig.landingPage.getLandingPage(req, res));
});
router.get("/invite", (req, res) => { router.get("/loading", async (req, res) => {
let config = req.config if (!req.session?.discordAuthStatus?.loading)
config.invite ? null : (config.invite = {}) return res.redirect("/manage");
const scopes = config.invite.scopes || ["bot"]
if (req.query.redirect && !req.query.g) res.render("loading", {
return res.redirect( req,
`https://discord.com/oauth2/authorize?client_id=${ themeConfig,
config.invite.clientId || config.bot.user.id bot: config.bot,
}&scope=${scopes.join("%20")}&permissions=${ });
config.invite.permissions || "0" });
}&response_type=code&redirect_uri=${req.query.redirect}${
config.invite.otherParams || ""
}`
)
if (req.query.redirect && req.query.g)
return res.redirect(
`https://discord.com/oauth2/authorize?client_id=${
config.invite.clientId || config.bot.user.id
}&scope=${scopes.join("%20")}&permissions=${
config.invite.permissions || "0"
}&response_type=code&redirect_uri=${
req.query.redirect
}&guild_id=${req.query.g}${config.invite.otherParams || ""}`
)
if (req.query.g) { router.get("/invite", (req, res) => {
let thingymabob = config.invite.redirectUri const config = req.config;
? `&response_type=code&redirect_uri=${config.invite.redirectUri}` config.invite ? null : (config.invite = {});
: null;
if(!thingymabob) thingymabob = config.invite.specialredirectUri
? `&response_type=code&redirect_uri=${config.invite.specialRedirectUri.replace("{SERVER}", req.query.g)}`
: "";
return res.redirect( const scopes = config.invite.scopes || ["bot"];
`https://discord.com/oauth2/authorize?client_id=${
config.invite.clientId || config.bot.user.id
}&scope=${scopes.join("%20")}&permissions=${
config.invite.permissions || "0"
}${thingymabob}&guild_id=${req.query.g}${config.invite.otherParams || ""}`
)
}
res.redirect( if (req.query.redirect && !req.query.g)
`https://discord.com/oauth2/authorize?client_id=${ return res.redirect(`https://discord.com/oauth2/authorize?client_id=${config.invite.clientId || config.bot.user.id}&scope=${scopes.join("%20")}&permissions=${config.invite.permissions || "0"}&response_type=code&redirect_uri=${req.query.redirect}${config.invite.otherParams || ""}`);
config.invite.clientId || config.bot.user.id if (req.query.redirect && req.query.g)
}&scope=${scopes.join("%20")}&permissions=${ return res.redirect(`https://discord.com/oauth2/authorize?client_id=${config.invite.clientId || config.bot.user.id}&scope=${scopes.join("%20")}&permissions=${config.invite.permissions || "0"}&response_type=code&redirect_uri=${req.query.redirect}&guild_id=${req.query.g}${config.invite.otherParams || ""}`);
config.invite.permissions || "0"
}${
config.invite.redirectUri
? `&response_type=code&redirect_uri=${config.invite.redirectUri}`
: ""
}${config.invite.otherParams || ""}`
)
})
if (!config.supportServer) config.supportServer = {} if (req.query.g) {
let thingymabob = config.invite.redirectUri ? `&response_type=code&redirect_uri=${config.invite.redirectUri}` : null;
if (!thingymabob) thingymabob = config.invite.specialredirectUri ? `&response_type=code&redirect_uri=${config.invite.specialRedirectUri.replace("{SERVER}", req.query.g)}` : "";
router.get(config.supportServer.slash || "/support-server", (req, res) => { return res.redirect(`https://discord.com/oauth2/authorize?client_id=${config.invite.clientId || config.bot.user.id}&scope=${scopes.join("%20")}&permissions=${config.invite.permissions || "0"}${thingymabob}&guild_id=${req.query.g}${config.invite.otherParams || ""}`);
let config = req.config }
config.supportServer ? null : (config.supportServer = {})
if (!config.supportServer.inviteUrl)
return res.send({
error: true,
message:
"No inviteUrl defined (discord-dashboard config.supportServer).",
})
if (
!config.supportServer.inviteUrl
.toLowerCase()
.startsWith("https://discord.gg/") &&
!config.supportServer.inviteUrl
.toLowerCase()
.startsWith("https://discord.com/")
)
return res.send({
error: true,
message:
"Invite url should start with 'https://discord.gg/' or 'https://discord.com/'.",
})
res.redirect(config.supportServer.inviteUrl)
})
return router res.redirect(`https://discord.com/oauth2/authorize?client_id=${config.invite.clientId || config.bot.user.id}&scope=${scopes.join("%20")}&permissions=${config.invite.permissions || "0"}${config.invite.redirectUri ? `&response_type=code&redirect_uri=${config.invite.redirectUri}` : ""}${config.invite.otherParams || ""}`);
} });
if (!config.supportServer) config.supportServer = {};
router.get(config.supportServer.slash || "/support-server", (req, res) => {
const config = req.config;
config.supportServer ? null : (config.supportServer = {});
if (!config.supportServer.inviteUrl)
return res.send({
error: true,
message: "No inviteUrl defined (discord-dashboard config.supportServer).",
});
if (!config.supportServer.inviteUrl
.toLowerCase()
.startsWith("https://discord.gg/") &&
!config.supportServer.inviteUrl
.toLowerCase()
.startsWith("https://discord.com/")
) return res.send({
error: true,
message: "Invite url should start with 'https://discord.gg/' or 'https://discord.com/'.",
});
res.redirect(config.supportServer.inviteUrl);
});
return router;
};

View file

@ -1,47 +1,52 @@
const EventEmitter = require('events'); const EventEmitter = require("events"),
const DBDEvents = new EventEmitter(); express = require("express"),
const version = require("./package.json").version; app = express(),
session = require("express-session"),
bodyParser = require("body-parser"),
partials = require("express-partials"),
router = require("./router"),
initServer = require("./InitFunctions/initServer");
const err = (text) => { const version = require("./package.json").version;
return text + ` Do you need help? Join our Discord server: ${'https://discord.gg/CzfMGtrdaA'.blue}`; const DBDEvents = new EventEmitter();
}
class Dashboard { class Dashboard {
constructor(config) { constructor(config) {
let notSetYetAndRequired = []; const notSetYetAndRequired = [];
if (!config.port) notSetYetAndRequired.push('port');
if (!config.theme) notSetYetAndRequired.push('theme'); if (!config.port) notSetYetAndRequired.push("port");
if (!config.client) notSetYetAndRequired.push('client'); if (!config.theme) notSetYetAndRequired.push("theme");
if (!config.redirectUri) notSetYetAndRequired.push('redirectUri'); if (!config.client) notSetYetAndRequired.push("client");
if (!config.bot) notSetYetAndRequired.push('bot'); if (!config.redirectUri) notSetYetAndRequired.push("redirectUri");
if (!config.settings) notSetYetAndRequired.push('settings'); if (!config.bot) notSetYetAndRequired.push("bot");
if (!config.domain) notSetYetAndRequired.push('domain'); if (!config.settings) notSetYetAndRequired.push("settings");
if (notSetYetAndRequired[0]) throw new Error(err(`You need to define some more things: ${notSetYetAndRequired.join(', ')}.`)); if (!config.domain) notSetYetAndRequired.push("domain");
if (notSetYetAndRequired[0]) throw new Error(`You need to define some more things: ${notSetYetAndRequired.join(", ")}.`);
this.config = config; this.config = config;
this.modules = []; this.modules = [];
} }
async init() { async init() {
const modules = this.modules; const config = this.config,
const config = this.config; modules = this.modules;
const express = require('express');
const app = express();
const session = require('express-session');
const bodyParser = require('body-parser');
const partials = require('express-partials');
const v13support = require('discord.js').version.slice(0, 2) == "13";
app.use(bodyParser.urlencoded({ app.use(bodyParser.urlencoded({ extended: true }));
extended: true
}));
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(partials()); app.use(partials());
app.set('views', config.theme.viewsPath);
app.use(express.static(config.theme.staticPath));app.use('/', express.static(config.theme.staticPath));app.use('/:a/', express.static(config.theme.staticPath));app.use('/:a/:b/', express.static(config.theme.staticPath));app.use('/:a/:b/:c/', express.static(config.theme.staticPath));app.use('/:a/:b/:c/:d/', express.static(config.theme.staticPath));
app.set('view engine', 'ejs');
let sessionData = { app.use(express.static(config.theme.staticPath));
secret: config.cookiesSecret || 'total_secret_cookie_secret', app.use("/", express.static(config.theme.staticPath));
app.use("/:a/", express.static(config.theme.staticPath));
app.use("/:a/:b/", express.static(config.theme.staticPath));
app.use("/:a/:b/:c/", express.static(config.theme.staticPath));
app.use("/:a/:b/:c/:d/", express.static(config.theme.staticPath));
app.set("views", config.theme.viewsPath);
app.set("view engine", "ejs");
const sessionData = {
secret: config.cookiesSecret || "total_secret_cookie_secret",
resave: true, resave: true,
saveUninitialized: true, saveUninitialized: true,
cookie: { cookie: {
@ -49,13 +54,14 @@ class Dashboard {
maxAge: 253402300799999, maxAge: 253402300799999,
}, },
}; };
config.sessionSaveSession ? sessionData.store = config.sessionSaveSession : null; config.sessionSaveSession ? sessionData.store = config.sessionSaveSession : null;
app.use(session(sessionData)); app.use(session(sessionData));
let themeConfig = config.theme.themeConfig; const themeConfig = config.theme.themeConfig;
app.get('*', (req,res,next) => { app.get("*", (req, res, next) => {
DBDEvents.emit('websiteView', req.session.user ? req.session.user : {loggedIn: false}); DBDEvents.emit("websiteView", req.session.user ? req.session.user : { loggedIn: false });
next(); next();
}); });
@ -63,7 +69,7 @@ class Dashboard {
app.use((req, res, next) => { app.use((req, res, next) => {
req.DBDEvents = DBDEvents; req.DBDEvents = DBDEvents;
if(req.session.loggedInLastTime == true){ if (req.session.loggedInLastTime == true) {
req.displayLoggedInInfo = true; req.displayLoggedInInfo = true;
req.session.loggedInLastTime = false; req.session.loggedInLastTime = false;
} }
@ -77,18 +83,20 @@ class Dashboard {
req.botToken = config.bot.token; req.botToken = config.bot.token;
req.guildAfterAuthorization = config.guildAfterAuthorization || {}; req.guildAfterAuthorization = config.guildAfterAuthorization || {};
req.websiteTitle = config.websiteTitle || "Discord Web Dashboard"; req.websiteTitle = config.websiteTitle || "Discord Bot Dashboard";
req.iconUrl = config.iconUrl || 'https://www.nomadfoods.com/wp-content/uploads/2018/08/placeholder-1-e1533569576673.png'; req.iconUrl = config.iconUrl || "https://www.nomadfoods.com/wp-content/uploads/2018/08/placeholder-1-e1533569576673.png";
req.app = app; req.app = app;
req.config = config; req.config = config;
next(); next();
}); });
require('./router')(app, config, themeConfig, modules); router(app, config, themeConfig, modules);
this.app = app; this.app = app;
let sio = require('./InitFunctions/initServer')(app, config, themeConfig, modules);
const sio = initServer(app, config, themeConfig, modules);
this.server = sio.server; this.server = sio.server;
this.io = sio.io; this.io = sio.io;
} }
@ -104,8 +112,8 @@ class Dashboard {
module.exports = { module.exports = {
Dashboard, Dashboard,
formTypes: require('./ModuleExportsFunctions/formTypes'), formTypes: require("./ModuleExportsFunctions/formTypes"),
customPagesTypes: require('./ModuleExportsFunctions/customPagesTypes'), customPagesTypes: require("./ModuleExportsFunctions/customPagesTypes"),
DBDEvents, DBDEvents,
version version,
} };

View file

@ -1,19 +1,14 @@
{ {
"name": "discord-dashboard", "name": "discord-dashboard",
"version": "2.3.61", "version": "1.0",
"description": "Create an Dashboard for your bot in 10 minutes without APIs knowledge and slapping code from scratch!", "description": "dashboard",
"main": "index.js", "main": "index.js",
"directories": {
"test": "test"
},
"typings": ".d.ts", "typings": ".d.ts",
"dependencies": { "dependencies": {
"assistants-safe-storage": "^1.0.0", "assistants-safe-storage": "^1.0.0",
"body-parser": "^1.20.0", "body-parser": "^1.20.0",
"colors": "^1.4.0", "colors": "^1.4.0",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"discord-dashboard": "^2.3.39",
"discord-dashboard-pp-system": "^1.0.2",
"discord-oauth2": "^2.10.0", "discord-oauth2": "^2.10.0",
"discord.js": "*", "discord.js": "*",
"ejs": "^3.1.8", "ejs": "^3.1.8",
@ -24,32 +19,103 @@
"https": "^1.0.0", "https": "^1.0.0",
"keyv": "^4.5.2", "keyv": "^4.5.2",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.7",
"readline-sync": "^1.4.10", "quick.db": "^7.1.3",
"socket.io": "^4.5.1", "socket.io": "^4.5.1"
"uuid": "^8.3.2"
}, },
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"author": "breftejk",
"license": "CC BY-NC-SA 4.0",
"homepage": "https://dbd-docs.assistantscenter.com/",
"keywords": [
"discord",
"discord.js",
"discordjs",
"discord dashboard",
"discord web dashboard",
"web dashboard",
"dashboard"
],
"repository": {
"type": "git",
"url": "https://github.com/Assistants-Center/Discord.js-Web-Dashboard.git"
},
"devDependencies": { "devDependencies": {
"dbd-dark-dashboard": "^1.6.58", "dbd-dark-dashboard": "^1.6.58",
"eslint": "^8.23.0",
"javascript-obfuscator": "^4.0.0", "javascript-obfuscator": "^4.0.0",
"prettier": "2.7.1" "prettier": "2.7.1"
},
"eslintConfig": {
"env": {
"commonjs": true,
"es6": true,
"es2020": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {
"arrow-spacing": [
"warn",
{
"before": true,
"after": true
}
],
"comma-dangle": [
"error",
"always-multiline"
],
"comma-spacing": "error",
"comma-style": "error",
"dot-location": [
"error",
"property"
],
"handle-callback-err": "off",
"indent": [
"error",
"tab",
{
"SwitchCase": 1
}
],
"keyword-spacing": "error",
"max-nested-callbacks": [
"error",
{
"max": 4
}
],
"max-statements-per-line": [
"error",
{
"max": 2
}
],
"no-console": "off",
"no-multi-spaces": "error",
"no-multiple-empty-lines": [
"error",
{
"max": 2,
"maxEOF": 1,
"maxBOF": 0
}
],
"no-trailing-spaces": [
"error"
],
"no-var": "error",
"object-curly-spacing": [
"error",
"always"
],
"prefer-const": "error",
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
],
"space-in-parens": "error",
"space-infix-ops": "error",
"space-unary-ops": "error",
"yoda": "error"
}
} }
} }

282
router.js
View file

@ -1,173 +1,137 @@
const cookieParser = require("cookie-parser"),
underMaintenancePageDefault = require("./underMaintenancePageDefault"),
error404pageDefault = require("./404pagedefault");
const mainRouter = require("./Routes/main"),
dashboardRouter = require("./Routes/dashboard"),
discordRouter = require("./Routes/discord");
module.exports = (app, config, themeConfig, modules) => { module.exports = (app, config, themeConfig, modules) => {
app.use(require("cookie-parser")()) app.use(cookieParser());
app.use((req, res, next) => { app.use((req, res, next) => {
req.bot = config.bot req.bot = config.bot;
next() next();
}) });
if (themeConfig.defaultLocales) { if (themeConfig.defaultLocales) {
app.use((req, res, next) => { app.use((req, res, next) => {
if (req.cookies?.lang) req.lang = req.cookies.lang if (req.cookies?.lang) req.lang = req.cookies.lang;
else req.lang = req.acceptsLanguages()[0].replace("-", "") else req.lang = req.acceptsLanguages()[0].replace("-", "");
if (themeConfig.locales) { if (themeConfig.locales) {
if (Object.keys(themeConfig.locales).includes(req.lang)) { if (Object.keys(themeConfig.locales).includes(req.lang)) req.locales = themeConfig.locales[req.lang];
req.locales = themeConfig.locales[req.lang] else req.locales = themeConfig.locales[Object.keys(themeConfig.locales)[0]];
} else { } else
req.locales = req.locales = themeConfig.defaultLocales[Object.keys(themeConfig.defaultLocales).includes(req.lang) ? req.lang : "enUS"];
themeConfig.locales[Object.keys(themeConfig.locales)[0]]
}
} else {
req.locales =
themeConfig.defaultLocales[
Object.keys(themeConfig.defaultLocales).includes(
req.lang
)
? req.lang
: "enUS"
]
}
next() next();
}) });
} }
app.use( app.use("/discord", discordRouter(app, config, themeConfig, modules));
"/discord",
require("./Routes/discord")(app, config, themeConfig, modules)
)
if (config.useUnderMaintenance) { if (config.useUnderMaintenance) {
app.get( app.get(config.underMaintenanceAccessPage || "/total-secret-get-access", (req, res) => {
config.underMaintenanceAccessPage || "/total-secret-get-access", res.send(`
(req, res) => { <form action="${config.domain}${config.underMaintenanceAccessPage || "/total-secret-get-access"}" method="POST" >
res.send(` <input id="accessKey" name="accessKey"/>
<form action="${config.domain}${ <button role="submit">Submit</button>
config.underMaintenanceAccessPage || </form>
"/total-secret-get-access" `);
}" method="POST" > });
<input id="accessKey" name="accessKey"/>
<button role="submit">Submit</button>
</form>
`)
}
)
app.post( app.post(config.underMaintenanceAccessPage || "/total-secret-get-access", (req, res) => {
config.underMaintenanceAccessPage || "/total-secret-get-access", if (!req.body) req.body = {};
(req, res) => {
if (!req.body) req.body = {}
const accessKey = req.body.accessKey
if (accessKey != config.underMaintenanceAccessKey)
return res.send("Wrong key.")
req.session.umaccess = true
res.redirect("/")
}
)
app.use((req, res, next) => { const accessKey = req.body.accessKey;
if (req.originalUrl.startsWith("/loading")) return next()
if (!req.session.umaccess && !req.session.user) {
if (!config.useThemeMaintenance)
return res.send(
config.underMaintenanceCustomHtml ||
require("./underMaintenancePageDefault")(
config.underMaintenance,
false
)
)
else
res.render("maintenance", {
req: req,
bot: config.bot,
themeConfig: req.themeConfig,
loggedIn: false,
defaultMaintenanceConfig: config.underMaintenance || {},
})
} else if (
!req.session.umaccess &&
config.ownerIDs &&
!config.ownerIDs.includes(req.session.user.id)
) {
if (!config.useThemeMaintenance)
return res.send(
config.underMaintenanceCustomHtml ||
require("./underMaintenancePageDefault")(
config.underMaintenance,
true
)
)
else
res.render("maintenance", {
req: req,
bot: config.bot,
themeConfig: req.themeConfig,
loggedIn: true,
defaultMaintenanceConfig: config.underMaintenance || {},
})
} else next()
})
}
app.use("/", require("./Routes/main")(app, config, themeConfig, modules)) if (accessKey != config.underMaintenanceAccessKey) return res.send("Wrong key.");
app.use(
"/",
require("./Routes/dashboard")(app, config, themeConfig, modules)
)
config.theme.init(app, config) req.session.umaccess = true;
res.redirect("/");
});
let customPages = config.customPages || [] app.use((req, res, next) => {
customPages.forEach((p) => { if (req.originalUrl.startsWith("/loading")) return next();
if (p.type == "redirect") {
app.get(p.endpoint, async (req, res) => {
let endpoint = await p.getEndpoint({
user: req.session.user || {},
req,
})
res.redirect(endpoint)
})
} else if (p.type == "html") {
app.get(p.endpoint, async (req, res) => {
let html = await p.getHtml({
user: req.session.user || {},
req,
})
res.send(html)
})
} else if (p.type == "json") {
app.get(p.endpoint, async (req, res) => {
let json = await p.getJson({
user: req.session.user || {},
req,
})
res.send(json)
})
}
})
modules.forEach((module) => { if (!req.session.umaccess && !req.session.user) {
module.app({ if (!config.useThemeMaintenance)
app: app, return res.send(config.underMaintenanceCustomHtml || underMaintenancePageDefault(config.underMaintenance, false));
config: this.config, else
themeConfig: themeConfig, res.render("maintenance", {
}) req: req,
}) bot: config.bot,
themeConfig: req.themeConfig,
loggedIn: false,
defaultMaintenanceConfig: config.underMaintenance || {},
});
} else if (!req.session.umaccess && config.ownerIDs && !config.ownerIDs.includes(req.session.user.id)) {
if (!config.useThemeMaintenance)
return res.send(config.underMaintenanceCustomHtml || underMaintenancePageDefault(config.underMaintenance, true));
else
res.render("maintenance", {
req: req,
bot: config.bot,
themeConfig: req.themeConfig,
loggedIn: true,
defaultMaintenanceConfig: config.underMaintenance || {},
});
} else next();
});
}
if (!config.useTheme404) { app.use("/", mainRouter(app, config, themeConfig, modules));
app.get("*", (req, res) => { app.use("/", dashboardRouter(app, config, themeConfig, modules));
let text =
config.html404 || config.theme.init(app, config);
require("./404pagedefault")(
config.websiteTitle || themeConfig.websiteName const customPages = config.customPages || [];
)
res.send( customPages.forEach(p => {
text.replace( if (p.type == "redirect") {
"{{websiteTitle}}", app.get(p.endpoint, async (req, res) => {
config.websiteTitle || themeConfig.websiteName const endpoint = await p.getEndpoint({
) user: req.session.user || {},
) req,
}) });
}
} res.redirect(endpoint);
});
} else if (p.type == "html") {
app.get(p.endpoint, async (req, res) => {
const html = await p.getHtml({
user: req.session.user || {},
req,
});
res.send(html);
});
} else if (p.type == "json") {
app.get(p.endpoint, async (req, res) => {
const json = await p.getJson({
user: req.session.user || {},
req,
});
res.send(json);
});
}
});
modules.forEach(module => {
module.app({
app: app,
config: this.config,
themeConfig: themeConfig,
});
});
if (!config.useTheme404) {
app.get("*", (req, res) => {
const text = config.html404 || error404pageDefault(config.websiteTitle || themeConfig.websiteName);
res.send(text.replace("{{websiteTitle}}", config.websiteTitle || themeConfig.websiteName));
});
}
};

File diff suppressed because it is too large Load diff

View file

@ -1,288 +1,289 @@
const icons = [ const icons = [
'address-book', "address-book",
'address-card', "address-card",
'adjust', "adjust",
'air-freshener', "air-freshener",
'align-center', "align-center",
'align-left', "align-left",
'align-right', "align-right",
'ambulance', "ambulance",
'angle-double-down', "angle-double-down",
'angle-double-left', "angle-double-left",
'angle-double-right', "angle-double-right",
'angle-double-up', "angle-double-up",
'angle-down', "angle-down",
'angle-left', "angle-left",
'angle-right', "angle-right",
'angle-up', "angle-up",
'archive', "archive",
'arrow-alt-circle-down', "arrow-alt-circle-down",
'arrow-alt-circle-left', "arrow-alt-circle-left",
'arrow-alt-circle-right', "arrow-alt-circle-right",
'arrow-alt-circle-up', "arrow-alt-circle-up",
'arrow-down', "arrow-down",
'arrow-left', "arrow-left",
'arrow-right', "arrow-right",
'arrow-up', "arrow-up",
'arrows-alt', "arrows-alt",
'arrows-alt-h', "arrows-alt-h",
'arrows-alt-v', "arrows-alt-v",
'assistive-listening-systems', "assistive-listening-systems",
'asterisk', "asterisk",
'at', "at",
'atlas', "atlas",
'award', "award",
'backspace', "backspace",
'backward', "backward",
'bahai', "bahai",
'ban', "ban",
'band-aid', "band-aid",
'bars', "bars",
'battery-empty', "battery-empty",
'battery-full', "battery-full",
'battery-half', "battery-half",
'battery-quarter', "battery-quarter",
'battery-three-quarters', "battery-three-quarters",
'bed', "bed",
'beer', "beer",
'bell', "bell",
'bell-slash', "bell-slash",
'birthday-cake', "birthday-cake",
'bolt', "bolt",
'bomb', "bomb",
'bone', "bone",
'book', "book",
'book-dead', "book-dead",
'book-medical', "book-medical",
'book-open', "book-open",
'bookmark', "bookmark",
'border-all', "border-all",
'border-none', "border-none",
'border-style', "border-style",
'bowling-ball', "bowling-ball",
'box', "box",
'box-open', "box-open",
'briefcase', "briefcase",
'broadcast-tower', "broadcast-tower",
'bug', "bug",
'building', "building",
'bullhorn', "bullhorn",
'calculator', "calculator",
'calendar', "calendar",
'calendar-alt', "calendar-alt",
'calendar-check', "calendar-check",
'calendar-day', "calendar-day",
'calendar-minus', "calendar-minus",
'calendar-plus', "calendar-plus",
'calendar-times', "calendar-times",
'calendar-week', "calendar-week",
'camera', "camera",
'caret-down', "caret-down",
'caret-left', "caret-left",
'caret-right', "caret-right",
'caret-up', "caret-up",
'certificate', "certificate",
'chair', "chair",
'chalkboard', "chalkboard",
'charging-station', "charging-station",
'chart-bar', "chart-bar",
'chart-line', "chart-line",
'chart-pie', "chart-pie",
'check', "check",
'check-circle', "check-circle",
'check-square', "check-square",
'circle', "circle",
'circle-notch', "circle-notch",
'clipboard', "clipboard",
'clock', "clock",
'clone', "clone",
'cloud', "cloud",
'cloud-download-alt', "cloud-download-alt",
'cloud-meatball', "cloud-meatball",
'cloud-moon', "cloud-moon",
'cloud-moon-rain', "cloud-moon-rain",
'cloud-rain', "cloud-rain",
'cloud-showers-heavy', "cloud-showers-heavy",
'cloud-sun', "cloud-sun",
'cloud-sun-rain', "cloud-sun-rain",
'cloud-upload-alt', "cloud-upload-alt",
'code', "code",
'code-branch', "code-branch",
'cog', "cog",
'cogs', "cogs",
'columns', "columns",
'comment', "comment",
'comment-alt', "comment-alt",
'comment-dollar', "comment-dollar",
'comment-dots', "comment-dots",
'comment-medical', "comment-medical",
'comment-slash', "comment-slash",
'comments', "comments",
'comments-dollar', "comments-dollar",
'compact-disc', "compact-disc",
'compass', "compass",
'compress-alt', "compress-alt",
'cookie', "cookie",
'cookie-bite', "cookie-bite",
'copy', "copy",
'credit-card', "credit-card",
'crop', "crop",
'crop-alt', "crop-alt",
'cut', "cut",
'database', "database",
'desktop', "desktop",
'edit', "edit",
'envelope', "envelope",
'envelope-open', "envelope-open",
'eraser', "eraser",
'ethernet', "ethernet",
'exchange-alt', "exchange-alt",
'exclamation', "exclamation",
'exclamation-circle', "exclamation-circle",
'exclamation-triangle', "exclamation-triangle",
'expand', "expand",
'expand-alt', "expand-alt",
'external-link-alt', "external-link-alt",
'eye', "eye",
'eye-dropper', "eye-dropper",
'eye-slash', "eye-slash",
'fan', "fan",
'file', "file",
'file-alt', "file-alt",
'file-archive', "file-archive",
'file-audio', "file-audio",
'file-code', "file-code",
'file-download', "file-download",
'fill', "fill",
'fill-drip', "fill-drip",
'filter', "filter",
'fingerprint', "fingerprint",
'fire', "fire",
'fire-alt', "fire-alt",
'folder', "folder",
'folder-open', "folder-open",
'forward', "forward",
'gamepad', "gamepad",
'ghost', "ghost",
'gift', "gift",
'gifts', "gifts",
'globe', "globe",
'globe-africa', "globe-africa",
'globe-asia', "globe-asia",
'globe-europe', "globe-europe",
'headphones', "headphones",
'headphones-alt', "headphones-alt",
'headset', "headset",
'heart', "heart",
'heart-broken', "heart-broken",
'heartbeat', "heartbeat",
'history', "history",
'home', "home",
'info', "info",
'keyboard', "keyboard",
'layer-group', "layer-group",
'list', "list",
'lock', "lock",
'lock-open', "lock-open",
'map-marker', "map-marker",
'map-marker-alt', "map-marker-alt",
'microphone', "microphone",
'microphone-alt', "microphone-alt",
'microphone-alt-slash', "microphone-alt-slash",
'minus', "minus",
'mobile', "mobile",
'mobile-alt', "mobile-alt",
'moon', "moon",
'mouse', "mouse",
'mouse-pointer', "mouse-pointer",
'music', "music",
'network-wired', "network-wired",
'neuter', "neuter",
'paperclip', "paperclip",
'paste', "paste",
'pause', "pause",
'paw', "paw",
'pen', "pen",
'pencil-alt', "pencil-alt",
'percent', "percent",
'percentage', "percentage",
'phone', "phone",
'phone-alt', "phone-alt",
'phone-slash', "phone-slash",
'phone-volume', "phone-volume",
'photo-video', "photo-video",
'power-off', "power-off",
'question', "question",
'question-circle', "question-circle",
'redo', "redo",
'redo-alt', "redo-alt",
'reply', "reply",
'robot', "robot",
'rocket', "rocket",
'rss', "rss",
'satellite-dish', "satellite-dish",
'save', "save",
'search', "search",
'server', "server",
'shapes', "shapes",
'share', "share",
'share-alt', "share-alt",
'shield-alt', "shield-alt",
'signal', "signal",
'skull', "skull",
'skull-crossbones', "skull-crossbones",
'sliders-h', "sliders-h",
'sort', "sort",
'spinner', "spinner",
'times', "times",
'times-circle', "times-circle",
'toggle-off', "toggle-off",
'toggle-on', "toggle-on",
'toolbox', "toolbox",
'tools', "tools",
'trash', "trash",
'trash-alt', "trash-alt",
'tv', "tv",
'undo', "undo",
'undo-alt', "undo-alt",
'unlink', "unlink",
'unlock', "unlock",
'unlock-alt', "unlock-alt",
'upload', "upload",
'user', "user",
'user-alt', "user-alt",
'volume-down', "volume-down",
'volume-mute', "volume-mute",
'volume-off', "volume-off",
'volume-up', "volume-up",
'wifi', "wifi",
'wrench' "wrench",
] ];
const otherIcons = [ const otherIcons = [
'youtube', "youtube",
'discord', "discord",
'node', "node",
'apple', "apple",
'sellsy', "sellsy",
'app-store', "app-store",
'cloudflare', "cloudflare",
'dev', "dev",
'github-alt', "github-alt",
'gitlab', "gitlab",
'google', "google",
'itunes-note', "itunes-note",
'node-js', "node-js",
'npm', "npm",
'spotify', "spotify",
'usb', "usb",
'windows' "windows",
] ];
function run() { function run() {
return { return {
icons, icons,
otherIcons otherIcons,
} };
} }
module.exports = run() module.exports = run();

View file

@ -1,69 +1,48 @@
const colors = require('colors') const consolePrefix = `${"[".blue}${"dbd-soft-ui".yellow}${"]".blue} `;
const npmUpdater = require('./utils/updater/npm') const Keyv = require("keyv");
const fileUpdater = require('./utils/updater/files') const path = require("path");
const consolePrefix = `${'['.blue}${'dbd-soft-ui'.yellow}${']'.blue} ` const { readFileSync } = require("fs");
const Keyv = require('keyv')
const path = require('path')
module.exports = (themeConfig = {}) => { module.exports = (themeConfig = {}) => {
return { return {
themeCodename: 'softui', themeCodename: "softui",
viewsPath: path.join(__dirname, '/views'), viewsPath: path.join(__dirname, "/views"),
staticPath: path.join(__dirname, '/views/src'), staticPath: path.join(__dirname, "/views/src"),
themeConfig: { themeConfig: {
...themeConfig, ...themeConfig,
defaultLocales: require('./locales.js') defaultLocales: require("./locales.js"),
}, },
messages: { messages: {
error: { error: {
addonLicense: `${consolePrefix}${'Failed to initialise {{ADDON}}.\nThe license this addon was installed with does not match your current discord-dashboard license.' addonLicense: `${consolePrefix}${"Failed to initialise {{ADDON}}.\nThe license this addon was installed with does not match your current discord-dashboard license.".cyan}`,
.cyan },
}` success: {
}, addonLoaded: `${consolePrefix}${"Successfully loaded {{ADDON}}.".cyan}`,
success: { },
addonLoaded: `${consolePrefix}${'Successfully loaded {{ADDON}}.'.cyan },
}` embedBuilderComponent: readFileSync(path.join(__dirname, "/embedBuilderComponent.txt"), "utf8"),
} init: async (app, config) => {
}, if (!config?.useTheme404) return console.log(`${consolePrefix}${"You need to set useTheme404 to true in your DBD config otherwise Soft-UI will not work correctly!\n\nDashboard has not fully initialised due to this. Pages will 404!".red}`);
embedBuilderComponent: require('fs').readFileSync(
path.join(__dirname, '/embedBuilderComponent.txt'),
'utf8'
),
init: async (app, config) => {
if(!config?.useTheme404) return console.log(`${consolePrefix}${'You need to set useTheme404 to true in your DBD config otherwise Soft-UI will not work correctly!\n\nDashboard has not fully initialised due to this. Pages will 404!'.red}`);
let outdated = false const db = new Keyv(themeConfig.dbdriver || "sqlite://" + path.join(__dirname, "/database.sqlite"));
; (async () => {
let check = await npmUpdater.update()
await fileUpdater.update()
if (!check) outdated = true
})()
const db = new Keyv( db.on("error", (err) => {
themeConfig.dbdriver || console.log("Connection Error", err);
'sqlite://' + path.join(__dirname, '/database.sqlite') process.exit();
) });
db.on('error', (err) => { themeConfig = { ...themeConfig, defaultLocales: require("./locales.js") };
console.log('Connection Error', err)
process.exit()
})
themeConfig = { require("./utils/functions/errorHandler")(config, themeConfig, db);
...themeConfig, require("./utils/functions/settingsPage")(config, themeConfig, db);
defaultLocales: require('./locales.js') // await require('./utils/addonManager').execute(themeConfig, config, app, module.exports.messages);
} require("./utils/initPages").init(config, themeConfig, app, db);
},
};
};
require('./utils/functions/errorHandler')(config, themeConfig, db) module.exports.partials = __dirname + "/views/partials";
require('./utils/functions/settingsPage')(config, themeConfig, db) module.exports.formTypes = require("./utils/formtypes");
// await require('./utils/addonManager').execute(themeConfig, config, app, module.exports.messages); module.exports.Feed = require("./utils/feedHandler");
require('./utils/initPages').init(config, themeConfig, app, db) module.exports.cmdHandler = require("./utils/cmdHandler");
} module.exports.version = require("./package.json").version;
}
}
module.exports.partials = __dirname + '/views/partials'
module.exports.formTypes = require('./utils/formtypes')
module.exports.Feed = require('./utils/feedHandler')
module.exports.cmdHandler = require('./utils/cmdHandler')
module.exports.version = require('./package.json').version

View file

@ -1,95 +1,94 @@
module.exports = { module.exports = {
enUS: { enUS: {
name: 'English', name: "English",
index: { index: {
feeds: ['Current Users', 'CPU', 'System Platform', 'Server Count'], feeds: ["Current Users", "CPU", "System Platform", "Server Count"],
card: { card: {
category: 'Soft UI', category: "Soft UI",
title: 'Assistants - The center of everything', title: "Assistants - The center of everything",
description: description: "Assistants Discord Bot management panel. Assistants Bot was created to give others the ability to do what they want. Just.<br>That's an example text.<br><br><b><i>Feel free to use HTML</i></b>",
"Assistants Discord Bot management panel. Assistants Bot was created to give others the ability to do what they want. Just.<br>That's an example text.<br><br><b><i>Feel free to use HTML</i></b>", footer: "Learn More",
footer: 'Learn More', image: "/img/soft-ui.webp",
image: '/img/soft-ui.webp', linkText: "Learn more",
linkText: 'Learn more' },
}, feedsTitle: "Feeds",
feedsTitle: 'Feeds', graphTitle: "Graphs",
graphTitle: 'Graphs' },
}, manage: {
manage: { settings: {
settings: { memberCount: "Members",
memberCount: 'Members', info: {
info: { info: "Info",
info: 'Info', server: "Server Information",
server: 'Server Information' },
} },
} },
}, privacyPolicy: {
privacyPolicy: { title: "Privacy Policy",
title: 'Privacy Policy', description: "Privacy Policy and Terms of Service",
description: 'Privacy Policy and Terms of Service' },
}, partials: {
partials: { sidebar: {
sidebar: { dash: "Dashboard",
dash: 'Dashboard', manage: "Manage Guilds",
manage: 'Manage Guilds', commands: "Commands",
commands: 'Commands', pp: "Privacy Policy",
pp: 'Privacy Policy', admin: "Admin",
admin: 'Admin', account: "Account Pages",
account: 'Account Pages', login: "Sign In",
login: 'Sign In', logout: "Sign Out",
logout: 'Sign Out' },
}, navbar: {
navbar: { home: "Home",
home: 'Home', pages: {
pages: { manage: "Manage Guilds",
manage: 'Manage Guilds', settings: "Manage Guilds",
settings: 'Manage Guilds', commands: "Commands",
commands: 'Commands', pp: "Privacy Policy",
pp: 'Privacy Policy', admin: "Admin Panel",
admin: 'Admin Panel', error: "Error",
error: 'Error', credits: "Credits",
credits: 'Credits', debug: "Debug",
debug: 'Debug', leaderboard: "Leaderboard",
leaderboard: 'Leaderboard', profile: "Profile",
profile: 'Profile', maintenance: "Under Maintenance",
maintenance: 'Under Maintenance' },
} },
}, title: {
title: { pages: {
pages: { manage: "Manage Guilds",
manage: 'Manage Guilds', settings: "Manage Guilds",
settings: 'Manage Guilds', commands: "Commands",
commands: 'Commands', pp: "Privacy Policy",
pp: 'Privacy Policy', admin: "Admin Panel",
admin: 'Admin Panel', error: "Error",
error: 'Error', credits: "Credits",
credits: 'Credits', debug: "Debug",
debug: 'Debug', leaderboard: "Leaderboard",
leaderboard: 'Leaderboard', profile: "Profile",
profile: 'Profile', maintenance: "Under Maintenance",
maintenance: 'Under Maintenance' },
} },
}, preloader: {
preloader: { text: "Page is loading...",
text: 'Page is loading...' },
}, premium: {
premium: { title: "Want more from Assistants?",
title: 'Want more from Assistants?', description: "Check out premium features below!",
description: 'Check out premium features below!', buttonText: "Become Premium",
buttonText: 'Become Premium' },
}, settings: {
settings: { title: "Site Configuration",
title: 'Site Configuration', description: "Configurable Viewing Options",
description: 'Configurable Viewing Options', theme: {
theme: { title: "Site Theme",
title: 'Site Theme', description: "Make the site more appealing for your eyes!",
description: 'Make the site more appealing for your eyes!' },
}, language: {
language: { title: "Site Language",
title: 'Site Language', description: "Select your preferred language!",
description: 'Select your preferred language!' },
} },
} },
} },
} };
}

View file

@ -1,18 +1,8 @@
{ {
"name": "dbd-soft-ui", "name": "dbd-soft-ui",
"version": "1.6.48-beta.1", "description": "dashboard theme",
"version": "1.0",
"typings": "dbd-soft-ui.d.ts", "typings": "dbd-soft-ui.d.ts",
"author": {
"name": "iMidnight"
},
"contributors": [
"PlainDevelopment",
"Breftejk"
],
"bugs": {
"url": "https://github.com/Assistants-Center/dbd-soft-ui/issues"
},
"bundleDependencies": [],
"dependencies": { "dependencies": {
"@keyv/sqlite": "^3.6.1", "@keyv/sqlite": "^3.6.1",
"colors": "1.4.0", "colors": "1.4.0",
@ -21,29 +11,100 @@
"nodeactyl": "^3.2.2", "nodeactyl": "^3.2.2",
"quick.db": "^7.1.3" "quick.db": "^7.1.3"
}, },
"deprecated": false,
"description": "Soft UI DBD Theme: An awesome - feature packed theme to use with discord-dashboard!",
"homepage": "https://softui.assistantscenter.com/",
"keywords": [
"discord",
"discord.js",
"discordjs",
"discord dashboard",
"discord web dashboard",
"web dashboard",
"dashboard"
],
"license": "MIT",
"main": "index.js", "main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/Assistants-Center/DBD-Soft-UI.git"
},
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\"" "test": "echo \"Error: no test specified\""
}, },
"devDependencies": { "devDependencies": {
"express": "^4.18.2", "express": "^4.18.2",
"eslint": "^8.23.0",
"prettier": "2.7.1" "prettier": "2.7.1"
},
"eslintConfig": {
"env": {
"commonjs": true,
"es6": true,
"es2020": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {
"arrow-spacing": [
"warn",
{
"before": true,
"after": true
}
],
"comma-dangle": [
"error",
"always-multiline"
],
"comma-spacing": "error",
"comma-style": "error",
"dot-location": [
"error",
"property"
],
"handle-callback-err": "off",
"indent": [
"error",
"tab",
{
"SwitchCase": 1
}
],
"keyword-spacing": "error",
"max-nested-callbacks": [
"error",
{
"max": 4
}
],
"max-statements-per-line": [
"error",
{
"max": 2
}
],
"no-console": "off",
"no-multi-spaces": "error",
"no-multiple-empty-lines": [
"error",
{
"max": 2,
"maxEOF": 1,
"maxBOF": 0
}
],
"no-trailing-spaces": [
"error"
],
"no-var": "error",
"object-curly-spacing": [
"error",
"always"
],
"prefer-const": "error",
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
],
"space-in-parens": "error",
"space-infix-ops": "error",
"space-unary-ops": "error",
"yoda": "error"
}
} }
} }

View file

@ -1,27 +1,24 @@
const npmUpdater = require('../../utils/updater/npm')
const fileUpdater = require('../../utils/updater/files')
module.exports = { module.exports = {
page: '/control', page: "/control",
execute: async (req, res, app, config, themeConfig, info) => { // eslint-disable-next-line no-unused-vars
execute: async (req, res, app, config, themeConfig, info) => {
const { uuid, action } = req.query;
const { uuid, action } = req.query if (!uuid && action && req.query.type) {
if (!uuid && action && req.query.type) { return res.redirect("/admin?result=true");
if (req.query.type === 'npm') await npmUpdater.update() }
if (req.query.type === 'live') await fileUpdater.update()
return res.redirect('/admin?result=true')
}
if (!uuid || !action) return res.sendStatus(412)
try { if (!uuid || !action) return res.sendStatus(412);
if (action === 'start') await themeConfig.nodeactyl.startServer(uuid)
if (action === 'restart') await themeConfig.nodeactyl.restartServer(uuid) try {
if (action === 'stop') await themeConfig.nodeactyl.stopServer(uuid) if (action === "start") await themeConfig.nodeactyl.startServer(uuid);
if (action === 'kill') await themeConfig.nodeactyl.killServer(uuid) if (action === "restart") await themeConfig.nodeactyl.restartServer(uuid);
} catch (error) { if (action === "stop") await themeConfig.nodeactyl.stopServer(uuid);
console.error(error) if (action === "kill") await themeConfig.nodeactyl.killServer(uuid);
return res.redirect('/admin?result=false') } catch (error) {
} console.error(error);
return res.redirect('/admin?result=true') return res.redirect("/admin?result=false");
} }
} return res.redirect("/admin?result=true");
}
};

View file

@ -1,193 +1,197 @@
const db = require('quick.db') const db = require("quick.db");
const { icons, otherIcons } = require('../../icons') const { icons, otherIcons } = require("../../icons");
module.exports = { module.exports = {
page: '/feed', page: "/feed",
execute: async (req, res, app, config, themeConfig, info) => { // eslint-disable-next-line no-unused-vars
if (req.query.action === 'delete') { execute: async (req, res, app, config, themeConfig, info) => {
const deleteFeed = req.query.feed if (req.query.action === "delete") {
if (!deleteFeed) return res.redirect('/admin?error=invalidFeed') const deleteFeed = req.query.feed;
if (!/^\d+$/.test(deleteFeed))
return res.redirect('/admin?error=invalidFeed') if (!deleteFeed) return res.redirect("/admin?error=invalidFeed");
if (deleteFeed !== '1' && deleteFeed !== '2' && deleteFeed !== '3') if (!/^\d+$/.test(deleteFeed)) return res.redirect("/admin?error=invalidFeed");
return res.redirect('/admin?error=invalidFeed') if (deleteFeed !== "1" && deleteFeed !== "2" && deleteFeed !== "3") return res.redirect("/admin?error=invalidFeed");
if (deleteFeed === '1') {
if (!db.get('feeds.one')) if (deleteFeed === "1") {
return res.redirect('/admin?error=invalidFeed') if (!db.get("feeds.one")) return res.redirect("/admin?error=invalidFeed");
if (db.get('feeds.two')) {
const f = await db.get('feeds.two') if (db.get("feeds.two")) {
await db.set('feeds.one', { const f = await db.get("feeds.two");
color: f.color,
description: f.description, await db.set("feeds.one", {
published: f.published, color: f.color,
icon: f.icon, description: f.description,
diff: f.diff published: f.published,
}) icon: f.icon,
} else { diff: f.diff,
await db.delete('feeds.one') });
} } else await db.delete("feeds.one");
if (db.get('feeds.three')) {
const f = await db.get('feeds.three') if (db.get("feeds.three")) {
await db.set('feeds.two', { const f = await db.get("feeds.three");
color: f.color,
description: f.description, await db.set("feeds.two", {
published: f.published, color: f.color,
icon: f.icon, description: f.description,
diff: f.diff published: f.published,
}) icon: f.icon,
await db.delete('feeds.three') diff: f.diff,
} });
} else if (deleteFeed === '2') {
if (!db.get('feeds.two')) await db.delete("feeds.three");
return res.redirect('/admin?error=invalidFeed') }
if (db.get('feeds.one')) { } else if (deleteFeed === "2") {
const f = await db.get('feeds.one') if (!db.get("feeds.two")) return res.redirect("/admin?error=invalidFeed");
await db.set('feeds.two', {
color: f.color, if (db.get("feeds.one")) {
description: f.description, const f = await db.get("feeds.one");
published: f.published, await db.set("feeds.two", {
icon: f.icon, color: f.color,
diff: f.diff description: f.description,
}) published: f.published,
await db.delete('feeds.one') icon: f.icon,
} else { diff: f.diff,
await db.delete('feeds.two') });
} await db.delete("feeds.one");
} else if (deleteFeed === '3') { } else {
if (!db.get('feeds.three')) await db.delete("feeds.two");
return res.redirect('/admin?error=invalidFeed') }
await db.delete('feeds.three') } else if (deleteFeed === "3") {
if (db.get('feeds.two')) { if (!db.get("feeds.three")) return res.redirect("/admin?error=invalidFeed");
const f = await db.get('feeds.two')
await db.set('feeds.three', { await db.delete("feeds.three");
color: f.color,
description: f.description, if (db.get("feeds.two")) {
published: f.published, const f = await db.get("feeds.two");
icon: f.icon,
diff: f.diff await db.set("feeds.three", {
}) color: f.color,
} description: f.description,
if (db.get('feeds.one')) { published: f.published,
const f = await db.get('feeds.one') icon: f.icon,
await db.set('feeds.two', { diff: f.diff,
color: f.color, });
description: f.description, }
published: f.published,
icon: f.icon, if (db.get("feeds.one")) {
diff: f.diff const f = await db.get("feeds.one");
})
} await db.set("feeds.two", {
} color: f.color,
return res.redirect('/admin') description: f.description,
} else if (req.query.action === 'create') { published: f.published,
const { color, description, icon } = req.query icon: f.icon,
if (!color || !description || !icon) diff: f.diff,
return res.redirect('/admin?error=missingData') });
if ( }
color !== 'red' && }
color !== 'orange' && return res.redirect("/admin");
color !== 'pink' && } else if (req.query.action === "create") {
color !== 'gray' && const { color, description, icon } = req.query;
color !== 'green' && if (!color || !description || !icon) return res.redirect("/admin?error=missingData");
color !== 'blue' &&
color !== 'dark' if (color !== "red" && color !== "orange" && color !== "pink" && color !== "gray" && color !== "green" && color !== "blue" && color !== "dark") return res.redirect("/admin?error=invalidData");
) if (description.length < 3 || description.length > 128) return res.redirect("/admin?error=invalidData");
return res.redirect('/admin?error=invalidData') if (!icons.includes(icon) && !otherIcons.includes(icon)) return res.redirect("/admin?error=invalidData");
if (description.length < 3 || description.length > 128)
return res.redirect('/admin?error=invalidData') let diff;
if (!icons.includes(icon) && !otherIcons.includes(icon)) let col;
return res.redirect('/admin?error=invalidData')
let diff if (otherIcons.includes(icon)) diff = true;
let col if (color === "red") col = "danger";
if (otherIcons.includes(icon)) diff = true if (color === "orange") col = "warning";
if (color === 'red') col = 'danger' if (color === "pink") col = "primary";
if (color === 'orange') col = 'warning' if (color === "gray") col = "secondary";
if (color === 'pink') col = 'primary' if (color === "green") col = "success";
if (color === 'gray') col = 'secondary' if (color === "blue") col = "info";
if (color === 'green') col = 'success' if (color === "dark") col = "dark";
if (color === 'blue') col = 'info'
if (color === 'dark') col = 'dark' if (db.get("feeds.three") && db.get("feeds.two") && db.get("feeds.one")) {
if ( await db.delete("feeds.one");
db.get('feeds.three') &&
db.get('feeds.two') && const f3 = db.get("feeds.three");
db.get('feeds.one') const f2 = db.get("feeds.two");
) {
await db.delete('feeds.one') await db.set("feeds.two", {
const f3 = db.get('feeds.three') color: f3.color,
const f2 = db.get('feeds.two') description: f3.description,
await db.set('feeds.two', { published: f3.published,
color: f3.color, icon: f3.icon,
description: f3.description, diff: f3.diff,
published: f3.published, });
icon: f3.icon,
diff: f3.diff await db.set("feeds.one", {
}) color: f2.color,
await db.set('feeds.one', { description: f2.description,
color: f2.color, published: f2.published,
description: f2.description, icon: f2.icon,
published: f2.published, diff: f2.diff,
icon: f2.icon, });
diff: f2.diff
}) await db.set("feeds.three", {
await db.set('feeds.three', { color: col,
color: col, description: description,
description: description, published: Date.now(),
published: Date.now(), icon: icon,
icon: icon, diff: diff,
diff: diff });
}) } else {
} else { if (!db.get("feeds.three")) {
if (!db.get('feeds.three')) await db.set("feeds.three", {
await db.set('feeds.three', { color: col,
color: col, description: description,
description: description, published: Date.now(),
published: Date.now(), icon: icon,
icon: icon, diff: diff,
diff: diff });
}) } else if (!db.get("feeds.two")) {
else if (!db.get('feeds.two')) { const f3 = db.get("feeds.three");
const f3 = db.get('feeds.three')
await db.set('feeds.two', { await db.set("feeds.two", {
color: f3.color, color: f3.color,
description: f3.description, description: f3.description,
published: f3.published, published: f3.published,
icon: f3.icon, icon: f3.icon,
diff: f3.diff diff: f3.diff,
}) });
await db.set('feeds.three', {
color: col, await db.set("feeds.three", {
description: description, color: col,
published: Date.now(), description: description,
icon: icon, published: Date.now(),
diff: diff icon: icon,
}) diff: diff,
} else { });
const f3 = db.get('feeds.three') } else {
const f2 = db.get('feeds.two') const f3 = db.get("feeds.three");
await db.set('feeds.one', { const f2 = db.get("feeds.two");
color: f2.color,
description: f2.description, await db.set("feeds.one", {
published: f2.published, color: f2.color,
icon: f2.icon, description: f2.description,
diff: f2.diff published: f2.published,
}) icon: f2.icon,
await db.set('feeds.two', { diff: f2.diff,
color: f3.color, });
description: f3.description,
published: f3.published, await db.set("feeds.two", {
icon: f3.icon, color: f3.color,
diff: f3.diff description: f3.description,
}) published: f3.published,
await db.set('feeds.three', { icon: f3.icon,
color: col, diff: f3.diff,
description: description, });
published: Date.now(),
icon: icon, await db.set("feeds.three", {
diff: diff color: col,
}) description: description,
} published: Date.now(),
} icon: icon,
return res.redirect('/admin') diff: diff,
} });
} }
} }
return res.redirect("/admin");
}
},
};

View file

@ -1,48 +1,45 @@
const db = require('quick.db') const db = require("quick.db");
module.exports = { module.exports = {
page: '/admin', page: "/admin",
execute: async (req, res, app, config, themeConfig, info, database) => { execute: async (req, res, app, config, themeConfig, info, database) => {
if (!req.session.user) return res.redirect('/discord?r=/admin/') if (!req.session.user) return res.redirect("/discord?r=/admin/");
if (!config.ownerIDs?.includes(req.session.user.id)) if (!config.ownerIDs?.includes(req.session.user.id)) return res.redirect("/");
return res.redirect('/') if (!themeConfig.nodeactyl && themeConfig.admin?.pterodactyl?.enabled) return res.send("Unable to contact Pterodactyl, are your details correct?");
if (!themeConfig.nodeactyl && themeConfig.admin?.pterodactyl?.enabled)
return res.send(
'Unable to contact Pterodactyl, are your details correct?'
)
async function getServers() { async function getServers() {
if (!themeConfig?.admin?.pterodactyl?.enabled) return [] if (!themeConfig?.admin?.pterodactyl?.enabled) return [];
const serverData = []
for (const uuid of themeConfig?.admin?.pterodactyl?.serverUUIDs) {
let dataStatus = await themeConfig?.nodeactyl?.getServerStatus(uuid)
let data = await themeConfig?.nodeactyl?.getServerDetails(uuid)
serverData.push({ const serverData = [];
name: data.name.toString(), const serverUUIDS = themeConfig?.admin?.pterodactyl?.serverUUIDs;
uuid: data.uuid.toString(), for (const uuid of serverUUIDS) {
desc: data.description.toString(), const dataStatus = await themeConfig?.nodeactyl?.getServerStatus(uuid);
node: data.node.toString(), const data = await themeConfig?.nodeactyl?.getServerDetails(uuid);
status: dataStatus.toString()
})
}
return serverData
}
let allFeedsUsed = false serverData.push({
if (db.get('feeds.one') && db.get('feeds.two') && db.get('feeds.three')) name: data.name.toString(),
allFeedsUsed = true uuid: data.uuid.toString(),
const d = await getServers() desc: data.description.toString(),
res.render('admin', { node: data.node.toString(),
req, status: dataStatus.toString(),
sData: d, });
ldata: await database.get('logs'), }
themeConfig: req.themeConfig,
node: themeConfig.nodeactyl, return serverData;
bot: config.bot, }
allFeedsUsed,
config, const d = await getServers();
require
}) res.render("admin", {
} req,
} sData: d,
ldata: await database.get("logs"),
themeConfig: req.themeConfig,
node: themeConfig.nodeactyl,
bot: config.bot,
allFeedsUsed: (db.get("feeds.one") && db.get("feeds.two") && db.get("feeds.three")) ? true : false,
config,
require,
});
},
};

View file

@ -1,11 +1,11 @@
module.exports = { module.exports = {
page: '/blacklisted', page: "/blacklisted",
execute: async (req, res, app, config, themeConfig, info) => { execute: async (req, res, app, config, themeConfig, info) => {
res.render('blacklisted', { res.render("blacklisted", {
req, req,
config, config,
themeConfig, themeConfig,
info info,
}) });
} },
} };

View file

@ -1,12 +1,12 @@
module.exports = { module.exports = {
page: '/commands', page: "/commands",
execute: async (req, res, app, config, themeConfig, info) => { execute: async (req, res, app, config, themeConfig, info) => {
if (themeConfig.commands) if (themeConfig.commands)
res.render('commands.ejs', { res.render("commands", {
req, req,
config, config,
themeConfig, themeConfig,
info info,
}) });
} },
} };

View file

@ -1,11 +1,11 @@
module.exports = { module.exports = {
page: '/credits', page: "/credits",
execute: async (req, res, app, config, themeConfig, info) => { execute: async (req, res, app, config, themeConfig, info) => {
res.render('credits', { res.render("credits", {
req: req, req: req,
config, config,
themeConfig, themeConfig,
info info,
}) });
} },
} };

View file

@ -1,70 +1,45 @@
const fetch = require('node-fetch') const fetch = require("node-fetch");
const fs = require('fs') const fs = require("fs");
let DBD = require('discord-dashboard') const DBD = require("../../../../index");
module.exports = { module.exports = {
page: '/debug', page: "/debug",
execute: async (req, res, app, config, themeConfig, info) => { execute: async (req, res, app, config, themeConfig, info) => {
/* /*
Do not remove this page. Do not remove this page.
It will be used with support in the discord server. It will be used with support in the discord server.
*/ */
if (!req.session.user) return res.redirect('/discord?r=/debug/') if (!req.session.user) return res.redirect("/discord?r=/debug/");
if (!config.ownerIDs?.includes(req.session.user.id)) if (!config.ownerIDs?.includes(req.session.user.id)) return res.redirect("/");
return res.redirect('/')
let onlineFiles = { const onlineFiles = {
index: await fetch( index: await fetch("https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/index.ejs"),
`https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/index.ejs` guild: await fetch("https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/guild.ejs"),
), guilds: await fetch("https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/guilds.ejs"),
guild: await fetch( };
`https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/guild.ejs`
),
guilds: await fetch(
`https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/guilds.ejs`
)
}
onlineFiles.index = await onlineFiles.index.text() onlineFiles.index = await onlineFiles.index.text();
onlineFiles.guild = await onlineFiles.guild.text() onlineFiles.guild = await onlineFiles.guild.text();
onlineFiles.guilds = await onlineFiles.guilds.text() onlineFiles.guilds = await onlineFiles.guilds.text();
let localFiles = {
index: await fs.readFileSync(
`${__dirname}/../..//views/index.ejs`,
'utf-8'
),
guild: await fs.readFileSync(
`${__dirname}/../../views/settings.ejs`,
'utf-8'
),
guilds: await fs.readFileSync(
`${__dirname}/../../views/guilds.ejs`,
'utf-8'
)
}
let onlineV = await fetch( const localFiles = {
`https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/utils/updater/versionsOnline.json` index: await fs.readFileSync(`${__dirname}/../../views/index.ejs`, "utf-8"),
) guild: await fs.readFileSync(`${__dirname}/../../views/settings.ejs`, "utf-8"),
const localV = require(`${__dirname}/../../utils/updater/versions.json`) guilds: await fs.readFileSync(`${__dirname}/../../views/guilds.ejs`, "utf-8"),
onlineV = await onlineV.json() };
res.render('debug', { res.render("debug", {
license: require(`discord-dashboard`).licenseInfo().type, // replace with discord-dashboard onlineFiles,
onlineV, localFiles,
localV, rawUptime: process.uptime(),
onlineFiles, nodeVersion: process.version,
localFiles, themeConfig,
rawUptime: process.uptime(), discordVersion: require("discord.js").version,
nodeVersion: process.version, dbdVersion: DBD.version,
themeConfig, themeVersion: require("dbd-soft-ui").version,
discordVersion: require('discord.js').version, req,
dbdVersion: DBD.version, config,
themeVersion: require(`dbd-soft-ui`).version, info,
themePartials: require(`${__dirname}/../../utils/updater/versions.json`), });
req, },
config, };
info
})
}
}

View file

@ -1,8 +1,8 @@
module.exports = { module.exports = {
page: '/shards/get', page: "/shards/get",
execute: async (req, res, app, config, themeConfig, info, db) => { execute: async (req, res, app, config, themeConfig, info, db) => {
let returned = await db.get('stats') const returned = await db.get("stats");
res.json(returned) res.json(returned);
} },
} };

View file

@ -1,11 +1,11 @@
module.exports = { module.exports = {
page: '/privacy-policy', page: "/privacy-policy",
execute: async (req, res, app, config, themeConfig, info) => { execute: async (req, res, app, config, themeConfig, info) => {
res.render('pp', { res.render("pp", {
req, req,
config, config,
themeConfig, themeConfig,
info info,
}) });
} },
} };

View file

@ -1,11 +1,11 @@
module.exports = { module.exports = {
page: '/settings/:id/:category', page: "/settings/:id/:category",
execute: async (req, res, app, config, themeConfig, info) => { // eslint-disable-next-line no-unused-vars
const categoryExists = config.settings?.find( execute: async (req, res, app, config, themeConfig, info) => {
(s) => s.categoryId === req.params.category const categoryExists = config.settings?.find(s => s.categoryId === req.params.category);
)
if (!categoryExists) return config.errorPage(req, res, null, 404)
await config.guildSettings(req, res, false, req.params.category) if (!categoryExists) return config.errorPage(req, res, null, 404);
}
} await config.guildSettings(req, res, false, req.params.category);
},
};

View file

@ -1,6 +1,7 @@
module.exports = { module.exports = {
page: '/settings/:id/', page: "/settings/:id/",
execute: async (req, res, app, config, themeConfig, info) => { // eslint-disable-next-line no-unused-vars
await config.guildSettings(req, res, true) execute: async (req, res, app, config, themeConfig, info) => {
} await config.guildSettings(req, res, true);
} },
};

View file

@ -1,11 +1,12 @@
module.exports = { module.exports = {
page: '/shards', page: "/shards",
execute: async (req, res, app, config, themeConfig, info, db) => { // eslint-disable-next-line no-unused-vars
res.render('shards', { execute: async (req, res, app, config, themeConfig, info, db) => {
req: req, res.render("shards", {
config, req: req,
themeConfig, config,
info themeConfig,
}) info,
} });
} },
};

View file

@ -1,476 +1,392 @@
module.exports = { module.exports = {
page: '/guild/update/:guildId/', page: "/guild/update/:guildId/",
execute: async (req, res, app, config, themeConfig, info) => { // eslint-disable-next-line no-unused-vars
const data = req.body execute: async (req, res, app, config, themeConfig, info) => {
const data = req.body;
let setNewRes let setNewRes;
let errors = [] const errors = [];
let successes = [] const successes = [];
if (!req.session?.user) if (!req.session?.user) return res.send({
return res.send({ success: false,
success: false, message: "User is not logged in",
message: 'User is not logged in' });
})
const userGuildMemberObject = config.bot.guilds.cache const userGuildMemberObject = config.bot.guilds.cache.get(req.params.guildId).members.cache.get(req.session.user.id);
.get(req.params.guildId) const guildObject = config.bot.guilds.cache.get(req.params.guildId);
.members.cache.get(req.session.user.id)
const guildObject = config.bot.guilds.cache.get(req.params.guildId)
let category = config.settings?.find((c) => c.categoryId == req.query.categoryId) const category = config.settings?.find(c => c.categoryId == req.query.categoryId);
const catO = [];
const catToggle = [];
let catO = []; if (data.categoryToggle) {
let catToggle = []; for (const s of data.categoryToggle) {
if (!config.useCategorySet) try {
const category = config.settings?.find(c => c?.categoryId == s.id);
if (data.categoryToggle) { await category.setNew({
for (const s of data.categoryToggle) { guild: { id: req.params.guildId },
if (!config.useCategorySet) try { newData: s.value,
let category = config.settings?.find( });
(c) => c?.categoryId == s.id } catch (err) {
) errors.push(`Category ${s.id} %is%Failed to save%is%categoryToggle`);
await category.setNew({ }
guild: { id: req.params.guildId }, else {
newData: s.value if (category?.categoryId == s.id) catO.push({
}) optionId: category.categoryId == s.id ? "categoryToggle" : s.id,
} catch (err) { data: s.value,
errors.push(`Category ${s.id} %is%Failed to save%is%categoryToggle`); });
} else catToggle.push({
else { optionId: s.id,
if (category?.categoryId == s.id) catO.push({ data: s.value,
optionId: category.categoryId == s.id ? "categoryToggle" : s.id, });
data: s.value }
}); }
else catToggle.push({ if ("categoryToggle" in data && !category) {
optionId: s.id, return res.send({
data: s.value success: true,
}); message: "Saved toggle",
} errors: [],
} successes: [],
if ("categoryToggle" in data && !category) { });
return res.send({ }
success: true, }
message: "Saved toggle",
errors: [],
successes: [],
})
}
}
if (!category) if (!category) return res.send({
return res.send({ error: true,
error: true, message: "No category found",
message: "No category found", });
})
const subOptions = category.categoryOptionsList.filter((o) => o.optionType.type == "multiRow") const subOptions = category.categoryOptionsList.filter(o => o.optionType.type == "multiRow").map(o => o.optionType.options).flat();
.map((o) => o.optionType.options)
.flat()
const newOptionsList = [ const newOptionsList = [
...category.categoryOptionsList.filter((o) => o.optionType.type != "multiRow"), ...category.categoryOptionsList.filter((o) => o.optionType.type != "multiRow"),
...subOptions ...subOptions,
] ];
if (data.options) for (let option of newOptionsList) { if (data.options)
let d = data.options.find((o) => o.id === option.optionId); for (const option of newOptionsList) {
let canUse = {} const d = data.options.find(o => o.id === option.optionId);
let canUse = {};
if (!d && !d?.id) continue; if (!d && !d?.id) continue;
if (option.allowedCheck) canUse = await option.allowedCheck({ if (option.allowedCheck) canUse = await option.allowedCheck({
guild: { id: req.params.guildId }, guild: { id: req.params.guildId },
user: { id: req.session.user.id }, user: { id: req.session.user.id },
}) });
else canUse = { allowed: true, errorMessage: null }
else canUse = {
allowed: true,
errorMessage: null,
};
if (canUse.allowed == false) { if (canUse.allowed == false) {
setNewRes = { error: canUse.errorMessage } setNewRes = {
errors.push( error: canUse.errorMessage,
option.optionName + };
"%is%" +
setNewRes.error +
"%is%" +
option.optionId
)
} else if (option.optionType != "spacer") {
if (config.useCategorySet) {
if (option.optionType.type == "rolesMultiSelect" || option.optionType.type == "channelsMultiSelect" || option.optionType.type == "multiSelect" || option.optionType.type == 'tagInput') {
if (!d.value || d.value == null || d.value == undefined) catO.push({
optionId: option.optionId,
data: [],
})
else if (typeof d.value != "object") catO.push({
optionId: option.optionId,
data: [d.value],
})
else catO.push({
optionId: option.optionId,
data: d.value,
})
} else if (option.optionType.type == "switch") {
if (
d.value ||
d.value == null ||
d.value == undefined ||
d.value == false
) {
if (d.value || d.value == null || d.value == undefined || d.value == false) {
if (d.value == null || d.value == undefined || d.value == false)
catO.push({
optionId: option.optionId,
data: false
});
else
catO.push({
optionId: option.optionId,
data: true
});
}
}
} else if (option.optionType.type == "embedBuilder") {
if (
d.value == null ||
d.value == undefined
)
catO.push({
optionId: option.optionId,
data: option.optionType.data,
})
else {
try {
const parsedResponse = JSON.parse(
d.value
)
catO.push({
optionId: option.optionId,
data: parsedResponse,
})
} catch (err) {
catO.push({
optionId: option.optionId,
data: option.optionType.data,
})
}
}
} else {
if (
d.value == undefined ||
d.value == null
)
catO.push({
optionId: option.optionId,
data: null,
})
else
catO.push({
optionId: option.optionId,
data: d.value,
})
}
} else {
if (
option.optionType.type ==
'rolesMultiSelect' ||
option.optionType.type ==
'channelsMultiSelect' ||
option.optionType.type == 'multiSelect' ||
option.optionType.type == 'tagInput'
) {
if (
!d.value ||
d.value == null ||
d.value == undefined
) {
setNewRes = await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData: []
})
setNewRes ? null : (setNewRes = {})
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(option.optionName)
}
} else if (
typeof d.value != 'object'
) {
setNewRes = await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData: [d.value]
})
setNewRes ? null : (setNewRes = {})
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(option.optionName)
}
} else {
setNewRes = await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData: d.value
})
setNewRes ? null : (setNewRes = {})
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(option.optionName)
}
}
} else if (
option.optionType.type == 'embedBuilder'
) {
if (
d.value !== null ||
d.value !== undefined
) {
setNewRes =
(await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData: JSON.parse(
d.value
)
})) || {}
setNewRes ? null : (setNewRes = {})
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(option.optionName)
}
} else {
try {
const parsedResponse = JSON.parse(
d.value
)
setNewRes =
(await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData: parsedResponse
})) || {}
setNewRes ? null : (setNewRes = {})
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(
option.optionName
)
}
} catch (err) {
setNewRes =
(await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData:
option.optionType.data
})) || {}
setNewRes = {
error: 'JSON parse for embed builder went wrong, your settings have been reset.'
}
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(
option.optionName
)
}
}
}
} else {
if (
d.value == undefined ||
d.value == null
) {
setNewRes =
(await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData: null
})) || {}
setNewRes ? null : (setNewRes = {})
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(option.optionName)
}
} else {
setNewRes =
(await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject
},
user: {
id: req.session.user.id,
object: userGuildMemberObject
},
newData: d.value
})) || {}
setNewRes ? null : (setNewRes = {})
if (setNewRes.error) {
errors.push(
option.optionName +
'%is%' +
setNewRes.error +
'%is%' +
option.optionId
)
} else {
successes.push(option.optionName)
}
}
}
}
}
}
if (config.useCategorySet && catO.length) { errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
let sNR = await category.setNew({ } else if (option.optionType != "spacer") {
guild: { if (config.useCategorySet) {
id: req.params.guildId, if (option.optionType.type == "rolesMultiSelect" || option.optionType.type == "channelsMultiSelect" || option.optionType.type == "multiSelect" || option.optionType.type == "tagInput") {
object: guildObject, if (!d.value || d.value == null || d.value == undefined) catO.push({
}, optionId: option.optionId,
user: { data: [],
id: req.session.user.id, });
object: userGuildMemberObject, else if (typeof d.value != "object") catO.push({
}, optionId: option.optionId,
data: catO, data: [d.value],
}) });
sNR ? null : (sNR = {}) else catO.push({
if (sNR.error) { optionId: option.optionId,
errors.push(category.categoryId + "%is%" + sNR.error) data: d.value,
} else { });
successes.push(category.categoryId) } else if (option.optionType.type == "switch") {
} if (d.value || d.value == null || d.value == undefined || d.value == false) {
} if (d.value || d.value == null || d.value == undefined || d.value == false) {
if (d.value == null || d.value == undefined || d.value == false)
catO.push({
optionId: option.optionId,
data: false,
});
else
catO.push({
optionId: option.optionId,
data: true,
});
}
}
} else if (option.optionType.type == "embedBuilder") {
if (d.value == null || d.value == undefined)
catO.push({
optionId: option.optionId,
data: option.optionType.data,
});
else {
try {
const parsedResponse = JSON.parse(d.value);
if (config.useCategorySet && catToggle.length) for (const opt of catToggle) { catO.push({
let cat = config.settings?.find((c) => c.categoryId == opt.optionId); optionId: option.optionId,
data: parsedResponse,
});
} catch (err) {
catO.push({
optionId: option.optionId,
data: option.optionType.data,
});
}
}
} else {
if (d.value == undefined || d.value == null)
catO.push({
optionId: option.optionId,
data: null,
});
else
catO.push({
optionId: option.optionId,
data: d.value,
});
}
} else {
if (option.optionType.type == "rolesMultiSelect" || option.optionType.type == "channelsMultiSelect" || option.optionType.type == "multiSelect" || option.optionType.type == "tagInput") {
if (!d.value || d.value == null || d.value == undefined) {
setNewRes = await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
newData: [],
});
if (!cat) { setNewRes ? null : (setNewRes = {});
errors.push(`Category ${opt.optionId} %is%Doesn't exist%is%categoryToggle`);
continue;
}
try { if (setNewRes.error)
await cat.setNew({ errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
guild: { else
id: req.params.guildId, successes.push(option.optionName);
object: guildObject, } else if (typeof d.value != "object") {
}, setNewRes = await option.setNew({
user: { guild: {
id: req.session.user.id, id: req.params.guildId,
object: userGuildMemberObject, object: guildObject,
}, },
data: [{ user: {
optionId: "categoryToggle", id: req.session.user.id,
data: opt.data object: userGuildMemberObject,
}], },
}); newData: [d.value],
} catch (err) { });
errors.push(`Category ${opt.optionId} %is%${err}%is%categoryToggle`);
}
}
req.DBDEvents.emit('guildSettingsUpdated', { setNewRes ? null : (setNewRes = {});
user: req.session.user,
changes: { successes, errors }
})
res.send({ if (setNewRes.error)
success: true, errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
message: 'saved changed', else
errors, successes.push(option.optionName);
successes } else {
}) setNewRes = await option.setNew({
} guild: {
} id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
newData: d.value,
});
setNewRes ? null : (setNewRes = {});
if (setNewRes.error)
errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
else
successes.push(option.optionName);
}
} else if (option.optionType.type == "embedBuilder") {
if (d.value !== null || d.value !== undefined) {
setNewRes = (await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
newData: JSON.parse(
d.value,
),
})) || {};
setNewRes ? null : (setNewRes = {});
if (setNewRes.error)
errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
else
successes.push(option.optionName);
} else {
try {
const parsedResponse = JSON.parse(d.value);
setNewRes = (await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
newData: parsedResponse,
})) || {};
setNewRes ? null : (setNewRes = {});
if (setNewRes.error)
errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
else
successes.push(option.optionName);
} catch (err) {
setNewRes = (await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
newData: option.optionType.data,
})) || {};
setNewRes = {
error: "JSON parse for embed builder went wrong, your settings have been reset.",
};
if (setNewRes.error)
errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
else
successes.push(option.optionName);
}
}
} else {
if (d.value == undefined || d.value == null) {
setNewRes = (await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
newData: null,
})) || {};
setNewRes ? null : (setNewRes = {});
if (setNewRes.error)
errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
else
successes.push(option.optionName);
} else {
setNewRes = (await option.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
newData: d.value,
})) || {};
setNewRes ? null : (setNewRes = {});
if (setNewRes.error)
errors.push(option.optionName + "%is%" + setNewRes.error + "%is%" + option.optionId);
else
successes.push(option.optionName);
}
}
}
}
}
if (config.useCategorySet && catO.length) {
let sNR = await category.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
data: catO,
});
sNR ? null : (sNR = {});
if (sNR.error)
errors.push(category.categoryId + "%is%" + sNR.error);
else
successes.push(category.categoryId);
}
if (config.useCategorySet && catToggle.length)
for (const opt of catToggle) {
const cat = config.settings?.find(c => c.categoryId == opt.optionId);
if (!cat) {
errors.push(`Category ${opt.optionId} %is%Doesn't exist%is%categoryToggle`);
continue;
}
try {
await cat.setNew({
guild: {
id: req.params.guildId,
object: guildObject,
},
user: {
id: req.session.user.id,
object: userGuildMemberObject,
},
data: [{
optionId: "categoryToggle",
data: opt.data,
}],
});
} catch (err) {
errors.push(`Category ${opt.optionId} %is%${err}%is%categoryToggle`);
}
}
req.DBDEvents.emit("guildSettingsUpdated", {
user: req.session.user,
changes: {
successes,
errors,
},
});
res.send({
success: true,
message: "saved changed",
errors,
successes,
});
},
};

View file

@ -1,23 +1,21 @@
module.exports = { module.exports = {
page: '/stats/logs/update', page: "/stats/logs/update",
execute: async (req, res, app, config, themeConfig, info, db) => { execute: async (req, res, app, config, themeConfig, info, db) => {
if ( if ("Bearer " + themeConfig.admin?.logs?.key !== req.headers.authorization) return res.json({ status: "Invalid sharding key" });
'Bearer ' + themeConfig.admin?.logs?.key !==
req.headers.authorization
)
return res.json({ status: 'Invalid sharding key' })
const logs = await db.get('logs') const logs = await db.get("logs");
let newLogs = [] let newLogs = [];
if (!logs || !logs.length || !logs[0]) if (!logs || !logs.length || !logs[0])
newLogs = [req.body] newLogs = [req.body];
else else
newLogs = [req.body, ...logs] newLogs = [req.body, ...logs];
await db.set('logs', newLogs) await db.set("logs", newLogs);
res.json({ status: 'Completed' }) res.json({
} status: "Completed",
} });
},
};

View file

@ -1,36 +1,34 @@
module.exports = { module.exports = {
page: '/stats/shards/update', page: "/stats/shards/update",
execute: async (req, res, app, config, themeConfig, info, db) => { execute: async (req, res, app, config, themeConfig, info, db) => {
if ( if ("Bearer " + themeConfig.shardspage?.key !== req.headers.authorization) return res.json({ status: "Invalid sharding key" });
'Bearer ' + themeConfig.shardspage?.key !==
req.headers.authorization
)
return res.json({ status: 'Invalid sharding key' })
const stats = await db.get('stats') const stats = await db.get("stats");
const clean = req.body.map((s) => { const clean = req.body.map((s) => {
if (!stats) return { if (!stats) return {
...s, ...s,
ping: [0, 0, 0, 0, 0, 0, 0, 0, 0, s.ping] ping: [0, 0, 0, 0, 0, 0, 0, 0, 0, s.ping],
} };
const currentSaved = stats?.find((x) => x.id === s.id) const currentSaved = stats?.find((x) => x.id === s.id);
if (!currentSaved) return { if (!currentSaved) return {
...s, ...s,
ping: [0, 0, 0, 0, 0, 0, 0, 0, 0, s.ping] ping: [0, 0, 0, 0, 0, 0, 0, 0, 0, s.ping],
} };
const nextPing = currentSaved?.ping?.slice(1, 10) const nextPing = currentSaved?.ping?.slice(1, 10);
return { return {
...s, ...s,
ping: nextPing ? [...nextPing, s.ping] : [0, 0, 0, 0, 0, 0, 0, 0, 0, s.ping], ping: nextPing ? [...nextPing, s.ping] : [0, 0, 0, 0, 0, 0, 0, 0, 0, s.ping],
} };
}) });
await db.set('stats', clean) await db.set("stats", clean);
res.json({ status: 'Completed' }) res.json({
} status: "Completed",
} });
},
};

View file

@ -1,52 +1,42 @@
module.exports = (commands, prefix) => { module.exports = (commands, prefix) => {
if (!commands) if (!commands) throw new Error("No commands were provided to the Soft UI cmdHandler.");
throw new Error('No commands were provided to the Soft UI cmdHandler.') if (!prefix) prefix = "/";
if (!prefix) prefix = '!'
let finalCategories = [] const finalCategories = [];
let categories = [] const categories = [];
commands.map((cmd) => { commands.map(cmd => {
if (!categories.includes(cmd.category)) { if (!categories.includes(cmd.category)) categories.push(cmd.category);
categories.push(cmd.category) });
}
})
for (const category of categories) { for (const category of categories) {
if ( if (category.toLowerCase().includes("admin") || category.toLowerCase().includes("owner") || category.toLowerCase().includes("development") || category.toLowerCase().includes("suncountry") || category.toLowerCase().includes("iat")) continue;
category.toLowerCase().includes('admin') || const commandsArr = [];
category.toLowerCase().includes('owner') ||
category.toLowerCase().includes('development')
)
continue
let commandsArr = []
commands commands.filter(cmd => cmd.category === category).map(cmd => {
.filter((cmd) => cmd.category === category) const obj = {
.map((cmd) => { commandName: cmd.name,
let obj = { commandUsage: `${cmd.usage ? cmd.usage : `${prefix}${cmd.name}`}`,
commandName: cmd.name, commandDescription: cmd.description,
commandUsage: `${cmd.usage ? cmd.usage : `${prefix}${cmd.name}`}`, commandAlias: cmd.aliases?.join(", ") || "None",
commandDescription: cmd.description, };
commandAlias: cmd.aliases?.join(', ') || 'None' commandsArr.push(obj);
} });
commandsArr.push(obj)
})
const categoryObj = { const categoryObj = {
categoryId: category, categoryId: category,
category: `${capitalizeFirstLetter(category)}`, category: `${capitalizeFirstLetter(category)}`,
subTitle: `${capitalizeFirstLetter(category)} commands`, subTitle: `${capitalizeFirstLetter(category)} commands`,
list: commandsArr list: commandsArr,
} };
finalCategories.push(categoryObj) finalCategories.push(categoryObj);
} }
function capitalizeFirstLetter(string) { function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1) return string.charAt(0).toUpperCase() + string.slice(1);
} }
return finalCategories return finalCategories;
} };

View file

@ -1,165 +1,171 @@
const db = require('quick.db') const db = require("quick.db");
const consolePrefix = `${'['.blue}${'dbd-soft-ui'.yellow}${']'.blue} ` const consolePrefix = `${"[".blue}${"dbd-soft-ui".yellow}${"]".blue} `;
const colors = require('colors') const colors = require("colors");
const { icons, otherIcons } = require('../icons') const { icons, otherIcons } = require("../icons");
module.exports = class Feed { module.exports = class Feed {
constructor() { constructor() {
this.setColor = function (color) { this.setColor = function (color) {
if (!color) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red('Invalid color.')}`.cyan}`); if (!color) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red("Invalid color.")}`.cyan}`);
if ( if (color !== "red" && color !== "orange" && color !== "pink" && color !== "gray" && color !== "green" && color !== "blue" && color !== "dark") throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red("Invalid color.")}`.cyan}`);
color !== 'red' &&
color !== 'orange' &&
color !== 'pink' &&
color !== 'gray' &&
color !== 'green' &&
color !== 'blue' &&
color !== 'dark'
) {
throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red('Invalid color.')}`.cyan}`);
}
this.color = color; this.color = color;
return this; return this;
} };
this.setDescription = function (description) { this.setDescription = function (description) {
if (!description) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red('Invalid description.')}`.cyan}`); if (!description) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red("Invalid description.")}`.cyan}`);
if (description.length < 3 || description.length > 128) console.log(`${consolePrefix}${'Invalid description'.cyan}`); if (description.length < 3 || description.length > 128) console.log(`${consolePrefix}${"Invalid description".cyan}`);
this.description = description;
return this;
}
this.setIcon = function (icon) { this.description = description;
if (!icon) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red('Invalid icon.')}`.cyan}`); return this;
if (!icons.includes(icon) && !otherIcons.includes(icon)) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red('Invalid icon.')}`.cyan}`); };
this.icon = icon;
return this;
}
this.getFeed = function (id) { this.setIcon = function (icon) {
if (!id) throw new Error(`${consolePrefix}${`Failed to get feed. ${colors.red('Invalid id.')}`.cyan}`); if (!icon) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red("Invalid icon.")}`.cyan}`);
let feedName = ''; if (!icons.includes(icon) && !otherIcons.includes(icon)) throw new Error(`${consolePrefix}${`Failed to modify feed. ${colors.red("Invalid icon.")}`.cyan}`);
switch (id) {
case 1:
feedName = 'one';
break;
case 2:
feedName = 'two';
break;
case 3:
feedName = 'three';
break;
case "all":
feedName = 'all';
break;
default:
throw new Error(`${consolePrefix}${`Failed to get feed. ${colors.red('Invalid id.')}`.cyan}`);
}
let feed = db.get(`feeds${feedName === "all" ? "" : `.${feedName}`}`) this.icon = icon;
if (!feed) throw new Error(`${consolePrefix}${`Failed to get feed. ${colors.red('Feed not found.')}`.cyan}`); return this;
this.feed = feed; };
return this;
}
this.delete = function () { this.getFeed = function (id) {
if (!this.feed)throw new Error(`${consolePrefix}${`Failed to delete feed. ${colors.red('Feed not selected')}`.cyan}`); if (!id) throw new Error(`${consolePrefix}${`Failed to get feed. ${colors.red("Invalid id.")}`.cyan}`);
db.delete(`feeds.${this.feed.id}`);
return this;
}
this.send = async function () { let feedName = "";
const { color, description, icon } = this; switch (id) {
case 1:
feedName = "one";
break;
case 2:
feedName = "two";
break;
case 3:
feedName = "three";
break;
case "all":
feedName = "all";
break;
default:
throw new Error(`${consolePrefix}${`Failed to get feed. ${colors.red("Invalid id.")}`.cyan}`);
}
let diff; const feed = db.get(`feeds${feedName === "all" ? "" : `.${feedName}`}`);
let col;
if (otherIcons.includes(icon)) diff = true;
if (color === 'red') col = 'danger'; if (!feed) throw new Error(`${consolePrefix}${`Failed to get feed. ${colors.red("Feed not found.")}`.cyan}`);
if (color === 'orange') col = 'warning';
if (color === 'pink') col = 'primary';
if (color === 'gray') col = 'secondary';
if (color === 'green') col = 'success';
if (color === 'blue') col = 'info';
if (color === 'dark') col = 'dark';
if (db.get('feeds.three') && db.get('feeds.two') && db.get('feeds.one')) { this.feed = feed;
await db.delete('feeds.one') return this;
const f3 = db.get('feeds.three') };
const f2 = db.get('feeds.two')
await db.set('feeds.two', { this.delete = function () {
color: f3.color, if (!this.feed) throw new Error(`${consolePrefix}${`Failed to delete feed. ${colors.red("Feed not selected")}`.cyan}`);
description: f3.description,
published: f3.published, db.delete(`feeds.${this.feed.id}`);
icon: f3.icon,
diff: f3.diff return this;
}) };
await db.set('feeds.one', {
color: f2.color, this.send = async function () {
description: f2.description, const { color, description, icon } = this;
published: f2.published,
icon: f2.icon, let diff;
diff: f2.diff let col;
}) if (otherIcons.includes(icon)) diff = true;
await db.set('feeds.three', {
color: col, if (color === "red") col = "danger";
description: description, if (color === "orange") col = "warning";
published: Date.now(), if (color === "pink") col = "primary";
icon: icon, if (color === "gray") col = "secondary";
diff: diff if (color === "green") col = "success";
}) if (color === "blue") col = "info";
} else { if (color === "dark") col = "dark";
if (!db.get('feeds.three')) {
await db.set('feeds.three', { if (db.get("feeds.three") && db.get("feeds.two") && db.get("feeds.one")) {
color: col, await db.delete("feeds.one");
description: description,
published: Date.now(), const f3 = db.get("feeds.three");
icon: icon, const f2 = db.get("feeds.two");
diff: diff
}) await db.set("feeds.two", {
} else if (!db.get('feeds.two')) { color: f3.color,
const f3 = db.get('feeds.three') description: f3.description,
await db.set('feeds.two', { published: f3.published,
color: f3.color, icon: f3.icon,
description: f3.description, diff: f3.diff,
published: f3.published, });
icon: f3.icon,
diff: f3.diff await db.set("feeds.one", {
}) color: f2.color,
await db.set('feeds.three', { description: f2.description,
color: col, published: f2.published,
description: description, icon: f2.icon,
published: Date.now(), diff: f2.diff,
icon: icon, });
diff: diff
}) await db.set("feeds.three", {
} else { color: col,
const f3 = db.get('feeds.three') description: description,
const f2 = db.get('feeds.two') published: Date.now(),
await db.set('feeds.one', { icon: icon,
color: f2.color, diff: diff,
description: f2.description, });
published: f2.published, } else {
icon: f2.icon, if (!db.get("feeds.three")) {
diff: f2.diff await db.set("feeds.three", {
}) color: col,
await db.set('feeds.two', { description: description,
color: f3.color, published: Date.now(),
description: f3.description, icon: icon,
published: f3.published, diff: diff,
icon: f3.icon, });
diff: f3.diff } else if (!db.get("feeds.two")) {
}) const f3 = db.get("feeds.three");
await db.set('feeds.three', {
color: col, await db.set("feeds.two", {
description: description, color: f3.color,
published: Date.now(), description: f3.description,
icon: icon, published: f3.published,
diff: diff icon: f3.icon,
}) diff: f3.diff,
} });
}
} await db.set("feeds.three", {
} color: col,
} description: description,
published: Date.now(),
icon: icon,
diff: diff,
});
} else {
const f3 = db.get("feeds.three");
const f2 = db.get("feeds.two");
await db.set("feeds.one", {
color: f2.color,
description: f2.description,
published: f2.published,
icon: f2.icon,
diff: f2.diff,
});
await db.set("feeds.two", {
color: f3.color,
description: f3.description,
published: f3.published,
icon: f3.icon,
diff: f3.diff,
});
await db.set("feeds.three", {
color: col,
description: description,
published: Date.now(),
icon: icon,
diff: diff,
});
}
}
};
}
};

View file

@ -1,63 +1,63 @@
module.exports = { module.exports = {
multiRow: (options) => { multiRow: (options) => {
// Validate Data // Validate Data
if (options && (!options.length || !options[0])) throw new Error("Options in the 'collapsable' form type should be an array."); if (options && (!options.length || !options[0])) throw new Error("Options in the 'collapsable' form type should be an array.");
const hasType = (object) => object.hasOwnProperty('optionType') && object.optionType?.hasOwnProperty('type'); const hasType = object => Object.prototype.hasOwnProperty.call(object, "optionType") && Object.prototype.hasOwnProperty.call(object.optionType, "type");
if (options && !options.every(hasType)) throw new Error("Invalid form type provided in the 'multiRow' form type."); if (options && !options.every(hasType)) throw new Error("Invalid form type provided in the 'multiRow' form type.");
if (options && options.find(obj => obj.optionType.type == "multiRow")) throw new Error("You cannot use the form type 'multiRow' in the 'multiRow' form type."); if (options && options.find(obj => obj.optionType.type == "multiRow")) throw new Error("You cannot use the form type 'multiRow' in the 'multiRow' form type.");
return { return {
type: "multiRow", type: "multiRow",
options options,
} };
}, },
spacer: (themeOptions = {}) => { spacer: (themeOptions = {}) => {
return { return {
type: 'spacer', type: "spacer",
themeOptions themeOptions,
} };
}, },
emojiPicker: (disabled, themeOptions = {}) => { emojiPicker: (disabled, themeOptions = {}) => {
return { return {
type: 'emojiPicker', type: "emojiPicker",
disabled, disabled,
themeOptions themeOptions,
} };
}, },
slider: (min, max, step, disabled, themeOptions = {}) => { slider: (min, max, step, disabled, themeOptions = {}) => {
return { return {
type: 'slider', type: "slider",
min, min,
max, max,
step, step,
disabled, disabled,
themeOptions themeOptions,
} };
}, },
date: (disabled, themeOptions = {}) => { date: (disabled, themeOptions = {}) => {
return { return {
type: 'date', type: "date",
disabled, disabled,
themeOptions themeOptions,
} };
}, },
numberPicker: (min, max, disabled, themeOptions = {}) => { numberPicker: (min, max, disabled, themeOptions = {}) => {
return { return {
type: 'numberPicker', type: "numberPicker",
min, min,
max, max,
disabled, disabled,
themeOptions themeOptions,
} };
}, },
tagInput: (disabled, themeOptions = {}) => { tagInput: (disabled, themeOptions = {}) => {
return { return {
type: 'tagInput', type: "tagInput",
disabled, disabled,
themeOptions themeOptions,
} };
} },
} };

View file

@ -1,47 +1,44 @@
module.exports = function (config, themeConfig) { module.exports = function (config, themeConfig) {
config.errorPage = function (req, res, error, type) { config.errorPage = function (req, res, error, type) {
if (type == 404) { let title, subtitle, description = null;
title = themeConfig?.error?.error404?.title || '404'
subtitle =
themeConfig?.error?.error404?.subtitle || 'Page not found'
description =
themeConfig?.error?.error404?.description ||
'The page you are looking for does not exist.'
}
title = themeConfig?.error?.dbdError?.title || type.toString() if (type == 404) {
subtitle = themeConfig?.error?.dbdError?.subtitle || 'An error occurred' title = themeConfig?.error?.error404?.title || "404";
description = subtitle = themeConfig?.error?.error404?.subtitle || "Page not found";
themeConfig?.error?.dbdError?.description || description = themeConfig?.error?.error404?.description || "The page you are looking for does not exist.";
'Please contact us if the issue persists or try again later.' }
if (error) { title = themeConfig?.error?.dbdError?.title || type.toString();
console.error(error) subtitle = themeConfig?.error?.dbdError?.subtitle || "An error occurred";
} description =
themeConfig?.error?.dbdError?.description ||
"Please contact us if the issue persists or try again later.";
if (themeConfig?.error?.errorHandler) if (error) console.error(error);
themeConfig.error.errorHandler({
req,
res,
error: {
type,
path: error?.path || null,
error: error?.stack || `Page ${req.originalUrl} not found!`
},
user: req?.session?.user || null
})
return res.render('error', { if (themeConfig?.error?.errorHandler)
strError: error?.stack?.split('\n'), themeConfig.error.errorHandler({
req, req,
bot: config.bot, res,
config, error: {
type, type,
themeConfig, path: error?.path || null,
title, error: error?.stack || `Page ${req.originalUrl} not found!`,
subtitle, },
description, user: req?.session?.user || null,
error: error || undefined });
})
} return res.render("error", {
} strError: error?.stack?.split("\n"),
req,
bot: config.bot,
config,
type,
themeConfig,
title,
subtitle,
description,
error: error || undefined,
});
};
};

View file

@ -1,399 +1,266 @@
const Discord = require('discord.js') const { Permissions } = require("discord.js");
module.exports = function (config, themeConfig) { module.exports = function (config, themeConfig) {
config.guildSettings = async function (req, res, home, category) { // eslint-disable-next-line no-unused-vars
if (!req.session.user) return res.redirect('/discord?r=/guild/' + req.params.id) config.guildSettings = async function (req, res, home, category) {
if (!req.session.user) return res.redirect("/discord?r=/guild/" + req.params.id);
let bot = config.bot const bot = config.bot;
if (!bot.guilds.cache.get(req.params.id)) { if (!bot.guilds.cache.get(req.params.id)) {
try { try {
await bot.guilds.fetch(req.params.id) await bot.guilds.fetch(req.params.id);
} catch (err) { } } catch (e) { /* ... */ }
} }
if (!bot.guilds.cache.get(req.params.id)) return res.redirect('/manage?error=noPermsToManageGuild') if (!bot.guilds.cache.get(req.params.id)) return res.redirect("/manage?error=noPermsToManageGuild");
if ( if (!bot.guilds.cache.get(req.params.id).members.cache.get(req.session.user.id)) {
!bot.guilds.cache try {
.get(req.params.id) await bot.guilds.cache.get(req.params.id).members.fetch(req.session.user.id);
.members.cache.get(req.session.user.id) } catch (e) { /* ... */ }
) { }
try {
await bot.guilds.cache
.get(req.params.id)
.members.fetch(req.session.user.id)
} catch (err) { }
}
for (let PermissionRequired of req.requiredPermissions) {
let converted = PermissionRequired[0]
const DiscordJsVersion = Discord.version.split('.')[0]
if (DiscordJsVersion === '14') converted = await convert14(PermissionRequired[0])
if ( // for (const PermissionRequired of req.requiredPermissions) {
!bot.guilds.cache // const permissionsReq = Permissions.FLAGS[PermissionRequired[0]];
.get(req.params.id)
.members.cache.get(req.session.user.id)
.permissions.has(converted)
) {
return res.redirect('/manage?error=noPermsToManageGuild')
}
}
if (bot.guilds.cache.get(req.params.id).channels.cache.size < 1) { // if (!bot.guilds.cache.get(req.params.id).members.cache.get(req.session.user.id).permissions.has(permissionsReq))
try { // return res.redirect("/manage?error=noPermsToManageGuild");
await bot.guilds.cache.get(req.params.id).channels.fetch() // }
} catch (err) { }
}
if (bot.guilds.cache.get(req.params.id).roles.cache.size < 2) { if (bot.guilds.cache.get(req.params.id).channels.cache.size < 1) {
try { try {
await bot.guilds.cache.get(req.params.id).roles.fetch() await bot.guilds.cache.get(req.params.id).channels.fetch();
} catch (err) { } } catch (e) { /* ... */ }
} }
let actual = {} if (bot.guilds.cache.get(req.params.id).roles.cache.size < 2) {
let toggle = {} try {
let premium = {} await bot.guilds.cache.get(req.params.id).roles.fetch();
} catch (e) { /* ... */ }
}
let canUseList = {} const actual = {};
const toggle = {};
const premium = {};
if (config.settings?.length) for (const category of config.settings) { const canUseList = {};
if (!canUseList[category.categoryId]) canUseList[category.categoryId] = {};
if (!actual[category.categoryId]) actual[category.categoryId] = {}
if (config.useCategorySet) { if (config.settings?.length)
let catGAS = await category.getActualSet({ for (const category of config.settings) {
guild: { if (!canUseList[category.categoryId]) canUseList[category.categoryId] = {};
id: req.params.id, if (!actual[category.categoryId]) actual[category.categoryId] = {};
object: bot.guilds.cache.get(req.params.id),
},
user: {
id: req.session.user.id,
object: bot.guilds.cache
.get(req.params.id)
.members.cache.get(req.session.user.id),
},
});
if (category.toggleable) { if (config.useCategorySet) {
if (!toggle[category.categoryId]) { let catGAS = await category.getActualSet({
toggle[category.categoryId] = {} guild: {
} id: req.params.id,
toggle[category.categoryId] = catGAS.find(o => o.optionId === "categoryToggle") || null; object: bot.guilds.cache.get(req.params.id),
catGAS = catGAS.filter((c) => c.optionId !== 'categoryToggle') },
} user: {
if (category.premium) { id: req.session.user.id,
if (!premium[category.categoryId]) { object: bot.guilds.cache.get(req.params.id).members.cache.get(req.session.user.id),
premium[category.categoryId] = {} },
} });
premium[category.categoryId] = await s.premiumUser({
guild: {
id: req.params.id
},
user: {
id: req.session.user.id,
tag: req.session.user.tag
}
})
}
if (category.premium && premium[category.categoryId] == false) return res.redirect( if (category.toggleable) {
`/settings/${req.params.id}?error=premiumRequired` if (!toggle[category.categoryId]) {
) toggle[category.categoryId] = {};
}
toggle[category.categoryId] = catGAS.find(o => o.optionId === "categoryToggle") || null;
catGAS = catGAS.filter(c => c.optionId !== "categoryToggle");
}
if (category.premium) {
if (!premium[category.categoryId]) premium[category.categoryId] = {};
for (const o of catGAS) { premium[category.categoryId] = await category.premiumUser({
if (!o || !o?.optionId) { guild: {
console.log( id: req.params.id,
"WARNING: You haven't set the optionId for a category option in your config. This is required for the category option to work." },
) user: {
continue; id: req.session.user.id,
} tag: req.session.user.tag,
const option = category.categoryOptionsList.find( },
(c) => c.optionId == o.optionId });
) }
if (option) {
if (option.allowedCheck) {
const canUse = await option.allowedCheck({
guild: {
id: req.params.id,
},
user: {
id: req.session.user.id,
},
})
if (typeof canUse != "object") if (category.premium && premium[category.categoryId] == false)
throw new TypeError( return res.redirect(`/settings/${req.params.id}?error=premiumRequired`);
`${category.categoryId} category option with id ${option.optionId} allowedCheck function need to return {allowed: Boolean, errorMessage: String | null}`
)
canUseList[category.categoryId][
option.optionId
] = canUse
} else {
canUseList[category.categoryId][
option.optionId
] = {
allowed: true,
errorMessage: null,
}
}
if (option.optionType !== "spacer") { for (const o of catGAS) {
if (!actual[category.categoryId]) { if (!o || !o?.optionId) {
actual[category.categoryId] = {} console.log("WARNING: You haven't set the optionId for a category option in your config. This is required for the category option to work.");
} continue;
if ( }
!actual[category.categoryId][
option.optionId
]
) {
actual[category.categoryId][
option.optionId
] = o.data
}
} else actual[category.categoryId][option.optionId] = {
type: 'spacer',
themeOptions: option.themeOptions
}
} else console.log(`WARNING: Option ${o.optionId} in category ${category.categoryId} doesn't exist in your config.`)
} const option = category.categoryOptionsList.find(c => c.optionId == o.optionId);
} else for (const s of config.settings) {
if (!canUseList[s.categoryId]) canUseList[s.categoryId] = {}
if (s.toggleable) {
if (!toggle[s.categoryId]) {
toggle[s.categoryId] = {}
}
toggle[s.categoryId] = await s.getActualSet({
guild: {
id: req.params.id
}
})
}
if (s.premium) {
if (!premium[s.categoryId]) {
premium[s.categoryId] = {}
}
premium[s.categoryId] = await s.premiumUser({
guild: {
id: req.params.id
},
user: {
id: req.session.user.id,
tag: req.session.user.tag
}
})
}
if (category) { if (option) {
if (s.premium && premium[category] == false) { if (option.allowedCheck) {
return res.redirect( const canUse = await option.allowedCheck({
`/settings/${req.params.id}?error=premiumRequired` guild: { id: req.params.id },
) user: { id: req.session.user.id },
} });
}
for (const c of s.categoryOptionsList) { if (typeof canUse != "object") throw new TypeError(`${category.categoryId} category option with id ${option.optionId} allowedCheck function need to return {allowed: Boolean, errorMessage: String | null}`);
if (c.allowedCheck) {
const canUse = await c.allowedCheck({
guild: { id: req.params.id },
user: { id: req.session.user.id }
})
if (typeof canUse != 'object') {
throw new TypeError(
`${s.categoryId} category option with id ${c.optionId} allowedCheck function need to return {allowed: Boolean, errorMessage: String | null}`
)
}
canUseList[s.categoryId][c.optionId] = canUse
} else {
canUseList[s.categoryId][c.optionId] = {
allowed: true,
errorMessage: null
}
}
if (!actual[s.categoryId]) actual[s.categoryId] = {} canUseList[category.categoryId][option.optionId] = canUse;
} else {
canUseList[category.categoryId][option.optionId] = {
allowed: true,
errorMessage: null,
};
}
if (c.optionType.type == 'spacer') { if (option.optionType !== "spacer") {
actual[s.categoryId][c.optionId] = { if (!actual[category.categoryId]) actual[category.categoryId] = {};
type: 'spacer',
themeOptions: c.themeOptions
}
} else if (
c.optionType.type == 'collapsable' ||
c.optionType.type == 'modal'
) {
for (const item of c.optionType.options) {
if (
item.optionType.type == 'channelsMultiSelect' ||
item.optionType.type == 'roleMultiSelect' ||
item.optionType.type == 'tagInput'
) {
actual[s.categoryId][item.optionId] = []
}
}
} else {
if (!actual[s.categoryId]) {
actual[s.categoryId] = {}
}
if (!actual[s.categoryId][c.optionId]) {
if (c.optionType.type === "multiRow") {
for (const item of c.optionType.options) {
actual[s.categoryId][item.optionId] = await item.getActualSet(
{
guild: {
id: req.params.id,
object: bot.guilds.cache.get(req.params.id)
},
user: {
id: req.session.user.id,
object: bot.guilds.cache
.get(req.params.id)
.members.cache.get(req.session.user.id)
}
}
)
}
continue
}
actual[s.categoryId][c.optionId] = await c.getActualSet(
{
guild: {
id: req.params.id,
object: bot.guilds.cache.get(req.params.id)
},
user: {
id: req.session.user.id,
object: bot.guilds.cache
.get(req.params.id)
.members.cache.get(req.session.user.id)
}
}
)
}
}
}
}
}
let errors if (!actual[category.categoryId][option.optionId])
let success actual[category.categoryId][option.optionId] = o.data;
// boo } else actual[category.categoryId][option.optionId] = {
if (req.session.errors) { type: "spacer",
if (String(req.session.errors).includes('%is%')) { themeOptions: option.themeOptions,
errors = req.session.errors.split('%and%') };
} } else console.log(`WARNING: Option ${o.optionId} in category ${category.categoryId} doesn't exist in your config.`);
} }
} else
for (const s of config.settings) {
if (!canUseList[s.categoryId]) canUseList[s.categoryId] = {};
if (req.session.success) { if (s.toggleable) {
if (typeof req.session.success == 'boolean') { if (!toggle[s.categoryId]) toggle[s.categoryId] = {};
success = true
} else {
if (String(req.session.success).includes('%is%')) {
success = req.session.success.split('%and%')
}
}
}
req.session.errors = null toggle[s.categoryId] = await s.getActualSet({
req.session.success = null guild: {
id: req.params.id,
},
});
}
if (s.premium) {
if (!premium[s.categoryId]) premium[s.categoryId] = {};
const guild = bot.guilds.cache.get(req.params.id) premium[s.categoryId] = await s.premiumUser({
let gIcon guild: {
id: req.params.id,
},
user: {
id: req.session.user.id,
tag: req.session.user.tag,
},
});
}
if (!guild.iconURL()) gIcon = themeConfig?.icons?.noGuildIcon if (category)
else gIcon = guild.iconURL() if (s.premium && premium[category] == false)
return res.redirect(`/settings/${req.params.id}?error=premiumRequired`);
res.render('settings', { for (const c of s.categoryOptionsList) {
successes: success, if (c.allowedCheck) {
errors: errors, const canUse = await c.allowedCheck({
settings: config.settings, guild: { id: req.params.id },
actual: actual, user: { id: req.session.user.id },
toggle, });
premium,
canUseList,
bot: config.bot,
guild,
userid: req.session.user.id,
gIcon,
req: req,
guildid: req.params.id,
themeConfig: req.themeConfig,
config
})
}
}
async function convert14(perm) { if (typeof canUse != "object") throw new TypeError(`${s.categoryId} category option with id ${c.optionId} allowedCheck function need to return {allowed: Boolean, errorMessage: String | null}`);
var final = 'NULL'
switch (perm) { canUseList[s.categoryId][c.optionId] = canUse;
case 'CREATE_INSTANT_INVITE': } else {
final = 'CreateInstantInvite' canUseList[s.categoryId][c.optionId] = {
break allowed: true,
case 'KICK_MEMBERS': errorMessage: null,
final = 'KickMembers' };
break }
case 'BAN_MEMBERS':
final = 'BanMembers'
break
case 'ADMINISTRATOR':
final = 'Administrator'
break
case 'MANAGE_CHANNELS':
final = 'ManageChannels'
break
case 'MANAGE_GUILD':
final = 'ManageGuild'
break
case 'ADD_REACTIONS':
final = 'AddReactions'
break
case 'VIEW_AUDIT_LOG':
final = 'ViewAuditLog'
break
case 'PRIORITY_SPEAKER':
final = 'PrioritySpeaker'
break
case 'STREAM':
final = 'Stream'
break
case 'VIEW_CHANNEL':
final = 'ViewChannel'
break
case 'SEND_MESSAGES':
final = 'SendMessages'
break
case 'SEND_TTS_MESSAGES':
final = 'SendTTSMessages'
break
case 'MANAGE_MESSAGES':
final = 'ManageMessages'
break
case 'EMBED_LINKS':
final = 'ManageMessages'
break
case 'ATTACH_FILES':
final = 'AttachFiles'
break
case 'READ_MESSAGE_HISTORY':
final = 'ReadMessageHistory'
break
case 'MENTION_EVERYONE':
final = 'MentionEveryone'
break
case 'USE_EXTERNAL_EMOJIS':
final = 'UseExternalEmojis'
break
case 'VIEW_GUILD_INSIGHTS':
final = 'ViewGuildInsughts'
break
case 'CONNECT':
final = 'Connect'
break
case 'SPEAK':
final = 'Speak'
break
}
return final if (!actual[s.categoryId]) actual[s.categoryId] = {};
}
if (c.optionType.type == "spacer") {
actual[s.categoryId][c.optionId] = {
type: "spacer",
themeOptions: c.themeOptions,
};
} else if (c.optionType.type == "collapsable" || c.optionType.type == "modal") {
for (const item of c.optionType.options) {
if (item.optionType.type == "channelsMultiSelect" || item.optionType.type == "roleMultiSelect" || item.optionType.type == "tagInput")
actual[s.categoryId][item.optionId] = [];
}
} else {
if (!actual[s.categoryId]) actual[s.categoryId] = {};
if (!actual[s.categoryId][c.optionId]) {
if (c.optionType.type === "multiRow") {
for (const item of c.optionType.options) {
actual[s.categoryId][item.optionId] = await item.getActualSet({
guild: {
id: req.params.id,
object: bot.guilds.cache.get(req.params.id),
},
user: {
id: req.session.user.id,
object: bot.guilds.cache.get(req.params.id).members.cache.get(req.session.user.id),
},
});
}
continue;
}
actual[s.categoryId][c.optionId] = await c.getActualSet({
guild: {
id: req.params.id,
object: bot.guilds.cache.get(req.params.id),
},
user: {
id: req.session.user.id,
object: bot.guilds.cache.get(req.params.id).members.cache.get(req.session.user.id),
},
});
}
}
}
}
}
let errors;
let success;
if (req.session.errors) {
if (String(req.session.errors).includes("%is%")) {
errors = req.session.errors.split("%and%");
}
}
if (req.session.success) {
if (typeof req.session.success == "boolean")
success = true;
else {
if (String(req.session.success).includes("%is%")) {
success = req.session.success.split("%and%");
}
}
}
req.session.errors = null;
req.session.success = null;
const guild = bot.guilds.cache.get(req.params.id);
let gIcon;
if (!guild.iconURL()) gIcon = themeConfig?.icons?.noGuildIcon;
else gIcon = guild.iconURL();
res.render("settings", {
successes: success,
errors: errors,
settings: config.settings,
actual: actual,
toggle,
premium,
canUseList,
bot: config.bot,
guild,
userid: req.session.user.id,
gIcon,
req: req,
guildid: req.params.id,
themeConfig: req.themeConfig,
config,
});
};
};

View file

@ -1,89 +1,66 @@
const fs = require('fs') const fs = require("fs");
const colors = require('colors') const colors = require("colors");
const consolePrefix = `${'['.blue}${'dbd-soft-ui'.yellow}${']'.blue} ` const consolePrefix = `${"[".blue}${"dbd-soft-ui".yellow}${"]".blue} `;
const Nodeactyl = require('nodeactyl') const Nodeactyl = require("nodeactyl");
module.exports = { module.exports = {
init: async function (config, themeConfig, app, db) { init: async function (config, themeConfig, app, db) {
let info; let info;
if (themeConfig?.customThemeOptions?.info) info = await themeConfig.customThemeOptions.info({ config: config }); if (themeConfig?.customThemeOptions?.info) info = await themeConfig.customThemeOptions.info({ config: config });
if(themeConfig?.admin?.pterodactyl?.enabled) {
themeConfig.nodeactyl = new Nodeactyl.NodeactylClient(
themeConfig.admin?.pterodactyl?.panelLink,
themeConfig.admin?.pterodactyl?.apiKey
)
try { if (themeConfig?.admin?.pterodactyl?.enabled) {
await themeConfig.nodeactyl.getAccountDetails(); themeConfig.nodeactyl = new Nodeactyl.NodeactylClient(themeConfig.admin?.pterodactyl?.panelLink, themeConfig.admin?.pterodactyl?.apiKey);
} catch (error) {
console.log(`${consolePrefix}${('Failed to connect to Pterodactyl panel!\nEnsure you\'ve used a CLIENT api key, (found at ' + themeConfig.admin.pterodactyl.panelLink + '/account/api)').red}`);
}
}
const eventFolders = fs.readdirSync(`${__dirname}/../pages`)
for (const folder of eventFolders) { try {
const eventFiles = fs await themeConfig.nodeactyl.getAccountDetails();
.readdirSync(`${__dirname}/../pages/${folder}`) } catch (error) {
.filter((file) => file.endsWith('.js')); console.log(`${consolePrefix}${("Failed to connect to Pterodactyl panel!\nEnsure you've used a CLIENT api key, (found at " + themeConfig.admin.pterodactyl.panelLink + "/account/api)").red}`);
for (const file of eventFiles) { }
const e = require(`${__dirname}/../pages/${folder}/${file}`); }
try {
if (folder === 'admin') {
await app.get(e.page, async function (req, res) {
if (!req.session.user) return res.sendStatus(401)
if (!config.ownerIDs?.includes(req.session.user.id)) return res.sendStatus(403);
e.execute(
req,
res,
app,
config,
themeConfig,
info,
db
)
})
} else if (folder === 'post') {
await app.post(e.page, function (req, res) {
e.execute(
req,
res,
app,
config,
themeConfig,
info,
db
)
})
} else if (folder === 'get') {
await app.use(e.page, async function (req, res) {
e.execute(
req,
res,
app,
config,
themeConfig,
info,
db
)
})
}
} catch (error) {
console.log(`${consolePrefix}${'Failed to load:'.cyan} ${colors.red(e.page)}`);
console.log(`Page handler ${file}: ${error}`);
}
}
}
app.use('*', async function (req, res) { const eventFolders = fs.readdirSync(`${__dirname}/../pages`);
res.status(404)
config.errorPage(req, res, undefined, 404)
})
app.use((err, req, res, next) => { for (const folder of eventFolders) {
res.status(500) const eventFiles = fs.readdirSync(`${__dirname}/../pages/${folder}`).filter((file) => file.endsWith(".js"));
config.errorPage(req, res, err, 500)
})
console.log(`${consolePrefix}${'Initialised all pages!'.cyan}`); for (const file of eventFiles) {
} const e = require(`${__dirname}/../pages/${folder}/${file}`);
}
try {
if (folder === "admin") {
await app.get(e.page, async function (req, res) {
if (!req.session.user) return res.sendStatus(401);
if (!config.ownerIDs?.includes(req.session.user.id)) return res.sendStatus(403);
e.execute(req, res, app, config, themeConfig, info, db);
});
} else if (folder === "post") {
await app.post(e.page, function (req, res) {
e.execute(req, res, app, config, themeConfig, info, db);
});
} else if (folder === "get") {
await app.use(e.page, async function (req, res) {
e.execute(req, res, app, config, themeConfig, info, db);
});
}
} catch (error) {
console.log(`${consolePrefix}${"Failed to load:".cyan} ${colors.red(e.page)}`);
console.log(`Page handler ${file}: ${error}`);
}
}
}
app.use("*", async function (req, res) {
res.status(404);
config.errorPage(req, res, undefined, 404);
});
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
res.status(500);
config.errorPage(req, res, err, 500);
});
console.log(`${consolePrefix}${"Initialised all pages!".cyan}`);
},
};

View file

@ -1,80 +0,0 @@
const fetch = require('node-fetch')
const fs = require('fs')
const consolePrefix = `\x1b[34m[\x1b[33mdbd-soft-ui\x1b[34m]\x1b[36m `
const colors = require('colors')
async function update() {
let failed3 = 0
let failed4 = 0
try {
await fetch(`https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/utils/updater/versionsOnline.json`);
} catch (error) {
failed3++
console.log(`${consolePrefix}Failed to check live for updates.`)
}
if (failed3 === 0) {
let checkArray = await fetch(`https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/utils/updater/versionsOnline.json`);
try {
checkArray = await checkArray.json()
} catch (error) {
failed4++
console.log(`${consolePrefix}Failed to check live for updates.`)
}
if (failed4 === 0) {
let latestVersions = [];
let currentVersions = fs.readFileSync(__dirname + '/versions.json');
currentVersions = JSON.parse(currentVersions);
let needsUpdating = [];
for (const latestFile of checkArray) {
if (latestFile.version > currentVersions[latestFile.name]) {
needsUpdating.push({
name: latestFile.name,
type: latestFile.type
})
const { name, type } = latestFile
if (type === 'partial') {
let failedFile = 0
let fileRaw = await fetch(`https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/partials/${name}.ejs`);
try {
fileRaw = await fileRaw.text()
} catch (error) {
failedFile++
console.log(
`${consolePrefix}Failed to update ${colors.red(
name
)}.`
)
}
if (failedFile === 0) {
await fs.writeFileSync(
`${__dirname}/../../views/partials/${name}.ejs`,
fileRaw
)
currentVersions[name] = latestFile.version
await fs.writeFileSync(
`${__dirname}/versions.json`,
JSON.stringify(currentVersions)
)
console.log(
`${consolePrefix}Successfully updated ${colors.green(
name
)}`
)
}
}
}
}
}
}
}
exports.update = async () => {
await update()
}

View file

@ -1,3 +0,0 @@
exports.update = () => {
return;
}

View file

@ -1,17 +0,0 @@
{
"colorscheme": "1.0.64",
"feeds": "1.0.62",
"footer": "1.0.1",
"graph": "1.0.2",
"iconsList": "1.0.0",
"meta": "0.0.0",
"navbar": "1.0.11",
"popup": "1.1.5",
"preload": "0.0.0",
"preloader": "1.1.14",
"premium": "1.0.0",
"scripts": "0.0.0",
"secret": "1.0.0",
"sidebar": "0.0.0",
"theme": "1.1.0"
}

View file

@ -1,57 +0,0 @@
[
{
"name": "colorscheme",
"version": "1.0.64",
"type": "partial"
},
{
"name": "footer",
"version": "1.0.1",
"type": "partial"
},
{
"name": "graph",
"version": "1.0.2",
"type": "partial"
},
{
"name": "iconsList",
"version": "1.0.0",
"type": "partial"
},
{
"name": "navbar",
"version": "1.0.11",
"type": "partial"
},
{
"name": "popup",
"version": "1.1.5",
"type": "partial"
},
{
"name": "preloader",
"version": "1.1.14",
"type": "partial"
},
{
"name": "premium",
"version": "1.0.0",
"type": "partial"
},
{
"name": "secret",
"version": "1.0.0",
"type": "partial"
},
{
"name": "theme",
"version": "1.1.0",
"type": "partial"
},
{
"name": "preload",
"version": "0.0.0",
"type": "partial"
}
]

File diff suppressed because one or more lines are too long

View file

@ -1,167 +1,155 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<%- include('partials/preloader.ejs', {now: 'commands'}) %> <%- include("partials/preloader.ejs", {now: "commands"}) %>
<script> <script>
// docuemnt on read // document on read
document.addEventListener('DOMContentLoaded', function() { document.addEventListener("DOMContentLoaded", function() {
$('.glow').removeClass('active'); $(".glow").removeClass("active");
$('.active_all').addClass('active'); $(".active_all").addClass("active");
}); });
$(function () {
$('#all').click(function () { $(function () {
$('.item').slideDown("slow"); $("#all").click(function () {
$('.glow').removeClass('active'); $(".item").slideDown("slow");
$('.active_all').addClass('active'); $(".glow").removeClass("active");
return false; $(".active_all").addClass("active");
}); return false;
<% themeConfig.commands?.forEach(category => { %> });
$('#<%= category.categoryId %>').click(function () { <% themeConfig.commands?.forEach(category => { %>
$('.item').not('.<%= category.categoryId %>').slideUp(300); $("#<%= category.categoryId %>").click(function () {
$('.<%= category.categoryId %>').slideDown("slow"); $(".item").not(".<%= category.categoryId %>").slideUp(300);
$('.glow').removeClass('active'); $(".<%= category.categoryId %>").slideDown("slow");
$('.active_<%= category.categoryId %>').addClass('active'); $(".glow").removeClass("active");
return false; $(".active_<%= category.categoryId %>").addClass("active");
}); return false;
<% }) %> });
}); <% }) %>
</script> });
<%- themeConfig?.customHtml %> </script>
<%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100" id="scroll"> <body class="g-sidenav-show bg-gray-100" id="scroll">
<%- include('partials/preload.ejs') %> <%- include("partials/preload.ejs") %>
<%- include('partials/sidebar.ejs', {config: config, now:'commands'}) %> <%- include("partials/sidebar.ejs", {config: config, now:"commands"}) %>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<!-- Navbar --> <!-- Navbar -->
<%- include('partials/navbar.ejs', {now:'commands'}) %> <%- include("partials/navbar.ejs", {now:"commands"}) %>
<!-- End Navbar --> <!-- End Navbar -->
<div class="container-fluid py-4"> <div class="container-fluid py-4">
<div class="row"> <div class="row">
<div class="container-fluid"> <div class="container-fluid">
<% themeConfig.commands?.forEach(category => { %> <% themeConfig.commands?.forEach(category => { %>
<section id="<%= category.categoryId %>"> <% if (!category.hideSidebarItem) { %>
<div class="col-12 item <%= category.categoryId %>" id="divtable"> <section id="<%= category.categoryId %>">
<div class="card mb-4 command-card"> <div class="col-12 item <%= category.categoryId %>" id="divtable">
<div class="card-header pb-0"> <div class="card mb-4 command-card">
<h4><%= category.category %></h4> <div class="card-header pb-0">
<a><%= category.subTitle %></a> <h4><%= category.category %></h4>
</div> <a><%= category.subTitle %></a>
<div class="card-body px-0 pt-0 pb-2"> </div>
<div class="table-responsive p-0"> <div class="card-body px-0 pt-0 pb-2">
<table class="table align-items-center mb-0" name="commandsTable" id="table"> <div class="table-responsive p-0">
<thead> <table class="table align-items-center mb-0" name="commandsTable" id="table">
<tr> <thead>
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7"> <tr>
Name <th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">
</th> Name
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2"> </th>
Command Usage <th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2">
</th> Command Usage
<% if(!category.hideDescription) { %> </th>
<th class="text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7"> <% if(!category.hideDescription) { %>
Description <th class="text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">
</th> Description
<% } %> </th>
<% if(!category.hideAlias) { %> <% } %>
<th class="text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7"> <% if(!category.hideAlias) { %>
Aliases <th class="text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">
</th> Aliases
<% } %> </th>
<th class="text-secondary opacity-7"></th> <% } %>
</tr> <th class="text-secondary opacity-7"></th>
</thead> </tr>
<tbody> </thead>
<% category.list.forEach((item)=>{ %> <tbody>
<tr> <% category.list.forEach((item)=>{ %>
<td> <tr>
<div class="d-flex px-2 py-1"> <td>
<div> <div class="d-flex px-2 py-1">
<% if(category.image){ %> <div>
<%- category.image %> <% if(category.image){ %>
<% } %> <%- category.image %>
</div> <% } %>
<div class="d-flex flex-column justify-content-center"> </div>
<h6 class="mb-0 text-sm"><%= item.commandName %></h6> <div class="d-flex flex-column justify-content-center">
</div> <h6 class="mb-0 text-sm"><%= item.commandName %></h6>
</div> </div>
</td> </div>
<td> </td>
<p class="text-xs font-weight-bold mb-0"><%= item.commandUsage %></p> <td>
</td> <p class="text-xs font-weight-bold mb-0"><%= item.commandUsage %></p>
<% if(!category.hideDescription) { %> </td>
<td class="align-middle text-center text-sm"> <% if(!category.hideDescription) { %>
<p class="text-xs font-weight-bold mb-0"><%= item.commandDescription %></p> <td class="align-middle text-center text-sm">
</td> <p class="text-xs font-weight-bold mb-0"><%= item.commandDescription %></p>
<% } %> </td>
<% if(!category.hideAlias) { %> <% } %>
<td class="align-middle text-center"> <% if(!category.hideAlias) { %>
<span class="text-secondary text-xs font-weight-bold"><%= item.commandAlias %></span> <td class="align-middle text-center">
</td> <span class="text-secondary text-xs font-weight-bold"><%= item.commandAlias %></span>
<% } %> </td>
<td class="align-middle"> <% } %>
<a class="text-secondary font-weight-bold text-xs" <td class="align-middle">
data-toggle="tooltip" <a class="text-secondary font-weight-bold text-xs"
data-original-title="Edit user"> data-toggle="tooltip"
data-original-title="Edit user">
</a> </a>
</td> </td>
</tr> </tr>
<% }) %> <% }) %>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<% }) %> <% } %>
</div> <% }) %>
</div> </div>
</main> </div>
<%- include('partials/footer.ejs') %> </main>
<script> <%- include("partials/footer.ejs") %>
$('#searchBar').on('change keyup paste enter', function () { <script>
var input = $(this).val().toLowerCase(); $("#searchBar").on("change keyup paste enter", function () {
const divs = $(".command-card").toArray() const input = $(this).val().toLowerCase();
const divs = $(".command-card").toArray()
if (!input || input.length <= 0) { if (!input || input.length <= 0) {
$('.item').show(); $(".item").show();
$(divs).show(); $(divs).show();
} }
$('tr').show() $("tr").show()
$('tr:not(:contains(' + input + '))').hide() $("tr:not(:contains(" + input + "))").hide()
for (const item of divs) { for (const item of divs) {
try { try {
const tbody = item.firstChild.nextElementSibling.nextElementSibling.firstChild.nextElementSibling.firstChild.nextElementSibling.firstChild.nextElementSibling.nextElementSibling const tbody = item.firstChild.nextElementSibling.nextElementSibling.firstChild.nextElementSibling.firstChild.nextElementSibling.firstChild.nextElementSibling.nextElementSibling
if ($(tbody).children(':visible').length == 0) $(item).hide() if ($(tbody).children(":visible").length == 0) $(item).hide()
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
} }
}); });
</script> </script>
<%- include('partials/scripts.ejs', {now: "commands"}) %> <%- include("partials/scripts.ejs", {now: "commands"}) %>
</body> </body>
</html> </html>

View file

@ -1,32 +1,32 @@
<style> <style>
.select2-results__option.select2-results__option--selectable:before { .select2-results__option.select2-results__option--selectable:before {
content: "# "; content: "# ";
} }
</style> </style>
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<select placeholder="Select" class="multiSelect form-control" <select placeholder="Select" class="multiSelect form-control"
formType="channelMultiSelect" formType="channelMultiSelect"
id="<%= option.optionId %>" id="<%= option.optionId %>"
defaultValue="" defaultValue=""
<% if(option.optionType.disabled){ %>disabled <% if(option.optionType.disabled){ %>disabled
<% } %> <% } %>
<% if(option.optionType.required){ %>required <% if(option.optionType.required){ %>required
<% } %> <% } %>
style="width:100%;background: #f9f9ff;border-color: #f9f9ff;<% if(!Allowed.allowed){ %>border-color: red;<% } %>" style="width:100%;background: #f9f9ff;border-color: #f9f9ff;<% if(!Allowed.allowed){ %>border-color: red;<% } %>"
multiple="multiple" multiple="multiple"
<% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %> <% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %>
> >
<% if (actual[s.categoryId][option.optionId]) { <% if (actual[s.categoryId][option.optionId]) {
let ioooooo = 0; let ioooooo = 0;
let functiona = option.optionType.function(bot, guildid, userid); let functiona = option.optionType.function(bot, guildid, userid);
functiona.values.forEach(value=>{ %> functiona.values.forEach(value=>{ %>
<option value="<%= value %>" <option value="<%= value %>"
<% if(actual[s.categoryId][option.optionId].includes(value)){ %>selected <% if(actual[s.categoryId][option.optionId].includes(value)){ %>selected
<% } %> <% } %>
><%= functiona.keys[ioooooo] %></option> ><%= functiona.keys[ioooooo] %></option>
<% ioooooo++; })} %> <% ioooooo++; })} %>
</select> </select>
<br> <br>

View file

@ -1,19 +1,19 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<select <select
<% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %> <% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %>
formType="channelSelect" formType="channelSelect"
defaultValue="" defaultValue=""
class="form-select" class="form-select"
id="<%= option.optionId %>" class="col-md-12" id="<%= option.optionId %>" class="col-md-12"
style="<% if(!Allowed.allowed){ %>border-color: red;<% } %> "> style="<% if(!Allowed.allowed){ %>border-color: red;<% } %> ">
<% <%
let ioooooo = 0; let ioooooo = 0;
let functiona = option.optionType.function(bot, guildid, userid); let functiona = option.optionType.function(bot, guildid, userid);
functiona.values.forEach(value=>{ %> functiona.values.forEach(value=>{ %>
<option value="<%= value %>" <option value="<%= value %>"
<% if(actual[s.categoryId][option.optionId] == value){ %>selected <% if(actual[s.categoryId][option.optionId] == value){ %>selected
<% } %> <% } %>
><%= functiona.keys[ioooooo] %></option> ><%= functiona.keys[ioooooo] %></option>
<% ioooooo++; }); %> <% ioooooo++; }); %>
</select> </select>

View file

@ -1,14 +1,14 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<label class="container"> <label class="container">
<input type="checkbox" id="<%= option.optionId %>" <input type="checkbox" id="<%= option.optionId %>"
formType="checkbox" formType="checkbox"
id="<%= option.optionId %>" id="<%= option.optionId %>"
formType="checkbox" formType="checkbox"
defaultValue="" defaultValue=""
<% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %> <% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %>
<% if(!Allowed.allowed){ %>style="border-color: red;"<% } %> <% if(!Allowed.allowed){ %>style="border-color: red;"<% } %>
> >
<span class="checkmark round"></span> <span class="checkmark round"></span>
</label> </label>
<br> <br>

View file

@ -1,9 +1,9 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<input type="color" id="<%= option.optionId %>" <input type="color" id="<%= option.optionId %>"
id="<%= option.optionId %>" id="<%= option.optionId %>"
formType="colorSelect" formType="colorSelect"
class="form-control form-control-color" class="form-control form-control-color"
value="<%= actual[s.categoryId][option.optionId] || option.optionType.data || "#ffffff" %>" value="<%= actual[s.categoryId][option.optionId] || option.optionType.data || "#ffffff" %>"
<% if(option.optionType.disabled){ %>disabled<% } %> <% if(option.optionType.disabled){ %>disabled<% } %>
<% if(!Allowed.allowed){ %>style="border-color: red;" disabled<% } %> <% if(!Allowed.allowed){ %>style="border-color: red;" disabled<% } %>
> >

View file

@ -1,26 +1,26 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<input <input
defaultValue="" defaultValue=""
class="form-control" class="form-control"
type="date" type="date"
id="<%= option.optionId %>" id="<%= option.optionId %>"
formType="date" formType="date"
<% if(actual[s.categoryId][option.optionId]){ %> <% if(actual[s.categoryId][option.optionId]){ %>
value="<%= actual[s.categoryId][option.optionId] %>" value="<%= actual[s.categoryId][option.optionId] %>"
<% } else { %> <% } else { %>
value="<%- new Date().toISOString().slice(0, 10) %>" value="<%- new Date().toISOString().slice(0, 10) %>"
<% } %> <% } %>
<% if(option?.themeOptions?.min) { %> <% if(option?.themeOptions?.min) { %>
min="<%= option.themeOptions.min%>" min="<%= option.themeOptions.min%>"
<% } %> <% } %>
<% if(option?.themeOptions?.max) { %> <% if(option?.themeOptions?.max) { %>
max="<%= option.themeOptions.max%>" max="<%= option.themeOptions.max%>"
<% } %> <% } %>
<% if(!Allowed.allowed){ %> <% if(!Allowed.allowed){ %>
style="border-color: red;" style="border-color: red;"
<% } %> <% } %>
<% if (!Allowed.allowed || option.optionType.disabled) { %> <% if (!Allowed.allowed || option.optionType.disabled) { %>
disabled disabled
<% } %> <% } %>
> >

View file

@ -1,106 +1,106 @@
<style> <style>
.iframe-container { .iframe-container {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */ padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */
} }
@media (max-width: 570px) { @media (max-width: 570px) {
.iframe-container { .iframe-container {
padding-top: 150%; padding-top: 150%;
} }
} }
@media (min-width: 570px) and (max-width: 760px) { @media (min-width: 570px) and (max-width: 760px) {
.iframe-container { .iframe-container {
padding-top: 130%; padding-top: 130%;
} }
} }
@media (min-width: 760px) and (max-width: 980px) { @media (min-width: 760px) and (max-width: 980px) {
.iframe-container { .iframe-container {
padding-top: 110%; padding-top: 110%;
} }
} }
@media (min-width: 980px) and (max-width: 1247px) { @media (min-width: 980px) and (max-width: 1247px) {
.iframe-container { .iframe-container {
padding-top: 95%; padding-top: 95%;
} }
} }
.responsive-iframe { .responsive-iframe {
border: none; border: none;
border-radius: 10px; border-radius: 10px;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
</style> </style>
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<textarea id="<%= option.optionId %>" name="<%= option.optionId %>" formType="embedBuilder" <textarea id="<%= option.optionId %>" name="<%= option.optionId %>" formType="embedBuilder"
style="visibility: hidden;width: .1px;height: .1px"><%- JSON.stringify(actual[s.categoryId][option.optionId]) || "" %></textarea> style="visibility: hidden;width: .1px;height: .1px"><%- JSON.stringify(actual[s.categoryId][option.optionId]) || "" %></textarea>
<div class="iframe-container"> <div class="iframe-container">
<% <%
let embedContent; let embedContent;
if (actual[s.categoryId][option.optionId] == null) { if (actual[s.categoryId][option.optionId] == null) {
if (option.optionType.data.defaultJson) { if (option.optionType.data.defaultJson) {
embedContent = JSON.stringify(option.optionType.data.defaultJson, null, 3); embedContent = JSON.stringify(option.optionType.data.defaultJson, null, 3);
} else { } else {
embedContent = `{ embedContent = `{
content: "Did you know that if you don't know something, you don't know it? This riddle was solved by me. Don't thank me.", content: "Did you know that if you don't know something, you don't know it? This riddle was solved by me. Don't thank me.",
embed: { embed: {
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
url: "https://discord.com", url: "https://discord.com",
description: "There was a boar, everyone liked a boar. One day the boar ate my dinner and escaped through the chimney. I haven't seen a boar since then.", description: "There was a boar, everyone liked a boar. One day the boar ate my dinner and escaped through the chimney. I haven't seen a boar since then.",
author: { author: {
name: "Assistants Center", name: "Assistants Center",
url: "https://assistants.ga", url: "https://assistants.ga",
icon_url: "https://media.discordapp.net/attachments/911644960590270484/934513385402413076/ac_fixed.png" icon_url: "https://media.discordapp.net/attachments/911644960590270484/934513385402413076/ac_fixed.png"
}, },
image: { image: {
url: "https://unsplash.it/380/200" url: "https://unsplash.it/380/200"
}, },
footer: { footer: {
text: "Crated with Discord-Dashboard", text: "Crated with Discord-Dashboard",
icon_url: "https://cdn.discordapp.com/emojis/870635912437047336.png" icon_url: "https://cdn.discordapp.com/emojis/870635912437047336.png"
}, },
fields: [ fields: [
{ {
name: "Hello", name: "Hello",
value: "Hi, Assistants Center loves you <:ac_love:806492057996230676>" value: "Hi, Assistants Center loves you <:ac_love:806492057996230676>"
}, },
{ {
name: "Do you know that", name: "Do you know that",
value: "You can use custom emojis there, even from server where bot isn't <:Kekwlaugh:722088222766923847>", value: "You can use custom emojis there, even from server where bot isn't <:Kekwlaugh:722088222766923847>",
inline: false inline: false
}, },
] ]
} }
}`; }`;
} }
} else { } else {
if (typeof actual[s.categoryId][option.optionId] === "string") embedContent = actual[s.categoryId][option.optionId]; if (typeof actual[s.categoryId][option.optionId] === "string") embedContent = actual[s.categoryId][option.optionId];
else embedContent = JSON.stringify(actual[s.categoryId][option.optionId], null, 3); else embedContent = JSON.stringify(actual[s.categoryId][option.optionId], null, 3);
} }
%> %>
<iframe class="responsive-iframe" <iframe class="responsive-iframe"
src="data:text/html;charset=utf-8,<%= encodeURIComponent(config.theme.embedBuilderComponent.replace('{{ContentJsonReplacer}}', embedContent).replace('{{msgSource}}', option.optionId).replace('{{botusername}}', option.optionType.data.username).replace('{{botavatar}}', option.optionType.data.avatarURL)) %>"></iframe> src="data:text/html;charset=utf-8,<%= encodeURIComponent(config.theme.embedBuilderComponent.replace('{{ContentJsonReplacer}}', embedContent).replace('{{msgSource}}', option.optionId).replace('{{botusername}}', option.optionType.data.username).replace('{{botavatar}}', option.optionType.data.avatarURL)) %>"></iframe>
</div> </div>
<script> <script>
setTimeout(() => { setTimeout(() => {
window.addEventListener('message', function (e) { window.addEventListener('message', function (e) {
if (e.data[0] === '<%= option.optionId %>') { if (e.data[0] === '<%= option.optionId %>') {
document.getElementById('<%= option.optionId %>').innerHTML = JSON.stringify(e.data[1]); document.getElementById('<%= option.optionId %>').innerHTML = JSON.stringify(e.data[1]);
optionEdited(document.getElementById('<%= option.optionId %>')) optionEdited(document.getElementById('<%= option.optionId %>'))
} }
}, false); }, false);
}, 1200); }, 1200);
</script> </script>

View file

@ -1,176 +1,176 @@
<style> <style>
* { * {
padding: 0; padding: 0;
margin: 0; margin: 0;
box-sizing: border-box; box-sizing: border-box;
} }
img { img {
display: block; display: block;
} }
.emoji-picker { .emoji-picker {
background-color: #303841; background-color: #303841;
width: 400px; width: 400px;
border-radius: 5px; border-radius: 5px;
height: 400px; height: 400px;
display: flex; display: flex;
} }
.emoji-selectables { .emoji-selectables {
background-color: #212427; background-color: #212427;
width: 45px; width: 45px;
height: 100%; height: 100%;
padding: 10px 15px; padding: 10px 15px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.emoji-selectables span { .emoji-selectables span {
margin-bottom: 7px; margin-bottom: 7px;
cursor: pointer; cursor: pointer;
} }
.emoji-selectables span.active img { .emoji-selectables span.active img {
filter: none; filter: none;
} }
.emoji-selectables span img { .emoji-selectables span img {
width: 25px; width: 25px;
display: block; display: block;
display: flex; display: flex;
align-items: center; align-items: center;
filter: grayscale(100%) filter: grayscale(100%)
} }
.emoji-content div { .emoji-content div {
width: 100%; width: 100%;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
padding: 5px; padding: 5px;
} }
.emoji-content span { .emoji-content span {
display: block; display: block;
padding: 5px; padding: 5px;
cursor: pointer; cursor: pointer;
} }
.emoji-content span:hover { .emoji-content span:hover {
transform: scale(1.1); transform: scale(1.1);
background-color: #3f4953; background-color: #3f4953;
border-radius: 5px; border-radius: 5px;
} }
.picker-emoji-content { .picker-emoji-content {
display: none; display: none;
} }
.picker-emoji-sel.face { .picker-emoji-sel.face {
color: aliceblue; color: aliceblue;
font-size: 10px; font-size: 10px;
} }
.picker-emoji-content.active { .picker-emoji-content.active {
display: flex; display: flex;
display: flex; display: flex;
height: 100%; height: 100%;
overflow-y: scroll; overflow-y: scroll;
} }
.emoji-content span img { .emoji-content span img {
width: 32px; width: 32px;
height: 32px; height: 32px;
} }
.picker-emoji-content::-webkit-scrollbar-thumb { .picker-emoji-content::-webkit-scrollbar-thumb {
height: 10px; height: 10px;
background-color: #65B88D; background-color: #65B88D;
border-radius: 100px; border-radius: 100px;
} }
.picker-emoji-content::-webkit-scrollbar-track { .picker-emoji-content::-webkit-scrollbar-track {
background-color: #303841; background-color: #303841;
} }
.picker-emoji-content::-webkit-scrollbar { .picker-emoji-content::-webkit-scrollbar {
width: 6px; width: 6px;
} }
img { img {
display: block; display: block;
} }
</style> </style>
<link href="https://www.jqueryscript.net/css/jquerysctipttop.css" rel="stylesheet" type="text/css"> <link href="https://www.jqueryscript.net/css/jquerysctipttop.css" rel="stylesheet" type="text/css">
<% if(!Allowed.allowed){ %> <% if(!Allowed.allowed){ %>
<span style="color: red;"> <span style="color: red;">
<%- Allowed.errorMessage %> <%- Allowed.errorMessage %>
</span> </span>
<br> <br>
<% } %> <% } %>
<input defaultValue="<%= actual[s.categoryId][option.optionId] || "" %>" class="d-none" type="text" id="<%= option.optionId %>" formType="emojiPicker" type="text" onchange="optionEdited(this)"> <input defaultValue="<%= actual[s.categoryId][option.optionId] || "" %>" class="d-none" type="text" id="<%= option.optionId %>" formType="emojiPicker" type="text" onchange="optionEdited(this)">
<div class="dropdown"> <div class="dropdown">
<a href="javascript:;" class="btn bg-transparent" data-bs-toggle="dropdown" id="navbarDropdownMenuLink2" style="width: fit-content; height: fit-content; aspect-ratio: 1/1; justify-content: center; display: flex; align-items: center; max-width: 100px; <% if (option.optionType.disabled && !Allowed.allowed) { %>border-color: red;<% } %>"> <a href="javascript:;" class="btn bg-transparent" data-bs-toggle="dropdown" id="navbarDropdownMenuLink2" style="width: fit-content; height: fit-content; aspect-ratio: 1/1; justify-content: center; display: flex; align-items: center; max-width: 100px; <% if (option.optionType.disabled && !Allowed.allowed) { %>border-color: red;<% } %>">
<% if(actual[s.categoryId][option.optionId]){ %> <% if(actual[s.categoryId][option.optionId]){ %>
<% if (/\d/.test(actual[s.categoryId][option.optionId])) { %> <% if (/\d/.test(actual[s.categoryId][option.optionId])) { %>
<img src="https://cdn.discordapp.com/emojis/<%= actual[s.categoryId][option.optionId] %>.png" style="width: 72px; height: 72px;"> <img src="https://cdn.discordapp.com/emojis/<%= actual[s.categoryId][option.optionId] %>.png" style="width: 72px; height: 72px;">
<% } else { %> <% } else { %>
<span style="font-size: 20px;"><%= actual[s.categoryId][option.optionId] %></span> <span style="font-size: 20px;"><%= actual[s.categoryId][option.optionId] %></span>
<% } %> <% } %>
<% } %> <% } %>
</a> </a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink2"> <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink2">
<div id="emojis"> <div id="emojis">
</div> </div>
</div> </div>
</div> </div>
<script src="/js/core/DisMojiPicker.js"></script> <script src="/js/core/DisMojiPicker.js"></script>
<script src="https://twemoji.maxcdn.com/v/latest/twemoji.min.js" crossorigin="anonymous"></script> <script src="https://twemoji.maxcdn.com/v/latest/twemoji.min.js" crossorigin="anonymous"></script>
<% if(!option.optionType.disabled && Allowed.allowed){ %> <% if(!option.optionType.disabled && Allowed.allowed){ %>
<script> <script>
const emojis = <%- JSON.stringify(bot.guilds.cache.get(req.params.id).emojis.cache.map(e => { const emojis = <%- JSON.stringify(bot.guilds.cache.get(req.params.id).emojis.cache.map(e => {
return { return {
animated: e.animated, animated: e.animated,
name: e.name, name: e.name,
id: e.id id: e.id
} }
})) %> })) %>
$(".dropdown").click(function(e){ $(".dropdown").click(function(e){
e.stopPropagation(); e.stopPropagation();
}) })
$("#emojis").disMojiPicker(emojis) $("#emojis").disMojiPicker(emojis)
$("#emojis").picker(emoji => { $("#emojis").picker(emoji => {
let custom = {} let custom = {}
if (emoji) if (emoji)
$("#navbarDropdownMenuLink2").dropdown("toggle") $("#navbarDropdownMenuLink2").dropdown("toggle")
if (emojis.find(x => x.name === emoji)) { if (emojis.find(x => x.name === emoji)) {
custom = emojis.find(x => x.name === emoji) custom = emojis.find(x => x.name === emoji)
} }
$("#<%= option.optionId %>").val(custom ? custom.id : emoji) $("#<%= option.optionId %>").val(custom ? custom.id : emoji)
$("#<%= option.optionId %>").trigger("change") $("#<%= option.optionId %>").trigger("change")
if (custom?.id) if (custom?.id)
return $("#navbarDropdownMenuLink2").html( return $("#navbarDropdownMenuLink2").html(
`<img src="https://cdn.discordapp.com/emojis/${custom.id}.${custom.animated ? "gif" : "png"}" alt="${custom.name}" style="width: 72px; height: 72px;"/>` `<img src="https://cdn.discordapp.com/emojis/${custom.id}.${custom.animated ? "gif" : "png"}" alt="${custom.name}" style="width: 72px; height: 72px;"/>`
) )
else $("#navbarDropdownMenuLink2").html(` else $("#navbarDropdownMenuLink2").html(`
<span style="width: 72px; height: 72px;"> <span style="width: 72px; height: 72px;">
${twemoji.parse(emoji)} ${twemoji.parse(emoji)}
</span> </span>
`) `)
}); });
twemoji.parse(document.body, "<%= bot.guilds.cache.get(req.params.id).emojis.cache.map(e => e.id) %>"); twemoji.parse(document.body, "<%= bot.guilds.cache.get(req.params.id).emojis.cache.map(e => e.id) %>");
</script> </script>
<% } %> <% } %>

View file

@ -1,33 +1,33 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<input <% if(!Allowed.allowed){ %>style="border-color: red;" disabled <input <% if(!Allowed.allowed){ %>style="border-color: red;" disabled
<% } %> <% } %>
type="text" id="<%= option.optionId %>" class="col-md-12 form-control" type="text" id="<%= option.optionId %>" class="col-md-12 form-control"
id="<%= option.optionId %>" id="<%= option.optionId %>"
formType="input" formType="input"
defaultValue="<% if(actual[s.categoryId][option.optionId]){ %><%= actual[s.categoryId][option.optionId] %><% } %>" defaultValue="<% if(actual[s.categoryId][option.optionId]){ %><%= actual[s.categoryId][option.optionId] %><% } %>"
<% if(option.optionType.required){ %>required <% if(option.optionType.required){ %>required
<% } %> <% } %>
<% if(option.optionType.disabled){ %>disabled <% if(option.optionType.disabled){ %>disabled
<% } %> <% } %>
placeholder="<%= option.optionType.data %>" placeholder="<%= option.optionType.data %>"
<% if(actual[s.categoryId][option.optionId]){ %>value="<%= actual[s.categoryId][option.optionId] %>" <% if(actual[s.categoryId][option.optionId]){ %>value="<%= actual[s.categoryId][option.optionId] %>"
<% } %> <% } %>
<% if(option.optionType.min){ %>minlength="<%= option.optionType.min %>" <% if(option.optionType.min){ %>minlength="<%= option.optionType.min %>"
<% } %> <% } %>
<% if(option.optionType.max){ %>maxlength="<%= option.optionType.max %>" <% if(option.optionType.max){ %>maxlength="<%= option.optionType.max %>"
<% } %> <% } %>
/> />
<% if (option?.themeOptions?.optionPlaceholder) { %> <% if (option?.themeOptions?.optionPlaceholder) { %>
<div style="margin: 0px -5px;"> <div style="margin: 0px -5px;">
<% option?.themeOptions?.optionPlaceholder?.values.forEach(array => { %> <% option?.themeOptions?.optionPlaceholder?.values.forEach(array => { %>
<span style="<% if(option.themeOptions.optionPlaceholder.clickable && Allowed.allowed){ %>cursor: pointer;<% } %> color: #9db4cc;" <span style="<% if(option.themeOptions.optionPlaceholder.clickable && Allowed.allowed){ %>cursor: pointer;<% } %> color: #9db4cc;"
class="_87eb" class="_87eb"
<% if(option.themeOptions.optionPlaceholder.clickable && Allowed.allowed){ %> <% if(option.themeOptions.optionPlaceholder.clickable && Allowed.allowed){ %>
onclick="$('#<%= option.optionId %>').val(this.innerHTML);" onclick="$('#<%= option.optionId %>').val(this.innerHTML);"
<% } %> <% } %>
><%- array %></span> ><%- array %></span>
<% }) %> <% }) %>
</div> </div>
<% } %> <% } %>

View file

@ -1,10 +1,9 @@
<div class="formTypes"> <div class="formTypes">
<% option.optionType.options.forEach(opt => { %> <% option.optionType.options.forEach(opt => { %>
<div class="formtype-item mt-3"> <div class="formtype-item mt-3">
<h4 class="m-0"><%- opt?.optionName || ""%></h4> <h4 class="m-0"><%- opt?.optionName || ""%></h4>
<p><%- opt?.optionDescription || ""%></p> <p><%- opt?.optionDescription || ""%></p>
<%- include(`./${opt.optionType.type}.ejs`, {option: opt, s, Allowed}) %> <%- include(`./${opt.optionType.type}.ejs`, {option: opt, s, Allowed}) %>
</div> </div>
<% }) %> <% }) %>
</div> </div>

View file

@ -1,29 +1,29 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<select placeholder="Select" class="multiSelect js-example-basic-multiple" <select placeholder="Select" class="multiSelect js-example-basic-multiple"
<% if(option.optionType.disabled){ %>disabled <% if(option.optionType.disabled){ %>disabled
<% } %> <% } %>
<% if(option.optionType.required){ %>required <% if(option.optionType.required){ %>required
<% } %> <% } %>
id="<%= option.optionId %>" id="<%= option.optionId %>"
defaultValue="" defaultValue=""
formType="multiSelect" formType="multiSelect"
style="width:100%;background: #f9f9ff;border-color: #f9f9ff;" style="width:100%;background: #f9f9ff;border-color: #f9f9ff;"
class="col-md-12" multiple="multiple" class="col-md-12" multiple="multiple"
<% if(!Allowed.allowed){ %>style="border-color: red;" disabled<% } %> <% if(!Allowed.allowed){ %>style="border-color: red;" disabled<% } %>
> >
<% <%
let ioo = 0; let ioo = 0;
option.optionType.data.values.forEach(value => { option.optionType.data.values.forEach(value => {
%> %>
<option value="<%= value %>" <option value="<%= value %>"
<% if(actual[s.categoryId][option.optionId].includes(value)) { %> <% if(actual[s.categoryId][option.optionId].includes(value)) { %>
selected selected
<% } <% }
%> %>
> <%= option.optionType.data.keys[ioo] %> </option> > <%= option.optionType.data.keys[ioo] %> </option>
<% <%
ioo++; ioo++;
}) })
%> %>
</select> </select>

View file

@ -1,27 +1,27 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<input <input
<% if(actual[s.categoryId][option.optionId]){ %> <% if(actual[s.categoryId][option.optionId]){ %>
defaultValue="<%= actual[s.categoryId][option.optionId] %>" defaultValue="<%= actual[s.categoryId][option.optionId] %>"
value="<%= actual[s.categoryId][option.optionId] %>" value="<%= actual[s.categoryId][option.optionId] %>"
<% } %> <% } %>
class="form-control" class="form-control"
type="number" type="number"
id="<%= option.optionId %>" id="<%= option.optionId %>"
formType="numberPicker" formType="numberPicker"
<% if (option.optionType.min) { %> <% if (option.optionType.min) { %>
min="<%= option.optionType.min %>" min="<%= option.optionType.min %>"
onkeyup="if(this.value < <%= option.optionType.min %>) this.value = <%= option.optionType.min %>" onkeyup="if(this.value < <%= option.optionType.min %>) this.value = <%= option.optionType.min %>"
<% } %> <% } %>
<% if (option.optionType.max) { %> <% if (option.optionType.max) { %>
max="<%= option.optionType.max %>" max="<%= option.optionType.max %>"
onkeyup="if(this.value > <%= option.optionType.max %>) this.value = <%= option.optionType.max %>" onkeyup="if(this.value > <%= option.optionType.max %>) this.value = <%= option.optionType.max %>"
<% } %> <% } %>
<% if(!Allowed.allowed ){ %> <% if(!Allowed.allowed ){ %>
style="border-color: red !important" style="border-color: red !important"
disabled disabled
<% } %> <% } %>
<% if (Allowed.allowed && option.optionType.disabled) { %> <% if (Allowed.allowed && option.optionType.disabled) { %>
disabled disabled
<% } %> <% } %>
> >

View file

@ -1,26 +1,26 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<select placeholder="Select" class="multiSelect form-control" <select placeholder="Select" class="multiSelect form-control"
formType="rolesMultiSelect" formType="rolesMultiSelect"
id="<%= option.optionId %>" id="<%= option.optionId %>"
defaultValue="" defaultValue=""
<% if(option.optionType.disabled){ %>disabled <% if(option.optionType.disabled){ %>disabled
<% } %> <% } %>
<% if(option.optionType.required){ %>required <% if(option.optionType.required){ %>required
<% } %> <% } %>
style="width:100%;background: #f9f9ff;border-color: #f9f9ff;<% if(!Allowed.allowed){ %>border-color: red;<% } %>" style="width:100%;background: #f9f9ff;border-color: #f9f9ff;<% if(!Allowed.allowed){ %>border-color: red;<% } %>"
multiple="multiple" multiple="multiple"
<% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %> <% if(!Allowed.allowed || option.optionType.disabled){ %>disabled<% } %>
> >
<% if (actual[s.categoryId][option.optionId]) { <% if (actual[s.categoryId][option.optionId]) {
let ioooooo = 0; let ioooooo = 0;
let functiona = option.optionType.function(bot, guildid, userid); let functiona = option.optionType.function(bot, guildid, userid);
functiona.values.forEach(value=>{ %> functiona.values.forEach(value=>{ %>
<option value="<%= value %>" <option value="<%= value %>"
<% if(actual[s.categoryId][option.optionId].includes(value)){ %>selected <% if(actual[s.categoryId][option.optionId].includes(value)){ %>selected
<% } %> <% } %>
><%= functiona.keys[ioooooo] %></option> ><%= functiona.keys[ioooooo] %></option>
<% ioooooo++; })} %> <% ioooooo++; })} %>
</select> </select>
<br> <br>

View file

@ -1,21 +1,21 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<select class="form-control" <select class="form-control"
<% if(option.optionType.disabled){ %>disabled <% if(option.optionType.disabled){ %>disabled
<% } %> <% } %>
id="<%= option.optionId %>" class="col-md-12" id="<%= option.optionId %>" class="col-md-12"
formType="rolesSelect" formType="rolesSelect"
defaultValue="" defaultValue=""
<% if(!Allowed.allowed){ %>style="border-color: red;" disabled<% } %> <% if(!Allowed.allowed){ %>style="border-color: red;" disabled<% } %>
> >
<% <%
let iooooooo = 0; let iooooooo = 0;
let functiona = option.optionType.function(bot, guildid, userid); let functiona = option.optionType.function(bot, guildid, userid);
functiona.values.forEach(value=>{ %> functiona.values.forEach(value=>{ %>
<option value="<%= value %>" <option value="<%= value %>"
<% if(actual[s.categoryId][option.optionId] == value){ %>selected <% if(actual[s.categoryId][option.optionId] == value){ %>selected
<% } %> <% } %>
><%= functiona.keys[iooooooo] %></option> ><%= functiona.keys[iooooooo] %></option>
<% <%
iooooooo++; iooooooo++;
}) %> }) %>
</select> </select>

View file

@ -1,22 +1,22 @@
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<select class="form-control" <select class="form-control"
<% if(!Allowed.allowed){ %>style="border-color: red;" <% if(!Allowed.allowed){ %>style="border-color: red;"
<% } %> <% } %>
formType="select" formType="select"
id="<%= option.optionId %>" id="<%= option.optionId %>"
<% if(!Allowed.allowed || option.optionType.disabled){ %> <% if(!Allowed.allowed || option.optionType.disabled){ %>
disabled disabled
<% } %> <% } %>
name="<%= option.optionId %>"> name="<%= option.optionId %>">
<% <%
let ioo = 0; let ioo = 0;
option.optionType.data.values.forEach(value=>{ %> option.optionType.data.values.forEach(value=>{ %>
<option value="<%= value %>" <option value="<%= value %>"
<% if(actual[s.categoryId][option.optionId] == value){ %>selected <% if(actual[s.categoryId][option.optionId] == value){ %>selected
<% } %> <% } %>
><%= option.optionType.data.keys[ioo] %> ><%= option.optionType.data.keys[ioo] %>
</option> </option>
<% <%
ioo++; ioo++;
}) %> }) %>
</select> </select>

View file

@ -1,99 +1,99 @@
<style> <style>
.form-control.slider { .form-control.slider {
padding: 0 .75rem; padding: 0 .75rem;
} }
datalist.slider { datalist.slider {
margin: 0 !important; margin: 0 !important;
} }
option.slider.text-sm { option.slider.text-sm {
font-weight: bold; font-weight: bold;
} }
option.slider:nth-last-child(1) { option.slider:nth-last-child(1) {
margin-right: 5px; margin-right: 5px;
} }
.form-control.slider::after { .form-control.slider::after {
background: none !important; background: none !important;
} }
.form-control.slider::before { .form-control.slider::before {
background: none !important; background: none !important;
} }
.form-control:focus { .form-control:focus {
box-shadow: none !important; box-shadow: none !important;
border: none !important; border: none !important;
} }
.form-control.slider.slider { .form-control.slider.slider {
-webkit-appearance: none; -webkit-appearance: none;
padding: 0 !important; padding: 0 !important;
margin-top: 10px; margin-top: 10px;
width: 97.8%; width: 97.8%;
height: 15px; height: 15px;
border-radius: 5px; border-radius: 5px;
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
outline: none; outline: none;
opacity: 0.7; opacity: 0.7;
-webkit-transition: .2s; -webkit-transition: .2s;
transition: opacity .2s; transition: opacity .2s;
} }
.form-control.slider.slider::-webkit-slider-thumb { .form-control.slider.slider::-webkit-slider-thumb {
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
margin-bottom: 8px; margin-bottom: 8px;
width: 25px; width: 25px;
height: 25px; height: 25px;
border-radius: 50%; border-radius: 50%;
background-image: linear-gradient(310deg, rgb(16, 18, 31) 0%, rgb(46, 52, 89) 100%); background-image: linear-gradient(310deg, rgb(16, 18, 31) 0%, rgb(46, 52, 89) 100%);
cursor: pointer; cursor: pointer;
} }
.form-control.slider.slider::-moz-range-thumb { .form-control.slider.slider::-moz-range-thumb {
width: 25px; width: 25px;
height: 25px; height: 25px;
border-radius: 50%; border-radius: 50%;
background-image: linear-gradient(310deg, rgb(16, 18, 31) 0%, rgb(46, 52, 89) 100%); background-image: linear-gradient(310deg, rgb(16, 18, 31) 0%, rgb(46, 52, 89) 100%);
cursor: pointer; cursor: pointer;
} }
</style> </style>
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<% if(option?.themeOptions?.dataList) { %> <% if(option?.themeOptions?.dataList) { %>
<datalist class="slider" id="steplist"> <datalist class="slider" id="steplist">
<% option.themeOptions.dataList.forEach(data => { %> <% option.themeOptions.dataList.forEach(data => { %>
<option class="slider text-sm" style="user-select: none;"><strong><%- data %></strong></option> <option class="slider text-sm" style="user-select: none;"><strong><%- data %></strong></option>
<% }) %> <% }) %>
</datalist> </datalist>
<% } %> <% } %>
<input <input
<% if(actual[s.categoryId][option.optionId]){ %> <% if(actual[s.categoryId][option.optionId]){ %>
defaultValue="<%= actual[s.categoryId][option.optionId] %>" defaultValue="<%= actual[s.categoryId][option.optionId] %>"
value="<%= actual[s.categoryId][option.optionId] %>" value="<%= actual[s.categoryId][option.optionId] %>"
<% } %> <% } %>
class="form-control slider" class="form-control slider"
formType="slider" formType="slider"
id="<%= option.optionId %>" id="<%= option.optionId %>"
type="range" type="range"
list="steplist" list="steplist"
step="<%= option.optionType.step %>" step="<%= option.optionType.step %>"
min="<%= option.optionType.min %>" min="<%= option.optionType.min %>"
max="<%= option.optionType.max %>" max="<%= option.optionType.max %>"
<% if (option.themeOptions?.showValue) { %> <% if (option.themeOptions?.showValue) { %>
oninput="updateSlider(this.value, this.id)" oninput="updateSlider(this.value, this.id)"
<% } %> <% } %>
style="border: none !important; <% if(!Allowed.allowed){ %> border-color: red; <% } %>" style="border: none !important; <% if(!Allowed.allowed){ %> border-color: red; <% } %>"
<% if(!Allowed.allowed){ %> <% if(!Allowed.allowed){ %>
disabled disabled
<% } %> <% } %>
<% if (Allowed.allowed && option.optionType.disabled) { %> <% if (Allowed.allowed && option.optionType.disabled) { %>
disabled disabled
<% } %> <% } %>
> >
<% if (option.themeOptions?.showValue) { %> <% if (option.themeOptions?.showValue) { %>
<p class="mt-2" style="margin-bottom: 0 !important;">Slider is set to <b><span id="value_<%= option.optionId %>"><% if(actual[s.categoryId][option.optionId]){ %><%= actual[s.categoryId][option.optionId] %><% } %></span></b></p> <p class="mt-2" style="margin-bottom: 0 !important;">Slider is set to <b><span id="value_<%= option.optionId %>"><% if(actual[s.categoryId][option.optionId]){ %><%= actual[s.categoryId][option.optionId] %><% } %></span></b></p>
<% } %> <% } %>

View file

@ -2,77 +2,77 @@
if (actual[s.categoryId][option.optionId]) val = "checked"; if (actual[s.categoryId][option.optionId]) val = "checked";
%> %>
<style> <style>
/* The switch - the box around the slider */ /* The switch - the box around the slider */
.toggleSwitch { .toggleSwitch {
position: relative; position: relative;
display: inline-block; display: inline-block;
width: 60px; width: 60px;
height: 34px; height: 34px;
} }
/* Hide default HTML checkbox */ /* Hide default HTML checkbox */
.toggleSwitch input { .toggleSwitch input {
opacity: 0; opacity: 0;
width: 0; width: 0;
height: 0; height: 0;
} }
/* The slider */ /* The slider */
.tslider { .tslider {
position: absolute; position: absolute;
cursor: pointer; cursor: pointer;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background-color: #ccc; background-color: #ccc;
-webkit-transition: .4s; -webkit-transition: .4s;
transition: .4s; transition: .4s;
} }
.tslider:before { .tslider:before {
position: absolute; position: absolute;
content: ""; content: "";
height: 26px; height: 26px;
width: 26px; width: 26px;
left: 4px; left: 4px;
bottom: 4px; bottom: 4px;
background-color: white; background-color: white;
-webkit-transition: .4s; -webkit-transition: .4s;
transition: .4s; transition: .4s;
} }
input:checked + .tslider { input:checked + .tslider {
background-color: #2196F3; background-color: #2196F3;
} }
input:focus + .tslider { input:focus + .tslider {
box-shadow: 0 0 1px #2196F3; box-shadow: 0 0 1px #2196F3;
} }
input:checked + .tslider:before { input:checked + .tslider:before {
-webkit-transform: translateX(26px); -webkit-transform: translateX(26px);
-ms-transform: translateX(26px); -ms-transform: translateX(26px);
transform: translateX(26px); transform: translateX(26px);
} }
/* Rounded sliders */ /* Rounded sliders */
.tslider.round { .tslider.round {
border-radius: 34px; border-radius: 34px;
} }
.tslider.round:before { .tslider.round:before {
border-radius: 50%; border-radius: 50%;
} }
</style> </style>
<% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %> <% if(!Allowed.allowed){ %><span style="color: red;"><%- Allowed.errorMessage %></span><br><% } %>
<label class="toggleSwitch"> <label class="toggleSwitch">
<input type="checkbox" id="<%= option.optionId %>" <input type="checkbox" id="<%= option.optionId %>"
formtype="switch" formtype="switch"
defaultValue="" defaultValue=""
id="<%= option.optionId %>" <%- val %> id="<%= option.optionId %>" <%- val %>
<% if(option.optionType.disabled || !Allowed.allowed ){ %>disabled<% } %> <% if(option.optionType.disabled || !Allowed.allowed ){ %>disabled<% } %>
> >
<span class="tslider round"></span> <span class="tslider round"></span>

View file

@ -2,24 +2,24 @@
<select <select
<% if (actual[s.categoryId][option.optionId]) {%> <% if (actual[s.categoryId][option.optionId]) {%>
defaultValue="<%= JSON.stringify(actual[s.categoryId][option.optionId])%>" defaultValue="<%= JSON.stringify(actual[s.categoryId][option.optionId])%>"
<% } %> <% } %>
id="<%= option.optionId %>" id="<%= option.optionId %>"
getValue="<%= option.optionId %>" getValue="<%= option.optionId %>"
class="tags form-control" class="tags form-control"
multiple="multiple" multiple="multiple"
formType="tagInput" formType="tagInput"
<% if(!Allowed.allowed){ %> <% if(!Allowed.allowed){ %>
style="border-color: red;" style="border-color: red;"
disabled disabled
<% } %> <% } %>
<% if (Allowed.allowed && option.optionType.disabled) { %> <% if (Allowed.allowed && option.optionType.disabled) { %>
disabled disabled
<% } %> <% } %>
> >
<% if (actual[s.categoryId][option.optionId]) {%> <% if (actual[s.categoryId][option.optionId]) {%>
<% actual[s.categoryId][option.optionId].forEach(value=>{ %> <% actual[s.categoryId][option.optionId].forEach(value=>{ %>
<option value="<%= value %>" selected><%= value %></option> <option value="<%= value %>" selected><%= value %></option>
<% }) %> <% }) %>
<% } %> <% } %>
</select> </select>

View file

@ -1,221 +1,206 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<%- include('partials/preloader.ejs', {now: 'credits'}) %> <%- include('partials/preloader.ejs', {now: 'credits'}) %>
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100" id="scroll"> <body class="g-sidenav-show bg-gray-100" id="scroll">
<%- include('partials/preload.ejs') %> <%- include('partials/preload.ejs') %>
<%- include('partials/sidebar.ejs', {config: config, now:'credits'}) %> <%- include('partials/sidebar.ejs', {config: config, now:'credits'}) %>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<!-- Navbar --> <!-- Navbar -->
<%- include('partials/navbar.ejs', {now:'credits'}) %> <%- include('partials/navbar.ejs', {now:'credits'}) %>
<!-- End Navbar --> <!-- End Navbar -->
<div class="container-fluid py-4" style="padding-bottom: 0px !important;"> <div class="container-fluid py-4" style="padding-bottom: 0px !important;">
<div id="discordRocket" style="display: none;"> <div id="discordRocket" style="display: none;">
<div id="rocketDiscord" <div id="rocketDiscord"
style="position: absolute; margin: 0; top: 50%; left: 50%; -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%); z-index: 420;"> style="position: absolute; margin: 0; top: 50%; left: 50%; -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%); z-index: 420;">
<i class="fab fa-discord fa-10x" aria-hidden="true"></i> <i class="fab fa-discord fa-10x" aria-hidden="true"></i>
</div> </div>
<p style="font-size: 150%; position: absolute; margin: 0; top: 50%; left: 50%; transform: translate(-50%, -50%);"> <p style="font-size: 150%; position: absolute; margin: 0; top: 50%; left: 50%; transform: translate(-50%, -50%);">
Taking you to <b>discord.gg</b></p> Taking you to <b>discord.gg</b></p>
<!-- i cant figure out how to center this --> <!-- i cant figure out how to center this -->
</div> </div>
<section class="py-sm-7 py-5 position-relative" id="mainSection" style="padding-top: 0px !important;"> <section class="py-sm-7 py-5 position-relative" id="mainSection" style="padding-top: 0px !important;">
<div> <div>
<div class="row mb-4"> <div class="row mb-4">
<div class="col-lg-12 mb-lg-0 mb-4" style="padding: 0px"> <div class="col-lg-12 mb-lg-0 mb-4" style="padding: 0px">
<div class="card"> <div class="card">
<div class="card-body p-3"> <div class="card-body p-3">
<div class="row"> <div class="row">
<div class="col-lg-6"> <div class="col-lg-6">
<div class="d-flex flex-column h-100"> <div class="d-flex flex-column h-100">
<p class="mb-1 pt-2 text-bold">Soft-UI Theme</p> <p class="mb-1 pt-2 text-bold">Soft-UI Theme</p>
<h5 class="font-weight-bolder">Soft UI Theme</h5> <h5 class="font-weight-bolder">Soft UI Theme</h5>
<p>The Discord-Dashboard Soft UI theme was created as a feature-packed theme for DBD users!</p> <p>The Discord-Dashboard Soft UI theme was created as a feature-packed theme for DBD users!</p>
<p class="mb-1 mt-5"> Made with <i class="fa fa-heart"></i> by <a <p class="mb-1 mt-5"> Made with <i class="fa fa-heart"></i> by <a
href="https://github.com/PlainDevelopment" href="https://github.com/PlainDevelopment"
class="font-weight-bold text-gradient text-primary" class="font-weight-bold text-gradient text-primary"
style="font-weight: 700 !important;">PlainDevelopment</a> and <a style="font-weight: 700 !important;">PlainDevelopment</a> and <a
href="https://github.com/iMidnights" href="https://github.com/iMidnights"
class="font-weight-bold text-gradient text-primary" class="font-weight-bold text-gradient text-primary"
style="font-weight: 700 !important;">iMidnight</a></p> style="font-weight: 700 !important;">iMidnight</a></p>
<a class="text-body text-sm font-weight-bold mb-0 icon-move-right" <a class="text-body text-sm font-weight-bold mb-0 icon-move-right"
href="https://github.com/Assistants-Center"> href="https://github.com/Assistants-Center">
Visit our Github page Visit our Github page
<i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i> <i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i>
</a> </a>
</div> </div>
</div> </div>
<div class="col-lg-5 ms-auto text-center mt-5 mt-lg-0"> <div class="col-lg-5 ms-auto text-center mt-5 mt-lg-0">
<div class="bg-gradient-primary border-radius-lg h-100" <div class="bg-gradient-primary border-radius-lg h-100"
style="background-image: url('/img/soft-ui.webp') !important; background-repeat: no-repeat; background-size: contain; background-position: center;"> style="background-image: url('/img/soft-ui.webp') !important; background-repeat: no-repeat; background-size: contain; background-position: center;">
<div class="position-relative d-flex align-items-center justify-content-center h-100" <div class="position-relative d-flex align-items-center justify-content-center h-100"
style="min-height: 210px !important;"> style="min-height: 210px !important;">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row mt-4 d-flex" style="justify-content: space-between;"> <div class="row mt-4 d-flex" style="justify-content: space-between;">
<div class="card" style="width: 300px; height: 465px; text-align: center;"> <div class="card" style="width: 300px; height: 465px; text-align: center;">
<div class="p-3"> <div class="p-3">
<img class="img border-radius-lg max-width-200 w-100 position-relative z-index-2" <img class="img border-radius-lg max-width-200 w-100 position-relative z-index-2"
src="https://cdn.discordapp.com/avatars/715195498495082627/1eae1059ab1d33da0f99cd370c2014cf.webp" src="https://cdn.discordapp.com/avatars/715195498495082627/1eae1059ab1d33da0f99cd370c2014cf.webp"
style="width: 200px; height: 200px;" style="width: 200px; height: 200px;"
alt="Plain"> alt="Plain">
</div> </div>
<hr> <hr>
<div> <div>
<div class="p-3 text-center" style="text-align: left !important; padding-top: 0 !important;"> <div class="p-3 text-center" style="text-align: left !important; padding-top: 0 !important;">
<h2 class="text-gradient text-primary">Plain</h2> <h2 class="text-gradient text-primary">Plain</h2>
<h5 class="mt-1" style="margin-bottom: 0;">Soft UI Developer</h5> <h5 class="mt-1" style="margin-bottom: 0;">Soft UI Developer</h5>
<p>Spent over 6 hours typing out all the feed icons.</p> <p>Spent over 6 hours typing out all the feed icons.</p>
<div style="position: absolute; bottom: 15px;"> <div style="position: absolute; bottom: 15px;">
<a class="text-body text-bg font-weight-bold mb-0 icon-move-right" <a class="text-body text-bg font-weight-bold mb-0 icon-move-right"
href="https://github.com/PlainDevelopment"> href="https://github.com/PlainDevelopment">
Plain's Github Plain's Github
<i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i> <i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="card" style="width: 300px; height: 465px; text-align: center;"> <div class="card" style="width: 300px; height: 465px; text-align: center;">
<div class="p-3"> <div class="p-3">
<img class="img border-radius-lg max-width-200 w-100 position-relative z-index-2" <img class="img border-radius-lg max-width-200 w-100 position-relative z-index-2"
src="https://cdn.discordapp.com/avatars/427534456169955352/5cff8985bb22c7b2bad7e0823412a45e.webp" src="https://cdn.discordapp.com/avatars/427534456169955352/5cff8985bb22c7b2bad7e0823412a45e.webp"
style="width: 200px; height: 200px;" style="width: 200px; height: 200px;"
alt="iMidnight"> alt="iMidnight">
</div> </div>
<hr> <hr>
<div> <div>
<div class="p-3 text-center" style="text-align: left !important; padding-top: 0 !important;"> <div class="p-3 text-center" style="text-align: left !important; padding-top: 0 !important;">
<h2 class="text-gradient text-primary">iMidnight</h2> <h2 class="text-gradient text-primary">iMidnight</h2>
<h5 class="mt-1" style="margin-bottom: 0;">Soft UI Developer</h5> <h5 class="mt-1" style="margin-bottom: 0;">Soft UI Developer</h5>
<p>Potato Brain.</p> <p>Potato Brain.</p>
<div style="position: absolute; bottom: 15px;"> <div style="position: absolute; bottom: 15px;">
<a class="text-body text-bg font-weight-bold mb-0 icon-move-right" <a class="text-body text-bg font-weight-bold mb-0 icon-move-right"
href="https://github.com/iMidnights"> href="https://github.com/iMidnights">
iMidnight's Github iMidnight's Github
<i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i> <i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="card" style="width: 300px; height: 465px; text-align: center;"> <div class="card" style="width: 300px; height: 465px; text-align: center;">
<div class="p-3"> <div class="p-3">
<img class="img border-radius-lg max-width-200 w-100 position-relative z-index-2" <img class="img border-radius-lg max-width-200 w-100 position-relative z-index-2"
src="https://avatars.githubusercontent.com/u/62174194" src="https://avatars.githubusercontent.com/u/62174194"
style="width: 200px; height: 200px;" style="width: 200px; height: 200px;"
alt="Breathtake"> alt="Breathtake">
</div> </div>
<hr> <hr>
<div> <div>
<div class="p-3 text-center" style="text-align: left !important; padding-top: 0 !important;"> <div class="p-3 text-center" style="text-align: left !important; padding-top: 0 !important;">
<h2 class="text-gradient text-primary">Breathtake</h2> <h2 class="text-gradient text-primary">Breathtake</h2>
<h5 class="mt-1" style="margin-bottom: 0;">Discord Dashboard Developer</h5> <h5 class="mt-1" style="margin-bottom: 0;">Discord Dashboard Developer</h5>
<p>Project Ants.</p> <p>Project Ants.</p>
<div style="position: absolute; bottom: 15px;"> <div style="position: absolute; bottom: 15px;">
<a class="text-body text-bg font-weight-bold mb-0 icon-move-right" <a class="text-body text-bg font-weight-bold mb-0 icon-move-right"
href="https://github.com/breftejk"> href="https://github.com/breftejk">
Breathtake's Github Breathtake's Github
<i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i> <i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</section> </section>
<% <%
const images = ["curved-1", "curved-2", "curved-3", "curved-4", "curved-5", "curved-6", "curved-7", "curved-8", "curved-9", "curved-10", "curved-11", "curved-12", "curved-13", "curved-14", "curved-15", "curved-16", "curved-17", "curved-18"]; const images = ["curved-1", "curved-2", "curved-3", "curved-4", "curved-5", "curved-6", "curved-7", "curved-8", "curved-9", "curved-10", "curved-11", "curved-12", "curved-13", "curved-14", "curved-15", "curved-16", "curved-17", "curved-18"];
const image = images[Math.floor(Math.random() * images.length)]; const image = images[Math.floor(Math.random() * images.length)];
%> %>
<section class="pb-7 position-relative" id="getHelp"> <section class="pb-7 position-relative" id="getHelp">
<div class="page-header min-vh-50 m-3 border-radius-xl" <div class="page-header min-vh-50 m-3 border-radius-xl"
style="background-image: url('/img/curved-images/<%- image %>.webp');"> style="background-image: url('/img/curved-images/<%- image %>.webp');">
<span class="mask bg-gradient-dark opacity-8"></span> <span class="mask bg-gradient-dark opacity-8"></span>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-lg-6 text-center mx-auto"> <div class="col-lg-6 text-center mx-auto">
<h1 class="text-white mt-4 mb-1">Got a question?</h1> <h1 class="text-white mt-4 mb-1">Got a question?</h1>
<p class="lead text-white mb-6">Join our discord server!</p> <p class="lead text-white mb-6">Join our discord server!</p>
</div> </div>
<button type="button" style="border: none; background: none; cursor: pointer;" id="discordButton" <button type="button" style="border: none; background: none; cursor: pointer;" id="discordButton"
onclick="supportServer()"> onclick="supportServer()">
<i class="fab fa-discord fa-7x" aria-hidden="true"></i> <i class="fab fa-discord fa-7x" aria-hidden="true"></i>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<%- include('partials/footer.ejs') %> <%- include('partials/footer.ejs') %>
</section> </section>
</div> </div>
</main> </main>
<script> <script>
let disableFunc = false; let disableFunc = false;
var win; var win;
function supportServer() { function supportServer() {
if (disableFunc) return; if (disableFunc) return;
disableFunc = true; disableFunc = true;
$('#discordButton').parent().css('overflow', 'hidden'); $('#discordButton').parent().css('overflow', 'hidden');
$('#discordButton').animate({'margin-top': '-=50px'}); $('#discordButton').animate({'margin-top': '-=50px'});
$('#discordButton').animate({'margin-top': '+=500px', opacity: 0}, function () { $('#discordButton').animate({'margin-top': '+=500px', opacity: 0}, function () {
$(this).hide(); $(this).hide();
}); });
$("#discordRocket").fadeIn(); $("#discordRocket").fadeIn();
setTimeout(function () { setTimeout(function () {
$('#rocketDiscord').animate({'margin-top': '+=600px'}, 1); $('#rocketDiscord').animate({'margin-top': '+=600px'}, 1);
$("#mainSection").fadeOut(); $("#mainSection").fadeOut();
$("#main2").fadeOut(); $("#main2").fadeOut();
$("#getHelp").fadeOut(); $("#getHelp").fadeOut();
}, 1000) }, 1000)
setTimeout(function () { setTimeout(function () {
setTimeout(function () { setTimeout(function () {
$('#rocketDiscord').animate({'margin-top': '+=75px'}); $('#rocketDiscord').animate({'margin-top': '+=75px'});
$('#rocketDiscord').animate({'margin-top': '-=1000px'}, 1500); $('#rocketDiscord').animate({'margin-top': '-=1000px'}, 1500);
setTimeout(function () { setTimeout(function () {
window.open('https://discord.gg/EdJFwNvNS9', '_blank', 'location=yes,height=1200,width=800'); window.open('https://discord.gg/EdJFwNvNS9', '_blank', 'location=yes,height=1200,width=800');
$("#rocketDiscord").fadeOut(); $("#rocketDiscord").fadeOut();
$("#discordRocket").fadeOut(); $("#discordRocket").fadeOut();
setTimeout(function () { setTimeout(function () {
disableFunc = false; disableFunc = false;
location.reload(); location.reload();
}, 3500) }, 3500)
}, 1200) }, 1200)
}, 1500) }, 1500)
}, 2000); }, 2000);
} }
</script> </script>

View file

@ -1,386 +1,285 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<link rel="stylesheet" href="../testcdn/a05ee437b7ade39c78f8.css" data-n-p=""> <link rel="stylesheet" href="../testcdn/a05ee437b7ade39c78f8.css" data-n-p="">
<%- include('partials/preloader.ejs', {now: 'debug'}) %> <%- include("partials/preloader.ejs", {now: "debug"}) %>
<% <%
let seconds = Math.round(rawUptime % 60); let seconds = Math.round(rawUptime % 60);
if (seconds > 59) seconds = Math.round(seconds % 60); if (seconds > 59) seconds = Math.round(seconds % 60);
let minutes = Math.floor(rawUptime / 60); let minutes = Math.floor(rawUptime / 60);
let hours = Math.floor(minutes / 60); let hours = Math.floor(minutes / 60);
let days = Math.floor(hours / 24); let days = Math.floor(hours / 24);
minutes = minutes % 60; minutes = minutes % 60;
hours = hours % 24; hours = hours % 24;
let filterUptime = `${days}d, ${hours}h, ${minutes}m, ${seconds}s`; let filterUptime = `${days}d, ${hours}h, ${minutes}m, ${seconds}s`;
if (!days) filterUptime = `${hours}h, ${minutes}m, ${seconds}s`; if (!days) filterUptime = `${hours}h, ${minutes}m, ${seconds}s`;
if (!hours) filterUptime = `${minutes}m, ${seconds}s`; if (!hours) filterUptime = `${minutes}m, ${seconds}s`;
if (!minutes) filterUptime = `${seconds}s`; if (!minutes) filterUptime = `${seconds}s`;
let modified = 0; let modified = 0;
if (onlineFiles.index.replace(/\s+/g, '') !== localFiles.index.replace(/\s+/g, '')) modified++; const info = []
if (onlineFiles.guild.replace(/\s+/g, '') !== localFiles.guild.replace(/\s+/g, '')) modified++; const versions = []
if (onlineFiles.guilds.replace(/\s+/g, '') !== localFiles.guilds.replace(/\s+/g, '')) modified++; if (modified !== 0) modded = "true"
else modded = "false"
const info = [] let information = [
const versions = [] {name: "Theme", value: "Soft UI Theme"},
if (modified !== 0) modded = "true" {name: "Modified", value: `${modded}`},
else modded = "false" {name: "Uptime", value: `${filterUptime}`},
// {name: "Permissions", value: req.requiredPermissions},
{name: "Redirect URI", value: `${config.redirectUri?.includes("/discord/callback")}`}
]
let information = [ let modules = [
{name: "Theme", value: "Soft UI Theme"}, {name: "Node JS", version: `${nodeVersion.split("v")[1]}`},
{name: "Modified", value: `${modded}`}, {name: "Discord JS", version: `${discordVersion}`, npm: "discord.js"},
{name: "License Type", value: `${license}`}, {name: "Discord Dashboard", version: `${dbdVersion}`, npm: "discord-dashboard"},
{name: "Uptime", value: `${filterUptime}`}, {name: "Theme", version: `${themeVersion}`, npm: "soft-ui"},
{name: "Permissions", value: req.requiredPermissions}, ]
{name: "Redirect URI", value: `${config.redirectUri?.includes("/discord/callback")}`}
]
let modules = [ const settings = config.settings
{name: "Node JS", version: `${nodeVersion.split("v")[1]}`},
{name: "Discord JS", version: `${discordVersion}`, npm: "discord.js"},
{name: "Discord Dashboard", version: `${dbdVersion}`, npm: "discord-dashboard"},
{name: "Theme", version: `${themeVersion}`, npm: "soft-ui"},
]
onlineV.forEach(online => { let debug = {information, modules, versions, settings, themeConfig}
const current = localV[online.name];
const latest = online.version;
const name = online.name;
versions.push({name: name, current: current, latest: latest}) var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(debug));
}); %>
<%- themeConfig?.customHtml %>
const settings = config.settings
let debug = {information, modules, versions, settings, themeConfig}
var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(debug));
%>
<%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100" id="scroll"> <body class="g-sidenav-show bg-gray-100" id="scroll">
<%- include('partials/preload.ejs') %> <%- include("partials/preload.ejs") %>
<%- include('partials/sidebar.ejs', {config: config, now:'debug'}) %> <%- include("partials/sidebar.ejs", {config: config, now:"debug"}) %>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<!-- Navbar --> <!-- Navbar -->
<%- include('partials/navbar.ejs', {now:'debug'}) %> <%- include("partials/navbar.ejs", {now:"debug"}) %>
<!-- End Navbar --> <!-- End Navbar -->
<div class="container-fluid py-4"> <div class="container-fluid py-4">
<div class="modal fade" id="exampleModalSignUp" tabindex="-1" role="dialog" <div class="modal fade" id="exampleModalSignUp" tabindex="-1" role="dialog"
aria-labelledby="exampleModalSignTitle" aria-hidden="true"> aria-labelledby="exampleModalSignTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-sm" role="document"> <div class="modal-dialog modal-dialog-centered modal-sm" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body p-0"> <div class="modal-body p-0">
<div class="card card-plain"> <div class="card card-plain">
<div class="card-header pb-0 text-left"> <div class="card-header pb-0 text-left">
<h4 class="font-weight-bolder text-primary text-gradient">Download Log file.</h4> <h4 class="font-weight-bolder text-primary text-gradient">Download Log file.</h4>
<p class="mb-0" <p class="mb-0"
style="text-align: center;">This log contains the dashboard's Theme Config and all options with any personal information redacted.</p> style="text-align: center;">This log contains the dashboard"s Theme Config and all options with any personal information redacted.</p>
</div> </div>
<div class="card-body pb-3" id="form1"> <div class="card-body pb-3" id="form1">
<form role="form text-left"> <form role="form text-left">
<div class="text-center"> <div class="text-center">
<% <%
//new date //new date
const date = new Date(); const date = new Date();
//convert unix to string //convert unix to string
const dateString = date.toString(); const dateString = date.toString();
//split date string //split date string
const dateSplit = dateString.split(" "); const dateSplit = dateString.split(" ");
//get date //get date
const dateFinal = dateSplit[2] + "-" + dateSplit[1] + "-" + dateSplit[3]; const dateFinal = dateSplit[2] + "-" + dateSplit[1] + "-" + dateSplit[3];
//get time //get time
const timeFinal = dateSplit[4]; const timeFinal = dateSplit[4];
//split by space and join by - //split by space and join by -
const timeFinal2 = timeFinal.replace(/[&\/\\#, +()$~%.'":*?<>{}]/g, '-'); const timeFinal2 = timeFinal.replace(/[&\/\\#, +()$~%."":*?<>{}]/g, "-");
%> %>
<a href="data:<%- data %>" <a href="data:<%- data %>"
download="Log_SoftUI_<%- timeFinal2 %>_<%- dateFinal %>.json" download="Log_SoftUI_<%- timeFinal2 %>_<%- dateFinal %>.json"
class="btn bg-gradient-primary">download JSON</a> class="btn bg-gradient-primary">download JSON</a>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer text-center pt-0 px-sm-4 px-1"> <div class="card-footer text-center pt-0 px-sm-4 px-1">
Paste this in the <a Paste this in the <a
href="https://discord.com/channels/803034737261936670/803036935785414717" href="https://discord.com/channels/803034737261936670/803036935785414717"
target="_blank" class="text-dark font-weight-bolder">#😖»get-help</a> channel. target="_blank" class="text-dark font-weight-bolder">#😖»get-help</a> channel.
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="row"> <div class="row">
<div class="col-xl-6"> <div class="col-xl-6">
<div class="row pb-4"> <div class="row pb-4">
<div class="col-md-6"> <div class="col-md-6">
<div class="card"> <div class="card">
<div class="card-header mx-4 p-3 text-center"> <div class="card-header mx-4 p-3 text-center">
<div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg"> <div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg">
<i class="fab fa-node-js opacity-10" aria-hidden="true"></i> <i class="fab fa-node-js opacity-10" aria-hidden="true"></i>
</div> </div>
</div> </div>
<div class="card-body pt-0 p-3 text-center"> <div class="card-body pt-0 p-3 text-center">
<h6 class="text-center mb-0">Node JS</h6> <h6 class="text-center mb-0">Node JS</h6>
<span class="text-xs">Version</span> <span class="text-xs">Version</span>
<hr class="horizontal dark my-3"> <hr class="horizontal dark my-3">
<h5 class="mb-0"><%- nodeVersion.split("v")[1] %></h5> <h5 class="mb-0"><%- nodeVersion.split("v")[1] %></h5>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-6 mt-md-0 mt-4"> <div class="col-md-6 mt-md-0 mt-4">
<div class="card"> <div class="card">
<div class="card-header mx-4 p-3 text-center"> <div class="card-header mx-4 p-3 text-center">
<div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg"> <div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg">
<i class="fab fa-discord opacity-10" aria-hidden="true"></i> <i class="fab fa-discord opacity-10" aria-hidden="true"></i>
</div> </div>
</div> </div>
<div class="card-body pt-0 p-3 text-center"> <div class="card-body pt-0 p-3 text-center">
<h6 class="text-center mb-0">Discord.JS</h6> <h6 class="text-center mb-0">Discord.JS</h6>
<span class="text-xs">Version</span> <span class="text-xs">Version</span>
<hr class="horizontal dark my-3"> <hr class="horizontal dark my-3">
<h5 class="mb-0"><%- discordVersion %></h5> <h5 class="mb-0"><%- discordVersion %></h5>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-xl-6"> <div class="col-xl-6">
<style> <style>
.fab { .fab {
color: rgb(232, 230, 227) !important; color: rgb(232, 230, 227) !important;
} }
.fas { .fas {
color: rgb(232, 230, 227) !important; color: rgb(232, 230, 227) !important;
} }
</style> </style>
<div class="row"> <div class="row">
<div class="col-md-6 mb-4"> <div class="col-md-6 mb-4">
<div class="card"> <div class="card">
<div class="card-header mx-4 p-3 text-center"> <div class="card-header mx-4 p-3 text-center">
<div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg"> <div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg">
<i class="fas fa-landmark opacity-10" aria-hidden="true"></i> <i class="fas fa-landmark opacity-10" aria-hidden="true"></i>
</div> </div>
</div> </div>
<div class="card-body pt-0 p-3 text-center"> <div class="card-body pt-0 p-3 text-center">
<h6 class="text-center mb-0">Discord Dashboard</h6> <h6 class="text-center mb-0">Discord Dashboard</h6>
<span class="text-xs">Version</span> <span class="text-xs">Version</span>
<hr class="horizontal dark my-3"> <hr class="horizontal dark my-3">
<h5 class="mb-0"><%- dbdVersion %></h5> <h5 class="mb-0"><%- dbdVersion %></h5>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-6 mt-md-0 mt-4 mb-4"> <div class="col-md-6 mt-md-0 mt-4 mb-4">
<div class="card"> <div class="card">
<div class="card-header mx-4 p-3 text-center"> <div class="card-header mx-4 p-3 text-center">
<div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg"> <div class="icon icon-shape icon-lg bg-gradient-primary shadow text-center border-radius-lg">
<i class="fas fa-cloud opacity-10" aria-hidden="true"></i> <i class="fas fa-cloud opacity-10" aria-hidden="true"></i>
</div> </div>
</div> </div>
<div class="card-body pt-0 p-3 text-center"> <div class="card-body pt-0 p-3 text-center">
<h6 class="text-center mb-0">Theme</h6> <h6 class="text-center mb-0">Theme</h6>
<span class="text-xs">Version</span> <span class="text-xs">Version</span>
<hr class="horizontal dark my-3"> <hr class="horizontal dark my-3">
<h5 class="mb-0"><%- themeVersion %></h5> <h5 class="mb-0"><%- themeVersion %></h5>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-4 mb-lg-0 mb-4"> <div class="col-md-4 mb-lg-0 mb-4">
<div class="card"> <div class="card">
<div class="card-header pb-0 p-3"> <div class="card-header pb-0 p-3">
<div class="row"> <div class="row">
<div class="col-6 d-flex align-items-center"> <div class="col-6 d-flex align-items-center">
<h6 class="mb-0">Dashboard Logs</h6> <h6 class="mb-0">Dashboard Logs</h6>
</div> </div>
</div> </div>
</div> </div>
<div class="card-body p-3"> <div class="card-body p-3">
<div class="row"> <div class="row">
<div class="col-md-12 mb-md-0 mb-4"> <div class="col-md-12 mb-md-0 mb-4">
<div data-bs-toggle="modal" style="cursor: pointer;" <div data-bs-toggle="modal" style="cursor: pointer;"
data-bs-target="#exampleModalSignUp" data-bs-target="#exampleModalSignUp"
class="alert alert-primary text-white font-weight-bold text-center" class="alert alert-primary text-white font-weight-bold text-center"
role="alert"> role="alert">
Download Logs Download Logs
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-4 mb-lg-0 mb-4"> <div class="col-md-4 mb-lg-0 mb-4">
<div class="card"> <div class="card">
<div class="card-header pb-0 p-3"> <div class="card-header pb-0 p-3">
<div class="row"> <div class="row">
<div class="col-6 d-flex align-items-center"> <div class="col-6 d-flex align-items-center">
<h6 class="mb-0">Theme Modification</h6> <h6 class="mb-0">Theme Modification</h6>
</div> </div>
</div> </div>
</div> </div>
<div class="card-body p-3"> <div class="card-body p-3">
<div class="row"> <div class="row">
<div class="col-md-12 mb-md-0 mb-4"> <div class="col-md-12 mb-md-0 mb-4">
<% if(modified !== 0){ %> <% if(modified !== 0){ %>
<div class="alert alert-danger text-white font-weight-bold" <div class="alert alert-danger text-white font-weight-bold"
role="alert"> role="alert">
This theme has been modified! This theme has been modified!
</div> </div>
<% } else{ %> <% } else{ %>
<div class="alert alert-success text-white font-weight-bold" <div class="alert alert-success text-white font-weight-bold"
role="alert"> role="alert">
This theme has not been modified! This theme has not been modified!
</div> </div>
<% } %> <% } %>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-4 mb-lg-0 mb-4"> <div class="col-md-4 mb-lg-0 mb-4">
<div class="card"> <div class="card">
<div class="card-header pb-0 p-3"> <div class="card-header pb-0 p-3">
<div class="row"> <div class="row">
<div class="col-6 d-flex align-items-center"> <div class="col-6 d-flex align-items-center">
<h6 class="mb-0">Dashboard Information</h6> <h6 class="mb-0">Dashboard Information</h6>
</div> </div>
<div style="text-align: right;" class="col-6 align-items-right"> <div style="text-align: right;" class="col-6 align-items-right">
<a style="text-align: right;">Uptime: <%- filterUptime %></a> <a style="text-align: right;">Uptime: <%- filterUptime %></a>
</div> </div>
</div> </div>
</div> </div>
<div class="card-body p-3"> <div class="card-body p-3">
<div class="row"> <div class="row">
<div class="col-md-12 mb-md-0 mb-4"> <div class="col-md-12 mb-md-0 mb-4">
<% if (license == "opensource") { %> <div class="alert alert-warning text-white font-weight-bold" role="alert">
<div class="alert alert-primary text-white font-weight-bold" License type: <span style="text-transform: capitalize;">No License</span>
role="alert"> </div>
License type: <span </div>
style="text-transform: capitalize;"><%- license %></span> </div>
</div> </div>
<% } else if (license == "personal") { %> </div>
<div class="alert alert-success text-white font-weight-bold" </div>
role="alert"> </div>
License type: <span <div class="col-md-12 mt-4">
style="text-transform: capitalize;"><%- license %></span> <div class="col-12 col-lg-12 mb-4">
</div> <div class="card ">
<% } else if (license == "production") { %> <div class="card-header pb-0 p-3">
<div class="alert alert-info text-white font-weight-bold" role="alert"> <div class="d-flex justify-content-between">
License type: <span <h6 class="mb-2">Partial Information</h6>
style="text-transform: capitalize;"><%- license %></span> </div>
</div> </div>
<% } else { %> </div>
<div class="alert alert-warning text-white font-weight-bold" </div>
role="alert"> </div>
License type: <span </div>
style="text-transform: capitalize;">Unknown</span> </div>
</div> <div class="row">
<% } %> </div>
</div> <%- include("partials/footer.ejs") %>
</div> </div>
</div> </main>
</div> </div>
</div> <%- include("partials/scripts.ejs", {now: "debug"}) %>
</div>
<div class="col-md-12 mt-4">
<div class="col-12 col-lg-12 mb-4">
<div class="card ">
<div class="card-header pb-0 p-3">
<div class="d-flex justify-content-between">
<h6 class="mb-2">Partial Information</h6>
</div>
</div>
<div class="table-responsive">
<table class="table align-items-center ">
<tbody>
<% onlineV.forEach(online => { %>
<%
const latest = onlineV[online.version];
const current = localV[online.name];
const newest = online.version;
%>
<tr>
<td class="w-30">
<div class="d-flex px-2 py-1 align-items-center">
<div class="ms-2">
<p class="text-xs font-weight-bold mb-0">Name:</p>
<h6 class="text-sm mb-0"
style="text-transform: capitalize;"><%- online.name %></h6>
</div>
</div>
</td>
<td>
<div class="text-center">
<p class="text-xs font-weight-bold mb-0">Version:</p>
<h6 class="text-sm mb-0"><%- current %></h6>
</div>
</td>
<td>
<div class="text-center">
<p class="text-xs font-weight-bold mb-0">Type:</p>
<h6 class="text-sm mb-0"
style="text-transform: capitalize;"><%- online.type %></h6>
</div>
</td>
<td class="align-middle text-sm">
<div class="col text-center">
<p class="text-xs font-weight-bold mb-0">Latest:</p>
<%
let update = true;
if (newest > current) update = true;
if (newest == current) update = false;
%>
<% if (update) { %>
<span class="badge bg-gradient-danger"><%- online.version %></span>
<% } else { %>
<span class="badge bg-gradient-success"><%- online.version %></span>
<% } %>
</div>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
</div>
<%- include('partials/footer.ejs') %>
</div>
</main>
</div>
<%- include('partials/scripts.ejs', {now: "debug"}) %>
</body> </body>
</html> </html>

View file

@ -1,151 +1,136 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<%- include('partials/preloader.ejs', {now: 'error'}) %> <%- include('partials/preloader.ejs', {now: 'error'}) %>
<% <%
let data let data
if (error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) { if (error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) {
data = "text/json;charset=utf-8," + encodeURIComponent(error) + "\n" data = "text/json;charset=utf-8," + encodeURIComponent(error) + "\n"
data += `${error.path}` data += `${error.path}`
} }
%> %>
<% if (error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) { %> <% if (error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) { %>
<script> <script>
function copyToClipboard(text) { function copyToClipboard(text) {
if (window.clipboardData && window.clipboardData.setData) { if (window.clipboardData && window.clipboardData.setData) {
return window.clipboardData.setData("Text", text); return window.clipboardData.setData("Text", text);
} }
else if (document.queryCommandSupported && document.queryCommandSupported("copy")) { else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
var textarea = document.createElement("textarea"); var textarea = document.createElement("textarea");
textarea.textContent = text; textarea.textContent = text;
textarea.style.position = "fixed"; textarea.style.position = "fixed";
document.body.appendChild(textarea); document.body.appendChild(textarea);
textarea.select(); textarea.select();
try { try {
document.execCommand("copy"); document.execCommand("copy");
} }
catch (ex) { catch (ex) {
console.warn("Copy to clipboard failed.", ex); console.warn("Copy to clipboard failed.", ex);
prompt("Copy to clipboard: Ctrl+C, Enter", text); prompt("Copy to clipboard: Ctrl+C, Enter", text);
} }
finally { finally {
document.body.removeChild(textarea); document.body.removeChild(textarea);
sweetalert("success", "Copied to clipboard", 3000) sweetalert("success", "Copied to clipboard", 3000)
} }
} }
} }
</script> </script>
<% } %> <% } %>
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100" id="scroll"> <body class="g-sidenav-show bg-gray-100" id="scroll">
<%- include('partials/preload.ejs') %> <%- include('partials/preload.ejs') %>
<header> <header>
<div class="page-header min-vh-85"> <div class="page-header min-vh-85">
<% <%
const images = ["curved-1", "curved-2", "curved-3", "curved-4", "curved-5", "curved-6", "curved-7", "curved-8", "curved-9", "curved-10", "curved-11", "curved-12", "curved-13", "curved-14", "curved-15", "curved-16", "curved-17", "curved-18"]; const images = ["curved-1", "curved-2", "curved-3", "curved-4", "curved-5", "curved-6", "curved-7", "curved-8", "curved-9", "curved-10", "curved-11", "curved-12", "curved-13", "curved-14", "curved-15", "curved-16", "curved-17", "curved-18"];
const image = images[Math.floor(Math.random() * images.length)]; const image = images[Math.floor(Math.random() * images.length)];
%> %>
<div style="background-image: url('/img/curved-images/<%- image %>.webp') !important; background: no-repeat; background-size: cover;" <div style="background-image: url('/img/curved-images/<%- image %>.webp') !important; background: no-repeat; background-size: cover;"
class="position-absolute fixed-top ms-auto w-50 h-100 z-index-0 d-none d-sm-none d-md-block border-radius-section border-top-end-radius-0 border-top-start-radius-0 border-bottom-end-radius-0"> class="position-absolute fixed-top ms-auto w-50 h-100 z-index-0 d-none d-sm-none d-md-block border-radius-section border-top-end-radius-0 border-top-start-radius-0 border-bottom-end-radius-0">
<span class="mask bg-gradient-primary ms-auto h-100 z-index-0 d-none d-sm-none d-md-block border-radius-section border-top-end-radius-0 border-top-start-radius-0 border-bottom-end-radius-0"> <span class="mask bg-gradient-primary ms-auto h-100 z-index-0 d-none d-sm-none d-md-block border-radius-section border-top-end-radius-0 border-top-start-radius-0 border-bottom-end-radius-0">
</span> </span>
</div> </div>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-lg-7 d-flex"> <div class="col-lg-7 d-flex">
<div class="card card-body blur text-md-start text-center px-sm-5 shadow-lg mt-sm-5 py-sm-5"> <div class="card card-body blur text-md-start text-center px-sm-5 shadow-lg mt-sm-5 py-sm-5">
<h2 class="text-gradient text-primary mb-0"> <%- title %></h2> <h2 class="text-gradient text-primary mb-0"> <%- title %></h2>
<h2 class="text-dark mb-4"><%- subtitle %></h2> <h2 class="text-dark mb-4"><%- subtitle %></h2>
<p class="lead text-dark pe-md-5 me-md-5"> <p class="lead text-dark pe-md-5 me-md-5">
<%- description %> <%- description %>
</p> </p>
<% if (req.originalUrl !== "/") { %> <% if (req.originalUrl !== "/") { %>
<div class="buttons"> <div class="buttons">
<a href="/" class="btn btn-rounded bg-gradient-primary mt-4">Return to home</a> <a href="/" class="btn btn-rounded bg-gradient-primary mt-4">Return to home</a>
<!-- <a target="_blank" href="https://discord.gg/CHbfcSbEgd" class="btn btn-rounded btn-outline-secondary mt-4 ms-2">Get help</a> --> <!-- <a target="_blank" href="https://discord.gg/CHbfcSbEgd" class="btn btn-rounded btn-outline-secondary mt-4 ms-2">Get help</a> -->
</div> </div>
<% } %> <% } %>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</header> </header>
</main> </main>
<%- include('partials/scripts.ejs', {now: "index"}) %> <%- include('partials/scripts.ejs', {now: "index"}) %>
<% if(error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) { %> <% if(error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) { %>
<div class="modal fade" id="exampleModalSignUp" tabindex="-1" role="dialog" aria-labelledby="exampleModalSignTitle" <div class="modal fade" id="exampleModalSignUp" tabindex="-1" role="dialog" aria-labelledby="exampleModalSignTitle"
aria-hidden="true"> aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-sm" role="document" style="max-width: 700px;"> <div class="modal-dialog modal-dialog-centered modal-sm" role="document" style="max-width: 700px;">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body p-0"> <div class="modal-body p-0">
<div class="card card-plain"> <div class="card card-plain">
<div class="card-body pb-3" id="form1"> <div class="card-body pb-3" id="form1">
<h4 class="font-weight-bolder text-primary text-gradient">Viewing Error</h4> <h4 class="font-weight-bolder text-primary text-gradient">Viewing Error</h4>
<pre><%= error %><br><br>Error occured at: <%- error.path %><br>Check console logs for more information</pre> <pre><%= error %><br><br>Error occured at: <%- error.path %><br>Check console logs for more information</pre>
</div> </div>
<div class="d-flex" style="justify-content: flex-end; margin-right: 20px"> <div class="d-flex" style="justify-content: flex-end; margin-right: 20px">
<!-- <!--
<button onclick="copyToClipboard(`<%= strError %>`)" class="btn btn-primary" style="margin-left: 10px;">Copy <button onclick="copyToClipboard(`<%= strError %>`)" class="btn btn-primary" style="margin-left: 10px;">Copy
error error
</button> </button>
--> -->
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<% if (error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) { %> <% if (error !== undefined && error && config.ownerIDs?.includes(req.session?.user?.id) && !themeConfig?.error?.dbdError?.disableSecretMenu) { %>
<script> <script>
if (window.addEventListener) { if (window.addEventListener) {
const konami = <%- JSON.stringify(themeConfig?.error?.dbdError?.secretMenuCombination || ["69", "82", "82", "79", "82"]) %> //this spells error const konami = <%- JSON.stringify(themeConfig?.error?.dbdError?.secretMenuCombination || ["69", "82", "82", "79", "82"]) %> //this spells error
let let
currentCount = 0; currentCount = 0;
let entered = []; let entered = [];
window.addEventListener("keydown", function (e) { window.addEventListener("keydown", function (e) {
if (e.keyCode.toString() === konami[currentCount]) { if (e.keyCode.toString() === konami[currentCount]) {
if (currentCount !== 0 && entered[currentCount - 1] !== konami[currentCount - 1]) { if (currentCount !== 0 && entered[currentCount - 1] !== konami[currentCount - 1]) {
// User has messed with variables in console to try show it smh // User has messed with variables in console to try show it smh
entered = []; entered = [];
return currentCount = 0; return currentCount = 0;
} }
if (!konami[currentCount + 1]) { if (!konami[currentCount + 1]) {
// Correct code // Correct code
$('#exampleModalSignUp').modal('show'); $('#exampleModalSignUp').modal('show');
currentCount = 0; currentCount = 0;
return entered = []; return entered = [];
} }
entered.push(e.keyCode.toString()); entered.push(e.keyCode.toString());
currentCount++; currentCount++;
} else { } else {
currentCount = 0; currentCount = 0;
return entered = []; return entered = [];
} }
}, true); }, true);
} }
</script> </script>
<% } %> <% } %>
<% } %> <% } %>
</body> </body>

View file

@ -1,29 +1,13 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<script> <script>
window.onload = function () { window.onload = function () {
if(window.location.search.startsWith("?redirect=")) window.opener.location = window.location.replace("?redirect=", ""); if(window.location.search.startsWith("?redirect=")) window.opener.location = window.location.replace("?redirect=", "");
else window.location.href = `settings/<%= req.params.id %>`; else window.location.href = `settings/<%= req.params.id %>`;
} }
</script> </script>
</head> </head>
<body class="g-sidenav-show bg-gray-100"> <body class="g-sidenav-show bg-gray-100">

View file

@ -1,115 +1,100 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<%- include('partials/preloader.ejs', {now:'manage'}) %> <%- include('partials/preloader.ejs', {now:'manage'}) %>
<link rel="stylesheet" href="/css/dashboard/guilds.css"> <link rel="stylesheet" href="/css/dashboard/guilds.css">
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100" id="scroll"> <body class="g-sidenav-show bg-gray-100" id="scroll">
<%- include('partials/preload.ejs') %> <%- include('partials/preload.ejs') %>
<%- include('partials/sidebar.ejs', {config: config, now:'manage'}) %> <%- include('partials/sidebar.ejs', {config: config, now:'manage'}) %>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<%- include('partials/navbar.ejs', {now:'manage'}) %> <%- include('partials/navbar.ejs', {now:'manage'}) %>
<div class="container-fluid py-4" style="padding-bottom: 0px !important;"> <div class="container-fluid py-4" style="padding-bottom: 0px !important;">
<div class="row"> <div class="row">
<div class="col-12" id="divtable"> <div class="col-12" id="divtable">
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header pb-0" style="text-align: center;"> <div class="card-header pb-0" style="text-align: center;">
<h2 class="mb-1"> <h2 class="mb-1">
Your servers Your servers
</h2> </h2>
<p class="mb-0 font-weight-bold text-sm"> <p class="mb-0 font-weight-bold text-sm">
Select the server you want to configure Select the server you want to configure
</p> </p>
</div> </div>
<div class="card-body px-0 pt-0 pb-2"> <div class="card-body px-0 pt-0 pb-2">
<div style="margin-bottom: 35px; margin-top: 0px; text-align: center;"> <div style="margin-bottom: 35px; margin-top: 0px; text-align: center;">
<% <%
for(var i in req.session.guilds){ %> for(var i in req.session.guilds){ %>
<% if((req.session.guilds[i].permissions & 0x00000020) == 0x00000020){ %> <% if((req.session.guilds[i].permissions & 0x00000020) == 0x00000020){ %>
<% if(bot.guilds.cache.get(req.session.guilds[i].id)){ <% if(bot.guilds.cache.get(req.session.guilds[i].id)){
const guild = bot.guilds.cache.get(req.session.guilds[i].id); const guild = bot.guilds.cache.get(req.session.guilds[i].id);
let icon; let icon;
if (!guild.iconURL()) icon = themeConfig?.icons?.noGuildIcon; if (!guild.iconURL()) icon = themeConfig?.icons?.noGuildIcon;
else icon = guild.iconURL() + "?size=256"; else icon = guild.iconURL() + "?size=256";
%> %>
<a oncontextmenu="window.location='/guild/<%- guild.id %>'; return false;" <a oncontextmenu="window.location='/guild/<%- guild.id %>'; return false;"
onclick="window.location='/settings/<%- guild.id %>'"> onclick="window.location='/settings/<%- guild.id %>'">
<div max="20" scale="110" perspective="400" class="_82d1" <div max="20" scale="110" perspective="400" class="_82d1"
data-guildname="<%- guild.name %>" data-guildname="<%- guild.name %>"
style="background-image: url(&quot;<%- icon %>&quot;);"></div> style="background-image: url(&quot;<%- icon %>&quot;);"></div>
</a> </a>
<% } } } %> <% } } } %>
</div> </div>
<div class="_4204" style="margin-bottom: 35px; text-align: center;"> <div class="_4204" style="margin-bottom: 35px; text-align: center;">
<% for (var i in req.session.guilds){ %> <% for (var i in req.session.guilds){ %>
<% if((req.session.guilds[i].permissions & 0x00000020) == 0x00000020){ %> <% if((req.session.guilds[i].permissions & 0x00000020) == 0x00000020){ %>
<% <%
if(!bot.guilds.cache.get(req.session.guilds[i].id)){ if(!bot.guilds.cache.get(req.session.guilds[i].id)){
let icon = `https://cdn.discordapp.com/icons/${req.session.guilds[i].id}/${req.session.guilds[i].icon}.png`; let icon = `https://cdn.discordapp.com/icons/${req.session.guilds[i].id}/${req.session.guilds[i].icon}.png`;
const friendlyName = req.session.guilds[i].name.replace('`', ''); const friendlyName = req.session.guilds[i].name.replace('`', '');
if (!req.session.guilds[i].icon) icon = themeConfig.icons.noGuildIcon; if (!req.session.guilds[i].icon) icon = themeConfig.icons.noGuildIcon;
else icon = icon + "?size=256" else icon = icon + "?size=256"
%> %>
<!--href="../invite?g=<%- req.session.guilds[i].id %>"--> <!--href="../invite?g=<%- req.session.guilds[i].id %>"-->
<a onclick="const newWindow = window.open(`/invite?g=<%- req.session.guilds[i].id %><%- config.invite?.redirectUri ? `&redirect=${config.invite.redirectUri.replace('{SERVER}', req.session.guilds[i].id)}` : '' %>`, 'Add bot to guild', 'scrollbars=no, resizable=no, status=no, location=no, toolbar=no, menubar=no, width=500, height=800'); checkRefresh()"> <a onclick="const newWindow = window.open(`/invite?g=<%- req.session.guilds[i].id %><%- config.invite?.redirectUri ? `&redirect=${config.invite.redirectUri.replace('{SERVER}', req.session.guilds[i].id)}` : '' %>`, 'Add bot to guild', 'scrollbars=no, resizable=no, status=no, location=no, toolbar=no, menubar=no, width=500, height=800'); checkRefresh()">
<div max="20" scale="110" perspective="700" class="_82d1" <div max="20" scale="110" perspective="700" class="_82d1"
data-guildname="<%- req.session.guilds[i].name %>" data-guildname="<%- req.session.guilds[i].name %>"
style="background-image: url(&quot;<%- icon %>&quot;); filter: grayscale(1);"></div> style="background-image: url(&quot;<%- icon %>&quot;); filter: grayscale(1);"></div>
</a> </a>
<% } } } %> <% } } } %>
<script> <script>
function checkRefresh() { function checkRefresh() {
setInterval(() => { setInterval(() => {
if (newWindow.closed) location.reload(); if (newWindow.closed) location.reload();
}, 500); }, 500);
} }
</script> </script>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<%- include('partials/footer.ejs') %> <%- include('partials/footer.ejs') %>
</div> </div>
</div> </div>
<!-- Core JS Files --> <!-- Core JS Files -->
<script src="../assets/js/core/popper.min.js"></script> <script src="../assets/js/core/popper.min.js"></script>
<script src="../assets/js/core/bootstrap.min.js"></script> <script src="../assets/js/core/bootstrap.min.js"></script>
<script src="../assets/js/plugins/perfect-scrollbar.min.js"></script> <script src="../assets/js/plugins/perfect-scrollbar.min.js"></script>
<script src="../assets/js/plugins/smooth-scrollbar.min.js"></script> <script src="../assets/js/plugins/smooth-scrollbar.min.js"></script>
<script> <script>
var win = navigator.platform.indexOf('Win') > -1; var win = navigator.platform.indexOf('Win') > -1;
if (win && document.querySelector('#sidenav-scrollbar')) { if (win && document.querySelector('#sidenav-scrollbar')) {
var options = { var options = {
damping: '0.5' damping: '0.5'
} }
Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options); Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options);
} }
</script> </script>
<!-- Github buttons --> <!-- Github buttons -->
<script async defer src="https://buttons.github.io/buttons.js"></script> <script async defer src="https://buttons.github.io/buttons.js"></script>
<!-- Control Center for Soft Dashboard: parallax effects, scripts for the example pages etc --> <!-- Control Center for Soft Dashboard: parallax effects, scripts for the example pages etc -->
<%- include('partials/scripts.ejs', {now: "guilds"}) %> <%- include('partials/scripts.ejs', {now: "guilds"}) %>
</body> </body>
</html> </html>

View file

@ -1,36 +1,21 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<%- include('partials/preloader.ejs', {now:'index', req: req}) %> <%- include('partials/preloader.ejs', {now:'index', req: req}) %>
<% if (req.query?.guild_id) { %> <% if (req.query?.guild_id) { %>
<script> <script>
window.onload = function () { window.onload = function () {
window.onunload = refreshParent; window.onunload = refreshParent;
function refreshParent() { function refreshParent() {
window.opener.location = `/settings/<%= req.query?.guild_id %>`; window.opener.location = `/settings/<%= req.query?.guild_id %>`;
window.close(); window.close();
return return
}; };
window.opener.location = `/settings/<%= req.query?.guild_id %>`; window.opener.location = `/settings/<%= req.query?.guild_id %>`;
window.close(); window.close();
} }
</script> </script>
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
<% } %> <% } %>
<head> <head>
</head> </head>
@ -38,115 +23,115 @@
<%- include('partials/preload.ejs') %> <%- include('partials/preload.ejs') %>
<%- include('partials/sidebar.ejs', {config: config, now:'index'}) %> <%- include('partials/sidebar.ejs', {config: config, now:'index'}) %>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<!-- Navbar --> <!-- Navbar -->
<%- include('partials/navbar.ejs', {now:'index'}) %> <%- include('partials/navbar.ejs', {now:'index'}) %>
<!-- End Navbar --> <!-- End Navbar -->
<div class="container-fluid py-4" style="padding-bottom: 0px !important;"> <div class="container-fluid py-4" style="padding-bottom: 0px !important;">
<div class="row mb-3"> <div class="row mb-3">
<% <%
let i = 0; let i = 0;
customThemeOptions.cards.forEach((stats) => { customThemeOptions.cards.forEach((stats) => {
%> %>
<div class="col-xl-3 col-sm-6 mb-xl-0 mb-4"> <div class="col-xl-3 col-sm-6 mb-xl-0 mb-4">
<div class="card"> <div class="card">
<div class="card-body p-3"> <div class="card-body p-3">
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<div class="numbers"> <div class="numbers">
<p class="text-sm mb-0 text-capitalize font-weight-bold"> <p class="text-sm mb-0 text-capitalize font-weight-bold">
<%- req?.locales?.index?.feeds[i] || stats.title %></p> <%- req?.locales?.index?.feeds[i] || stats.title %></p>
<h5 class="font-weight-bolder mb-0"> <h5 class="font-weight-bolder mb-0">
<%- stats.getValue %> <%- stats.getValue %>
</h5> </h5>
</div> </div>
<% if(stats.progressBar && stats.progressBar.enabled){ %> <% if(stats.progressBar && stats.progressBar.enabled){ %>
<div class="progress w-150" style="margin-top: 6px;"> <div class="progress w-150" style="margin-top: 6px;">
<div style="width: <%= stats.progressBar.getProgress %>% !important" <div style="width: <%= stats.progressBar.getProgress %>% !important"
aria-label="Progress Bar" aria-label="Progress Bar"
class="progress-bar bg-gradient-primary" class="progress-bar bg-gradient-primary"
role="progressbar" aria-valuenow="80" aria-valuemin="0" role="progressbar" aria-valuenow="80" aria-valuemin="0"
aria-valuemax="100"></div> aria-valuemax="100"></div>
</div> </div>
<% } %> <% } %>
</div> </div>
<div class="col-4 text-end"> <div class="col-4 text-end">
<div class="icon icon-shape bg-gradient-primary shadow text-center border-radius-md"> <div class="icon icon-shape bg-gradient-primary shadow text-center border-radius-md">
<i class="ni ni-<%= stats.icon %> text-lg opacity-10" aria-hidden="true"></i> <i class="ni ni-<%= stats.icon %> text-lg opacity-10" aria-hidden="true"></i>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<% i++ }); %> <% i++ }); %>
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-12 mb-lg-0 mb-4"> <div class="col-lg-12 mb-lg-0 mb-4">
<div class="card"> <div class="card">
<div class="card-body p-3"> <div class="card-body p-3">
<div class="row"> <div class="row">
<div class="col-lg-6"> <div class="col-lg-6">
<div class="d-flex flex-column h-100"> <div class="d-flex flex-column h-100">
<p class="mb-1 pt-2 text-bold"><%- req?.locales?.index?.card?.category %></p> <p class="mb-1 pt-2 text-bold"><%- req?.locales?.index?.card?.category %></p>
<h5 class="font-weight-bolder"><%- req?.locales?.index?.card?.title %></h5> <h5 class="font-weight-bolder"><%- req?.locales?.index?.card?.title %></h5>
<p><%- req?.locales?.index?.card?.description %></p> <p><%- req?.locales?.index?.card?.description %></p>
<p class="mb-5"><%= req?.locales?.index?.card?.footer %></p> <p class="mb-5"><%= req?.locales?.index?.card?.footer %></p>
<% if(themeConfig.index?.card?.link?.enabled) { %> <% if(themeConfig.index?.card?.link?.enabled) { %>
<a class="text-body text-sm font-weight-bold mb-0 icon-move-right mt-auto" <a class="text-body text-sm font-weight-bold mb-0 icon-move-right mt-auto"
href="<%- themeConfig.index.card.link.url %>"> href="<%- themeConfig.index.card.link.url %>">
<%- req?.locales?.index?.card?.link?.text %> <%- req?.locales?.index?.card?.link?.text %>
<i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i> <i class="fas fa-arrow-right text-sm ms-1" aria-hidden="true"></i>
</a> </a>
<% } %> <% } %>
</div> </div>
</div> </div>
<div class="col-lg-5 ms-auto text-center mt-5 mt-lg-0"> <div class="col-lg-5 ms-auto text-center mt-5 mt-lg-0">
<div class="bg-gradient-primary border-radius-lg h-100" <div class="bg-gradient-primary border-radius-lg h-100"
style="background-image: url('<%= req?.locales?.index?.card?.image %>') !important; background-repeat: no-repeat; background-size: contain; background-position: center;"> style="background-image: url('<%= req?.locales?.index?.card?.image %>') !important; background-repeat: no-repeat; background-size: contain; background-position: center;">
<div class="position-relative d-flex align-items-center justify-content-center h-100" <div class="position-relative d-flex align-items-center justify-content-center h-100"
style="min-height: 210px !important;"> style="min-height: 210px !important;">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row mt-3"> <div class="row mt-3">
<div class="col-lg-7 mb-lg-0 mb-4"> <div class="col-lg-7 mb-lg-0 mb-4">
<div class="card z-index-2"> <div class="card z-index-2">
<div class="card-body p-3"> <div class="card-body p-3">
<h5 class="font-weight-bolder"><%- req?.locales?.index?.feeds.title || "Feeds" %></h5> <h5 class="font-weight-bolder"><%- req?.locales?.index?.feeds.title || "Feeds" %></h5>
<%- include('partials/feeds.ejs', {require, admin:false}) %> <%- include('partials/feeds.ejs', {require, admin:false}) %>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-5 mb-4"> <div class="col-lg-5 mb-4">
<% if(themeConfig.index?.graph?.enabled) { %> <% if(themeConfig.index?.graph?.enabled) { %>
<div class="card z-index-2"> <div class="card z-index-2">
<div class="card-body p-3"> <div class="card-body p-3">
<h5 class="font-weight-bolder"><%- req?.locales?.index?.graph?.title %></h5> <h5 class="font-weight-bolder"><%- req?.locales?.index?.graph?.title %></h5>
<% if(themeConfig.index.graph.lineGraph) { %> <% if(themeConfig.index.graph.lineGraph) { %>
<div class="bg-gradient-dark border-radius-lg py-3 pe-1 mb-3"> <div class="bg-gradient-dark border-radius-lg py-3 pe-1 mb-3">
<% } %> <% } %>
<div class="chart"> <div class="chart">
<% if(!themeConfig.index.graph.lineGraph) { %> <% if(!themeConfig.index.graph.lineGraph) { %>
<canvas id="chart-line" class="chart-canvas" height="300"></canvas> <canvas id="chart-line" class="chart-canvas" height="300"></canvas>
<% } else { %> <% } else { %>
<canvas id="chart-bars" class="chart-canvas" height="170"></canvas> <canvas id="chart-bars" class="chart-canvas" height="170"></canvas>
<% } %> <% } %>
</div> </div>
<% if(themeConfig.index.graph.lineGraph) { %> <% if(themeConfig.index.graph.lineGraph) { %>
</div> </div>
<% } %> <% } %>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<% } %> <% } %>
</div> </div>
<%- include('partials/footer.ejs') %> <%- include('partials/footer.ejs') %>
</div> </div>
</div> </div>
</main> </main>

View file

@ -1,140 +1,140 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/soft-ui-dashboard.min.css"> <link rel="stylesheet" href="/css/soft-ui-dashboard.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Alatsi"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Alatsi">
<link rel="stylesheet" href="/css/nucleo-icons.css"> <link rel="stylesheet" href="/css/nucleo-icons.css">
<link rel="stylesheet" href="/css/nucleo-svg.css"> <link rel="stylesheet" href="/css/nucleo-svg.css">
<link rel="stylesheet" href="/css/soft-ui-dashboard.min.css"> <link rel="stylesheet" href="/css/soft-ui-dashboard.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@4/dark.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@4/dark.css">
<link rel="stylesheet" href="/css/jquery-ui.css"> <link rel="stylesheet" href="/css/jquery-ui.css">
<%- include('partials/colorscheme.ejs') %> <%- include('partials/colorscheme.ejs') %>
<title><%= themeConfig.websiteName %> - Loading</title> <title><%= themeConfig.websiteName %> - Loading</title>
<% if(req.cookies?.selectedTheme == "dark" || req.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %> <% if(req.cookies?.selectedTheme == "dark" || req.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %>
<link href="/css/darkMode.css" rel='stylesheet' <link href="/css/darkMode.css" rel='stylesheet'
<% if(req?.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %> <% if(req?.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %>
media="(prefers-color-scheme: dark)" media="(prefers-color-scheme: dark)"
<% } %> <% } %>
> >
<% } %> <% } %>
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body> <body>
<style> <style>
@media all and (min-width: 0px) and (max-width: 600px) { @media all and (min-width: 0px) and (max-width: 600px) {
.responsive { .responsive {
width: calc(100vw - 30px) width: calc(100vw - 30px)
} }
} }
@media all and (min-width: 0px) and (max-width: 590px) { @media all and (min-width: 0px) and (max-width: 590px) {
.responsive { .responsive {
margin-top: calc(100vh / 4) !important; margin-top: calc(100vh / 4) !important;
} }
} }
.preloader { .preloader {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
width: 100%; width: 100%;
height: 100vh; height: 100vh;
z-index: 99999999; z-index: 99999999;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: none; background-image: none;
background-color: #FFF; background-color: #FFF;
background-position: center; background-position: center;
} }
#scroll { #scroll {
height: 100% !important; height: 100% !important;
/* overflow: hidden; */ /* overflow: hidden; */
} }
.progress-bar { .progress-bar {
transition: width 1s ease !important; transition: width 1s ease !important;
} }
</style> </style>
<div class="preloader"> <div class="preloader">
<div class="progress-wrapper"> <div class="progress-wrapper">
<div id="progress-bar" class="progress"> <div id="progress-bar" class="progress">
<div id="progress" class="progress-bar bg-gradient-primary" role="progressbar" aria-valuenow="60" <div id="progress" class="progress-bar bg-gradient-primary" role="progressbar" aria-valuenow="60"
aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div> aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
</div> </div>
</div> </div>
<% if(themeConfig.preloader){ %> <% if(themeConfig.preloader){ %>
<% if(themeConfig.preloader.image) { %> <% if(themeConfig.preloader.image) { %>
<% if(!themeConfig.preloader.spinner) { %> <% if(!themeConfig.preloader.spinner) { %>
<div class="loader"> <div class="loader">
<img class="responsive preloader-image" src="<%- themeConfig.preloader.image %>" alt="" <img class="responsive preloader-image" src="<%- themeConfig.preloader.image %>" alt=""
style="border-radius: 5%; display: block; margin-left: auto; margin-right: auto; margin-top: calc(100vh / 5.8);"> style="border-radius: 5%; display: block; margin-left: auto; margin-right: auto; margin-top: calc(100vh / 5.8);">
</div> </div>
<% } %> <% } %>
<% } %> <% } %>
<% if(themeConfig.preloader.text){ %> <% if(themeConfig.preloader.text){ %>
<br> <br>
<div style="text-align: center;<% if(themeConfig.preloader.spinner) { %>margin-top: calc(100vh / 2.7);<% } %>"> <div style="text-align: center;<% if(themeConfig.preloader.spinner) { %>margin-top: calc(100vh / 2.7);<% } %>">
<h1 class="font-weight-bolder text-primary text-gradient"><span id="stateText">Loading...</span></h1> <h1 class="font-weight-bolder text-primary text-gradient"><span id="stateText">Loading...</span></h1>
<% if(themeConfig.preloader.spinner) { %> <% if(themeConfig.preloader.spinner) { %>
<div style="transform: scale(3); padding-top: 30px;"> <div style="transform: scale(3); padding-top: 30px;">
<div style="text-align: center; " class="spinner-border text-primary text-gradient" <div style="text-align: center; " class="spinner-border text-primary text-gradient"
role="status"> role="status">
<span class="visually-hidden">Loading...</span> <span class="visually-hidden">Loading...</span>
</div> </div>
<span id="stateText"></span> <span id="stateText"></span>
</div> </div>
<% } %> <% } %>
</div> </div>
<% } %> <% } %>
<% } %> <% } %>
</div> </div>
<script> <script>
<% if (req.session.user) { %> <% if (req.session.user) { %>
window.onload = function () { window.onload = function () {
window.close() window.close()
} }
<% } %> <% } %>
let i = 0; let i = 0;
const reFetch = async () => { const reFetch = async () => {
const res = await fetch('/discord/status/'); const res = await fetch('/discord/status/');
const json = await res.json(); const json = await res.json();
if (json.loading == false && json.success == true) { if (json.loading == false && json.success == true) {
location.href = '<%= `${req.session.r}?swal=logged` || `/?swal=logged` %>'; location.href = '<%= `${req.session.r}?swal=logged` || `/?swal=logged` %>';
} else if (json.loading == false && json.success == false) { } else if (json.loading == false && json.success == false) {
location.href = '/?error=' + json.state.error; location.href = '/?error=' + json.state.error;
} }
if (json.loading == false && json.success == true) { if (json.loading == false && json.success == true) {
<% if (req.session.r == "/manage") { %> <% if (req.session.r == "/manage") { %>
location.href = '<%= `${req.session.r}?swal=logged` || `/?swal=logged` %>'; location.href = '<%= `${req.session.r}?swal=logged` || `/?swal=logged` %>';
<% } else { %> <% } else { %>
window.close(); window.close();
<% } %> <% } %>
document.getElementById('progress').style.width = 100 + '%'; document.getElementById('progress').style.width = 100 + '%';
return; return;
} }
; ;
if (json.loading == true) { if (json.loading == true) {
document.getElementById('stateText').innerHTML = json.state.data; document.getElementById('stateText').innerHTML = json.state.data;
document.getElementById('progress').style.width = i + '%'; document.getElementById('progress').style.width = i + '%';
if (i > 100) { if (i > 100) {
document.getElementById('stateText').innerHTML = "Finishing up..."; document.getElementById('stateText').innerHTML = "Finishing up...";
} }
i = i + 10; i = i + 10;
} else if (json.loading == false && json.success == false) { } else if (json.loading == false && json.success == false) {
location.href = '/?error=' + json.state.error; location.href = '/?error=' + json.state.error;
} }
; ;
} }
setInterval(() => { setInterval(() => {
reFetch() reFetch()
}, 300); }, 300);
</script> </script>
</body> </body>
</html> </html>

View file

@ -1,167 +1,154 @@
<!--
=========================================================
* Soft UI Design System - v1.0.5
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-design-system
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
Coded by www.creative-tim.com
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -->
<% <%
let logged = `<a id="login" onclick="auth()" class="btn btn-sm bg-gradient-primary btn-round mb-0 me-1 mt-2 mt-md-0">Login</a>`; let logged = `<a id="login" onclick="auth()" class="btn btn-sm bg-gradient-primary btn-round mb-0 me-1 mt-2 mt-md-0">Login</a>`;
if (loggedIn) logged = '<a href="/discord/logout" class="btn btn-sm bg-gradient-primary btn-round mb-0 me-1 mt-2 mt-md-0">Logout</a>'; if (loggedIn) logged = '<a href="/discord/logout" class="btn btn-sm bg-gradient-primary btn-round mb-0 me-1 mt-2 mt-md-0">Logout</a>';
let title, let title,
contentTitle, contentTitle,
texts; texts;
if (defaultMaintenanceConfig !== {}) { if (defaultMaintenanceConfig !== {}) {
title = defaultMaintenanceConfig.title; title = defaultMaintenanceConfig.title;
contentTitle = defaultMaintenanceConfig.contentTitle; contentTitle = defaultMaintenanceConfig.contentTitle;
texts = defaultMaintenanceConfig.texts; texts = defaultMaintenanceConfig.texts;
if (!texts) texts = []; if (!texts) texts = [];
} }
%> %>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" itemscope itemtype="http://schema.org/WebPage"> <html lang="en" itemscope itemtype="http://schema.org/WebPage">
<head> <head>
<%- include('partials/preloader.ejs', {now: 'maintenance'}) %> <%- include('partials/preloader.ejs', {now: 'maintenance'}) %>
<%- include('partials/colorscheme.ejs') %> <%- include('partials/colorscheme.ejs') %>
<style> <style>
.blur.blur-rounded { .blur.blur-rounded {
border-radius: 17px; border-radius: 17px;
} }
a.btn.btn-sm.bg-gradient-primary.btn-round.mb-0.me-1.mt-2.mt-md-0 { a.btn.btn-sm.bg-gradient-primary.btn-round.mb-0.me-1.mt-2.mt-md-0 {
margin-top: auto !important; margin-top: auto !important;
margin-bottom: auto !important; margin-bottom: auto !important;
} }
</style> </style>
<script> <script>
function auth() { function auth() {
<% if (!req.session.user) { %> <% if (!req.session.user) { %>
const newWindow = window.open('/discord?r=/close%3Flogin=true', 'Log in with discord', `directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no, width=500, height=800`); const newWindow = window.open('/discord?r=/close%3Flogin=true', 'Log in with discord', `directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no, width=500, height=800`);
newWindow.focus(); newWindow.focus();
setInterval(() => { setInterval(() => {
if (newWindow.closed) window.location.href = `<%= req.originalUrl%>?swal=logged` if (newWindow.closed) window.location.href = `<%= req.originalUrl%>?swal=logged`
}, 500); }, 500);
<% } else { %> <% } else { %>
window.location.href = `<%= req.originalUrl%>?swal=logged` window.location.href = `<%= req.originalUrl%>?swal=logged`
<% } %> <% } %>
} }
</script> </script>
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body class="presentation-page"> <body class="presentation-page">
<%- include('partials/preload.ejs') %> <%- include('partials/preload.ejs') %>
<!-- Navbar --> <!-- Navbar -->
<div class="container position-sticky z-index-sticky top-0"> <div class="container position-sticky z-index-sticky top-0">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<nav class="maintenance navbar navbar-expand-lg blur blur-rounded top-0 z-index-fixed shadow position-absolute my-3 py-2 start-0 end-0 mx-4"> <nav class="maintenance navbar navbar-expand-lg blur blur-rounded top-0 z-index-fixed shadow position-absolute my-3 py-2 start-0 end-0 mx-4">
<div class="container-fluid px-0" style="flex-wrap: unset;"> <div class="container-fluid px-0" style="flex-wrap: unset;">
<a class="navbar-brand font-weight-bolder ms-sm-3" href="/"> <a class="navbar-brand font-weight-bolder ms-sm-3" href="/">
<img src="<%- themeConfig.icons.favicon %>" class="h-100" <img src="<%- themeConfig.icons.favicon %>" class="h-100"
style="border-radius: 50%; width:40px;" alt="main_logo"> style="border-radius: 50%; width:40px;" alt="main_logo">
<a style="margin-top: auto !important; margin-bottom: auto !important; font-weight: 800;"><%- themeConfig.websiteName %></a> <a style="margin-top: auto !important; margin-bottom: auto !important; font-weight: 800;"><%- themeConfig.websiteName %></a>
</a> </a>
<ul class="navbar-nav navbar-nav-hover ms-lg-12 ps-lg-5 w-100" style="flex-direction: row-reverse;"> <ul class="navbar-nav navbar-nav-hover ms-lg-12 ps-lg-5 w-100" style="flex-direction: row-reverse;">
<li class="nav navbar-nav navbar-right"> <li class="nav navbar-nav navbar-right">
<%- logged %> <%- logged %>
</li> </li>
</ul> </ul>
</div> </div>
</nav> </nav>
<!-- End Navbar --> <!-- End Navbar -->
</div> </div>
</div> </div>
</div> </div>
<header class="header-2"> <header class="header-2">
<% <%
const images = ["curved-1", "curved-2", "curved-3", "curved-4", "curved-5", "curved-6", "curved-7", "curved-8", "curved-9", "curved-10", "curved-11", "curved-12", "curved-13", "curved-14", "curved-15", "curved-16", "curved-17", "curved-18"]; const images = ["curved-1", "curved-2", "curved-3", "curved-4", "curved-5", "curved-6", "curved-7", "curved-8", "curved-9", "curved-10", "curved-11", "curved-12", "curved-13", "curved-14", "curved-15", "curved-16", "curved-17", "curved-18"];
const image = images[Math.floor(Math.random() * images.length)]; const image = images[Math.floor(Math.random() * images.length)];
%> %>
<div id="background" class="page-header min-vh-75 relative" <div id="background" class="page-header min-vh-75 relative"
style="background-image: url('/img/curved-images/<%- image %>.webp');"> style="background-image: url('/img/curved-images/<%- image %>.webp');">
<span class="mask bg-gradient-primary opacity-6"></span> <span class="mask bg-gradient-primary opacity-6"></span>
<div class="container" style="margin-top: 10vh"> <div class="container" style="margin-top: 10vh">
<div class="row"> <div class="row">
<div class="col-lg-7 text-center mx-auto"> <div class="col-lg-7 text-center mx-auto">
<h1 class="text-white pt-3 mt-n5"><%- contentTitle %></h1> <h1 class="text-white pt-3 mt-n5"><%- contentTitle %></h1>
<p class="lead text-white mt-3"> <p class="lead text-white mt-3">
<%- texts.map(text => '<p class="text-white">' + text + '</p>').join('') %> <%- texts.map(text => '<p class="text-white">' + text + '</p>').join('') %>
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<div class="position-absolute w-100 z-index-1 bottom-0"> <div class="position-absolute w-100 z-index-1 bottom-0">
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" <svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 40" preserveAspectRatio="none" shape-rendering="auto"> viewBox="0 24 150 40" preserveAspectRatio="none" shape-rendering="auto">
<defs> <defs>
<path id="gentle-wave" <path id="gentle-wave"
d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z"/> d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z"/>
</defs> </defs>
<g class="moving-waves"> <g class="moving-waves">
<use class="dark-wave-1" xlink:href="#gentle-wave" x="48" y="-1" fill="rgba(255,255,255,0.40"/> <use class="dark-wave-1" xlink:href="#gentle-wave" x="48" y="-1" fill="rgba(255,255,255,0.40"/>
<use class="dark-wave-2" xlink:href="#gentle-wave" x="48" y="3" fill="rgba(255,255,255,0.35)"/> <use class="dark-wave-2" xlink:href="#gentle-wave" x="48" y="3" fill="rgba(255,255,255,0.35)"/>
<use class="dark-wave-3" xlink:href="#gentle-wave" x="48" y="5" fill="rgba(255,255,255,0.25)"/> <use class="dark-wave-3" xlink:href="#gentle-wave" x="48" y="5" fill="rgba(255,255,255,0.25)"/>
<use class="dark-wave-4" xlink:href="#gentle-wave" x="48" y="8" fill="rgba(255,255,255,0.20)"/> <use class="dark-wave-4" xlink:href="#gentle-wave" x="48" y="8" fill="rgba(255,255,255,0.20)"/>
<use class="dark-wave-5" xlink:href="#gentle-wave" x="48" y="13" fill="rgba(255,255,255,0.15)"/> <use class="dark-wave-5" xlink:href="#gentle-wave" x="48" y="13" fill="rgba(255,255,255,0.15)"/>
<use class="dark-wave-6" xlink:href="#gentle-wave" x="48" y="16" fill="rgba(255,255,255,0.95"/> <use class="dark-wave-6" xlink:href="#gentle-wave" x="48" y="16" fill="rgba(255,255,255,0.95"/>
</g> </g>
</svg> </svg>
</div> </div>
</div> </div>
</header> </header>
<% if(defaultMaintenanceConfig.infoCards){ %> <% if(defaultMaintenanceConfig.infoCards){ %>
<section class="pt-4 pb-5 info-maintenance" id="count-stats" style="padding-top: 7rem !important;"> <section class="pt-4 pb-5 info-maintenance" id="count-stats" style="padding-top: 7rem !important;">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div style="box-shadow: none !important;" <div style="box-shadow: none !important;"
class="maintenance info col-lg-9 z-index-2 border-radius-xl mt-n10 mx-auto py-4 blur shadow-blur"> class="maintenance info col-lg-9 z-index-2 border-radius-xl mt-n10 mx-auto py-4 blur shadow-blur">
<div class="row"> <div class="row">
<% let c = 1; defaultMaintenanceConfig.infoCards.forEach(card => { %> <% let c = 1; defaultMaintenanceConfig.infoCards.forEach(card => { %>
<div class="col-md-4 position-relative"> <div class="col-md-4 position-relative">
<div class="p-3 text-center"> <div class="p-3 text-center">
<% if(card.title){ %><h1 class="text-gradient text-primary"> <% if(card.title){ %><h1 class="text-gradient text-primary">
<span><%- card.title %></span></h1> <span><%- card.title %></span></h1>
<% } %> <% } %>
<% if(card.subtitle){ %><h5 class="mt-3"><%- card.subtitle %></h5> <% if(card.subtitle){ %><h5 class="mt-3"><%- card.subtitle %></h5>
<% } %> <% } %>
<% if(card.description){ %><p class="text-sm"><%- card.description %></p> <% if(card.description){ %><p class="text-sm"><%- card.description %></p>
<% } %> <% } %>
</div> </div>
<% c++; if(c != 4) { %> <% c++; if(c != 4) { %>
<hr class="vertical dark"> <hr class="vertical dark">
<% } %> <% } %>
</div> </div>
<% }) %> <% }) %>
<!-- <div class="col-md-4 position-relative"> <!-- <div class="col-md-4 position-relative">
<div class="p-3 text-center"> <div class="p-3 text-center">
<h1 class="text-gradient text-primary"> <span id="state2" countTo="15">0</span>+</h1> <h1 class="text-gradient text-primary"> <span id="state2" countTo="15">0</span>+</h1>
<h5 class="mt-3">Design Blocks</h5> <h5 class="mt-3">Design Blocks</h5>
<p class="text-sm">Mix the sections, change the colors and unleash your creativity</p> <p class="text-sm">Mix the sections, change the colors and unleash your creativity</p>
</div> </div>
<hr class="vertical dark"> <hr class="vertical dark">
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="p-3 text-center"> <div class="p-3 text-center">
<h1 class="text-gradient text-primary" id="state3" countTo="4">0</h1> <h1 class="text-gradient text-primary" id="state3" countTo="4">0</h1>
<h5 class="mt-3">Pages</h5> <h5 class="mt-3">Pages</h5>
<p class="text-sm">Save 3-4 weeks of work when you use our pre-made pages for your website</p> <p class="text-sm">Save 3-4 weeks of work when you use our pre-made pages for your website</p>
</div> </div>
</div> --> </div> -->
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<% } %> <% } %>
<!-- Core JS Files --> <!-- Core JS Files -->

View file

@ -1,202 +1,202 @@
<html> <html>
<head> <head>
<link href="/types/styles.css" rel="stylesheet"/> <link href="/types/styles.css" rel="stylesheet"/>
<script src="/types/code.js"></script> <script src="/types/code.js"></script>
<link rel="stylesheet" href="/testcdn/f47b986ff7b093031dc7.css"> <link rel="stylesheet" href="/testcdn/f47b986ff7b093031dc7.css">
<link rel="stylesheet" href="/testcdn/guild.css"> <link rel="stylesheet" href="/testcdn/guild.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet"/> <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
</head> </head>
<body class="gui emptyContent emptyEmbed"> <body class="gui emptyContent emptyEmbed">
<button class="emojipicker">Emoji picker</button> <button class="emojipicker">Emoji picker</button>
<hr> <hr>
<div class="slidecontainer"> <div class="slidecontainer">
<input type="range" min="1" max="100" value="50" class="slider" id="myRange"> <input type="range" min="1" max="100" value="50" class="slider" id="myRange">
</div> </div>
<p>Slider is set to <b><span id="val"></span></b></p> <p>Slider is set to <b><span id="val"></span></b></p>
<hr> <hr>
<select id="channelSelect"> <select id="channelSelect">
<optgroup label="Category Name"> <optgroup label="Category Name">
<option value="54321">general</option> <option value="54321">general</option>
<option value="12345">commands</option> <option value="12345">commands</option>
</optgroup> </optgroup>
</select> </select>
<hr> <hr>
<div style="max-width: 640px;"><input type="number" value="0"></div> <div style="max-width: 640px;"><input type="number" value="0"></div>
<hr> <hr>
<label class="f76c"> <label class="f76c">
<input type="checkbox" checked=""> <input type="checkbox" checked="">
<span class="_3319"></span>Checkbox <span class="_3319"></span>Checkbox
</label> </label>
<hr> <hr>
<div class="c945" style="width: 90%; margin: 5rem;"> <div class="c945" style="width: 90%; margin: 5rem;">
<h2>Message content</h2> <h2>Message content</h2>
<hr> <hr>
<div class="a437"> <div class="a437">
<div class="e91f"> <div class="e91f">
<input type="text" placeholder="Message Content"> <input type="text" placeholder="Message Content">
</div> </div>
<div class="f039" style="border-left-color: rgb(134, 194, 50);"> <div class="f039" style="border-left-color: rgb(134, 194, 50);">
<div class="_221e"></div> <div class="_221e"></div>
<div class="_8d09"> <div class="_8d09">
<div class="e91f"> <div class="e91f">
<input type="text" placeholder="Embed Author"> <input type="text" placeholder="Embed Author">
</div> </div>
</div> </div>
<div class="_4956"> <div class="_4956">
<div class="e91f"> <div class="e91f">
<input type="text" placeholder="Title" value="New User! :D"> <input type="text" placeholder="Title" value="New User! :D">
</div> </div>
</div> </div>
<div class="_9c2a"> <div class="_9c2a">
<div class="e91f"> <div class="e91f">
<input type="text" placeholder="Description" value="Embed Description"> <input type="text" placeholder="Description" value="Embed Description">
</div> </div>
</div> </div>
<div class="_3594"> <div class="_3594">
<div class="e91f"> <div class="e91f">
<input type="text" placeholder="Footer Text" value="Look ma, this is a footer!"> <input type="text" placeholder="Footer Text" value="Look ma, this is a footer!">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<br> <br>
<div><label class="f76c"><input type="checkbox" checked=""><span class="_3319"></span>Show embed</label></div> <div><label class="f76c"><input type="checkbox" checked=""><span class="_3319"></span>Show embed</label></div>
<div style="width: 1px; height: 5px;"></div> <div style="width: 1px; height: 5px;"></div>
<div><label class="f76c"><input type="checkbox"><span class="_3319"></span>Show welcoming image</label></div> <div><label class="f76c"><input type="checkbox"><span class="_3319"></span>Show welcoming image</label></div>
</div> </div>
<script> <script>
/* -- ON SLIDER CHANGE, UPDATE PREVIEW COUNTER -- */ /* -- ON SLIDER CHANGE, UPDATE PREVIEW COUNTER -- */
var slider = document.getElementById("myRange"); var slider = document.getElementById("myRange");
var output = document.getElementById("val"); var output = document.getElementById("val");
output.innerHTML = slider.value; output.innerHTML = slider.value;
slider.oninput = function () { slider.oninput = function () {
output.innerHTML = this.value; output.innerHTML = this.value;
} }
/* -- -- */ /* -- -- */
function formatState(state) { function formatState(state) {
if (!state.id) { if (!state.id) {
return state.text; return state.text;
} }
var $state = $( var $state = $(
`<span>#${state.text}</span>` `<span>#${state.text}</span>`
); );
return $state; return $state;
} }
$("#channelSelect").select2({ $("#channelSelect").select2({
templateResult: formatState templateResult: formatState
}); });
new EmojiPicker({ new EmojiPicker({
trigger: [ trigger: [
{ {
selector: '.emojipicker' selector: '.emojipicker'
} }
], ],
closeButton: true closeButton: true
}); });
</script> </script>
<hr> <hr>
<div class="c945" style="width: 90%; margin: 5rem;"> <div class="c945" style="width: 90%; margin: 5rem;">
<h2>Items</h2> <h2>Items</h2>
<h3>Manage your shop. Add, edit or remove items.</h3> <h3>Manage your shop. Add, edit or remove items.</h3>
<hr> <hr>
<div class="_2242"> <div class="_2242">
<span> <span>
<div class="_46a4">Item</div> <div class="_46a4">Item</div>
</span> </span>
<div class="_46a4 _34a1"><i class="fa fa-plus">+</i></div> <div class="_46a4 _34a1"><i class="fa fa-plus">+</i></div>
</div> </div>
</div> </div>
<div class="c945" style="width: 90%; margin: 5rem;"> <div class="c945" style="width: 90%; margin: 5rem;">
<script> <script>
function myFunction(type) { function myFunction(type) {
var x = document.getElementById(`${type}input`).value; var x = document.getElementById(`${type}input`).value;
document.getElementById(type).innerHTML = x; document.getElementById(type).innerHTML = x;
} }
function setHref(item) { function setHref(item) {
var a = document.getElementById(item); //or grab it by tagname etc var a = document.getElementById(item); //or grab it by tagname etc
var x = document.getElementById("authorurlinput").value; var x = document.getElementById("authorurlinput").value;
a.href = x a.href = x
} }
</script> </script>
<div class="row"> <div class="row">
<div class="col-12 col-sm-6"> <div class="col-12 col-sm-6">
<h2>Currency</h2> <h2>Currency</h2>
<h3>Set a custom currency symbol.</h3> <h3>Set a custom currency symbol.</h3>
<hr> <hr>
<div> <div>
<div class="row" style="display: flex;"> <div class="row" style="display: flex;">
<div class="col-sm" style="width: 30%;"> <div class="col-sm" style="width: 30%;">
<p>Basic Settings</p> <p>Basic Settings</p>
<div style="max-width: 270px;"> <div style="max-width: 270px;">
<input id="titleinput" style="margin-top: 10px;" type="text" placeholder="Title" <input id="titleinput" style="margin-top: 10px;" type="text" placeholder="Title"
onkeyup="myFunction('title')"> onkeyup="myFunction('title')">
<input id="descriptioninput" style="margin-top: 10px;" type="text" placeholder="Description" <input id="descriptioninput" style="margin-top: 10px;" type="text" placeholder="Description"
onkeyup="myFunction('description')"> onkeyup="myFunction('description')">
<input id="" style="margin-top: 10px;" type="text" placeholder="Url"> <input id="" style="margin-top: 10px;" type="text" placeholder="Url">
</div> </div>
<br> <br>
<label class="f76c"> <label class="f76c">
<input type="checkbox"> <input type="checkbox">
<span class="_3319"> <span class="_3319">
</span>Wallet enabled </span>Wallet enabled
</label> </label>
</div> </div>
<div class="col-sm" style="width: 30%;"> <div class="col-sm" style="width: 30%;">
<p>Author settings</p> <p>Author settings</p>
<div style="max-width: 270px;"> <div style="max-width: 270px;">
<input id="authorinput" style="margin-top: 10px;" type="text" placeholder="Author Name" <input id="authorinput" style="margin-top: 10px;" type="text" placeholder="Author Name"
onkeyup="myFunction('author')"> onkeyup="myFunction('author')">
<input id="authorurlinput" style="margin-top: 10px;" type="text" placeholder="Author Link" <input id="authorurlinput" style="margin-top: 10px;" type="text" placeholder="Author Link"
onkeyup="setHref('author')"> onkeyup="setHref('author')">
<input id="" style="margin-top: 10px;" type="text" placeholder="Author Icon"> <input id="" style="margin-top: 10px;" type="text" placeholder="Author Icon">
</div> </div>
<br> <br>
<label class="f76c"> <label class="f76c">
<input type="checkbox"> <input type="checkbox">
<span class="_3319"> <span class="_3319">
</span>Wallet enabled </span>Wallet enabled
</label> </label>
</div> </div>
<div class="co-sm" style="width: 40%;"> <div class="co-sm" style="width: 40%;">
<div class=""> <div class="">
<div class="bce7"> <div class="bce7">
<div class="fcd5"> <div class="fcd5">
<div class="_25cb" style="font-size: 1.3rem;"><a id="author"></a></div> <div class="_25cb" style="font-size: 1.3rem;"><a id="author"></a></div>
<div id="title" class="_25cb">Server's store</div> <div id="title" class="_25cb">Server's store</div>
<div id="description" class="_03aa">You have <b>10$</b> in your bank.</div> <div id="description" class="_03aa">You have <b>10$</b> in your bank.</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<hr> <hr>
<div class="row" style="display: flex;"> <div class="row" style="display: flex;">
<div class="col-sm" style="width: 30%;"> <div class="col-sm" style="width: 30%;">
<p>Fields</p> <p>Fields</p>
<div style="max-width: 270px;"> <div style="max-width: 270px;">
<input style="margin-top: 10px;" type="text" placeholder="Title"> <input style="margin-top: 10px;" type="text" placeholder="Title">
<input style="margin-top: 10px;" type="text" placeholder="Description"> <input style="margin-top: 10px;" type="text" placeholder="Description">
<input style="margin-top: 10px;" type="text" placeholder="Url"> <input style="margin-top: 10px;" type="text" placeholder="Url">
</div> </div>
<br> <br>
<label class="f76c"> <label class="f76c">
<input type="checkbox"> <input type="checkbox">
<span class="_3319"> <span class="_3319">
</span>Wallet enabled </span>Wallet enabled
</label> </label>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<%- include('partials/scripts.ejs') %> <%- include('partials/scripts.ejs') %>
</body> </body>

View file

@ -1,187 +1,194 @@
<% <%
let currentScheme = themeConfig.colorScheme, let currentScheme = themeConfig.colorScheme,
currentCode = "310deg, #7928CA 0%, #FF0080 100%", currentCode = "310deg, #7928CA 0%, #FF0080 100%",
colone, colone,
coltwo; coltwo;
if (currentScheme == "pink") { if (currentScheme == "pink") {
currentCode = "310deg, #7928CA 0%, #FF0080 100%"; currentCode = "310deg, #7928CA 0%, #FF0080 100%";
colone = "#FF0080"; colone = "#FF0080";
coltwo = "#7928CA"; coltwo = "#7928CA";
} }
if (currentScheme == "red") { if (currentScheme == "red") {
currentCode = "310deg, #ea0606 0%, #ff667c 100%"; currentCode = "310deg, #ea0606 0%, #ff667c 100%";
colone = "#ea0606"; colone = "#ea0606";
coltwo = "#ff667c"; coltwo = "#ff667c";
} }
if (currentScheme == "green") { if (currentScheme == "green") {
currentCode = "310deg, #17ad37 0%, #98ec2d 100%"; currentCode = "310deg, #17ad37 0%, #98ec2d 100%";
colone = "#17ad37"; colone = "#17ad37";
coltwo = "#98ec2d"; coltwo = "#98ec2d";
} }
if (currentScheme == "yellow") { if (currentScheme == "yellow") {
currentCode = "310deg, #f53939 0%, #fbcf33 100%"; currentCode = "310deg, #f53939 0%, #fbcf33 100%";
colone = "#f53939"; colone = "#f53939";
coltwo = "#fbcf33"; coltwo = "#fbcf33";
} }
if (currentScheme == "dark") { if (currentScheme == "dark") {
currentCode = "310deg, #141727 0%, #3A416F 100%"; currentCode = "310deg, #141727 0%, #3A416F 100%";
colone = "#141727"; colone = "#141727";
coltwo = "#3A416F"; coltwo = "#3A416F";
} }
if (currentScheme == "blue") { if (currentScheme == "blue") {
currentCode = "310deg, #2152ff 0%, #21d4fd 100%"; currentCode = "310deg, #2152ff 0%, #21d4fd 100%";
colone = "#2152ff"; colone = "#2152ff";
coltwo = "#21d4fd"; coltwo = "#21d4fd";
} }
if (currentScheme == "custom") { if (currentScheme == "custom") {
if (!themeConfig.themeColors || !themeConfig.themeColors.primaryColor || !themeConfig.themeColors.secondaryColor) { if (!themeConfig.themeColors || !themeConfig.themeColors.primaryColor || !themeConfig.themeColors.secondaryColor) {
currentCode = "310deg, #7928CA 0%, #FF0080 100%"; currentCode = "310deg, #7928CA 0%, #FF0080 100%";
colone = "#FF0080"; colone = "#FF0080";
coltwo = "#7928CA"; coltwo = "#7928CA";
} else { } else {
currentCode = "310deg, " + themeConfig.themeColors.primaryColor + " 0%, " + themeConfig.themeColors.secondaryColor + " 100%"; currentCode = "310deg, " + themeConfig.themeColors.primaryColor + " 0%, " + themeConfig.themeColors.secondaryColor + " 100%";
colone = themeConfig.themeColors.primaryColor; colone = themeConfig.themeColors.primaryColor;
coltwo = themeConfig.themeColors.secondaryColor; coltwo = themeConfig.themeColors.secondaryColor;
} }
} }
%> %>
<meta name="theme-color" content="<%- colone %>"> <meta name="theme-color" content="<%- colone %>">
<style> <style>
:root { :root {
--gradient: <%= currentCode%> !important; --gradient: <%=currentCode%> !important;
--colone: <%= colone%> !important; --colone: <%=colone%> !important;
--coltwo: <%= coltwo%> !important; --coltwo: <%=coltwo%> !important;
} }
input:checked + .tslider { input:checked+.tslider {
background: linear-gradient(var(--gradient)) !important; background: linear-gradient(var(--gradient)) !important;
} }
option { option {
color: var(--colone); color: var(--colone);
} }
option:hover { option:hover {
background-color: none !important; background-color: none !important;
} }
.fixed-plugin .btn.bg-gradient-primary:not(:disabled):not(.disabled):not(.active) { .fixed-plugin .btn.bg-gradient-primary:not(:disabled):not(.disabled):not(.active) {
border: 1px solid var(--colone) !important; border: 1px solid var(--colone) !important;
color: var(--colone) !important; color: var(--colone) !important;
} }
.card.card-background.card-background-mask-primary::after, .swal2-popup.swal2-toast { .card.card-background.card-background-mask-primary::after,
background-image: linear-gradient(var(--gradient)) !important; .swal2-popup.swal2-toast {
} background-image: linear-gradient(var(--gradient)) !important;
}
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
border-color: var(--colone) !important; border-color: var(--colone) !important;
background-image: linear-gradient(var(--gradient)) !important; background-image: linear-gradient(var(--gradient)) !important;
} }
.swal2-title { .swal2-title {
color: #ebdddd !important; color: #ebdddd !important;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} }
.swal2-success-fix, .swal2-success-circular-line-left, .swal2-success-circular-line-right { .swal2-success-fix,
background: none !important; .swal2-success-circular-line-left,
} .swal2-success-circular-line-right {
background: none !important;
}
.swal2-success-ring { .swal2-success-ring {
color: rgba(0, 0, 0, 0) !important; color: rgba(0, 0, 0, 0) !important;
border: rgba(0, 0, 0, 0) !important; border: rgba(0, 0, 0, 0) !important;
} }
.swal2-icon.swal2-error, .swal2-icon.swal2-success { .swal2-icon.swal2-error,
border-color: #f9f9f9 !important; .swal2-icon.swal2-success {
color: #f9f9f9 !important; border-color: #f9f9f9 !important;
} color: #f9f9f9 !important;
}
.swal2-x-mark-line-right, .swal2-x-mark-line-left, .swal2-success-line-long, .swal2-success-line-tip { .swal2-x-mark-line-right,
background-color: #f9f9f9 !important; .swal2-x-mark-line-left,
} .swal2-success-line-long,
.swal2-success-line-tip {
background-color: #f9f9f9 !important;
}
.swal2-success-fix { .swal2-success-fix {
color: white !important; color: white !important;
} }
.swal2-icon.swal2-success [class^=swal2-success-line] { .swal2-icon.swal2-success [class^=swal2-success-line] {
display: block; display: block;
position: absolute; position: absolute;
z-index: 2; z-index: 2;
height: 0.3125em; height: 0.3125em;
border-radius: 0.125em; border-radius: 0.125em;
background-color: var(#f9f9f9) !important; background-color: var(#f9f9f9) !important;
} }
.bg-gradient-primary { .bg-gradient-primary {
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
} }
.card.card-background.card-background-mask-primary:after { .card.card-background.card-background-mask-primary:after {
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
opacity: .85; opacity: .85;
} }
.navbar-vertical .navbar-nav > .nav-item .nav-link.active .icon { .navbar-vertical .navbar-nav>.nav-item .nav-link.active .icon {
background-image: linear-gradient(var(--gradient)) !important; background-image: linear-gradient(var(--gradient)) !important;
} }
.text-gradient.text-primary { .text-gradient.text-primary {
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
} }
.btn-outline-primary { .btn-outline-primary {
color: var(--colone); color: var(--colone);
border-color: var(--colone); border-color: var(--colone);
} }
.nav-tabs .nav-link.active { .nav-tabs .nav-link.active {
background-size: 100% 4px; background-size: 100% 4px;
border-bottom: 4px solid var(--colone) !important; border-bottom: 4px solid var(--colone) !important;
color: var(--colone) !important; color: var(--colone) !important;
} }
.nav-tabs .nav-link:hover { .nav-tabs .nav-link:hover {
border: 0; border: 0;
border-bottom: 0px solid; border-bottom: 0px solid;
} }
.pagination.pagination-primary .page-item.active > .page-link, .pagination.pagination-primary .page-item.active>.page-link,
.pagination.pagination-primary .page-item.active > .page-link:focus, .pagination.pagination-primary .page-item.active>.page-link:focus,
.pagination.pagination-primary .page-item.active > .page-link:hover { .pagination.pagination-primary .page-item.active>.page-link:hover {
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
border: none; border: none;
} }
.sidenav[data-color="primary"] .navbar-nav > .nav-item > .nav-link.active .icon { .sidenav[data-color="primary"] .navbar-nav>.nav-item>.nav-link.active .icon {
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
} }
.blur-section.blur-gradient-primary { .blur-section.blur-gradient-primary {
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
} }
.blur-section.blur-gradient-primary { .blur-section.blur-gradient-primary {
background-image: linear-gradient(var(--gradient)); background-image: linear-gradient(var(--gradient));
} }
.form-control:focus { .form-control:focus {
box-shadow: var(--colone) 0px 0px 0px 2px !important; box-shadow: var(--colone) 0px 0px 0px 2px !important;
} }
.input-group .form-control:focus { .input-group .form-control:focus {
border-color: var(--colone) !important; border-color: var(--colone) !important;
} }
.themecol { .themecol {
color: var(--colone) !important; color: var(--colone) !important;
} }
.input-group .form-control:focus { .input-group .form-control:focus {
border-left-color: var(--colone) !important; border-left-color: var(--colone) !important;
border-right-color: var(--colone) !important; border-right-color: var(--colone) !important;
} }
</style> </style>

View file

@ -1,118 +1,118 @@
<div class="card-body px-0 pt-0 pb-2"> <div class="card-body px-0 pt-0 pb-2">
<div class="table-responsive p-0"> <div class="table-responsive p-0">
<% <%
let feeds = []; let feeds = [];
const db = require('quick.db'); const db = require('quick.db');
if (db.get('feeds.three')) { if (db.get('feeds.three')) {
const fd = db.get('feeds.three'); const fd = db.get('feeds.three');
const fdata = { const fdata = {
color: fd.color, color: fd.color,
description: fd.description, description: fd.description,
icon: fd.icon, icon: fd.icon,
published: fd.published, published: fd.published,
diff: fd.diff, diff: fd.diff,
feedNum: 3 feedNum: 3
} }
feeds.push(fdata); feeds.push(fdata);
} }
if (db.get('feeds.two')) { if (db.get('feeds.two')) {
const fd = db.get('feeds.two'); const fd = db.get('feeds.two');
const fdata = { const fdata = {
color: fd.color, color: fd.color,
description: fd.description, description: fd.description,
icon: fd.icon, icon: fd.icon,
published: fd.published, published: fd.published,
diff: fd.diff, diff: fd.diff,
feedNum: 2 feedNum: 2
} }
feeds.push(fdata); feeds.push(fdata);
} }
if (db.get('feeds.one')) { if (db.get('feeds.one')) {
const fd = db.get('feeds.one'); const fd = db.get('feeds.one');
const fdata = { const fdata = {
color: fd.color, color: fd.color,
description: fd.description, description: fd.description,
published: fd.published, published: fd.published,
icon: fd.icon, icon: fd.icon,
diff: fd.diff, diff: fd.diff,
feedNum: 1 feedNum: 1
} }
feeds.push(fdata); feeds.push(fdata);
} }
feeds.forEach(feed => { feeds.forEach(feed => {
var delta = Math.abs(Date.now() - feed.published) / 1000; var delta = Math.abs(Date.now() - feed.published) / 1000;
// calculate (and subtract) whole days // calculate (and subtract) whole days
var days = Math.floor(delta / 86400); var days = Math.floor(delta / 86400);
delta -= days * 86400; delta -= days * 86400;
// calculate (and subtract) whole hours // calculate (and subtract) whole hours
var hours = Math.floor(delta / 3600) % 24; var hours = Math.floor(delta / 3600) % 24;
delta -= hours * 3600; delta -= hours * 3600;
// calculate (and subtract) whole minutes // calculate (and subtract) whole minutes
var minutes = Math.floor(delta / 60) % 60; var minutes = Math.floor(delta / 60) % 60;
delta -= minutes * 60; delta -= minutes * 60;
// what's left is seconds // what's left is seconds
var seconds = delta % 60; // in theory the modulus is not required var seconds = delta % 60; // in theory the modulus is not required
let dateString = `loading`; let dateString = `loading`;
//stupid variable names but yeah :sweat_smile: //stupid variable names but yeah :sweat_smile:
if (seconds < 2) secsingle = "second"; if (seconds < 2) secsingle = "second";
else secsingle = "seconds"; else secsingle = "seconds";
if (minutes < 2) minsingle = "minute"; if (minutes < 2) minsingle = "minute";
else minsingle = "minutes"; else minsingle = "minutes";
if (hours < 2) hrsingle = "hour"; if (hours < 2) hrsingle = "hour";
else hrsingle = "hours"; else hrsingle = "hours";
if (days < 2) daysingle = "day"; if (days < 2) daysingle = "day";
else daysingle = "days"; else daysingle = "days";
if (minutes < 1) dateString = `${Math.round(seconds)} ${secsingle} ago`; if (minutes < 1) dateString = `${Math.round(seconds)} ${secsingle} ago`;
else if (hours < 1) dateString = `${minutes} ${minsingle} ago`; else if (hours < 1) dateString = `${minutes} ${minsingle} ago`;
else if (days < 1) dateString = `${hours} ${hrsingle} ago`; else if (days < 1) dateString = `${hours} ${hrsingle} ago`;
else dateString = `${days} ${daysingle} ago`; else dateString = `${days} ${daysingle} ago`;
let faString = "fas fa-"; let faString = "fas fa-";
if (feed.diff) faString = "fab fa-"; if (feed.diff) faString = "fab fa-";
%> %>
<div> <div>
<div class="alert alert-<%- feed.color %> text-white font-weight-bold" role="alert" <div class="alert alert-<%- feed.color %> text-white font-weight-bold" role="alert"
style="display: flex; margin-top: 20px;"> style="display: flex; margin-top: 20px;">
<div class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center gray-icon-bg" <div class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center gray-icon-bg"
style="margin: auto 0px; width: 30px !important; height: 30px !important;"> style="margin: auto 0px; width: 30px !important; height: 30px !important;">
<i class="<%- faString %><%- feed.icon %> invert-img" style="font-size: 80%; color: black;"></i> <i class="<%- faString %><%- feed.icon %> invert-img" style="font-size: 80%; color: black;"></i>
</div> </div>
<span style="margin: auto 0px"><%- feed.description %></span> <span style="margin: auto 0px"><%- feed.description %></span>
<span class="tagnamecolor-date" <span class="tagnamecolor-date"
style="color:rgb(155, 148, 148); margin: auto 0px; font-size: 75%; flex: 1; text-align: right; white-space: nowrap;"> style="color:rgb(155, 148, 148); margin: auto 0px; font-size: 75%; flex: 1; text-align: right; white-space: nowrap;">
<%- dateString %> <%- dateString %>
</span> </span>
<% if(admin) { %> <% if(admin) { %>
<div class="ms-auto text-end"> <div class="ms-auto text-end">
<a id="deleteFeed<%- feed.feedNum %>" class="btn btn-link text-text-gradient px-3 mb-0" <a id="deleteFeed<%- feed.feedNum %>" class="btn btn-link text-text-gradient px-3 mb-0"
style="color:white;" href="javascript:"><i class="far fa-trash-alt me-2"></i>Delete</a> style="color:white;" href="javascript:"><i class="far fa-trash-alt me-2"></i>Delete</a>
</div> </div>
<% } %> <% } %>
</div> </div>
</div> </div>
<% <%
}) })
if(!feeds[0]) { if(!feeds[0]) {
%> %>
<div> <div>
<span class="tagnamecolor-date" style="color:rgb(155, 148, 148); white-space: nowrap;"> <span class="tagnamecolor-date" style="color:rgb(155, 148, 148); white-space: nowrap;">
There are no feeds. There are no feeds.
</span> </span>
</div> </div>
<% <%
} }
%> %>
</div> </div>
</div> </div>

View file

@ -1,16 +1,20 @@
<footer class="footer"> <footer class="footer">
<div class="container-fluid"> <div class="container-fluid">
<div class="row align-items-center justify-content-lg-between"> <div class="row align-items-center justify-content-lg-between">
<div class="col-lg-6 mb-lg-0 mb-4"> <div class="col-lg-6 mb-lg-0 mb-4">
<div class="copyright text-center text-sm text-muted text-lg-start"> <div class="copyright text-center text-sm text-muted text-lg-start">
© <%= new Date().getFullYear() %> © <%= new Date().getFullYear() %>
<% if(themeConfig?.footer?.replaceDefault === true) { %> <% if(themeConfig?.footer?.replaceDefault === true) { %>
<a href="/credits" class="font-weight-bold" target="_blank">Assistants</a><% if(themeConfig?.footer?.text?.length) { %> | <%= themeConfig?.footer?.text %> <% } %> <a href="/credits" class="font-weight-bold"
<% } else { %> target="_blank">Assistants</a><% if(themeConfig?.footer?.text?.length) { %> |
Made with <i class="fa fa-heart"></i> by <a href="/credits" class="font-weight-bold" target="_blank">PlainDevelopment</a> and <a href="/credits" class="font-weight-bold" target="_blank">iMidnight</a> <%= themeConfig?.footer?.text %> <% } %>
<% } %> <% } else { %>
</div> Made with <i class="fa fa-heart"></i> by <a href="/credits" class="font-weight-bold"
</div> target="_blank">PlainDevelopment</a> and <a href="/credits" class="font-weight-bold"
</div> target="_blank">Jonny_Bro</a>
</div> <% } %>
</div>
</div>
</div>
</div>
</footer> </footer>

View file

@ -7,220 +7,220 @@ let gradone;
let gradtwo; let gradtwo;
function hexToRgba(hex, alpha) { function hexToRgba(hex, alpha) {
var r = parseInt(hex.substring(1,3), 16); var r = parseInt(hex.substring(1,3), 16);
var g = parseInt(hex.substring(3,5), 16); var g = parseInt(hex.substring(3,5), 16);
var b = parseInt(hex.substring(5,7), 16); var b = parseInt(hex.substring(5,7), 16);
return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')'; return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')';
} }
if (currentScheme == "blue") { if (currentScheme == "blue") {
colone = "#21d4fd"; colone = "#21d4fd";
coltwo = "#2152ff"; coltwo = "#2152ff";
gradone = "rgba(33,212,253,0.1)"; gradone = "rgba(33,212,253,0.1)";
gradtwo = "rgba(33,82,255,0.1)"; gradtwo = "rgba(33,82,255,0.1)";
} }
if (currentScheme == "pink") { if (currentScheme == "pink") {
colone = "#FF0080"; colone = "#FF0080";
coltwo = "#7928CA"; coltwo = "#7928CA";
gradone = "rgba(255,0,128,0.1)"; gradone = "rgba(255,0,128,0.1)";
gradtwo = "rgba(121,40,202,0.1)"; gradtwo = "rgba(121,40,202,0.1)";
} }
if (currentScheme == "red") { if (currentScheme == "red") {
colone = "#ea0606"; colone = "#ea0606";
coltwo = "#ff667c"; coltwo = "#ff667c";
gradone = "rgba(255,102,124,0.1)"; gradone = "rgba(255,102,124,0.1)";
gradtwo = "rgba(234,6,6,0.1)"; gradtwo = "rgba(234,6,6,0.1)";
} }
if (currentScheme == "green") { if (currentScheme == "green") {
colone = "#17ad37"; colone = "#17ad37";
coltwo = "#98ec2d"; coltwo = "#98ec2d";
gradone = "rgba(23,173,55,0.1)"; gradone = "rgba(23,173,55,0.1)";
gradtwo = "rgba(152,236,45,0.1)"; gradtwo = "rgba(152,236,45,0.1)";
} }
if (currentScheme == "yellow") { if (currentScheme == "yellow") {
colone = "#f53939"; colone = "#f53939";
coltwo = "#fbcf33"; coltwo = "#fbcf33";
gradone = "rgba(245,57,57,0.1)"; gradone = "rgba(245,57,57,0.1)";
gradtwo = "rgba(251,207,51,0.1)"; gradtwo = "rgba(251,207,51,0.1)";
} }
if (currentScheme == "dark") { if (currentScheme == "dark") {
colone = "#141727"; colone = "#141727";
coltwo = "#3A416F"; coltwo = "#3A416F";
gradone = "rgba(20,23,39,0.1)"; gradone = "rgba(20,23,39,0.1)";
gradtwo = "rgba(58,65,111,0.1)"; gradtwo = "rgba(58,65,111,0.1)";
} }
if (currentScheme == "custom") { if (currentScheme == "custom") {
if (!themeConfig.themeColors || !themeConfig.themeColors.primaryColor || !themeConfig.themeColors.secondaryColor) { if (!themeConfig.themeColors || !themeConfig.themeColors.primaryColor || !themeConfig.themeColors.secondaryColor) {
currentCode = "310deg, #7928CA 0%, #FF0080 100%"; currentCode = "310deg, #7928CA 0%, #FF0080 100%";
colone = "#FF0080"; colone = "#FF0080";
coltwo = "#7928CA"; coltwo = "#7928CA";
gradone = "rgba(255,0,128,0.1)"; gradone = "rgba(255,0,128,0.1)";
gradtwo = "rgba(121,40,202,0.1)"; gradtwo = "rgba(121,40,202,0.1)";
} else { } else {
currentCode = "310deg, " + themeConfig.themeColors.primaryColor + " 0%, " + themeConfig.themeColors.secondaryColor + " 100%"; currentCode = "310deg, " + themeConfig.themeColors.primaryColor + " 0%, " + themeConfig.themeColors.secondaryColor + " 100%";
colone = themeConfig.themeColors.primaryColor; colone = themeConfig.themeColors.primaryColor;
coltwo = themeConfig.themeColors.secondaryColor; coltwo = themeConfig.themeColors.secondaryColor;
gradone = hexToRgba(themeConfig.themeColors.primaryColor, 0.1); gradone = hexToRgba(themeConfig.themeColors.primaryColor, 0.1);
gradtwo = hexToRgba(themeConfig.themeColors.secondaryColor, 0.1); gradtwo = hexToRgba(themeConfig.themeColors.secondaryColor, 0.1);
} }
} }
%> %>
<script> <script>
<% <%
let graphType = "chart-bars"; // line-graph let graphType = "chart-bars"; // line-graph
if (!themeConfig.index.graph.lineGraph) graphType = "chart-line"; if (!themeConfig.index.graph.lineGraph) graphType = "chart-line";
%> %>
let ctx = document.getElementById("<%- graphType %>").getContext("2d"); // line graph let ctx = document.getElementById("<%- graphType %>").getContext("2d"); // line graph
<% if(graphType === "chart-bars") { %> <% if(graphType === "chart-bars") { %>
new Chart(ctx, { new Chart(ctx, {
type: "bar", type: "bar",
data: { data: {
labels: <%- JSON.stringify(customThemeOptions.graph.labels) %>, labels: <%- JSON.stringify(customThemeOptions.graph.labels) %>,
datasets: [{ datasets: [{
label: "<%= themeConfig.index.graph.tag %>", label: "<%= themeConfig.index.graph.tag %>",
tension: 0.4, tension: 0.4,
borderWidth: 0, borderWidth: 0,
borderRadius: 4, borderRadius: 4,
borderSkipped: false, borderSkipped: false,
backgroundColor: "#fff", backgroundColor: "#fff",
data: <%- JSON.stringify(data.values) %>, data: <%- JSON.stringify(data.values) %>,
maxBarThickness: 6 maxBarThickness: 6
},], },],
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
plugins: { plugins: {
legend: { legend: {
display: false, display: false,
} }
}, },
interaction: { interaction: {
intersect: false, intersect: false,
mode: 'index', mode: 'index',
}, },
scales: { scales: {
y: { y: {
grid: { grid: {
drawBorder: false, drawBorder: false,
display: false, display: false,
drawOnChartArea: false, drawOnChartArea: false,
drawTicks: false, drawTicks: false,
}, },
ticks: { ticks: {
suggestedMin: 0, suggestedMin: 0,
suggestedMax: 500, suggestedMax: 500,
beginAtZero: true, beginAtZero: true,
padding: 15, padding: 15,
font: { font: {
size: 14, size: 14,
family: "Open Sans", family: "Open Sans",
style: 'normal', style: 'normal',
lineHeight: 2 lineHeight: 2
}, },
color: "#fff" color: "#fff"
}, },
}, },
x: { x: {
grid: { grid: {
drawBorder: false, drawBorder: false,
display: false, display: false,
drawOnChartArea: false, drawOnChartArea: false,
drawTicks: false drawTicks: false
}, },
ticks: { ticks: {
display: false display: false
}, },
}, },
}, },
}, },
}); });
<% } else { %> <% } else { %>
var gradientStroke1 = ctx.createLinearGradient(0, 230, 0, 50); var gradientStroke1 = ctx.createLinearGradient(0, 230, 0, 50);
gradientStroke1.addColorStop(1, '<%= colone %>'); gradientStroke1.addColorStop(1, '<%= colone %>');
gradientStroke1.addColorStop(0.1, '<%= gradone %>'); gradientStroke1.addColorStop(0.1, '<%= gradone %>');
gradientStroke1.addColorStop(0, '<%= gradtwo %>'); //purple colors gradientStroke1.addColorStop(0, '<%= gradtwo %>'); //purple colors
new Chart(ctx, { new Chart(ctx, {
type: "line", type: "line",
data: { data: {
labels: <%- JSON.stringify(customThemeOptions.graph.labels) %>, labels: <%- JSON.stringify(customThemeOptions.graph.labels) %>,
datasets: [{ datasets: [{
label: "<%= themeConfig.index.graph.tag %>", label: "<%= themeConfig.index.graph.tag %>",
tension: 0.4, tension: 0.4,
borderWidth: 0, borderWidth: 0,
pointRadius: 0, pointRadius: 0,
borderColor: "<%- colone %>", borderColor: "<%- colone %>",
borderWidth: 3, borderWidth: 3,
backgroundColor: gradientStroke1, backgroundColor: gradientStroke1,
fill: true, fill: true,
data: <%- JSON.stringify(data.values) %>, data: <%- JSON.stringify(data.values) %>,
maxBarThickness: 6 maxBarThickness: 6
}, },
], ],
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
plugins: { plugins: {
legend: { legend: {
display: false, display: false,
} }
}, },
interaction: { interaction: {
intersect: false, intersect: false,
mode: 'index', mode: 'index',
}, },
scales: { scales: {
y: { y: {
suggestedMin: 0, suggestedMin: 0,
suggestedMax: <%- themeConfig.index.graph.max %>, suggestedMax: <%- themeConfig.index.graph.max %>,
grid: { grid: {
drawBorder: false, drawBorder: false,
display: true, display: true,
drawOnChartArea: true, drawOnChartArea: true,
drawTicks: false, drawTicks: false,
borderDash: [5, 5] borderDash: [5, 5]
}, },
ticks: { ticks: {
display: true, display: true,
padding: 10, padding: 10,
color: '#b2b9bf', color: '#b2b9bf',
font: { font: {
size: 11, size: 11,
family: "Open Sans", family: "Open Sans",
style: 'normal', style: 'normal',
lineHeight: 2 lineHeight: 2
}, },
} }
}, },
x: { x: {
grid: { grid: {
drawBorder: false, drawBorder: false,
display: false, display: false,
drawOnChartArea: false, drawOnChartArea: false,
drawTicks: false, drawTicks: false,
borderDash: [5, 5] borderDash: [5, 5]
}, },
ticks: { ticks: {
display: true, display: true,
color: '#b2b9bf', color: '#b2b9bf',
padding: 20, padding: 20,
font: { font: {
size: 11, size: 11,
family: "Open Sans", family: "Open Sans",
style: 'normal', style: 'normal',
lineHeight: 2 lineHeight: 2
}, },
} }
}, },
}, },
}, },
}); });
<% } %> <% } %>
</script> </script>

View file

@ -1,22 +1,22 @@
<div id="bigIconsList" style="display: none;"> <div id="bigIconsList" style="display: none;">
<% icons.forEach(async(icon) => { %> <% icons.forEach(async(icon) => { %>
<div style="text-align:center;width:15%;float: left;padding-right:10px;"> <div style="text-align:center;width:15%;float: left;padding-right:10px;">
<div class="icon-shape icon-sm shadow border-radius-md bg-white gray-icon-bg" style="margin: 0 auto"> <div class="icon-shape icon-sm shadow border-radius-md bg-white gray-icon-bg" style="margin: 0 auto">
<i class="fas fa-<%- icon %> feeds-icon"></i> <i class="fas fa-<%- icon %> feeds-icon"></i>
</div> </div>
<span class="tagnamecolor feeds-desc"> <span class="tagnamecolor feeds-desc">
<%- icon %> <%- icon %>
</span> </span>
</div> </div>
<% }); <% });
otherIcons.forEach(async(icon) => { %> otherIcons.forEach(async(icon) => { %>
<div style="text-align:center;width:15%;float: left;padding-right:10px;"> <div style="text-align:center;width:15%;float: left;padding-right:10px;">
<div class="icon-shape icon-sm shadow border-radius-md bg-white gray-icon-bg" style="margin: 0 auto"> <div class="icon-shape icon-sm shadow border-radius-md bg-white gray-icon-bg" style="margin: 0 auto">
<i class="fab fa-<%- icon %> feeds-icon"></i> <i class="fab fa-<%- icon %> feeds-icon"></i>
</div> </div>
<span class="tagnamecolor feeds-desc"> <span class="tagnamecolor feeds-desc">
<%- icon %> <%- icon %>
</span> </span>
</div> </div>
<% }); %> <% }); %>
</div> </div>

View file

@ -1,25 +1,45 @@
<meta charset="utf-8"/> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Meta Information --> <!-- Meta Information -->
<% if(themeConfig?.meta?.author){ %><meta name="author" content="<%- themeConfig.meta.author %>"><% } %> <% if(themeConfig?.meta?.author){ %>
<% if(themeConfig?.meta?.owner){ %><meta name="owner" content="<%- themeConfig.meta.owner %>"><% } %> <meta name="author" content="<%- themeConfig.meta.author %>"><% } %>
<% if(themeConfig?.meta?.ogLocale){ %><meta property="og:locale" content="<%- themeConfig.meta.ogLocale %>"><% } %> <% if(themeConfig?.meta?.owner){ %>
<% if(themeConfig?.meta?.ogTitle){ %><meta property="og:title" content="<%- themeConfig.meta.ogTitle %>"><% } %> <meta name="owner" content="<%- themeConfig.meta.owner %>"><% } %>
<% if(themeConfig?.meta?.twitterTitle){ %><meta property="twitter:title" content="<%- themeConfig.meta.twitterTitle %>"><% } %> <% if(themeConfig?.meta?.ogLocale){ %>
<% if(themeConfig?.meta?.description){ %><meta name="description" content="<%- themeConfig.meta.description %>"><% } %> <meta property="og:locale" content="<%- themeConfig.meta.ogLocale %>"><% } %>
<% if(themeConfig?.meta?.ogDescription){ %><meta property="og:description" content="<%- themeConfig.meta.ogDescription %>"><% } %> <% if(themeConfig?.meta?.ogTitle){ %>
<% if(themeConfig?.meta?.twitterDescription){ %><meta property="twitter:description" content="<%- themeConfig.meta.twitterDescription %>"><% } %> <meta property="og:title" content="<%- themeConfig.meta.ogTitle %>"><% } %>
<% if(themeConfig?.meta?.twitterDomain){ %><meta property="twitter:domain" content="<%- themeConfig.meta.twitterDomain %>"><% } %> <% if(themeConfig?.meta?.twitterTitle){ %>
<% if(themeConfig?.meta?.twitterUrl){ %><meta property="twitter:url" content="<%- themeConfig.meta.twitterUrl %>"><% } %> <meta property="twitter:title" content="<%- themeConfig.meta.twitterTitle %>"><% } %>
<% if(themeConfig?.meta?.twitterCard){ %><meta property="twitter:card" content="<%- themeConfig.meta.twitterCard %>"><% } %> <% if(themeConfig?.meta?.description){ %>
<% if(themeConfig?.meta?.twitterSite){ %><meta property="twitter:site" content="<%- themeConfig.meta.twitterSite %>"><% } %> <meta name="description" content="<%- themeConfig.meta.description %>"><% } %>
<% if(themeConfig?.meta?.twitterSiteId){ %><meta property="twitter:site:id" content="<%- themeConfig.meta.twitterSiteId %>"><% } %> <% if(themeConfig?.meta?.ogDescription){ %>
<% if(themeConfig?.meta?.twitterCreator){ %><meta property="twitter:creator" content="<%- themeConfig.meta.twitterCreator %>"><% } %> <meta property="og:description" content="<%- themeConfig.meta.ogDescription %>"><% } %>
<% if(themeConfig?.meta?.twitterCreatorId){ %><meta property="twitter:creator:id" content="<%- themeConfig.meta.twitterCreatorId %>"><% } %> <% if(themeConfig?.meta?.twitterDescription){ %>
<% if(themeConfig?.meta?.twitterImage){ %><meta property="twitter:image" content="<%- themeConfig.meta.twitterImage %>"><% } %> <meta property="twitter:description" content="<%- themeConfig.meta.twitterDescription %>"><% } %>
<% if(themeConfig?.meta?.ogImage){ %><meta property="og:image" itemprop="image" content="<%- themeConfig.meta.ogImage %>"><% } %> <% if(themeConfig?.meta?.twitterDomain){ %>
<% if(themeConfig?.meta?.ogType){ %><meta property="og:type" content="<%- themeConfig.meta.ogType %>"><% } %> <meta property="twitter:domain" content="<%- themeConfig.meta.twitterDomain %>"><% } %>
<% if(themeConfig?.meta?.ogUrl){ %><meta property="og:url" content="<%- themeConfig.meta.ogUrl %>"><% } %> <% if(themeConfig?.meta?.twitterUrl){ %>
<% if(themeConfig?.meta?.ogSiteName){ %><meta property="og:site_name" content="<%- themeConfig.meta.ogSiteName %>"><% } %> <meta property="twitter:url" content="<%- themeConfig.meta.twitterUrl %>"><% } %>
<% if(themeConfig?.meta?.twitterCard){ %>
<meta property="twitter:card" content="<%- themeConfig.meta.twitterCard %>"><% } %>
<% if(themeConfig?.meta?.twitterSite){ %>
<meta property="twitter:site" content="<%- themeConfig.meta.twitterSite %>"><% } %>
<% if(themeConfig?.meta?.twitterSiteId){ %>
<meta property="twitter:site:id" content="<%- themeConfig.meta.twitterSiteId %>"><% } %>
<% if(themeConfig?.meta?.twitterCreator){ %>
<meta property="twitter:creator" content="<%- themeConfig.meta.twitterCreator %>"><% } %>
<% if(themeConfig?.meta?.twitterCreatorId){ %>
<meta property="twitter:creator:id" content="<%- themeConfig.meta.twitterCreatorId %>"><% } %>
<% if(themeConfig?.meta?.twitterImage){ %>
<meta property="twitter:image" content="<%- themeConfig.meta.twitterImage %>"><% } %>
<% if(themeConfig?.meta?.ogImage){ %>
<meta property="og:image" itemprop="image" content="<%- themeConfig.meta.ogImage %>"><% } %>
<% if(themeConfig?.meta?.ogType){ %>
<meta property="og:type" content="<%- themeConfig.meta.ogType %>"><% } %>
<% if(themeConfig?.meta?.ogUrl){ %>
<meta property="og:url" content="<%- themeConfig.meta.ogUrl %>"><% } %>
<% if(themeConfig?.meta?.ogSiteName){ %>
<meta property="og:site_name" content="<%- themeConfig.meta.ogSiteName %>"><% } %>
<!-- End of Meta Information --> <!-- End of Meta Information -->

View file

@ -1,64 +1,64 @@
<% <%
let currentPage = "Dashboard"; let currentPage = "Dashboard";
if (now) { if (now) {
const pages = req?.locales?.partials?.navbar?.pages; const pages = req?.locales?.partials?.navbar?.pages;
if (now === 'manage') currentPage = pages?.manage || "Manage Guilds"; if (now === 'manage') currentPage = pages?.manage || "Manage Guilds";
if (now === 'settings') currentPage = pages?.settings || "Manage Guilds"; if (now === 'settings') currentPage = pages?.settings || "Manage Guilds";
if (now === 'commands') currentPage = pages?.commands || "Commands"; if (now === 'commands') currentPage = pages?.commands || "Commands";
if (now === 'pp') currentPage = pages?.pp || "Privacy Policy"; if (now === 'pp') currentPage = pages?.pp || "Privacy Policy";
if (now === 'admin') currentPage = pages?.admin || "Admin Panel"; if (now === 'admin') currentPage = pages?.admin || "Admin Panel";
if (now === 'error') currentPage = pages?.error || "Error"; if (now === 'error') currentPage = pages?.error || "Error";
if (now === 'credits') currentPage = pages?.credits || "Credits"; if (now === 'credits') currentPage = pages?.credits || "Credits";
if (now === 'debug') currentPage = pages?.debug || "Debug"; if (now === 'debug') currentPage = pages?.debug || "Debug";
if (now === 'leaderboard') currentPage = pages?.leaderboard || "Leaderboard"; if (now === 'leaderboard') currentPage = pages?.leaderboard || "Leaderboard";
if (now === 'profile') currentPage = pages?.profile || "Profile"; if (now === 'profile') currentPage = pages?.profile || "Profile";
if (now === 'maintenance') currentPage = pages?.maintenance || "Under Maintenance"; if (now === 'maintenance') currentPage = pages?.maintenance || "Under Maintenance";
if (now === 'shards') currentPage = pages?.shards || "Shards"; if (now === 'shards') currentPage = pages?.shards || "Shards";
} }
%> %>
<!-- Navbar --> <!-- Navbar -->
<nav style="padding-bottom: 0;" class="navbar navbar-main navbar-expand-lg px-0 mx-4 shadow-none border-radius-xl" <nav style="padding-bottom: 0;" class="navbar navbar-main navbar-expand-lg px-0 mx-4 shadow-none border-radius-xl"
id="navbarBlur" navbar-scroll="false"> id="navbarBlur" navbar-scroll="false">
<div class="container-fluid py-1 px-3"> <div class="container-fluid py-1 px-3">
<nav aria-label="breadcrumb"> <nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent mb-0 pb-0 pt-1 px-0 me-sm-6 me-5"> <ol class="breadcrumb bg-transparent mb-0 pb-0 pt-1 px-0 me-sm-6 me-5">
<li class="breadcrumb-item text-sm"><a class="opacity-9 text-dark" href="/"><%- req?.locales?.partials?.navbar?.home || "Home" %></a></li> <li class="breadcrumb-item text-sm"><a class="opacity-9 text-dark" href="/"><%- req?.locales?.partials?.navbar?.home || "Home" %></a></li>
<li class="breadcrumb-item text-sm text-dark active" aria-current="page"><%- currentPage %></li> <li class="breadcrumb-item text-sm text-dark active" aria-current="page"><%- currentPage %></li>
</ol> </ol>
<h6 class="font-weight-bolder mb-0"><%- currentPage %></h6> <h6 class="font-weight-bolder mb-0"><%- currentPage %></h6>
</nav> </nav>
<div class="collapse navbar-collapse mt-sm-0 mt-2 me-md-0 me-sm-4" id="navbar"> <div class="collapse navbar-collapse mt-sm-0 mt-2 me-md-0 me-sm-4" id="navbar">
<div class="ms-md-auto pe-md-3 d-flex align-items-center"> <div class="ms-md-auto pe-md-3 d-flex align-items-center">
</div> </div>
<ul class="navbar-nav justify-content-end"> <ul class="navbar-nav justify-content-end">
<li class="nav-item d-xl-none ps-3 d-flex align-items-center"> <li class="nav-item d-xl-none ps-3 d-flex align-items-center">
<a onclick="toggleSidenav()" style="cursor: pointer;" class="nav-link text-body p-0" <a onclick="toggleSidenav()" style="cursor: pointer;" class="nav-link text-body p-0"
id="iconNavbarSidenav"> id="iconNavbarSidenav">
<div class="sidenav-toggler-inner"> <div class="sidenav-toggler-inner">
<i class="sidenav-toggler-line"></i> <i class="sidenav-toggler-line"></i>
<i class="sidenav-toggler-line"></i> <i class="sidenav-toggler-line"></i>
<i class="sidenav-toggler-line"></i> <i class="sidenav-toggler-line"></i>
</div> </div>
</a> </a>
</li> </li>
<!--<% if(req.session.user) { %> <!--<% if(req.session.user) { %>
<li class="nav-item dropdown pe-2 d-flex align-items-center"> <li class="nav-item dropdown pe-2 d-flex align-items-center">
<a href="javascript:;" class="avatar rounded-circle" style="margin-top: 5px;"> <a href="javascript:;" class="avatar rounded-circle" style="margin-top: 5px;">
<img alt="Image placeholder" <img alt="Image placeholder"
src="<%= req.session.user.avatarURL || "https://w5fc.org/wp-content/uploads/2021/05/s9biyhs4lix61.jpg" %>"> src="<%= req.session.user.avatarURL || "https://w5fc.org/wp-content/uploads/2021/05/s9biyhs4lix61.jpg" %>">
</a> </a>
</li> </li>
<% } else { %> <% } else { %>
<li class="nav-item dropdown pe-2 d-flex align-items-center"> <li class="nav-item dropdown pe-2 d-flex align-items-center">
<a onclick="const newWindow = window.open('/discord?r=/close%3Flogin=true', 'Log in with discord', `scrollbars=no, resizable=no, status=no, location=no, toolbar=no, menubar=no, width=500, height=800`);" class="nav-link text-body p-0"> <a onclick="const newWindow = window.open('/discord?r=/close%3Flogin=true', 'Log in with discord', `scrollbars=no, resizable=no, status=no, location=no, toolbar=no, menubar=no, width=500, height=800`);" class="nav-link text-body p-0">
<i class="fa fa-user me-sm-1" aria-hidden="true"></i> <i class="fa fa-user me-sm-1" aria-hidden="true"></i>
<span class="d-sm-inline d-none">Sign In</span> <span class="d-sm-inline d-none">Sign In</span>
</a> </a>
</li> </li>
<% } %>--> <% } %>-->
</ul> </ul>
</div> </div>
</div> </div>
</nav> </nav>
<!-- End Navbar --> <!-- End Navbar -->

View file

@ -1,29 +1,29 @@
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<div class="modal fade" id="modal-default" tabindex="-1" role="dialog" aria-labelledby="modal-default" <div class="modal fade" id="modal-default" tabindex="-1" role="dialog" aria-labelledby="modal-default"
aria-hidden="true"> aria-hidden="true">
<div class="modal-dialog modal- modal-dialog-centered modal-" role="document"> <div class="modal-dialog modal- modal-dialog-centered modal-" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h6 class="modal-title" id="modal-title-default"><%- title %></h6> <h6 class="modal-title" id="modal-title-default"><%- title %></h6>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
onclick="resetURL()"> onclick="resetURL()">
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<h5><%- subtitle %></h5> <h5><%- subtitle %></h5>
<% errors.forEach(e=>{ %> <% errors.forEach(e=>{ %>
<%= e.split('%is%')[0] %>: <%= e.split('%is%')[1] %> <!--(id: <%= e.split('%is%')[2] %>)--> <%= e.split('%is%')[0] %>: <%= e.split('%is%')[1] %> <!--(id: <%= e.split('%is%')[2] %>)-->
<br> <br>
<% }) %> <% }) %>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn bg-gradient-primary" data-bs-dismiss="modal" <button type="button" class="btn bg-gradient-primary" data-bs-dismiss="modal"
onclick="resetURL()">Close onclick="resetURL()">Close
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,67 +1,67 @@
<style> <style>
@media all and (min-width: 0px) and (max-width: 600px) { @media all and (min-width: 0px) and (max-width: 600px) {
.responsive { .responsive {
width: calc(100vw - 30px) width: calc(100vw - 30px)
} }
} }
@media all and (min-width: 0px) and (max-width: 590px) { @media all and (min-width: 0px) and (max-width: 590px) {
.responsive { .responsive {
margin-top: calc(100vh / 4) !important; margin-top: calc(100vh / 4) !important;
} }
} }
.preloader { .preloader {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
width: 100%; width: 100%;
height: 100vh; height: 100vh;
z-index: 99999999; z-index: 99999999;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: none; background-image: none;
background-color: #FFF; background-color: #FFF;
background-position: center; background-position: center;
} }
#scroll { #scroll {
height: 100% !important; height: 100% !important;
/* overflow: hidden; */ /* overflow: hidden; */
} }
</style> </style>
<div class="preloader"> <div class="preloader">
<div class="progress-wrapper"> <div class="progress-wrapper">
<div id="progress-bar" class="progress"> <div id="progress-bar" class="progress">
<div id="progress" class="progress-bar bg-gradient-primary" role="progressbar" aria-valuenow="60" <div id="progress" class="progress-bar bg-gradient-primary" role="progressbar" aria-valuenow="60"
aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div> aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
</div> </div>
</div> </div>
<% if(themeConfig.preloader){ %> <% if(themeConfig.preloader){ %>
<% if(themeConfig.preloader.image) { %> <% if(themeConfig.preloader.image) { %>
<% if(!themeConfig.preloader.spinner) { %> <% if(!themeConfig.preloader.spinner) { %>
<div class="loader"> <div class="loader">
<img class="responsive preloader-image" src="<%- themeConfig.preloader.image %>" alt="" <img class="responsive preloader-image" src="<%- themeConfig.preloader.image %>" alt=""
style="border-radius: 5%; display: block; margin-left: auto; margin-right: auto; margin-top: calc(100vh / 5.8);"> style="border-radius: 5%; display: block; margin-left: auto; margin-right: auto; margin-top: calc(100vh / 5.8);">
</div> </div>
<% } %> <% } %>
<% } %> <% } %>
<% if(themeConfig.preloader.text){ %> <% if(themeConfig.preloader.text){ %>
<br> <br>
<div style="text-align: center;<% if(themeConfig.preloader.spinner) { %>margin-top: calc(100vh / 2.7);<% } %>"> <div style="text-align: center;<% if(themeConfig.preloader.spinner) { %>margin-top: calc(100vh / 2.7);<% } %>">
<h1 class="font-weight-bolder text-primary text-gradient"><%- req?.locales?.partials?.preloader?.text %></h1> <h1 class="font-weight-bolder text-primary text-gradient"><%- req?.locales?.partials?.preloader?.text %></h1>
<% if(themeConfig.preloader.spinner) { %> <% if(themeConfig.preloader.spinner) { %>
<div style="transform: scale(3); padding-top: 30px;"> <div style="transform: scale(3); padding-top: 30px;">
<div style="text-align: center; " class="spinner-border text-primary text-gradient" <div style="text-align: center; " class="spinner-border text-primary text-gradient"
role="status"> role="status">
<span class="visually-hidden">Loading...</span> <span class="visually-hidden">Loading...</span>
</div> </div>
</div> </div>
<% } %> <% } %>
</div> </div>
<% } %> <% } %>
<% } %> <% } %>
</div> </div>

View file

@ -1,18 +1,18 @@
<% <%
let currentPage = "Dashboard"; let currentPage = "Dashboard";
if (now) { if (now) {
const pages = req?.locales?.partials?.navbar?.pages; const pages = req?.locales?.partials?.navbar?.pages;
if (now === 'manage') currentPage = pages?.manage || "Manage Guilds"; if (now === 'manage') currentPage = pages?.manage || "Manage Guilds";
if (now === 'settings') currentPage = pages?.settings || "Manage Guilds"; if (now === 'settings') currentPage = pages?.settings || "Manage Guilds";
if (now === 'commands') currentPage = pages?.commands || "Commands"; if (now === 'commands') currentPage = pages?.commands || "Commands";
if (now === 'pp') currentPage = pages?.pp || "Privacy Policy"; if (now === 'pp') currentPage = pages?.pp || "Privacy Policy";
if (now === 'admin') currentPage = pages?.admin || "Admin Panel"; if (now === 'admin') currentPage = pages?.admin || "Admin Panel";
if (now === 'error') currentPage = pages?.error || "Error"; if (now === 'error') currentPage = pages?.error || "Error";
if (now === 'credits') currentPage = pages?.credits || "Credits"; if (now === 'credits') currentPage = pages?.credits || "Credits";
if (now === 'debug') currentPage = pages?.debug || "Debug"; if (now === 'debug') currentPage = pages?.debug || "Debug";
if (now === 'leaderboard') currentPage = pages?.leaderboard || "Leaderboard"; if (now === 'leaderboard') currentPage = pages?.leaderboard || "Leaderboard";
if (now === 'profile') currentPage = pages?.profile || "Profile"; if (now === 'profile') currentPage = pages?.profile || "Profile";
if (now === 'maintenance') currentPage = pages?.maintenance || "Under Maintenance"; if (now === 'maintenance') currentPage = pages?.maintenance || "Under Maintenance";
} }
%> %>
@ -21,13 +21,13 @@ if (now) {
<!-- Page Information --> <!-- Page Information -->
<link rel="icon" type="image/png" href="<%= themeConfig.icons.favicon %>"> <link rel="icon" type="image/png" href="<%= themeConfig.icons.favicon %>">
<title> <title>
<%= themeConfig.websiteName %> - <%- currentPage %> <%= themeConfig.websiteName %> - <%- currentPage %>
</title> </title>
<!-- End of Page Information --> <!-- End of Page Information -->
<!-- Stylesheets --> <!-- Stylesheets -->
<% if(themeConfig.preloader.image) { %> <% if(themeConfig.preloader.image) { %>
<link rel="prefetch" href="<%- themeConfig.preloader.image %>"/><% } %> <link rel="prefetch" href="<%- themeConfig.preloader.image %>"/><% } %>
<link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" as="style" onload="this.onload=null;this.rel='stylesheet'"> <link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" as="style" onload="this.onload=null;this.rel='stylesheet'">
@ -38,25 +38,25 @@ if (now) {
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@4/dark.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> <link rel="preload" href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@4/dark.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<link rel="preload" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/jquery-ui.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> <link rel="preload" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/jquery-ui.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript> <noscript>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Alatsi"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Alatsi">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/nucleo-icons.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/nucleo-icons.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/nucleo-svg.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/nucleo-svg.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/soft-ui-dashboard.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/soft-ui-dashboard.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@4/dark.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@4/dark.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/jquery-ui.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/css/jquery-ui.min.css">
</noscript> </noscript>
<% // By default system theme is loaded, unless a user has changed it. Probably could be optimised further but :shrug: <% // By default system theme is loaded, unless a user has changed it. Probably could be optimised further but :shrug:
if(req.cookies?.selectedTheme == "dark" || req.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %> if(req.cookies?.selectedTheme == "dark" || req.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %>
<link href="/css/darkMode.css" rel='stylesheet' <% if(req?.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %> media="(prefers-color-scheme: dark)"<% } %>> <link href="/css/darkMode.css" rel='stylesheet' <% if(req?.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %> media="(prefers-color-scheme: dark)"<% } %>>
<% if (themeConfig?.icons?.sidebar?.darkUrl) { %> <% if (themeConfig?.icons?.sidebar?.darkUrl) { %>
<style <% if(req?.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %> media="(prefers-color-scheme: dark)"<% } %>> <style <% if(req?.cookies?.selectedTheme == "auto" || !req.cookies?.selectedTheme) { %> media="(prefers-color-scheme: dark)"<% } %>>
.navbar-brand-img { .navbar-brand-img {
content:url("<%= themeConfig.icons.sidebar.darkUrl %>") !important; content:url("<%= themeConfig.icons.sidebar.darkUrl %>") !important;
} }
</style> </style>
<% } %> <% } %>
<% } %> <% } %>
<!-- End of Stylesheets --> <!-- End of Stylesheets -->
@ -68,127 +68,127 @@ if(req.cookies?.selectedTheme == "dark" || req.cookies?.selectedTheme == "auto"
<%- include('colorscheme.ejs') %> <%- include('colorscheme.ejs') %>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const swal = params.get('swal'); const swal = params.get('swal');
const result = params.get('result'); const result = params.get('result');
if (swal) { if (swal) {
if (swal === "savedSuccess") sweetalert('success', '<%= themeConfig?.sweetalert?.success?.settingsSave || 'Successfully saved setttings!' %>', 3000); if (swal === "savedSuccess") sweetalert('success', '<%= themeConfig?.sweetalert?.success?.settingsSave || 'Successfully saved setttings!' %>', 3000);
if (swal === "savedError") sweetalert('error', '<%= themeConfig?.sweetalert?.error?.settingsSave || 'Failed to save setttings!' %>', 3000); if (swal === "savedError") sweetalert('error', '<%= themeConfig?.sweetalert?.error?.settingsSave || 'Failed to save setttings!' %>', 3000);
<% if (req.session.user) { %>if (swal === "logged") sweetalert('success', '<%= themeConfig?.sweetalert?.success?.login || 'Successfully logged in!' %>', 3000); <% } %> <% if (req.session.user) { %>if (swal === "logged") sweetalert('success', '<%= themeConfig?.sweetalert?.success?.login || 'Successfully logged in!' %>', 3000); <% } %>
<% if (!req.session.user) { %>if (swal === "loggedout") sweetalert('success', '<%= themeConfig?.sweetalert?.success?.logout || 'Successfully logged out!' %>', 3000); <% } %> <% if (!req.session.user) { %>if (swal === "loggedout") sweetalert('success', '<%= themeConfig?.sweetalert?.success?.logout || 'Successfully logged out!' %>', 3000); <% } %>
params.delete('swal'); params.delete('swal');
} }
if (result) { if (result) {
if (result === "true") sweetalert('success', 'Checked for updates!', 3000); if (result === "true") sweetalert('success', 'Checked for updates!', 3000);
if (result === "false") sweetalert('error', 'Failed to check for updates!', 3000); if (result === "false") sweetalert('error', 'Failed to check for updates!', 3000);
params.delete('result'); params.delete('result');
} }
window.history.replaceState({}, document.title, `${window.location.pathname}${params.toString() ? "?" + params.toString() : ""}`); window.history.replaceState({}, document.title, `${window.location.pathname}${params.toString() ? "?" + params.toString() : ""}`);
}); });
var win = navigator.platform.indexOf('Win') > -1; var win = navigator.platform.indexOf('Win') > -1;
if (win && document.querySelector('#sidenav-scrollbar')) { if (win && document.querySelector('#sidenav-scrollbar')) {
var options = { var options = {
damping: '0.5' damping: '0.5'
} }
Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options); Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options);
} }
function setCookie(name, value, days) { function setCookie(name, value, days) {
var expires = ""; var expires = "";
if (days) { if (days) {
var date = new Date(); var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString(); expires = "; expires=" + date.toUTCString();
} }
document.cookie = name + "=" + (value || "") + expires + "; path=/"; document.cookie = name + "=" + (value || "") + expires + "; path=/";
} }
function getCookie(cname) { function getCookie(cname) {
let name = cname + "="; let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie); let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';'); let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) { for (let i = 0; i < ca.length; i++) {
let c = ca[i]; let c = ca[i];
while (c.charAt(0) == ' ') { while (c.charAt(0) == ' ') {
c = c.substring(1); c = c.substring(1);
} }
if (c.indexOf(name) == 0) { if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length); return c.substring(name.length, c.length);
} }
} }
return ""; return "";
} }
function deleteCookie(name) { function deleteCookie(name) {
document.cookie = name + '=; Max-Age=0' document.cookie = name + '=; Max-Age=0'
} }
let prog_width = 0; let prog_width = 0;
let disabled = false; let disabled = false;
document.onreadystatechange = function (e) { document.onreadystatechange = function (e) {
if (disabled) return; if (disabled) return;
if (document.readyState === "interactive") { if (document.readyState === "interactive") {
var all = document.getElementsByTagName("*"); var all = document.getElementsByTagName("*");
for (var i = 0, max = all.length; i < max; i++) { for (var i = 0, max = all.length; i < max; i++) {
checkProgress(all[i]); checkProgress(all[i]);
} }
} }
} }
function checkProgress(ele) { function checkProgress(ele) {
var all = document.getElementsByTagName("*"); var all = document.getElementsByTagName("*");
var per_inc = 100 / all.length; var per_inc = 100 / all.length;
if (disabled) return; if (disabled) return;
prog_width = prog_width + per_inc; prog_width = prog_width + per_inc;
$("#progress").width(`${Math.floor(prog_width)}%`); $("#progress").width(`${Math.floor(prog_width)}%`);
if (prog_width >= 100 && !disabled) { if (prog_width >= 100 && !disabled) {
disabled = true; disabled = true;
$(".preloader").fadeOut("slow") $(".preloader").fadeOut("slow")
//() => { $(".preloader").remove() } //() => { $(".preloader").remove() }
$("#scroll").css('overflow', 'auto'); $("#scroll").css('overflow', 'auto');
} else { } else {
checkProgress(ele); checkProgress(ele);
} }
} }
<% if (req.session.user) { %> <% if (req.session.user) { %>
let userID = '<%- req.session.user.id %>'; let userID = '<%- req.session.user.id %>';
let userTag = '<%- req.session.user.tag %>'; let userTag = '<%- req.session.user.tag %>';
<% } %> <% } %>
var win = navigator.platform.indexOf('Win') > -1; var win = navigator.platform.indexOf('Win') > -1;
if (win && document.querySelector('#sidenav-scrollbar')) { if (win && document.querySelector('#sidenav-scrollbar')) {
var options = { var options = {
damping: '0.5' damping: '0.5'
} }
Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options); Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options);
} }
function getCookie(cname) { function getCookie(cname) {
let name = cname + "="; let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie); let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';'); let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) { for (let i = 0; i < ca.length; i++) {
let c = ca[i]; let c = ca[i];
while (c.charAt(0) == ' ') { while (c.charAt(0) == ' ') {
c = c.substring(1); c = c.substring(1);
} }
if (c.indexOf(name) == 0) { if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length); return c.substring(name.length, c.length);
} }
} }
return ""; return "";
} }
</script> </script>
<!-- End of Scripts --> <!-- End of Scripts -->
<% if(now !== "maintenance" && now !== "error") { %> <% if(now !== "maintenance" && now !== "error") { %>
<%- include('theme.ejs') %> <%- include('theme.ejs') %>
<% } %> <% } %>

View file

@ -1,72 +1,72 @@
<% if (req.cookies?.premiumCard == "false" || !req.cookies?.premiumCard) { %> <% if (req.cookies?.premiumCard == "false" || !req.cookies?.premiumCard) { %>
<div class="rightCircle"><i class="fas fa-times"></i></div> <div class="rightCircle"><i class="fas fa-times"></i></div>
<div class="premium-card card card-background shadow-none card-background-mask-primary" id="sidenavCard"> <div class="premium-card card card-background shadow-none card-background-mask-primary" id="sidenavCard">
<div class="full-background" <div class="full-background"
style="background-image: url('<%- themeConfig.premium.card.bgImage %>'); margin-bottom: 0 !important;"></div> style="background-image: url('<%- themeConfig.premium.card.bgImage %>'); margin-bottom: 0 !important;"></div>
<div class="card-body text-start p-3 w-100"> <div class="card-body text-start p-3 w-100">
<div class="docs-info"> <div class="docs-info">
<h6 class="hide-click text-white up mb-0"><%- req?.locales?.partials?.premium?.title %></h6> <h6 class="hide-click text-white up mb-0"><%- req?.locales?.partials?.premium?.title %></h6>
<p class="hide-click text-xs font-weight-bold"><%- req?.locales?.partials?.premium?.description %></p> <p class="hide-click text-xs font-weight-bold"><%- req?.locales?.partials?.premium?.description %></p>
<a style="margin-bottom: 0 !important;" class="premium-button btn bg-gradient-primary mt-4 w-100" <a style="margin-bottom: 0 !important;" class="premium-button btn bg-gradient-primary mt-4 w-100"
target="_blank" target="_blank"
href="<%- themeConfig.premium.card.button.url %>" href="<%- themeConfig.premium.card.button.url %>"
type="button"><%- req?.locales?.partials?.premium?.buttonText %></a> type="button"><%- req?.locales?.partials?.premium?.buttonText %></a>
</div> </div>
</div> </div>
</div> </div>
<% } %> <% } %>
<script> <script>
$('.rightCircle').on('click', function () { $('.rightCircle').on('click', function () {
var date = new Date(); var date = new Date();
date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString(); var expires = "; expires=" + date.toGMTString();
document.cookie = "premiumCard=true" + expires + "; path=/"; document.cookie = "premiumCard=true" + expires + "; path=/";
$(".sidenav-footer").fadeOut("slow"); $(".sidenav-footer").fadeOut("slow");
}); });
</script> </script>
<style> <style>
.margin-top-0 { .margin-top-0 {
margin-top: 0 !important; margin-top: 0 !important;
} }
.sidenav-footer { .sidenav-footer {
width: 90%; width: 90%;
} }
.rightCircle { .rightCircle {
cursor: pointer; cursor: pointer;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
user-select: none; user-select: none;
position: absolute; position: absolute;
right: -5px; right: -5px;
top: -5px; top: -5px;
width: 20px; width: 20px;
height: 20px; height: 20px;
border-radius: 50%; border-radius: 50%;
background-color: #fff; background-color: #fff;
box-shadow: 0 0 0 1px #fff; box-shadow: 0 0 0 1px #fff;
z-index: 100; z-index: 100;
} }
.sidebarPremium { .sidebarPremium {
cursor: pointer; cursor: pointer;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
user-select: none; user-select: none;
position: absolute; position: absolute;
right: 10px; right: 10px;
width: 20px; width: 20px;
height: 7px; height: 7px;
border-radius: 50%; border-radius: 50%;
background-color: transparent; background-color: transparent;
z-index: 100; z-index: 100;
} }
</style> </style>

View file

@ -1,158 +1,158 @@
<!-- Core JS Files --> <!-- Core JS Files -->
<script src="https://cdn.jsdelivr.net/npm/jquery.skeleton.loader@1.2.0/dist/jquery.scheletrone.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/jquery.skeleton.loader@1.2.0/dist/jquery.scheletrone.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js" <script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js"
integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></script> integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></script>
<script> <script>
function login(url) { function login(url) {
<% if (!req.session.user) { %> <% if (!req.session.user) { %>
const newWindow = window.open('/discord', 'Log in with discord', `directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no, width=500, height=800`); const newWindow = window.open('/discord', 'Log in with discord', `directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no, width=500, height=800`);
newWindow.focus(); newWindow.focus();
setInterval(() => { setInterval(() => {
if (newWindow.closed) window.location.href = `${url}?swal=logged`; if (newWindow.closed) window.location.href = `${url}?swal=logged`;
}, 500); }, 500);
<% } else { %> <% } else { %>
window.location.href = `${url}?swal=alreadyloggedin`; window.location.href = `${url}?swal=alreadyloggedin`;
<% } %> <% } %>
} }
$('.account').click(function (e) { $('.account').click(function (e) {
e.preventDefault(); e.preventDefault();
login(e.currentTarget.href) login(e.currentTarget.href)
}); });
$('.theme').click(function () { $('.theme').click(function () {
$('.theme').removeClass('active'); $('.theme').removeClass('active');
$(this).addClass('active'); $(this).addClass('active');
const theme = $(this).attr('data-theme'); const theme = $(this).attr('data-theme');
setCookie('selectedTheme', theme, 365); setCookie('selectedTheme', theme, 365);
location.reload(); location.reload();
}); });
const sidenav = document.getElementById('sidenav-main'); const sidenav = document.getElementById('sidenav-main');
function hideSidenav() { function hideSidenav() {
body.classList.remove(className); body.classList.remove(className);
setTimeout(function () { setTimeout(function () {
sidenav.classList.remove('bg-white'); sidenav.classList.remove('bg-white');
}, 100); }, 100);
sidenav.classList.remove('bg-transparent'); sidenav.classList.remove('bg-transparent');
} }
function showSidenav() { function showSidenav() {
try { try {
body.classList.add(className); body.classList.add(className);
sidenav.classList.add('bg-white'); sidenav.classList.add('bg-white');
sidenav.classList.remove('bg-transparent'); sidenav.classList.remove('bg-transparent');
iconSidenav.classList.remove('d-none'); iconSidenav.classList.remove('d-none');
} catch (error) { } catch (error) {
} }
} }
<% if (!themeConfig?.sidebar?.gestures?.disabled) { %> <% if (!themeConfig?.sidebar?.gestures?.disabled) { %>
document.addEventListener('touchstart', handleTouchStart, false); document.addEventListener('touchstart', handleTouchStart, false);
document.addEventListener('touchmove', handleTouchMove, false); document.addEventListener('touchmove', handleTouchMove, false);
document.addEventListener('touchend', handleTouchEnd, false); document.addEventListener('touchend', handleTouchEnd, false);
const SWIPE_BLOCK_ELEMS = [ const SWIPE_BLOCK_ELEMS = [
'swipBlock', 'swipBlock',
'handle', 'handle',
'drag-ruble' 'drag-ruble'
] ]
let xDown = null; let xDown = null;
let yDown = null; let yDown = null;
let xDiff = null; let xDiff = null;
let yDiff = null; let yDiff = null;
let timeDown = null; let timeDown = null;
const TIME_THRESHOLD = <%= themeConfig?.sidebar?.gestures?.gestureTimer || 200 %>; const TIME_THRESHOLD = <%= themeConfig?.sidebar?.gestures?.gestureTimer || 200 %>;
const DIFF_THRESHOLD = <%= themeConfig?.sidebar?.gestures?.gestureSensitivity || 50 %>; const DIFF_THRESHOLD = <%= themeConfig?.sidebar?.gestures?.gestureSensitivity || 50 %>;
function handleTouchEnd() { function handleTouchEnd() {
let timeDiff = Date.now() - timeDown; let timeDiff = Date.now() - timeDown;
if (Math.abs(xDiff) > Math.abs(yDiff)) { if (Math.abs(xDiff) > Math.abs(yDiff)) {
if (Math.abs(xDiff) > DIFF_THRESHOLD && timeDiff < TIME_THRESHOLD) { if (Math.abs(xDiff) > DIFF_THRESHOLD && timeDiff < TIME_THRESHOLD) {
if (xDiff > 0) { if (xDiff > 0) {
hideSidenav() hideSidenav()
xDown = null; xDown = null;
yDown = null; yDown = null;
timeDown = null; timeDown = null;
} else { } else {
showSidenav() showSidenav()
xDown = null; xDown = null;
yDown = null; yDown = null;
timeDown = null; timeDown = null;
} }
} }
} }
xDown = null; xDown = null;
yDown = null; yDown = null;
timeDown = null; timeDown = null;
} }
function containsClassName(evntarget, classArr) { function containsClassName(evntarget, classArr) {
for (var i = classArr.length - 1; i >= 0; i--) { for (var i = classArr.length - 1; i >= 0; i--) {
if (evntarget.classList.contains(classArr[i])) { if (evntarget.classList.contains(classArr[i])) {
return true; return true;
} }
} }
} }
function handleTouchStart(evt) { function handleTouchStart(evt) {
let touchStartTarget = evt.target; let touchStartTarget = evt.target;
if (containsClassName(touchStartTarget, SWIPE_BLOCK_ELEMS)) { if (containsClassName(touchStartTarget, SWIPE_BLOCK_ELEMS)) {
return; return;
} }
timeDown = Date.now() timeDown = Date.now()
xDown = evt.touches[0].clientX; xDown = evt.touches[0].clientX;
yDown = evt.touches[0].clientY; yDown = evt.touches[0].clientY;
xDiff = 0; xDiff = 0;
yDiff = 0; yDiff = 0;
} }
function handleTouchMove(evt) { function handleTouchMove(evt) {
if (!xDown || !yDown) { if (!xDown || !yDown) {
return; return;
} }
var xUp = evt.touches[0].clientX; var xUp = evt.touches[0].clientX;
var yUp = evt.touches[0].clientY; var yUp = evt.touches[0].clientY;
xDiff = xDown - xUp; xDiff = xDown - xUp;
yDiff = yDown - yUp; yDiff = yDown - yUp;
} }
<% } %> <% } %>
function sweetalert(icons, text, timer) { function sweetalert(icons, text, timer) {
var is_mobile = !!navigator.userAgent.match(/iphone|android|blackberry/ig); var is_mobile = !!navigator.userAgent.match(/iphone|android|blackberry/ig);
let pos = 'top-end'; let pos = 'top-end';
if (is_mobile) pos = 'bottom-end'; if (is_mobile) pos = 'bottom-end';
const Toast = Swal.mixin({ const Toast = Swal.mixin({
toast: true, toast: true,
position: pos, position: pos,
showConfirmButton: false, showConfirmButton: false,
timer: timer, timer: timer,
timerProgressBar: true, timerProgressBar: true,
didOpen: (toast) => { didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer) toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer) toast.addEventListener('mouseleave', Swal.resumeTimer)
} }
}) })
Toast.fire({ Toast.fire({
icon: icons, icon: icons,
title: text title: text
}) })
} }
<% if (req.displayLoggedInInfo == true) { %> <% if (req.displayLoggedInInfo == true) { %>
window.onload = function () { window.onload = function () {
sweetalert("success", "<%= themeConfig?.sweetalert?.success?.login || 'Successfully signed in.' %>", 2000) sweetalert("success", "<%= themeConfig?.sweetalert?.success?.login || 'Successfully signed in.' %>", 2000)
}; };
<% } %> <% } %>
</script> </script>
<script src="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/js/plugins/chartjs.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/Assistants-Center/DBD-Soft-UI/views/src/js/plugins/chartjs.min.js"></script>
<script src="js/dashboard/sweetalert.js"></script> <script src="js/dashboard/sweetalert.js"></script>

File diff suppressed because one or more lines are too long

View file

@ -1,45 +1,45 @@
<% <%
for(var i in req.session.guilds){ %> for(var i in req.session.guilds){ %>
<% if((req.session.guilds[i].permissions & 0x00000020) == 0x00000020){ %> <% if((req.session.guilds[i].permissions & 0x00000020) == 0x00000020){ %>
<% if(!bot.guilds.cache.get(req.session.guilds[i].id)){ <% if(!bot.guilds.cache.get(req.session.guilds[i].id)){
let icon = `https://cdn.discordapp.com/icons/${req.session.guilds[i].id}/${req.session.guilds[i].icon}.png`; let icon = `https://cdn.discordapp.com/icons/${req.session.guilds[i].id}/${req.session.guilds[i].icon}.png`;
const friendlyName = req.session.guilds[i].name.replace('`', ''); const friendlyName = req.session.guilds[i].name.replace('`', '');
if (!req.session.guilds[i].icon) icon = themeConfig.iconURL; if (!req.session.guilds[i].icon) icon = themeConfig.iconURL;
%> %>
<a href="#"> <a href="#">
<img id="servericon" onclick="select<%- req.session.guilds[i].id %>()" onerror="this.src = '<%= icon %>';" <img id="servericon" onclick="select<%- req.session.guilds[i].id %>()" onerror="this.src = '<%= icon %>';"
src="https://cdn.discordapp.com/icons/<%= req.session.guilds[i].id %>/<%= req.session.guilds[i].icon %>.png"> src="https://cdn.discordapp.com/icons/<%= req.session.guilds[i].id %>/<%= req.session.guilds[i].icon %>.png">
</a> </a>
<script> <script>
async function select<%- req.session.guilds[i].id %>() { async function select<%- req.session.guilds[i].id %>() {
$('#select').html(`<%= friendlyName %>`); $('#select').html(`<%= friendlyName %>`);
$('#selectedImg').attr('src', '<%= icon %>'); $('#selectedImg').attr('src', '<%= icon %>');
$("#inviteButton").attr('href', "../invite?g=<%- req.session.guilds[i].id %>"); $("#inviteButton").attr('href', "../invite?g=<%- req.session.guilds[i].id %>");
$("#notInServer").show(); $("#notInServer").show();
setUser(`<%= friendlyName %>`, `<%= icon %>`, `Server ID: <%= req.session.guilds[i].id %>`); setUser(`<%= friendlyName %>`, `<%= icon %>`, `Server ID: <%= req.session.guilds[i].id %>`);
} }
</script> </script>
<% }else{ <% }else{
const guild = bot.guilds.cache.get(req.session.guilds[i].id); const guild = bot.guilds.cache.get(req.session.guilds[i].id);
let icon; let icon;
if (!guild.iconURL()) icon = themeConfig.iconURL; if (!guild.iconURL()) icon = themeConfig.iconURL;
else icon = guild.iconURL(); else icon = guild.iconURL();
const friendlyName = guild.name.replace('`', ''); const friendlyName = guild.name.replace('`', '');
%> %>
<a href="#" onclick="select<%- guild.id %>()"> <a href="#" onclick="select<%- guild.id %>()">
<img id="servericon" onerror="this.src = '<%= themeConfig.iconURL %>';" src="<%= icon %>"> <img id="servericon" onerror="this.src = '<%= themeConfig.iconURL %>';" src="<%= icon %>">
</a> </a>
<script> <script>
async function select<%- guild.id %>() { async function select<%- guild.id %>() {
$('#select').html(`<%= friendlyName %>`); $('#select').html(`<%= friendlyName %>`);
$('#selectedImg').attr('src', '<%= icon %>'); $('#selectedImg').attr('src', '<%= icon %>');
$("#notInServer").hide(); $("#notInServer").hide();
setUser(`<%= friendlyName %>`, `<%= icon %>`, `Server ID: <%= req.session.guilds[i].id %>`); setUser(`<%= friendlyName %>`, `<%= icon %>`, `Server ID: <%= req.session.guilds[i].id %>`);
window.location = "../guild/<%= req.session.guilds[i].id %>"; window.location = "../guild/<%= req.session.guilds[i].id %>";
} }
</script> </script>
<!--/guild/<%= req.session.guilds[i].id %>--> <!--/guild/<%= req.session.guilds[i].id %>-->
<% <%
} }
} }

View file

@ -1,342 +1,342 @@
<style> <style>
.navbar-vertical.navbar-expand-xs .navbar-collapse { .navbar-vertical.navbar-expand-xs .navbar-collapse {
height: auto !important; height: auto !important;
} }
</style> </style>
<aside class="sidenav navbar navbar-vertical navbar-expand-xs border-0 border-radius-xl my-3 fixed-start ms-3 ps" <aside class="sidenav navbar navbar-vertical navbar-expand-xs border-0 border-radius-xl my-3 fixed-start ms-3 ps"
style="float:left;" id="sidenav-main"> style="float:left;" id="sidenav-main">
<div id="sidebarMain"> <div id="sidebarMain">
<div class="sidenav-header"> <div class="sidenav-header">
<a onclick="toggleSidenav()"><i <a onclick="toggleSidenav()"><i
class="fas fa-times p-3 cursor-pointer text-secondary opacity-5 position-absolute end-0 top-0 d-none d-xl-none" class="fas fa-times p-3 cursor-pointer text-secondary opacity-5 position-absolute end-0 top-0 d-none d-xl-none"
aria-hidden="true" id="iconSidenav"></i></a> aria-hidden="true" id="iconSidenav"></i></a>
<a <a
<% if(themeConfig.icons.sidebar.alignCenter) { %> style="text-align: center;" <% if(themeConfig.icons.sidebar.alignCenter) { %> style="text-align: center;"
<% } %> <% } %>
class="navbar-brand m-0" href="/"> class="navbar-brand m-0" href="/">
<img src="<%- themeConfig.icons.sidebar.lightUrl %>" <img src="<%- themeConfig.icons.sidebar.lightUrl %>"
class="navbar-brand-img h-100" class="navbar-brand-img h-100"
<% if(themeConfig.icons.sidebar.borderRadius) { %>style="border-radius: <%- themeConfig.icons.sidebar.borderRadius %>;" <% if(themeConfig.icons.sidebar.borderRadius) { %>style="border-radius: <%- themeConfig.icons.sidebar.borderRadius %>;"
<% } %> <% } %>
alt="main_logo"> alt="main_logo">
<% if(!themeConfig.icons.sidebar.hideName){ %> <% if(!themeConfig.icons.sidebar.hideName){ %>
<span class="ms-1 font-weight-bold" id="sitename"><%= themeConfig.websiteName %></span> <span class="ms-1 font-weight-bold" id="sitename"><%= themeConfig.websiteName %></span>
<% } %> <% } %>
</a> </a>
</div> </div>
<hr class="horizontal dark mt-0"> <hr class="horizontal dark mt-0">
<div class="collapse navbar-collapse w-auto max-height-vh-80 h-80" id="sidenav-collapse-main"> <div class="collapse navbar-collapse w-auto max-height-vh-80 h-80" id="sidenav-collapse-main">
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link <% if(now == 'index'){ %>active<% } else { %>" href='/' <a class="nav-link <% if(now == 'index'){ %>active<% } else { %>" href='/'
<% } %> <% } %>
"> ">
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg class="text-dark" width="16px" height="16px" viewBox="0 0 45 40" version="1.1" <svg class="text-dark" width="16px" height="16px" viewBox="0 0 45 40" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<title>shop </title> <title>shop </title>
<g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Rounded-Icons" transform="translate(-1716.000000, -439.000000)" <g id="Rounded-Icons" transform="translate(-1716.000000, -439.000000)"
fill="#FFFFFF" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)"> <g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)">
<g id="shop-" transform="translate(0.000000, 148.000000)"> <g id="shop-" transform="translate(0.000000, 148.000000)">
<path class="color-background" <path class="color-background"
d="M46.7199583,10.7414583 L40.8449583,0.949791667 C40.4909749,0.360605034 39.8540131,0 39.1666667,0 L7.83333333,0 C7.1459869,0 6.50902508,0.360605034 6.15504167,0.949791667 L0.280041667,10.7414583 C0.0969176761,11.0460037 -1.23209662e-05,11.3946378 -1.23209662e-05,11.75 C-0.00758042603,16.0663731 3.48367543,19.5725301 7.80004167,19.5833333 L7.81570833,19.5833333 C9.75003686,19.5882688 11.6168794,18.8726691 13.0522917,17.5760417 C16.0171492,20.2556967 20.5292675,20.2556967 23.494125,17.5760417 C26.4604562,20.2616016 30.9794188,20.2616016 33.94575,17.5760417 C36.2421905,19.6477597 39.5441143,20.1708521 42.3684437,18.9103691 C45.1927731,17.649886 47.0084685,14.8428276 47.0000295,11.75 C47.0000295,11.3946378 46.9030823,11.0460037 46.7199583,10.7414583 Z" d="M46.7199583,10.7414583 L40.8449583,0.949791667 C40.4909749,0.360605034 39.8540131,0 39.1666667,0 L7.83333333,0 C7.1459869,0 6.50902508,0.360605034 6.15504167,0.949791667 L0.280041667,10.7414583 C0.0969176761,11.0460037 -1.23209662e-05,11.3946378 -1.23209662e-05,11.75 C-0.00758042603,16.0663731 3.48367543,19.5725301 7.80004167,19.5833333 L7.81570833,19.5833333 C9.75003686,19.5882688 11.6168794,18.8726691 13.0522917,17.5760417 C16.0171492,20.2556967 20.5292675,20.2556967 23.494125,17.5760417 C26.4604562,20.2616016 30.9794188,20.2616016 33.94575,17.5760417 C36.2421905,19.6477597 39.5441143,20.1708521 42.3684437,18.9103691 C45.1927731,17.649886 47.0084685,14.8428276 47.0000295,11.75 C47.0000295,11.3946378 46.9030823,11.0460037 46.7199583,10.7414583 Z"
id="Path" opacity="0.598981585"></path> id="Path" opacity="0.598981585"></path>
<path class="color-background" <path class="color-background"
d="M39.198,22.4912623 C37.3776246,22.4928106 35.5817531,22.0149171 33.951625,21.0951667 L33.92225,21.1107282 C31.1430221,22.6838032 27.9255001,22.9318916 24.9844167,21.7998837 C24.4750389,21.605469 23.9777983,21.3722567 23.4960833,21.1018359 L23.4745417,21.1129513 C20.6961809,22.6871153 17.4786145,22.9344611 14.5386667,21.7998837 C14.029926,21.6054643 13.533337,21.3722507 13.0522917,21.1018359 C11.4250962,22.0190609 9.63246555,22.4947009 7.81570833,22.4912623 C7.16510551,22.4842162 6.51607673,22.4173045 5.875,22.2911849 L5.875,44.7220845 C5.875,45.9498589 6.7517757,46.9451667 7.83333333,46.9451667 L19.5833333,46.9451667 L19.5833333,33.6066734 L27.4166667,33.6066734 L27.4166667,46.9451667 L39.1666667,46.9451667 C40.2482243,46.9451667 41.125,45.9498589 41.125,44.7220845 L41.125,22.2822926 C40.4887822,22.4116582 39.8442868,22.4815492 39.198,22.4912623 Z" d="M39.198,22.4912623 C37.3776246,22.4928106 35.5817531,22.0149171 33.951625,21.0951667 L33.92225,21.1107282 C31.1430221,22.6838032 27.9255001,22.9318916 24.9844167,21.7998837 C24.4750389,21.605469 23.9777983,21.3722567 23.4960833,21.1018359 L23.4745417,21.1129513 C20.6961809,22.6871153 17.4786145,22.9344611 14.5386667,21.7998837 C14.029926,21.6054643 13.533337,21.3722507 13.0522917,21.1018359 C11.4250962,22.0190609 9.63246555,22.4947009 7.81570833,22.4912623 C7.16510551,22.4842162 6.51607673,22.4173045 5.875,22.2911849 L5.875,44.7220845 C5.875,45.9498589 6.7517757,46.9451667 7.83333333,46.9451667 L19.5833333,46.9451667 L19.5833333,33.6066734 L27.4166667,33.6066734 L27.4166667,46.9451667 L39.1666667,46.9451667 C40.2482243,46.9451667 41.125,45.9498589 41.125,44.7220845 L41.125,22.2822926 C40.4887822,22.4116582 39.8442868,22.4815492 39.198,22.4912623 Z"
id="Path"></path> id="Path"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.dash || "Dashboard" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.dash || "Dashboard" %></span>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="/manage" id="serverSelector" <a href="/manage" id="serverSelector"
class="account nav-link <% if(now == 'manage'){ %>active<% } %>"> class="account nav-link <% if(now == 'manage'){ %>active<% } %>">
<div id="icon" class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> <div id="icon" class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg class="text-dark" width="16px" height="16px" viewBox="0 0 40 40" version="1.1" <svg class="text-dark" width="16px" height="16px" viewBox="0 0 40 40" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<title>settings</title> <title>settings</title>
<g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Rounded-Icons" transform="translate(-2020.000000, -442.000000)" <g id="Rounded-Icons" transform="translate(-2020.000000, -442.000000)"
fill="#FFFFFF" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)"> <g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)">
<g id="settings" transform="translate(304.000000, 151.000000)"> <g id="settings" transform="translate(304.000000, 151.000000)">
<polygon class="color-background" id="Path" opacity="0.596981957" <polygon class="color-background" id="Path" opacity="0.596981957"
points="18.0883333 15.7316667 11.1783333 8.82166667 13.3333333 6.66666667 6.66666667 0 0 6.66666667 6.66666667 13.3333333 8.82166667 11.1783333 15.315 17.6716667"> points="18.0883333 15.7316667 11.1783333 8.82166667 13.3333333 6.66666667 6.66666667 0 0 6.66666667 6.66666667 13.3333333 8.82166667 11.1783333 15.315 17.6716667">
</polygon> </polygon>
<path class="color-background" <path class="color-background"
d="M31.5666667,23.2333333 C31.0516667,23.2933333 30.53,23.3333333 30,23.3333333 C29.4916667,23.3333333 28.9866667,23.3033333 28.48,23.245 L22.4116667,30.7433333 L29.9416667,38.2733333 C32.2433333,40.575 35.9733333,40.575 38.275,38.2733333 L38.275,38.2733333 C40.5766667,35.9716667 40.5766667,32.2416667 38.275,29.94 L31.5666667,23.2333333 Z" d="M31.5666667,23.2333333 C31.0516667,23.2933333 30.53,23.3333333 30,23.3333333 C29.4916667,23.3333333 28.9866667,23.3033333 28.48,23.245 L22.4116667,30.7433333 L29.9416667,38.2733333 C32.2433333,40.575 35.9733333,40.575 38.275,38.2733333 L38.275,38.2733333 C40.5766667,35.9716667 40.5766667,32.2416667 38.275,29.94 L31.5666667,23.2333333 Z"
id="Path" opacity="0.596981957"></path> id="Path" opacity="0.596981957"></path>
<path class="color-background" <path class="color-background"
d="M33.785,11.285 L28.715,6.215 L34.0616667,0.868333333 C32.82,0.315 31.4483333,0 30,0 C24.4766667,0 20,4.47666667 20,10 C20,10.99 20.1483333,11.9433333 20.4166667,12.8466667 L2.435,27.3966667 C0.95,28.7083333 0.0633333333,30.595 0.00333333333,32.5733333 C-0.0583333333,34.5533333 0.71,36.4916667 2.11,37.89 C3.47,39.2516667 5.27833333,40 7.20166667,40 C9.26666667,40 11.2366667,39.1133333 12.6033333,37.565 L27.1533333,19.5833333 C28.0566667,19.8516667 29.01,20 30,20 C35.5233333,20 40,15.5233333 40,10 C40,8.55166667 39.685,7.18 39.1316667,5.93666667 L33.785,11.285 Z" d="M33.785,11.285 L28.715,6.215 L34.0616667,0.868333333 C32.82,0.315 31.4483333,0 30,0 C24.4766667,0 20,4.47666667 20,10 C20,10.99 20.1483333,11.9433333 20.4166667,12.8466667 L2.435,27.3966667 C0.95,28.7083333 0.0633333333,30.595 0.00333333333,32.5733333 C-0.0583333333,34.5533333 0.71,36.4916667 2.11,37.89 C3.47,39.2516667 5.27833333,40 7.20166667,40 C9.26666667,40 11.2366667,39.1133333 12.6033333,37.565 L27.1533333,19.5833333 C28.0566667,19.8516667 29.01,20 30,20 C35.5233333,20 40,15.5233333 40,10 C40,8.55166667 39.685,7.18 39.1316667,5.93666667 L33.785,11.285 Z"
id="Path"></path> id="Path"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.manage || "Manage Guilds" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.manage || "Manage Guilds" %></span>
</a> </a>
</li> </li>
<% if(themeConfig.shardspage?.enabled == true) { %> <% if(themeConfig.shardspage?.enabled == true) { %>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link <% if(now == 'shards'){ %>active<% } else { %>" href='/shards' <a class="nav-link <% if(now == 'shards'){ %>active<% } else { %>" href='/shards'
<% } %> <% } %>
"> ">
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg class="text-dark" xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M0 336c0 79.5 64.5 144 144 144H512c70.7 0 128-57.3 128-128c0-61.9-44-113.6-102.4-125.4c4.1-10.7 6.4-22.4 6.4-34.6c0-53-43-96-96-96c-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32C167.6 32 96 103.6 96 192c0 2.7 .1 5.4 .2 8.1C40.2 219.8 0 273.2 0 336z"/></svg> <svg class="text-dark" xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M0 336c0 79.5 64.5 144 144 144H512c70.7 0 128-57.3 128-128c0-61.9-44-113.6-102.4-125.4c4.1-10.7 6.4-22.4 6.4-34.6c0-53-43-96-96-96c-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32C167.6 32 96 103.6 96 192c0 2.7 .1 5.4 .2 8.1C40.2 219.8 0 273.2 0 336z"/></svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.shards || "Shards" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.shards || "Shards" %></span>
</a> </a>
</li> </li>
<% } %> <% } %>
<% if (now == "commands") { %> <% if (now == "commands") { %>
<li class="nav-item"> <li class="nav-item">
<a data-bs-toggle="collapse" href="#dashboardsExamples" <a data-bs-toggle="collapse" href="#dashboardsExamples"
class="nav-link <% if(now == 'commands'){ %>active<% } %> collapsed" class="nav-link <% if(now == 'commands'){ %>active<% } %> collapsed"
aria-controls="dashboardsExamples" role="button" aria-controls="dashboardsExamples" role="button"
aria-expanded="<% if(now == "commands"){ %>true<% } else{ %>false<% } %>"> aria-expanded="<% if(now == "commands"){ %>true<% } else{ %>false<% } %>">
<div class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center d-flex align-items-center justify-content-center me-2"> <div class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center d-flex align-items-center justify-content-center me-2">
<svg class="text-dark" width="16px" height="16px" viewBox="0 0 43 36" version="1.1" <svg class="text-dark" width="16px" height="16px" viewBox="0 0 43 36" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<title>credit-card</title> <title>credit-card</title>
<g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" <g id="Basic-Elements" stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd"> fill-rule="evenodd">
<g id="Rounded-Icons" transform="translate(-2169.000000, -745.000000)" <g id="Rounded-Icons" transform="translate(-2169.000000, -745.000000)"
fill="#FFFFFF" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)"> <g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)">
<g id="credit-card" transform="translate(453.000000, 454.000000)"> <g id="credit-card" transform="translate(453.000000, 454.000000)">
<path class="color-background" <path class="color-background"
d="M43,10.7482083 L43,3.58333333 C43,1.60354167 41.3964583,0 39.4166667,0 L3.58333333,0 C1.60354167,0 0,1.60354167 0,3.58333333 L0,10.7482083 L43,10.7482083 Z" d="M43,10.7482083 L43,3.58333333 C43,1.60354167 41.3964583,0 39.4166667,0 L3.58333333,0 C1.60354167,0 0,1.60354167 0,3.58333333 L0,10.7482083 L43,10.7482083 Z"
id="Path" opacity="0.593633743"></path> id="Path" opacity="0.593633743"></path>
<path class="color-background" <path class="color-background"
d="M0,16.125 L0,32.25 C0,34.2297917 1.60354167,35.8333333 3.58333333,35.8333333 L39.4166667,35.8333333 C41.3964583,35.8333333 43,34.2297917 43,32.25 L43,16.125 L0,16.125 Z M19.7083333,26.875 L7.16666667,26.875 L7.16666667,23.2916667 L19.7083333,23.2916667 L19.7083333,26.875 Z M35.8333333,26.875 L28.6666667,26.875 L28.6666667,23.2916667 L35.8333333,23.2916667 L35.8333333,26.875 Z"> d="M0,16.125 L0,32.25 C0,34.2297917 1.60354167,35.8333333 3.58333333,35.8333333 L39.4166667,35.8333333 C41.3964583,35.8333333 43,34.2297917 43,32.25 L43,16.125 L0,16.125 Z M19.7083333,26.875 L7.16666667,26.875 L7.16666667,23.2916667 L19.7083333,23.2916667 L19.7083333,26.875 Z M35.8333333,26.875 L28.6666667,26.875 L28.6666667,23.2916667 L35.8333333,23.2916667 L35.8333333,26.875 Z">
</path> </path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.commands || "Commands" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.commands || "Commands" %></span>
</a> </a>
<div class="collapse <% if(now == 'commands'){ %>show<% } %>" id="dashboardsExamples"> <div class="collapse <% if(now == 'commands'){ %>show<% } %>" id="dashboardsExamples">
<ul class="nav ms-4 ps-3"> <ul class="nav ms-4 ps-3">
<li class="nav-item "> <li class="nav-item ">
<a id="all" class="nav-link glow active_all" href="#"> <a id="all" class="nav-link glow active_all" href="#">
<span class="sidenav-mini-icon"> A </span> <span class="sidenav-mini-icon"> A </span>
<span class="sidenav-normal"> All </span> <span class="sidenav-normal"> All </span>
</a> </a>
</li> </li>
<% themeConfig.commands.forEach(category => { <% themeConfig.commands.forEach(category => {
if (category.hideSidebarItem) return; if (category.hideSidebarItem) return;
%> %>
<li class="nav-item"> <li class="nav-item">
<a id="<%= category.categoryId %>" class="nav-link glow active_<%= category.categoryId %>" <a id="<%= category.categoryId %>" class="nav-link glow active_<%= category.categoryId %>"
href="<% if(now !== 'commands'){ %>/commands<% } %>#<%= category.categoryId %>"> href="<% if(now !== 'commands'){ %>/commands<% } %>#<%= category.categoryId %>">
<span class="sidenav-mini-icon"> A </span> <span class="sidenav-mini-icon"> A </span>
<span class="sidenav-normal"> <%= category.category %> </span> <span class="sidenav-normal"> <%= category.category %> </span>
</a> </a>
</li> </li>
<% }) %> <% }) %>
</ul> </ul>
</div> </div>
</li> </li>
<% } else { %> <% } else { %>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/commands"> <a class="nav-link" href="/commands">
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg class="text-dark" width="16px" height="16px" viewBox="0 0 43 36" version="1.1" <svg class="text-dark" width="16px" height="16px" viewBox="0 0 43 36" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<title>credit-card</title> <title>credit-card</title>
<g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" <g id="Basic-Elements" stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd"> fill-rule="evenodd">
<g id="Rounded-Icons" transform="translate(-2169.000000, -745.000000)" <g id="Rounded-Icons" transform="translate(-2169.000000, -745.000000)"
fill="#FFFFFF" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)"> <g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)">
<g id="credit-card" transform="translate(453.000000, 454.000000)"> <g id="credit-card" transform="translate(453.000000, 454.000000)">
<path class="color-background" <path class="color-background"
d="M43,10.7482083 L43,3.58333333 C43,1.60354167 41.3964583,0 39.4166667,0 L3.58333333,0 C1.60354167,0 0,1.60354167 0,3.58333333 L0,10.7482083 L43,10.7482083 Z" d="M43,10.7482083 L43,3.58333333 C43,1.60354167 41.3964583,0 39.4166667,0 L3.58333333,0 C1.60354167,0 0,1.60354167 0,3.58333333 L0,10.7482083 L43,10.7482083 Z"
id="Path" opacity="0.593633743"></path> id="Path" opacity="0.593633743"></path>
<path class="color-background" <path class="color-background"
d="M0,16.125 L0,32.25 C0,34.2297917 1.60354167,35.8333333 3.58333333,35.8333333 L39.4166667,35.8333333 C41.3964583,35.8333333 43,34.2297917 43,32.25 L43,16.125 L0,16.125 Z M19.7083333,26.875 L7.16666667,26.875 L7.16666667,23.2916667 L19.7083333,23.2916667 L19.7083333,26.875 Z M35.8333333,26.875 L28.6666667,26.875 L28.6666667,23.2916667 L35.8333333,23.2916667 L35.8333333,26.875 Z"> d="M0,16.125 L0,32.25 C0,34.2297917 1.60354167,35.8333333 3.58333333,35.8333333 L39.4166667,35.8333333 C41.3964583,35.8333333 43,34.2297917 43,32.25 L43,16.125 L0,16.125 Z M19.7083333,26.875 L7.16666667,26.875 L7.16666667,23.2916667 L19.7083333,23.2916667 L19.7083333,26.875 Z M35.8333333,26.875 L28.6666667,26.875 L28.6666667,23.2916667 L35.8333333,23.2916667 L35.8333333,26.875 Z">
</path> </path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.commands || "Commands" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.commands || "Commands" %></span>
</a> </a>
</li> </li>
<% } %> <% } %>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link <% if(now == 'pp'){ %>active" <a class="nav-link <% if(now == 'pp'){ %>active"
<% } else { %>" href='/privacy-policy' <% } else { %>" href='/privacy-policy'
<% } %> <% } %>
> >
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg class="text-dark" width="16px" height="16px" viewBox="0 0 40 44" version="1.1" <svg class="text-dark" width="16px" height="16px" viewBox="0 0 40 44" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<title>document</title> <title>document</title>
<g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Rounded-Icons" transform="translate(-1870.000000, -591.000000)" <g id="Rounded-Icons" transform="translate(-1870.000000, -591.000000)"
fill="#FFFFFF" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)"> <g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)">
<g id="document" transform="translate(154.000000, 300.000000)"> <g id="document" transform="translate(154.000000, 300.000000)">
<path class="color-background" <path class="color-background"
d="M40,40 L36.3636364,40 L36.3636364,3.63636364 L5.45454545,3.63636364 L5.45454545,0 L38.1818182,0 C39.1854545,0 40,0.814545455 40,1.81818182 L40,40 Z" d="M40,40 L36.3636364,40 L36.3636364,3.63636364 L5.45454545,3.63636364 L5.45454545,0 L38.1818182,0 C39.1854545,0 40,0.814545455 40,1.81818182 L40,40 Z"
id="Path" opacity="0.603585379"></path> id="Path" opacity="0.603585379"></path>
<path class="color-background" <path class="color-background"
d="M30.9090909,7.27272727 L1.81818182,7.27272727 C0.814545455,7.27272727 0,8.08727273 0,9.09090909 L0,41.8181818 C0,42.8218182 0.814545455,43.6363636 1.81818182,43.6363636 L30.9090909,43.6363636 C31.9127273,43.6363636 32.7272727,42.8218182 32.7272727,41.8181818 L32.7272727,9.09090909 C32.7272727,8.08727273 31.9127273,7.27272727 30.9090909,7.27272727 Z M18.1818182,34.5454545 L7.27272727,34.5454545 L7.27272727,30.9090909 L18.1818182,30.9090909 L18.1818182,34.5454545 Z M25.4545455,27.2727273 L7.27272727,27.2727273 L7.27272727,23.6363636 L25.4545455,23.6363636 L25.4545455,27.2727273 Z M25.4545455,20 L7.27272727,20 L7.27272727,16.3636364 L25.4545455,16.3636364 L25.4545455,20 Z" d="M30.9090909,7.27272727 L1.81818182,7.27272727 C0.814545455,7.27272727 0,8.08727273 0,9.09090909 L0,41.8181818 C0,42.8218182 0.814545455,43.6363636 1.81818182,43.6363636 L30.9090909,43.6363636 C31.9127273,43.6363636 32.7272727,42.8218182 32.7272727,41.8181818 L32.7272727,9.09090909 C32.7272727,8.08727273 31.9127273,7.27272727 30.9090909,7.27272727 Z M18.1818182,34.5454545 L7.27272727,34.5454545 L7.27272727,30.9090909 L18.1818182,30.9090909 L18.1818182,34.5454545 Z M25.4545455,27.2727273 L7.27272727,27.2727273 L7.27272727,23.6363636 L25.4545455,23.6363636 L25.4545455,27.2727273 Z M25.4545455,20 L7.27272727,20 L7.27272727,16.3636364 L25.4545455,16.3636364 L25.4545455,20 Z"
id="Shape"></path> id="Shape"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.pp || "Privacy Policy" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.pp || "Privacy Policy" %></span>
</a> </a>
</li> </li>
<% if(req.session.user && config.ownerIDs?.includes(req.session.user.id)) { %> <% if(req.session.user && config.ownerIDs?.includes(req.session.user.id)) { %>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link <% if(now == 'admin'){ %>active" <a class="nav-link <% if(now == 'admin'){ %>active"
<% } else { %>" href='/admin' <% } else { %>" href='/admin'
<% } %> <% } %>
> >
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg class="text-dark" width="16px" height="16px" viewBox="0 0 42 42" version="1.1" <svg class="text-dark" width="16px" height="16px" viewBox="0 0 42 42" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Rounded-Icons" transform="translate(-2319.000000, -291.000000)" <g id="Rounded-Icons" transform="translate(-2319.000000, -291.000000)"
fill="#FFFFFF" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)"> <g id="Icons-with-opacity" transform="translate(1716.000000, 291.000000)">
<g id="box-3d-50" transform="translate(603.000000, 0.000000)"> <g id="box-3d-50" transform="translate(603.000000, 0.000000)">
<path class="color-background" <path class="color-background"
d="M22.7597136,19.3090182 L38.8987031,11.2395234 C39.3926816,10.9925342 39.592906,10.3918611 39.3459167,9.89788265 C39.249157,9.70436312 39.0922432,9.5474453 38.8987261,9.45068056 L20.2741875,0.1378125 L20.2741875,0.1378125 C19.905375,-0.04725 19.469625,-0.04725 19.0995,0.1378125 L3.1011696,8.13815822 C2.60720568,8.38517662 2.40701679,8.98586148 2.6540352,9.4798254 C2.75080129,9.67332903 2.90771305,9.83023153 3.10122239,9.9269862 L21.8652864,19.3090182 C22.1468139,19.4497819 22.4781861,19.4497819 22.7597136,19.3090182 Z" d="M22.7597136,19.3090182 L38.8987031,11.2395234 C39.3926816,10.9925342 39.592906,10.3918611 39.3459167,9.89788265 C39.249157,9.70436312 39.0922432,9.5474453 38.8987261,9.45068056 L20.2741875,0.1378125 L20.2741875,0.1378125 C19.905375,-0.04725 19.469625,-0.04725 19.0995,0.1378125 L3.1011696,8.13815822 C2.60720568,8.38517662 2.40701679,8.98586148 2.6540352,9.4798254 C2.75080129,9.67332903 2.90771305,9.83023153 3.10122239,9.9269862 L21.8652864,19.3090182 C22.1468139,19.4497819 22.4781861,19.4497819 22.7597136,19.3090182 Z"
id="Path"></path> id="Path"></path>
<path class="color-background" <path class="color-background"
d="M23.625,22.429159 L23.625,39.8805372 C23.625,40.4328219 24.0727153,40.8805372 24.625,40.8805372 C24.7802551,40.8805372 24.9333778,40.8443874 25.0722402,40.7749511 L41.2741875,32.673375 L41.2741875,32.673375 C41.719125,32.4515625 42,31.9974375 42,31.5 L42,14.241659 C42,13.6893742 41.5522847,13.241659 41,13.241659 C40.8447549,13.241659 40.6916418,13.2778041 40.5527864,13.3472318 L24.1777864,21.5347318 C23.8390024,21.7041238 23.625,22.0503869 23.625,22.429159 Z" d="M23.625,22.429159 L23.625,39.8805372 C23.625,40.4328219 24.0727153,40.8805372 24.625,40.8805372 C24.7802551,40.8805372 24.9333778,40.8443874 25.0722402,40.7749511 L41.2741875,32.673375 L41.2741875,32.673375 C41.719125,32.4515625 42,31.9974375 42,31.5 L42,14.241659 C42,13.6893742 41.5522847,13.241659 41,13.241659 C40.8447549,13.241659 40.6916418,13.2778041 40.5527864,13.3472318 L24.1777864,21.5347318 C23.8390024,21.7041238 23.625,22.0503869 23.625,22.429159 Z"
id="Path" opacity="0.7"></path> id="Path" opacity="0.7"></path>
<path class="color-background" <path class="color-background"
d="M20.4472136,21.5347318 L1.4472136,12.0347318 C0.953235098,11.7877425 0.352562058,11.9879669 0.105572809,12.4819454 C0.0361450918,12.6208008 6.47121774e-16,12.7739139 0,12.929159 L0,30.1875 L0,30.1875 C0,30.6849375 0.280875,31.1390625 0.7258125,31.3621875 L19.5528096,40.7750766 C20.0467945,41.0220531 20.6474623,40.8218132 20.8944388,40.3278283 C20.963859,40.1889789 21,40.0358742 21,39.8806379 L21,22.429159 C21,22.0503869 20.7859976,21.7041238 20.4472136,21.5347318 Z" d="M20.4472136,21.5347318 L1.4472136,12.0347318 C0.953235098,11.7877425 0.352562058,11.9879669 0.105572809,12.4819454 C0.0361450918,12.6208008 6.47121774e-16,12.7739139 0,12.929159 L0,30.1875 L0,30.1875 C0,30.6849375 0.280875,31.1390625 0.7258125,31.3621875 L19.5528096,40.7750766 C20.0467945,41.0220531 20.6474623,40.8218132 20.8944388,40.3278283 C20.963859,40.1889789 21,40.0358742 21,39.8806379 L21,22.429159 C21,22.0503869 20.7859976,21.7041238 20.4472136,21.5347318 Z"
id="Path" opacity="0.7"></path> id="Path" opacity="0.7"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.admin || "Admin" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.admin || "Admin" %></span>
</a> </a>
</li> </li>
<% } %> <% } %>
<% if(now == 'commands'){ %> <% if(now == 'commands'){ %>
<li class="nav-item mt-3"> <li class="nav-item mt-3">
<h6 class="ps-4 ms-2 text-uppercase text-xs font-weight-bolder opacity-6"><%- req?.locales?.partials?.sidebar.commands || "Commands" %></h6> <h6 class="ps-4 ms-2 text-uppercase text-xs font-weight-bolder opacity-6"><%- req?.locales?.partials?.sidebar.commands || "Commands" %></h6>
</li> </li>
<div class="form-group" style="width: 190px; margin-left: 33px !important;"> <div class="form-group" style="width: 190px; margin-left: 33px !important;">
<div class="input-group mb-4" style="margin-bottom: 0px !important;"> <div class="input-group mb-4" style="margin-bottom: 0px !important;">
<span class="input-group-text"><i class="ni ni-zoom-split-in"></i></span> <span class="input-group-text"><i class="ni ni-zoom-split-in"></i></span>
<input class="form-control" type="text" id="searchBar" <input class="form-control" type="text" id="searchBar"
placeholder="Search for commands.."> placeholder="Search for commands..">
</div> </div>
</div> </div>
<% } %> <% } %>
<li class="nav-item mt-3"> <li class="nav-item mt-3">
<h6 class="ps-4 ms-2 text-uppercase text-xs font-weight-bolder opacity-6"><%- req?.locales?.partials?.sidebar.account || "Account pages" %></h6> <h6 class="ps-4 ms-2 text-uppercase text-xs font-weight-bolder opacity-6"><%- req?.locales?.partials?.sidebar.account || "Account pages" %></h6>
</li> </li>
<% if(!req.session.user) { %> <% if(!req.session.user) { %>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link account" href="<%= req.originalUrl %>"> <a class="nav-link account" href="<%= req.originalUrl %>">
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg width="12px" height="12px" viewBox="0 0 40 44" version="1.1" <svg width="12px" height="12px" viewBox="0 0 40 44" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<title>document</title> <title>document</title>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-1870.000000, -591.000000)" fill="#FFFFFF" <g transform="translate(-1870.000000, -591.000000)" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g transform="translate(1716.000000, 291.000000)"> <g transform="translate(1716.000000, 291.000000)">
<g transform="translate(154.000000, 300.000000)"> <g transform="translate(154.000000, 300.000000)">
<path class="color-background opacity-6" <path class="color-background opacity-6"
d="M40,40 L36.3636364,40 L36.3636364,3.63636364 L5.45454545,3.63636364 L5.45454545,0 L38.1818182,0 C39.1854545,0 40,0.814545455 40,1.81818182 L40,40 Z"> d="M40,40 L36.3636364,40 L36.3636364,3.63636364 L5.45454545,3.63636364 L5.45454545,0 L38.1818182,0 C39.1854545,0 40,0.814545455 40,1.81818182 L40,40 Z">
</path> </path>
<path class="color-background" <path class="color-background"
d="M30.9090909,7.27272727 L1.81818182,7.27272727 C0.814545455,7.27272727 0,8.08727273 0,9.09090909 L0,41.8181818 C0,42.8218182 0.814545455,43.6363636 1.81818182,43.6363636 L30.9090909,43.6363636 C31.9127273,43.6363636 32.7272727,42.8218182 32.7272727,41.8181818 L32.7272727,9.09090909 C32.7272727,8.08727273 31.9127273,7.27272727 30.9090909,7.27272727 Z M18.1818182,34.5454545 L7.27272727,34.5454545 L7.27272727,30.9090909 L18.1818182,30.9090909 L18.1818182,34.5454545 Z M25.4545455,27.2727273 L7.27272727,27.2727273 L7.27272727,23.6363636 L25.4545455,23.6363636 L25.4545455,27.2727273 Z M25.4545455,20 L7.27272727,20 L7.27272727,16.3636364 L25.4545455,16.3636364 L25.4545455,20 Z"> d="M30.9090909,7.27272727 L1.81818182,7.27272727 C0.814545455,7.27272727 0,8.08727273 0,9.09090909 L0,41.8181818 C0,42.8218182 0.814545455,43.6363636 1.81818182,43.6363636 L30.9090909,43.6363636 C31.9127273,43.6363636 32.7272727,42.8218182 32.7272727,41.8181818 L32.7272727,9.09090909 C32.7272727,8.08727273 31.9127273,7.27272727 30.9090909,7.27272727 Z M18.1818182,34.5454545 L7.27272727,34.5454545 L7.27272727,30.9090909 L18.1818182,30.9090909 L18.1818182,34.5454545 Z M25.4545455,27.2727273 L7.27272727,27.2727273 L7.27272727,23.6363636 L25.4545455,23.6363636 L25.4545455,27.2727273 Z M25.4545455,20 L7.27272727,20 L7.27272727,16.3636364 L25.4545455,16.3636364 L25.4545455,20 Z">
</path> </path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.login || "Sign In" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.login || "Sign In" %></span>
</a> </a>
</li> </li>
<% } else { %> <% } else { %>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/discord/logout?r=/?swal=loggedout"> <a class="nav-link" href="/discord/logout?r=/?swal=loggedout">
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg width="12px" height="20px" viewBox="0 0 40 40" version="1.1" <svg width="12px" height="20px" viewBox="0 0 40 40" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<title>spaceship</title> <title>spaceship</title>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-1720.000000, -592.000000)" fill="#FFFFFF" <g transform="translate(-1720.000000, -592.000000)" fill="#FFFFFF"
fill-rule="nonzero"> fill-rule="nonzero">
<g transform="translate(1716.000000, 291.000000)"> <g transform="translate(1716.000000, 291.000000)">
<g transform="translate(4.000000, 301.000000)"> <g transform="translate(4.000000, 301.000000)">
<path class="color-background" <path class="color-background"
d="M39.3,0.706666667 C38.9660984,0.370464027 38.5048767,0.192278529 38.0316667,0.216666667 C14.6516667,1.43666667 6.015,22.2633333 5.93166667,22.4733333 C5.68236407,23.0926189 5.82664679,23.8009159 6.29833333,24.2733333 L15.7266667,33.7016667 C16.2013871,34.1756798 16.9140329,34.3188658 17.535,34.065 C17.7433333,33.98 38.4583333,25.2466667 39.7816667,1.97666667 C39.8087196,1.50414529 39.6335979,1.04240574 39.3,0.706666667 Z M25.69,19.0233333 C24.7367525,19.9768687 23.3029475,20.2622391 22.0572426,19.7463614 C20.8115377,19.2304837 19.9992882,18.0149658 19.9992882,16.6666667 C19.9992882,15.3183676 20.8115377,14.1028496 22.0572426,13.5869719 C23.3029475,13.0710943 24.7367525,13.3564646 25.69,14.31 C26.9912731,15.6116662 26.9912731,17.7216672 25.69,19.0233333 L25.69,19.0233333 Z"> d="M39.3,0.706666667 C38.9660984,0.370464027 38.5048767,0.192278529 38.0316667,0.216666667 C14.6516667,1.43666667 6.015,22.2633333 5.93166667,22.4733333 C5.68236407,23.0926189 5.82664679,23.8009159 6.29833333,24.2733333 L15.7266667,33.7016667 C16.2013871,34.1756798 16.9140329,34.3188658 17.535,34.065 C17.7433333,33.98 38.4583333,25.2466667 39.7816667,1.97666667 C39.8087196,1.50414529 39.6335979,1.04240574 39.3,0.706666667 Z M25.69,19.0233333 C24.7367525,19.9768687 23.3029475,20.2622391 22.0572426,19.7463614 C20.8115377,19.2304837 19.9992882,18.0149658 19.9992882,16.6666667 C19.9992882,15.3183676 20.8115377,14.1028496 22.0572426,13.5869719 C23.3029475,13.0710943 24.7367525,13.3564646 25.69,14.31 C26.9912731,15.6116662 26.9912731,17.7216672 25.69,19.0233333 L25.69,19.0233333 Z">
</path> </path>
<path class="color-background opacity-6" <path class="color-background opacity-6"
d="M1.855,31.4066667 C3.05106558,30.2024182 4.79973884,29.7296005 6.43969145,30.1670277 C8.07964407,30.6044549 9.36054508,31.8853559 9.7979723,33.5253085 C10.2353995,35.1652612 9.76258177,36.9139344 8.55833333,38.11 C6.70666667,39.9616667 0,40 0,40 C0,40 0,33.2566667 1.855,31.4066667 Z"> d="M1.855,31.4066667 C3.05106558,30.2024182 4.79973884,29.7296005 6.43969145,30.1670277 C8.07964407,30.6044549 9.36054508,31.8853559 9.7979723,33.5253085 C10.2353995,35.1652612 9.76258177,36.9139344 8.55833333,38.11 C6.70666667,39.9616667 0,40 0,40 C0,40 0,33.2566667 1.855,31.4066667 Z">
</path> </path>
<path class="color-background opacity-6" <path class="color-background opacity-6"
d="M17.2616667,3.90166667 C12.4943643,3.07192755 7.62174065,4.61673894 4.20333333,8.04166667 C3.31200265,8.94126033 2.53706177,9.94913142 1.89666667,11.0416667 C1.5109569,11.6966059 1.61721591,12.5295394 2.155,13.0666667 L5.47,16.3833333 C8.55036617,11.4946947 12.5559074,7.25476565 17.2616667,3.90166667 L17.2616667,3.90166667 Z"> d="M17.2616667,3.90166667 C12.4943643,3.07192755 7.62174065,4.61673894 4.20333333,8.04166667 C3.31200265,8.94126033 2.53706177,9.94913142 1.89666667,11.0416667 C1.5109569,11.6966059 1.61721591,12.5295394 2.155,13.0666667 L5.47,16.3833333 C8.55036617,11.4946947 12.5559074,7.25476565 17.2616667,3.90166667 L17.2616667,3.90166667 Z">
</path> </path>
<path class="color-background opacity-6" <path class="color-background opacity-6"
d="M36.0983333,22.7383333 C36.9280725,27.5056357 35.3832611,32.3782594 31.9583333,35.7966667 C31.0587397,36.6879974 30.0508686,37.4629382 28.9583333,38.1033333 C28.3033941,38.4890431 27.4704606,38.3827841 26.9333333,37.845 L23.6166667,34.53 C28.5053053,31.4496338 32.7452344,27.4440926 36.0983333,22.7383333 L36.0983333,22.7383333 Z"> d="M36.0983333,22.7383333 C36.9280725,27.5056357 35.3832611,32.3782594 31.9583333,35.7966667 C31.0587397,36.6879974 30.0508686,37.4629382 28.9583333,38.1033333 C28.3033941,38.4890431 27.4704606,38.3827841 26.9333333,37.845 L23.6166667,34.53 C28.5053053,31.4496338 32.7452344,27.4440926 36.0983333,22.7383333 L36.0983333,22.7383333 Z">
</path> </path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.logout || "Sign Out" %></span> <span class="nav-link-text ms-1"><%- req?.locales?.partials?.sidebar.logout || "Sign Out" %></span>
</a> </a>
</li> </li>
<% } %> <% } %>
</ul> </ul>
</div> </div>
<% if(themeConfig?.premium && req.session.user) { %> <% if(themeConfig?.premium && req.session.user) { %>
<div class="sidenav-footer mx-3 pb-4" style="position: absolute;bottom: 0;"> <div class="sidenav-footer mx-3 pb-4" style="position: absolute;bottom: 0;">
<%- include('premium.ejs') %> <%- include('premium.ejs') %>
</div> </div>
<% } %> <% } %>
</aside> </aside>

View file

@ -1,71 +1,71 @@
<div class="fixed-plugin"> <div class="fixed-plugin">
<a id="themeButton" class="fixed-plugin-button text-dark position-fixed px-3 py-2"> <a id="themeButton" class="fixed-plugin-button text-dark position-fixed px-3 py-2">
<i class="fa fa-cog py-2"> </i> <i class="fa fa-cog py-2"> </i>
</a> </a>
<div class="card shadow-lg "> <div class="card shadow-lg ">
<div class="card-header pb-0 pt-3 "> <div class="card-header pb-0 pt-3 ">
<div class="float-start"> <div class="float-start">
<h5 class="mt-3 mb-0"><%- req?.locales?.partials?.settings?.title || "Site Configuration" %></h5> <h5 class="mt-3 mb-0"><%- req?.locales?.partials?.settings?.title || "Site Configuration" %></h5>
<p><%- req?.locales?.partials?.settings?.description || "Configurable Viewing Options" %></p> <p><%- req?.locales?.partials?.settings?.description || "Configurable Viewing Options" %></p>
</div> </div>
<div class="float-end mt-4"> <div class="float-end mt-4">
<button aria-label="Close Panel" class="btn btn-link text-dark p-0 fixed-plugin-close-button"> <button aria-label="Close Panel" class="btn btn-link text-dark p-0 fixed-plugin-close-button">
<i class="fa fa-close"></i> <i class="fa fa-close"></i>
</button> </button>
</div> </div>
<!-- End Toggle Button --> <!-- End Toggle Button -->
</div> </div>
<hr class="horizontal dark my-1"> <hr class="horizontal dark my-1">
<div class="card-body pt-sm-3 pt-0"> <div class="card-body pt-sm-3 pt-0">
<!-- Sidebar Backgrounds --> <!-- Sidebar Backgrounds -->
<!-- Sidenav Type --> <!-- Sidenav Type -->
<div class="mt-3"> <div class="mt-3">
<h6 class="mb-0"><%- req?.locales?.partials?.settings?.theme?.title || "Site Theme" %></h6> <h6 class="mb-0"><%- req?.locales?.partials?.settings?.theme?.title || "Site Theme" %></h6>
<p class="text-sm"><%- req?.locales?.partials?.settings?.theme?.description || "Make the site more appealing for your eyes!" %></p> <p class="text-sm"><%- req?.locales?.partials?.settings?.theme?.description || "Make the site more appealing for your eyes!" %></p>
</div> </div>
<div class="d-flex"> <div class="d-flex">
<button data-theme="auto" <button data-theme="auto"
class="theme btn bg-gradient-primary w-100 px-3 mb-2 ms-2 <% if (req.cookies?.selectedTheme == "auto") { %>active<% } %>" class="theme btn bg-gradient-primary w-100 px-3 mb-2 ms-2 <% if (req.cookies?.selectedTheme == "auto") { %>active<% } %>"
data-class="bg-white"> data-class="bg-white">
Auto Auto
</button> </button>
<button data-theme="light" <button data-theme="light"
class="theme btn bg-gradient-primary w-100 mb-2 ms-2 <% if (req.cookies?.selectedTheme == "light") { %>active<% } %>" class="theme btn bg-gradient-primary w-100 mb-2 ms-2 <% if (req.cookies?.selectedTheme == "light") { %>active<% } %>"
data-class="bg-transparent"> data-class="bg-transparent">
Light Light
</button> </button>
<button data-theme="dark" <button data-theme="dark"
class="theme btn bg-gradient-primary w-100 px-3 mb-2 ms-2 <% if (req.cookies?.selectedTheme == "dark") { %>active<% } %>" class="theme btn bg-gradient-primary w-100 px-3 mb-2 ms-2 <% if (req.cookies?.selectedTheme == "dark") { %>active<% } %>"
data-class="bg-white"> data-class="bg-white">
Dark Dark
</button> </button>
</div> </div>
<div class="mt-5"> <div class="mt-5">
<h6 class="mb-0"><%- req?.locales?.partials?.settings?.language?.title || "Site Language" %></h6> <h6 class="mb-0"><%- req?.locales?.partials?.settings?.language?.title || "Site Language" %></h6>
<p class="text-sm"><%- req?.locales?.partials?.settings?.language?.description || "Select your preferred language!" %></p> <p class="text-sm"><%- req?.locales?.partials?.settings?.language?.description || "Select your preferred language!" %></p>
</div> </div>
<div class="d-flex"> <div class="d-flex">
<select name="languages" id="lang" class="form-control"> <select name="languages" id="lang" class="form-control">
<% <%
let locales = {}; let locales = {};
locales = (themeConfig.locales) ? themeConfig.locales : themeConfig.defaultLocales; locales = (themeConfig.locales) ? themeConfig.locales : themeConfig.defaultLocales;
Object.keys(locales).forEach((lang) => { %> Object.keys(locales).forEach((lang) => { %>
<option value="<%= lang %>" <%= lang === req?.lang ? 'selected' : '' %>><%= locales[lang].name %></option> <option value="<%= lang %>" <%= lang === req?.lang ? 'selected' : '' %>><%= locales[lang].name %></option>
<% }) %> <% }) %>
</select> </select>
</div> </div>
<p class="text-sm d-xl-none d-block mt-2">You can change the sidenav type just on desktop view.</p> <p class="text-sm d-xl-none d-block mt-2">You can change the sidenav type just on desktop view.</p>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
$("#lang").change(function () { $("#lang").change(function () {
var lang = $(this).val(); var lang = $(this).val();
setCookie('lang', lang, 365); setCookie('lang', lang, 365);
location.reload() location.reload()
}); });
</script> </script>
<script src="./js/configMenu.js"></script> <script src="./js/configMenu.js"></script>

View file

@ -1,478 +1,462 @@
<!--
=========================================================
* Now UI Dashboard - v1.5.0
=========================================================
* Product Page: https://www.creative-tim.com/product/now-ui-dashboard
* Copyright 2019 Creative Tim (http://www.creative-tim.com)
* Designed by www.invisionapp.com Coded by www.creative-tim.com
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<%- include('partials/preloader.ejs', {now: 'pp'}) %> <%- include('partials/preloader.ejs', {now: 'pp'}) %>
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100" id="scroll"> <body class="g-sidenav-show bg-gray-100" id="scroll">
<%- include('partials/preload.ejs') %> <%- include('partials/preload.ejs') %>
<%- include('partials/sidebar.ejs', {config: config, now: 'pp'}) %> <%- include('partials/sidebar.ejs', {config: config, now: 'pp'}) %>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<!-- Navbar --> <!-- Navbar -->
<%- include('partials/navbar.ejs', {now: 'pp'}) %> <%- include('partials/navbar.ejs', {now: 'pp'}) %>
<!-- End Navbar --> <!-- End Navbar -->
<div class="container-fluid py-4"> <div class="container-fluid py-4">
<div class="content"> <div class="content">
<div class="row"> <div class="row">
<div class="col-md-12 mb-4"> <div class="col-md-12 mb-4">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<h4 class="card-title"><%- req?.locales?.privacyPolicy?.title || "Privacy Policy" %></h4> <h4 class="card-title"><%- req?.locales?.privacyPolicy?.title || "Privacy Policy" %></h4>
<p class="category"><%- req?.locales?.privacyPolicy?.description || "Privacy Policy and Terms of Service" %></p> <p class="category"><%- req?.locales?.privacyPolicy?.description || "Privacy Policy and Terms of Service" %></p>
</div> </div>
<div class="card-body"> <div class="card-body">
<% if (req?.locales?.privacyPolicy?.pp){ %> <% if (req?.locales?.privacyPolicy?.pp){ %>
<%- req.locales.privacyPolicy.pp %> <%- req.locales.privacyPolicy.pp %>
<% } else { %> <% } else { %>
<p>Last updated: October 10, 2021</p> <p>Last updated: October 10, 2021</p>
<p>This Privacy Policy describes Our policies and procedures on the collection, use and <p>This Privacy Policy describes Our policies and procedures on the collection, use and
disclosure of Your information when You use the Service and tells You about Your disclosure of Your information when You use the Service and tells You about Your
privacy privacy
rights and how the law protects You.</p> rights and how the law protects You.</p>
<p>We use Your Personal data to provide and improve the Service. By using the Service, <p>We use Your Personal data to provide and improve the Service. By using the Service,
You You
agree to the collection and use of information in accordance with this Privacy agree to the collection and use of information in accordance with this Privacy
Policy. Policy.
This Privacy Policy has been created with the help of the <a This Privacy Policy has been created with the help of the <a
href="https://www.termsfeed.com/privacy-policy-generator/" target="_blank">Privacy href="https://www.termsfeed.com/privacy-policy-generator/" target="_blank">Privacy
Policy Generator</a>.</p> Policy Generator</a>.</p>
<h1>Interpretation and Definitions</h1> <h1>Interpretation and Definitions</h1>
<h2>Interpretation</h2> <h2>Interpretation</h2>
<p>The words of which the initial letter is capitalized have meanings defined under the <p>The words of which the initial letter is capitalized have meanings defined under the
following conditions. The following definitions shall have the same meaning following conditions. The following definitions shall have the same meaning
regardless regardless
of whether they appear in singular or in plural.</p> of whether they appear in singular or in plural.</p>
<h2>Definitions</h2> <h2>Definitions</h2>
<p>For the purposes of this Privacy Policy:</p> <p>For the purposes of this Privacy Policy:</p>
<ul> <ul>
<li> <li>
<p><strong>Account</strong> means a unique account created for You to access our <p><strong>Account</strong> means a unique account created for You to access our
Service or parts of our Service.</p> Service or parts of our Service.</p>
</li> </li>
<li> <li>
<p><strong>Company</strong> (referred to as either "the Company", "We", "Us" or <p><strong>Company</strong> (referred to as either "the Company", "We", "Us" or
"Our" in this Agreement) refers to <%= themeConfig.websiteName %>.</p> "Our" in this Agreement) refers to <%= themeConfig.websiteName %>.</p>
</li> </li>
<li> <li>
<p><strong>Cookies</strong> are small files that are placed on Your computer, <p><strong>Cookies</strong> are small files that are placed on Your computer,
mobile mobile
device or any other device by a website, containing the details of Your device or any other device by a website, containing the details of Your
browsing browsing
history on that website among its many uses.</p> history on that website among its many uses.</p>
</li> </li>
<li> <li>
<p><strong>Country</strong> refers to: United Kingdom</p> <p><strong>Country</strong> refers to: United Kingdom</p>
</li> </li>
<li> <li>
<p><strong>Device</strong> means any device that can access the Service such as <p><strong>Device</strong> means any device that can access the Service such as
a a
computer, a cellphone or a digital tablet.</p> computer, a cellphone or a digital tablet.</p>
</li> </li>
<li> <li>
<p><strong>Personal Data</strong> is any information that relates to an <p><strong>Personal Data</strong> is any information that relates to an
identified identified
or identifiable individual.</p> or identifiable individual.</p>
</li> </li>
<li> <li>
<p><strong>Service</strong> refers to the Website.</p> <p><strong>Service</strong> refers to the Website.</p>
</li> </li>
<li> <li>
<p><strong>Service Provider</strong> means any natural or legal person who <p><strong>Service Provider</strong> means any natural or legal person who
processes processes
the data on behalf of the Company. It refers to third-party companies or the data on behalf of the Company. It refers to third-party companies or
individuals employed by the Company to facilitate the Service, to provide individuals employed by the Company to facilitate the Service, to provide
the the
Service on behalf of the Company, to perform services related to the Service Service on behalf of the Company, to perform services related to the Service
or or
to assist the Company in analyzing how the Service is used.</p> to assist the Company in analyzing how the Service is used.</p>
</li> </li>
<li> <li>
<p><strong>Third-party Social Media Service</strong> refers to any website or <p><strong>Third-party Social Media Service</strong> refers to any website or
any any
social network website through which a User can log in or create an account social network website through which a User can log in or create an account
to to
use the Service.</p> use the Service.</p>
</li> </li>
<li> <li>
<p><strong>Usage Data</strong> refers to data collected automatically, either <p><strong>Usage Data</strong> refers to data collected automatically, either
generated by the use of the Service or from the Service infrastructure generated by the use of the Service or from the Service infrastructure
itself itself
(for example, the duration of a page visit).</p> (for example, the duration of a page visit).</p>
</li> </li>
<li> <li>
<p><strong>Website</strong> refers to <%= themeConfig.websiteName %>, accessible <p><strong>Website</strong> refers to <%= themeConfig.websiteName %>, accessible
from <a href="<%= config.domain %>" rel="external nofollow noopener" from <a href="<%= config.domain %>" rel="external nofollow noopener"
target="_blank"><%= config.domain %></a></p> target="_blank"><%= config.domain %></a></p>
</li> </li>
<li> <li>
<p><strong>You</strong> means the individual accessing or using the Service, or <p><strong>You</strong> means the individual accessing or using the Service, or
the the
company, or other legal entity on behalf of which such individual is company, or other legal entity on behalf of which such individual is
accessing accessing
or using the Service, as applicable.</p> or using the Service, as applicable.</p>
</li> </li>
</ul> </ul>
<h1>Collecting and Using Your Personal Data</h1> <h1>Collecting and Using Your Personal Data</h1>
<h2>Types of Data Collected</h2> <h2>Types of Data Collected</h2>
<h3>Personal Data</h3> <h3>Personal Data</h3>
<p>While using Our Service, We may ask You to provide Us with certain personally <p>While using Our Service, We may ask You to provide Us with certain personally
identifiable information that can be used to contact or identify You. Personally identifiable information that can be used to contact or identify You. Personally
identifiable information may include, but is not limited to:</p> identifiable information may include, but is not limited to:</p>
<ul> <ul>
<li>Usage Data</li> <li>Usage Data</li>
</ul> </ul>
<h3>Usage Data</h3> <h3>Usage Data</h3>
<p>Usage Data is collected automatically when using the Service.</p> <p>Usage Data is collected automatically when using the Service.</p>
<p>Usage Data may include information such as Your Device's Internet Protocol address <p>Usage Data may include information such as Your Device's Internet Protocol address
(e.g. (e.g.
IP address), browser type, browser version, the pages of our Service that You visit, IP address), browser type, browser version, the pages of our Service that You visit,
the the
time and date of Your visit, the time spent on those pages, unique device time and date of Your visit, the time spent on those pages, unique device
identifiers identifiers
and other diagnostic data.</p> and other diagnostic data.</p>
<p>When You access the Service by or through a mobile device, We may collect certain <p>When You access the Service by or through a mobile device, We may collect certain
information automatically, including, but not limited to, the type of mobile device information automatically, including, but not limited to, the type of mobile device
You You
use, Your mobile device unique ID, the IP address of Your mobile device, Your mobile use, Your mobile device unique ID, the IP address of Your mobile device, Your mobile
operating system, the type of mobile Internet browser You use, unique device operating system, the type of mobile Internet browser You use, unique device
identifiers identifiers
and other diagnostic data.</p> and other diagnostic data.</p>
<p>We may also collect information that Your browser sends whenever You visit our <p>We may also collect information that Your browser sends whenever You visit our
Service or Service or
when You access the Service by or through a mobile device.</p> when You access the Service by or through a mobile device.</p>
<h3>Information from Third-Party Social Media Services</h3> <h3>Information from Third-Party Social Media Services</h3>
<p>The Company allows You to create an account and log in to use the Service through the <p>The Company allows You to create an account and log in to use the Service through the
following Third-party Social Media Services:</p> following Third-party Social Media Services:</p>
<ul> <ul>
<li>Google</li> <li>Google</li>
<li>Facebook</li> <li>Facebook</li>
<li>Twitter</li> <li>Twitter</li>
</ul> </ul>
<p>If You decide to register through or otherwise grant us access to a Third-Party <p>If You decide to register through or otherwise grant us access to a Third-Party
Social Social
Media Service, We may collect Personal data that is already associated with Your Media Service, We may collect Personal data that is already associated with Your
Third-Party Social Media Service's account, such as Your name, Your email address, Third-Party Social Media Service's account, such as Your name, Your email address,
Your Your
activities or Your contact list associated with that account.</p> activities or Your contact list associated with that account.</p>
<p>You may also have the option of sharing additional information with the Company <p>You may also have the option of sharing additional information with the Company
through through
Your Third-Party Social Media Service's account. If You choose to provide such Your Third-Party Social Media Service's account. If You choose to provide such
information and Personal Data, during registration or otherwise, You are giving the information and Personal Data, during registration or otherwise, You are giving the
Company permission to use, share, and store it in a manner consistent with this Company permission to use, share, and store it in a manner consistent with this
Privacy Privacy
Policy.</p> Policy.</p>
<h3>Tracking Technologies and Cookies</h3> <h3>Tracking Technologies and Cookies</h3>
<p>We use Cookies and similar tracking technologies to track the activity on Our Service <p>We use Cookies and similar tracking technologies to track the activity on Our Service
and and
store certain information. Tracking technologies used are beacons, tags, and scripts store certain information. Tracking technologies used are beacons, tags, and scripts
to to
collect and track information and to improve and analyze Our Service. The collect and track information and to improve and analyze Our Service. The
technologies technologies
We use may include:</p> We use may include:</p>
<ul> <ul>
<li><strong>Cookies or Browser Cookies.</strong> A cookie is a small file placed on <li><strong>Cookies or Browser Cookies.</strong> A cookie is a small file placed on
Your Your
Device. You can instruct Your browser to refuse all Cookies or to indicate when Device. You can instruct Your browser to refuse all Cookies or to indicate when
a a
Cookie is being sent. However, if You do not accept Cookies, You may not be able Cookie is being sent. However, if You do not accept Cookies, You may not be able
to to
use some parts of our Service. Unless you have adjusted Your browser setting so use some parts of our Service. Unless you have adjusted Your browser setting so
that that
it will refuse Cookies, our Service may use Cookies. it will refuse Cookies, our Service may use Cookies.
</li> </li>
<li><strong>Flash Cookies.</strong> Certain features of our Service may use local <li><strong>Flash Cookies.</strong> Certain features of our Service may use local
stored stored
objects (or Flash Cookies) to collect and store information about Your objects (or Flash Cookies) to collect and store information about Your
preferences preferences
or Your activity on our Service. Flash Cookies are not managed by the same or Your activity on our Service. Flash Cookies are not managed by the same
browser browser
settings as those used for Browser Cookies. For more information on how You can settings as those used for Browser Cookies. For more information on how You can
delete Flash Cookies, please read "Where can I change the settings for delete Flash Cookies, please read "Where can I change the settings for
disabling, or disabling, or
deleting local shared objects?" available at <a deleting local shared objects?" available at <a
href="https://helpx.adobe.com/flash-player/kb/disable-local-shared-objects-flash.html#main_Where_can_I_change_the_settings_for_disabling__or_deleting_local_shared_objects_" href="https://helpx.adobe.com/flash-player/kb/disable-local-shared-objects-flash.html#main_Where_can_I_change_the_settings_for_disabling__or_deleting_local_shared_objects_"
rel="external nofollow noopener" target="_blank">https://helpx.adobe.com/flash-player/kb/disable-local-shared-objects-flash.html#main_Where_can_I_change_the_settings_for_disabling__or_deleting_local_shared_objects_</a> rel="external nofollow noopener" target="_blank">https://helpx.adobe.com/flash-player/kb/disable-local-shared-objects-flash.html#main_Where_can_I_change_the_settings_for_disabling__or_deleting_local_shared_objects_</a>
</li> </li>
<li><strong>Web Beacons.</strong> Certain sections of our Service and our emails may <li><strong>Web Beacons.</strong> Certain sections of our Service and our emails may
contain small electronic files known as web beacons (also referred to as clear contain small electronic files known as web beacons (also referred to as clear
gifs, gifs,
pixel tags, and single-pixel gifs) that permit the Company, for example, to pixel tags, and single-pixel gifs) that permit the Company, for example, to
count count
users who have visited those pages or opened an email and for other related users who have visited those pages or opened an email and for other related
website website
statistics (for example, recording the popularity of a certain section and statistics (for example, recording the popularity of a certain section and
verifying verifying
system and server integrity). system and server integrity).
</li> </li>
</ul> </ul>
<p>Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your <p>Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your
personal computer or mobile device when You go offline, while Session Cookies are personal computer or mobile device when You go offline, while Session Cookies are
deleted as soon as You close Your web browser. You can learn more about cookies deleted as soon as You close Your web browser. You can learn more about cookies
here: <a here: <a
href="https://www.termsfeed.com/privacy-policy-generator/#faq-8" href="https://www.termsfeed.com/privacy-policy-generator/#faq-8"
target="_blank">Cookies by TermsFeed Generator</a>.</p> target="_blank">Cookies by TermsFeed Generator</a>.</p>
<p>We use both Session and Persistent Cookies for the purposes set out below:</p> <p>We use both Session and Persistent Cookies for the purposes set out below:</p>
<ul> <ul>
<li> <li>
<p><strong>Necessary / Essential Cookies</strong></p> <p><strong>Necessary / Essential Cookies</strong></p>
<p>Type: Session Cookies</p> <p>Type: Session Cookies</p>
<p>Administered by: Us</p> <p>Administered by: Us</p>
<p>Purpose: These Cookies are essential to provide You with services available <p>Purpose: These Cookies are essential to provide You with services available
through the Website and to enable You to use some of its features. They help through the Website and to enable You to use some of its features. They help
to to
authenticate users and prevent fraudulent use of user accounts. Without authenticate users and prevent fraudulent use of user accounts. Without
these these
Cookies, the services that You have asked for cannot be provided, and We Cookies, the services that You have asked for cannot be provided, and We
only only
use these Cookies to provide You with those services.</p> use these Cookies to provide You with those services.</p>
</li> </li>
<li> <li>
<p><strong>Cookies Policy / Notice Acceptance Cookies</strong></p> <p><strong>Cookies Policy / Notice Acceptance Cookies</strong></p>
<p>Type: Persistent Cookies</p> <p>Type: Persistent Cookies</p>
<p>Administered by: Us</p> <p>Administered by: Us</p>
<p>Purpose: These Cookies identify if users have accepted the use of cookies on <p>Purpose: These Cookies identify if users have accepted the use of cookies on
the the
Website.</p> Website.</p>
</li> </li>
<li> <li>
<p><strong>Functionality Cookies</strong></p> <p><strong>Functionality Cookies</strong></p>
<p>Type: Persistent Cookies</p> <p>Type: Persistent Cookies</p>
<p>Administered by: Us</p> <p>Administered by: Us</p>
<p>Purpose: These Cookies allow us to remember choices You make when You use the <p>Purpose: These Cookies allow us to remember choices You make when You use the
Website, such as remembering your login details or language preference. The Website, such as remembering your login details or language preference. The
purpose of these Cookies is to provide You with a more personal experience purpose of these Cookies is to provide You with a more personal experience
and and
to avoid You having to re-enter your preferences every time You use the to avoid You having to re-enter your preferences every time You use the
Website.</p> Website.</p>
</li> </li>
</ul> </ul>
<p>For more information about the cookies we use and your choices regarding cookies, <p>For more information about the cookies we use and your choices regarding cookies,
please please
visit our Cookies Policy or the Cookies section of our Privacy Policy.</p> visit our Cookies Policy or the Cookies section of our Privacy Policy.</p>
<h2>Use of Your Personal Data</h2> <h2>Use of Your Personal Data</h2>
<p>The Company may use Personal Data for the following purposes:</p> <p>The Company may use Personal Data for the following purposes:</p>
<ul> <ul>
<li> <li>
<p><strong>To provide and maintain our Service</strong>, including to monitor <p><strong>To provide and maintain our Service</strong>, including to monitor
the the
usage of our Service.</p> usage of our Service.</p>
</li> </li>
<li> <li>
<p><strong>To manage Your Account:</strong> to manage Your registration as a <p><strong>To manage Your Account:</strong> to manage Your registration as a
user of user of
the Service. The Personal Data You provide can give You access to different the Service. The Personal Data You provide can give You access to different
functionalities of the Service that are available to You as a registered functionalities of the Service that are available to You as a registered
user. user.
</p> </p>
</li> </li>
<li> <li>
<p><strong>For the performance of a contract:</strong> the development, <p><strong>For the performance of a contract:</strong> the development,
compliance compliance
and undertaking of the purchase contract for the products, items or services and undertaking of the purchase contract for the products, items or services
You You
have purchased or of any other contract with Us through the Service.</p> have purchased or of any other contract with Us through the Service.</p>
</li> </li>
<li> <li>
<p><strong>To contact You:</strong> To contact You by email, telephone calls, <p><strong>To contact You:</strong> To contact You by email, telephone calls,
SMS, SMS,
or other equivalent forms of electronic communication, such as a mobile or other equivalent forms of electronic communication, such as a mobile
application's push notifications regarding updates or informative application's push notifications regarding updates or informative
communications communications
related to the functionalities, products or contracted services, including related to the functionalities, products or contracted services, including
the the
security updates, when necessary or reasonable for their implementation.</p> security updates, when necessary or reasonable for their implementation.</p>
</li> </li>
<li> <li>
<p><strong>To provide You</strong> with news, special offers and general <p><strong>To provide You</strong> with news, special offers and general
information information
about other goods, services and events which we offer that are similar to about other goods, services and events which we offer that are similar to
those those
that you have already purchased or enquired about unless You have opted not that you have already purchased or enquired about unless You have opted not
to to
receive such information.</p> receive such information.</p>
</li> </li>
<li> <li>
<p><strong>To manage Your requests:</strong> To attend and manage Your requests <p><strong>To manage Your requests:</strong> To attend and manage Your requests
to to
Us.</p> Us.</p>
</li> </li>
<li> <li>
<p><strong>For business transfers:</strong> We may use Your information to <p><strong>For business transfers:</strong> We may use Your information to
evaluate evaluate
or conduct a merger, divestiture, restructuring, reorganization, or conduct a merger, divestiture, restructuring, reorganization,
dissolution, or dissolution, or
other sale or transfer of some or all of Our assets, whether as a going other sale or transfer of some or all of Our assets, whether as a going
concern concern
or as part of bankruptcy, liquidation, or similar proceeding, in which or as part of bankruptcy, liquidation, or similar proceeding, in which
Personal Personal
Data held by Us about our Service users is among the assets transferred.</p> Data held by Us about our Service users is among the assets transferred.</p>
</li> </li>
<li> <li>
<p><strong>For other purposes</strong>: We may use Your information for other <p><strong>For other purposes</strong>: We may use Your information for other
purposes, such as data analysis, identifying usage trends, determining the purposes, such as data analysis, identifying usage trends, determining the
effectiveness of our promotional campaigns and to evaluate and improve our effectiveness of our promotional campaigns and to evaluate and improve our
Service, products, services, marketing and your experience.</p> Service, products, services, marketing and your experience.</p>
</li> </li>
</ul> </ul>
<p>We may share Your personal information in the following situations:</p> <p>We may share Your personal information in the following situations:</p>
<ul> <ul>
<li><strong>With Service Providers:</strong> We may share Your personal information <li><strong>With Service Providers:</strong> We may share Your personal information
with with
Service Providers to monitor and analyze the use of our Service, to contact You. Service Providers to monitor and analyze the use of our Service, to contact You.
</li> </li>
<li><strong>For business transfers:</strong> We may share or transfer Your personal <li><strong>For business transfers:</strong> We may share or transfer Your personal
information in connection with, or during negotiations of, any merger, sale of information in connection with, or during negotiations of, any merger, sale of
Company assets, financing, or acquisition of all or a portion of Our business to Company assets, financing, or acquisition of all or a portion of Our business to
another company. another company.
</li> </li>
<li><strong>With Affiliates:</strong> We may share Your information with Our <li><strong>With Affiliates:</strong> We may share Your information with Our
affiliates, affiliates,
in which case we will require those affiliates to honor this Privacy Policy. in which case we will require those affiliates to honor this Privacy Policy.
Affiliates include Our parent company and any other subsidiaries, joint venture Affiliates include Our parent company and any other subsidiaries, joint venture
partners or other companies that We control or that are under common control partners or other companies that We control or that are under common control
with with
Us. Us.
</li> </li>
<li><strong>With business partners:</strong> We may share Your information with Our <li><strong>With business partners:</strong> We may share Your information with Our
business partners to offer You certain products, services or promotions. business partners to offer You certain products, services or promotions.
</li> </li>
<li><strong>With other users:</strong> when You share personal information or <li><strong>With other users:</strong> when You share personal information or
otherwise otherwise
interact in the public areas with other users, such information may be viewed by interact in the public areas with other users, such information may be viewed by
all all
users and may be publicly distributed outside. If You interact with other users users and may be publicly distributed outside. If You interact with other users
or or
register through a Third-Party Social Media Service, Your contacts on the register through a Third-Party Social Media Service, Your contacts on the
Third-Party Social Media Service may see Your name, profile, pictures and Third-Party Social Media Service may see Your name, profile, pictures and
description of Your activity. Similarly, other users will be able to view description of Your activity. Similarly, other users will be able to view
descriptions of Your activity, communicate with You and view Your profile. descriptions of Your activity, communicate with You and view Your profile.
</li> </li>
<li><strong>With Your consent</strong>: We may disclose Your personal information <li><strong>With Your consent</strong>: We may disclose Your personal information
for for
any other purpose with Your consent. any other purpose with Your consent.
</li> </li>
</ul> </ul>
<h2>Retention of Your Personal Data</h2> <h2>Retention of Your Personal Data</h2>
<p>The Company will retain Your Personal Data only for as long as is necessary for the <p>The Company will retain Your Personal Data only for as long as is necessary for the
purposes set out in this Privacy Policy. We will retain and use Your Personal Data purposes set out in this Privacy Policy. We will retain and use Your Personal Data
to to
the extent necessary to comply with our legal obligations (for example, if we are the extent necessary to comply with our legal obligations (for example, if we are
required to retain your data to comply with applicable laws), resolve disputes, and required to retain your data to comply with applicable laws), resolve disputes, and
enforce our legal agreements and policies.</p> enforce our legal agreements and policies.</p>
<p>The Company will also retain Usage Data for internal analysis purposes. Usage Data is <p>The Company will also retain Usage Data for internal analysis purposes. Usage Data is
generally retained for a shorter period of time, except when this data is used to generally retained for a shorter period of time, except when this data is used to
strengthen the security or to improve the functionality of Our Service, or We are strengthen the security or to improve the functionality of Our Service, or We are
legally obligated to retain this data for longer time periods.</p> legally obligated to retain this data for longer time periods.</p>
<h2>Transfer of Your Personal Data</h2> <h2>Transfer of Your Personal Data</h2>
<p>Your information, including Personal Data, is processed at the Company's operating <p>Your information, including Personal Data, is processed at the Company's operating
offices and in any other places where the parties involved in the processing are offices and in any other places where the parties involved in the processing are
located. It means that this information may be transferred to — and maintained on — located. It means that this information may be transferred to — and maintained on —
computers located outside of Your state, province, country or other governmental computers located outside of Your state, province, country or other governmental
jurisdiction where the data protection laws may differ than those from Your jurisdiction where the data protection laws may differ than those from Your
jurisdiction.</p> jurisdiction.</p>
<p>Your consent to this Privacy Policy followed by Your submission of such information <p>Your consent to this Privacy Policy followed by Your submission of such information
represents Your agreement to that transfer.</p> represents Your agreement to that transfer.</p>
<p>The Company will take all steps reasonably necessary to ensure that Your data is <p>The Company will take all steps reasonably necessary to ensure that Your data is
treated treated
securely and in accordance with this Privacy Policy and no transfer of Your Personal securely and in accordance with this Privacy Policy and no transfer of Your Personal
Data will take place to an organization or a country unless there are adequate Data will take place to an organization or a country unless there are adequate
controls controls
in place including the security of Your data and other personal information.</p> in place including the security of Your data and other personal information.</p>
<h2>Disclosure of Your Personal Data</h2> <h2>Disclosure of Your Personal Data</h2>
<h3>Business Transactions</h3> <h3>Business Transactions</h3>
<p>If the Company is involved in a merger, acquisition or asset sale, Your Personal Data <p>If the Company is involved in a merger, acquisition or asset sale, Your Personal Data
may may
be transferred. We will provide notice before Your Personal Data is transferred and be transferred. We will provide notice before Your Personal Data is transferred and
becomes subject to a different Privacy Policy.</p> becomes subject to a different Privacy Policy.</p>
<h3>Law enforcement</h3> <h3>Law enforcement</h3>
<p>Under certain circumstances, the Company may be required to disclose Your Personal <p>Under certain circumstances, the Company may be required to disclose Your Personal
Data Data
if required to do so by law or in response to valid requests by public authorities if required to do so by law or in response to valid requests by public authorities
(e.g. (e.g.
a court or a government agency).</p> a court or a government agency).</p>
<h3>Other legal requirements</h3> <h3>Other legal requirements</h3>
<p>The Company may disclose Your Personal Data in the good faith belief that such action <p>The Company may disclose Your Personal Data in the good faith belief that such action
is is
necessary to:</p> necessary to:</p>
<ul> <ul>
<li>Comply with a legal obligation</li> <li>Comply with a legal obligation</li>
<li>Protect and defend the rights or property of the Company</li> <li>Protect and defend the rights or property of the Company</li>
<li>Prevent or investigate possible wrongdoing in connection with the Service</li> <li>Prevent or investigate possible wrongdoing in connection with the Service</li>
<li>Protect the personal safety of Users of the Service or the public</li> <li>Protect the personal safety of Users of the Service or the public</li>
<li>Protect against legal liability</li> <li>Protect against legal liability</li>
</ul> </ul>
<h2>Security of Your Personal Data</h2> <h2>Security of Your Personal Data</h2>
<p>The security of Your Personal Data is important to Us, but remember that no method of <p>The security of Your Personal Data is important to Us, but remember that no method of
transmission over the Internet, or method of electronic storage is 100% secure. transmission over the Internet, or method of electronic storage is 100% secure.
While We While We
strive to use commercially acceptable means to protect Your Personal Data, We cannot strive to use commercially acceptable means to protect Your Personal Data, We cannot
guarantee its absolute security.</p> guarantee its absolute security.</p>
<h1>Children's Privacy</h1> <h1>Children's Privacy</h1>
<p>Our Service does not address anyone under the age of 13. We do not knowingly collect <p>Our Service does not address anyone under the age of 13. We do not knowingly collect
personally identifiable information from anyone under the age of 13. If You are a personally identifiable information from anyone under the age of 13. If You are a
parent parent
or guardian and You are aware that Your child has provided Us with Personal Data, or guardian and You are aware that Your child has provided Us with Personal Data,
please please
contact Us. If We become aware that We have collected Personal Data from anyone contact Us. If We become aware that We have collected Personal Data from anyone
under under
the age of 13 without verification of parental consent, We take steps to remove that the age of 13 without verification of parental consent, We take steps to remove that
information from Our servers.</p> information from Our servers.</p>
<p>If We need to rely on consent as a legal basis for processing Your information and <p>If We need to rely on consent as a legal basis for processing Your information and
Your Your
country requires consent from a parent, We may require Your parent's consent before country requires consent from a parent, We may require Your parent's consent before
We We
collect and use that information.</p> collect and use that information.</p>
<h1>Links to Other Websites</h1> <h1>Links to Other Websites</h1>
<p>Our Service may contain links to other websites that are not operated by Us. If You <p>Our Service may contain links to other websites that are not operated by Us. If You
click click
on a third party link, You will be directed to that third party's site. We strongly on a third party link, You will be directed to that third party's site. We strongly
advise You to review the Privacy Policy of every site You visit.</p> advise You to review the Privacy Policy of every site You visit.</p>
<p>We have no control over and assume no responsibility for the content, privacy <p>We have no control over and assume no responsibility for the content, privacy
policies or policies or
practices of any third party sites or services.</p> practices of any third party sites or services.</p>
<h1>Changes to this Privacy Policy</h1> <h1>Changes to this Privacy Policy</h1>
<p>We may update Our Privacy Policy from time to time. We will notify You of any changes <p>We may update Our Privacy Policy from time to time. We will notify You of any changes
by by
posting the new Privacy Policy on this page.</p> posting the new Privacy Policy on this page.</p>
<p>We will let You know via email and/or a prominent notice on Our Service, prior to the <p>We will let You know via email and/or a prominent notice on Our Service, prior to the
change becoming effective and update the "Last updated" date at the top of this change becoming effective and update the "Last updated" date at the top of this
Privacy Privacy
Policy.</p> Policy.</p>
<p>You are advised to review this Privacy Policy periodically for any changes. Changes <p>You are advised to review this Privacy Policy periodically for any changes. Changes
to to
this Privacy Policy are effective when they are posted on this page.</p> this Privacy Policy are effective when they are posted on this page.</p>
<h1>Contact Us</h1> <h1>Contact Us</h1>
<p>If you have any questions about this Privacy Policy, You can contact us:</p> <p>If you have any questions about this Privacy Policy, You can contact us:</p>
<ul> <ul>
<li>By email: <a <li>By email: <a
href="mailto: <%= themeConfig.supporteMail %>"><%= themeConfig.supporteMail %></a> href="mailto: <%= themeConfig.supporteMail %>"><%= themeConfig.supporteMail %></a>
</li> </li>
<% } %> <% } %>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<%- include('partials/footer.ejs', {now: 'pp'}) %> <%- include('partials/footer.ejs', {now: 'pp'}) %>
</div> </div>
</div> </div>
<%- include('partials/scripts.ejs', {now: "pp"}) %> <%- include('partials/scripts.ejs', {now: "pp"}) %>
</body> </body>

View file

@ -1,451 +1,436 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<%- include('partials/preloader.ejs', {now:'settings'}) %> <%- include("partials/preloader.ejs", {now:"settings"}) %>
<link href='/css/dashboard/settings.css' rel='stylesheet'> <link href="/css/dashboard/settings.css" rel="stylesheet">
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100"> <body class="g-sidenav-show bg-gray-100">
<%- include('partials/preload.ejs') %> <%- include("partials/preload.ejs") %>
<aside <aside
class="sidenav navbar navbar-vertical navbar-expand-xs border-0 border-radius-xl my-3 fixed-start ms-3 ps" class="sidenav navbar navbar-vertical navbar-expand-xs border-0 border-radius-xl my-3 fixed-start ms-3 ps"
style="float:left;" id="sidenav-main"> style="float:left;" id="sidenav-main">
<div id="sidebarMain"> <div id="sidebarMain">
<div class="sidenav-header"> <div class="sidenav-header">
<a onclick="toggleSidenav()"><i <a onclick="toggleSidenav()"><i
class="fas fa-times p-3 cursor-pointer text-secondary opacity-5 position-absolute end-0 top-0 d-none d-xl-none" class="fas fa-times p-3 cursor-pointer text-secondary opacity-5 position-absolute end-0 top-0 d-none d-xl-none"
aria-hidden="true" id="iconSidenav"></i></a> aria-hidden="true" id="iconSidenav"></i></a>
<a <% if(themeConfig?.icons?.sidebar?.alignCenter) { %> style="text-align: center;" <a <% if(themeConfig?.icons?.sidebar?.alignCenter) { %> style="text-align: center;"
<% } %> <% } %>
class="navbar-brand m-0" href="/"> class="navbar-brand m-0" href="/">
<img src="<%= themeConfig.icons.sidebar.lightUrl %>" class="navbar-brand-img h-100" <% <img src="<%= themeConfig.icons.sidebar.lightUrl %>" class="navbar-brand-img h-100" <%
if(themeConfig.icons.sidebar.borderRadius) { %>style="border-radius: <%- if(themeConfig.icons.sidebar.borderRadius) { %>style="border-radius: <%-
themeConfig.icons.sidebar.borderRadius %>;" themeConfig.icons.sidebar.borderRadius %>;"
<% } %> <% } %>
alt="main_logo"> alt="main_logo">
<% if(!themeConfig.icons.sidebar.hideName){ %> <% if(!themeConfig.icons.sidebar.hideName){ %>
<span class="ms-1 font-weight-bold" id="sitename"> <span class="ms-1 font-weight-bold" id="sitename">
<%= themeConfig.websiteName %> <%= themeConfig.websiteName %>
</span> </span>
<% } %> <% } %>
</a> </a>
</div> </div>
<hr class="horizontal dark mt-0"> <hr class="horizontal dark mt-0">
<div class="collapse navbar-collapse w-auto max-height-vh-80 h-80" id="sidenav-collapse-main"> <div class="collapse navbar-collapse w-auto max-height-vh-80 h-80" id="sidenav-collapse-main">
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item" style="text-align: center;"> <li class="nav-item" style="text-align: center;">
<div class="configIcon border-radius-xl" <div class="configIcon border-radius-xl"
style="margin: 0 auto;width: fit-content;text-align: center;"> style="margin: 0 auto;width: fit-content;text-align: center;">
<img class="border-radius-xl" style="width: 100px; padding: 10px;" <img class="border-radius-xl" style="width: 100px; padding: 10px;"
src="<%= gIcon %>?size=64" alt=""> src="<%= gIcon %>?size=64" alt="">
</div> </div>
<h5 style="margin-top: 10px;"> <h5 style="margin-top: 10px;">
<%= guild.name %> <%= guild.name %>
</h5> </h5>
<p style="margin: 0 !important;"><i class="fa fa-user-friends" aria-hidden="true"></i> <p style="margin: 0 !important;"><i class="fa fa-user-friends" aria-hidden="true"></i>
<%= guild.memberCount %> Members <%= guild.memberCount %> Members
</p> </p>
</li> </li>
<li class="nav-item mt-3"> <li class="nav-item mt-3">
<a class="nav-link <% if(!req.params.category) { %>active<% } %>" <a class="nav-link <% if(!req.params.category) { %>active<% } %>"
href="/settings/<%- req.params.id %>/"> href="/settings/<%- req.params.id %>/">
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<svg class="text-dark" width="16px" height="16px" viewBox="0 0 45 40" version="1.1" <svg class="text-dark" width="16px" height="16px" viewBox="0 0 45 40" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<title>shop </title> <title>shop </title>
<g id="Basic-Elements" stroke="none" stroke-width="1" fill="none" <g id="Basic-Elements" stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd"> fill-rule="evenodd">
<g id="Rounded-Icons" transform="translate(-1716.000000, -439.000000)" <g id="Rounded-Icons" transform="translate(-1716.000000, -439.000000)"
fill="#FFFFFF" fill-rule="nonzero"> fill="#FFFFFF" fill-rule="nonzero">
<g id="Icons-with-opacity" <g id="Icons-with-opacity"
transform="translate(1716.000000, 291.000000)"> transform="translate(1716.000000, 291.000000)">
<g id="shop-" transform="translate(0.000000, 148.000000)"> <g id="shop-" transform="translate(0.000000, 148.000000)">
<path class="color-background" <path class="color-background"
d="M46.7199583,10.7414583 L40.8449583,0.949791667 C40.4909749,0.360605034 39.8540131,0 39.1666667,0 L7.83333333,0 C7.1459869,0 6.50902508,0.360605034 6.15504167,0.949791667 L0.280041667,10.7414583 C0.0969176761,11.0460037 -1.23209662e-05,11.3946378 -1.23209662e-05,11.75 C-0.00758042603,16.0663731 3.48367543,19.5725301 7.80004167,19.5833333 L7.81570833,19.5833333 C9.75003686,19.5882688 11.6168794,18.8726691 13.0522917,17.5760417 C16.0171492,20.2556967 20.5292675,20.2556967 23.494125,17.5760417 C26.4604562,20.2616016 30.9794188,20.2616016 33.94575,17.5760417 C36.2421905,19.6477597 39.5441143,20.1708521 42.3684437,18.9103691 C45.1927731,17.649886 47.0084685,14.8428276 47.0000295,11.75 C47.0000295,11.3946378 46.9030823,11.0460037 46.7199583,10.7414583 Z" d="M46.7199583,10.7414583 L40.8449583,0.949791667 C40.4909749,0.360605034 39.8540131,0 39.1666667,0 L7.83333333,0 C7.1459869,0 6.50902508,0.360605034 6.15504167,0.949791667 L0.280041667,10.7414583 C0.0969176761,11.0460037 -1.23209662e-05,11.3946378 -1.23209662e-05,11.75 C-0.00758042603,16.0663731 3.48367543,19.5725301 7.80004167,19.5833333 L7.81570833,19.5833333 C9.75003686,19.5882688 11.6168794,18.8726691 13.0522917,17.5760417 C16.0171492,20.2556967 20.5292675,20.2556967 23.494125,17.5760417 C26.4604562,20.2616016 30.9794188,20.2616016 33.94575,17.5760417 C36.2421905,19.6477597 39.5441143,20.1708521 42.3684437,18.9103691 C45.1927731,17.649886 47.0084685,14.8428276 47.0000295,11.75 C47.0000295,11.3946378 46.9030823,11.0460037 46.7199583,10.7414583 Z"
id="Path" opacity="0.598981585"></path> id="Path" opacity="0.598981585"></path>
<path class="color-background" <path class="color-background"
d="M39.198,22.4912623 C37.3776246,22.4928106 35.5817531,22.0149171 33.951625,21.0951667 L33.92225,21.1107282 C31.1430221,22.6838032 27.9255001,22.9318916 24.9844167,21.7998837 C24.4750389,21.605469 23.9777983,21.3722567 23.4960833,21.1018359 L23.4745417,21.1129513 C20.6961809,22.6871153 17.4786145,22.9344611 14.5386667,21.7998837 C14.029926,21.6054643 13.533337,21.3722507 13.0522917,21.1018359 C11.4250962,22.0190609 9.63246555,22.4947009 7.81570833,22.4912623 C7.16510551,22.4842162 6.51607673,22.4173045 5.875,22.2911849 L5.875,44.7220845 C5.875,45.9498589 6.7517757,46.9451667 7.83333333,46.9451667 L19.5833333,46.9451667 L19.5833333,33.6066734 L27.4166667,33.6066734 L27.4166667,46.9451667 L39.1666667,46.9451667 C40.2482243,46.9451667 41.125,45.9498589 41.125,44.7220845 L41.125,22.2822926 C40.4887822,22.4116582 39.8442868,22.4815492 39.198,22.4912623 Z" d="M39.198,22.4912623 C37.3776246,22.4928106 35.5817531,22.0149171 33.951625,21.0951667 L33.92225,21.1107282 C31.1430221,22.6838032 27.9255001,22.9318916 24.9844167,21.7998837 C24.4750389,21.605469 23.9777983,21.3722567 23.4960833,21.1018359 L23.4745417,21.1129513 C20.6961809,22.6871153 17.4786145,22.9344611 14.5386667,21.7998837 C14.029926,21.6054643 13.533337,21.3722507 13.0522917,21.1018359 C11.4250962,22.0190609 9.63246555,22.4947009 7.81570833,22.4912623 C7.16510551,22.4842162 6.51607673,22.4173045 5.875,22.2911849 L5.875,44.7220845 C5.875,45.9498589 6.7517757,46.9451667 7.83333333,46.9451667 L19.5833333,46.9451667 L19.5833333,33.6066734 L27.4166667,33.6066734 L27.4166667,46.9451667 L39.1666667,46.9451667 C40.2482243,46.9451667 41.125,45.9498589 41.125,44.7220845 L41.125,22.2822926 C40.4887822,22.4116582 39.8442868,22.4815492 39.198,22.4912623 Z"
id="Path"></path> id="Path"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
</div> </div>
<span class="nav-link-text ms-1">Home</span> <span class="nav-link-text ms-1">Home</span>
</a> </a>
</li> </li>
<li class="nav-item mt-3"> <li class="nav-item mt-3">
<h6 class="ps-4 ms-2 text-uppercase text-xs font-weight-bolder opacity-6">Settings <h6 class="ps-4 ms-2 text-uppercase text-xs font-weight-bolder opacity-6">Settings
Categories</h6> Categories</h6>
</li> </li>
<% settings.forEach(s=> { %> <% settings.forEach(s=> { %>
<a class="<%- s.categoryId %>"> <a class="<%- s.categoryId %>">
<% if(s.premium) { %> <% if(s.premium) { %>
<div class="sidebarPremium"><i style="color: var(--colone) !important;" <div class="sidebarPremium"><i style="color: var(--colone) !important;"
class="fas fa-crown"></i></div> class="fas fa-crown"></i></div>
<% } %> <% } %>
<li class="nav-item categories" id="<%- s.categoryId %>"> <li class="nav-item categories" id="<%- s.categoryId %>">
<a class="nav-link <% if (req.params.category == s.categoryId) { %>active<% } %>" <a class="nav-link <% if (req.params.category == s.categoryId) { %>active<% } %>"
id="<%- s.categoryId %>"> id="<%- s.categoryId %>">
<% if(s.categoryImageURL) { %> <% if(s.categoryImageURL) { %>
<div <div
class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center"> class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
<img width="20px" src="<%= s.categoryImageURL %>"> <img width="20px" src="<%= s.categoryImageURL %>">
</div> </div>
<% } %> <% } %>
<span class="nav-link-text ms-1"> <span class="nav-link-text ms-1">
<%- s.categoryName %> <%- s.categoryName %>
</span> </span>
<% if(s.toggleable) { %> <% if(s.toggleable) { %>
<span style="text-align: right; width: 100%;"> <span style="text-align: right; width: 100%;">
<div class="form-check form-switch ps-0" <div class="form-check form-switch ps-0"
style="float: right !important;"> style="float: right !important;">
<input name="<%- s.categoryId %>" <input name="<%- s.categoryId %>"
category="<%- s.categoryName %>" switch="true" category="<%- s.categoryName %>" switch="true"
class="form-check-input ms-auto category-toggle" class="form-check-input ms-auto category-toggle"
style="height: 20px !important; margin-left: 10px !important;" style="height: 20px !important; margin-left: 10px !important;"
type="checkbox" id="switch-<%= s.categoryId %>" type="checkbox" id="switch-<%= s.categoryId %>"
<%=toggle[s.categoryId] ? "checked" : "" %> <%=toggle[s.categoryId] ? "checked" : "" %>
> >
<label style="z-index: 100; position: relative;" <label style="z-index: 100; position: relative;"
class="form-check-label text-body ms-3 text-truncate w-80 mb-0 d-none" class="form-check-label text-body ms-3 text-truncate w-80 mb-0 d-none"
for="switch-<%= s.categoryId %>"></label> for="switch-<%= s.categoryId %>"></label>
</div> </div>
</span> </span>
<% } %> <% } %>
</a> </a>
</li> </li>
<% }) %> <% }) %>
</ul> </ul>
</div> </div>
<% if(themeConfig?.premium && req.session.user) { %> <% if(themeConfig?.premium && req.session.user) { %>
<div class="sidenav-footer mx-3 pb-4" style="position: absolute;bottom: 0;"> <div class="sidenav-footer mx-3 pb-4" style="position: absolute;bottom: 0;">
<%- include('partials/premium.ejs') %> <%- include("partials/premium.ejs") %>
</div> </div>
<% } %> <% } %>
</div> </div>
</aside> </aside>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<nav style="padding-bottom: 0;" <nav style="padding-bottom: 0;"
class="navbar navbar-main navbar-expand-lg px-0 mx-4 shadow-none border-radius-xl pb-4" id="navbarBlur" class="navbar navbar-main navbar-expand-lg px-0 mx-4 shadow-none border-radius-xl pb-4" id="navbarBlur"
navbar-scroll="false"> navbar-scroll="false">
<div class="container-fluid py-1 px-3"> <div class="container-fluid py-1 px-3">
<nav aria-label="breadcrumb"> <nav aria-label="breadcrumb">
<ol class="breadcrumb bg-transparent mb-0 pb-0 pt-1 px-0 me-sm-6 me-5"> <ol class="breadcrumb bg-transparent mb-0 pb-0 pt-1 px-0 me-sm-6 me-5">
<li class="breadcrumb-item text-sm"><a class="opacity-9 text-dark" <li class="breadcrumb-item text-sm"><a class="opacity-9 text-dark"
href="javascript:">Pages</a> href="javascript:">Pages</a>
</li> </li>
<li class="breadcrumb-item text-sm text-dark active" aria-current="page">Dashboard</li> <li class="breadcrumb-item text-sm text-dark active" aria-current="page">Dashboard</li>
</ol> </ol>
<h6 class="font-weight-bolder mb-0">Manage Guilds</h6> <h6 class="font-weight-bolder mb-0">Manage Guilds</h6>
</nav> </nav>
<div class="collapse navbar-collapse mt-sm-0 mt-2 me-md-0 me-sm-4" id="navbar"> <div class="collapse navbar-collapse mt-sm-0 mt-2 me-md-0 me-sm-4" id="navbar">
<div class="ms-md-auto pe-md-3 d-flex align-items-center"> <div class="ms-md-auto pe-md-3 d-flex align-items-center">
</div> </div>
<ul class="navbar-nav justify-content-end"> <ul class="navbar-nav justify-content-end">
<div class="_3a41" style="display: contents;"> <div class="_3a41" style="display: contents;">
<% for(var i in req.session.guilds){ if((req.session.guilds[i].permissions & <% for(var i in req.session.guilds){ if((req.session.guilds[i].permissions &
0x00000020)==0x00000020){ if(bot.guilds.cache.get(req.session.guilds[i].id)){ const 0x00000020)==0x00000020){ if(bot.guilds.cache.get(req.session.guilds[i].id)){ const
g=bot.guilds.cache.get(req.session.guilds[i].id); let icon; if (!g.iconURL()) g=bot.guilds.cache.get(req.session.guilds[i].id); let icon; if (!g.iconURL())
icon=themeConfig.icons.noGuildIcon; else icon=g.iconURL(); let gClass="server" ; if icon=themeConfig.icons.noGuildIcon; else icon=g.iconURL(); let gClass="server" ; if
(g.id===guild.id) gClass="server activeServer" ; %> (g.id===guild.id) gClass="server activeServer" ; %>
<a href="/settings/<%- g.id %>" style="padding-right: 10px;"> <a href="/settings/<%- g.id %>" style="padding-right: 10px;">
<div class="<%- gClass %>"><img height="64" width="64" src="<%- icon %>" <div class="<%- gClass %>"><img height="64" width="64" src="<%- icon %>"
alt="<%- g.name %>"></div> alt="<%- g.name %>"></div>
</a> </a>
<% } } } %> <% } } } %>
<a href="/manage"> <a href="/manage">
<div class="server"> <div class="server">
<div class="newServer"><i class="fa fa-plus" <div class="newServer"><i class="fa fa-plus"
style="margin: 0;position: absolute;top: 50%;left: 50%;-ms-transform: translate(-50%, -50%);transform: translate(-50%, -50%);"></i> style="margin: 0;position: absolute;top: 50%;left: 50%;-ms-transform: translate(-50%, -50%);transform: translate(-50%, -50%);"></i>
</div> </div>
</div> </div>
</a> </a>
</div> </div>
<li class="nav-item d-xl-none ps-3 d-flex align-items-center"> <li class="nav-item d-xl-none ps-3 d-flex align-items-center">
<a onclick="toggleSidenav()" style="cursor: pointer;" class="nav-link text-body p-0" <a onclick="toggleSidenav()" style="cursor: pointer;" class="nav-link text-body p-0"
id="iconNavbarSidenav"> id="iconNavbarSidenav">
<div class="sidenav-toggler-inner"> <div class="sidenav-toggler-inner">
<i class="sidenav-toggler-line"></i> <i class="sidenav-toggler-line"></i>
<i class="sidenav-toggler-line"></i> <i class="sidenav-toggler-line"></i>
<i class="sidenav-toggler-line"></i> <i class="sidenav-toggler-line"></i>
</div> </div>
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</nav> </nav>
<% const images=["curved-1", "curved-2" , "curved-3" , "curved-4" , "curved-5" , "curved-6" , "curved-7" <% const images=["curved-1", "curved-2" , "curved-3" , "curved-4" , "curved-5" , "curved-6" , "curved-7"
, "curved-8" , "curved-9" , "curved-10" , "curved-11" , "curved-12" , "curved-13" , "curved-14" , "curved-8" , "curved-9" , "curved-10" , "curved-11" , "curved-12" , "curved-13" , "curved-14"
, "curved-15" , "curved-16" , "curved-17" , "curved-18" ]; const image=images[Math.floor(Math.random() * , "curved-15" , "curved-16" , "curved-17" , "curved-18" ]; const image=images[Math.floor(Math.random() *
images.length)]; %> images.length)]; %>
<div class="container-fluid"> <div class="container-fluid">
<div class="page-header min-height-300 border-radius-xl mt-4" <div class="page-header min-height-300 border-radius-xl mt-4"
style="background-image: url('/img/curved-images/<%- image %>.webp'); background-position-y: 50%;"> style="background-image: url("/img/curved-images/<%- image %>.webp"); background-position-y: 50%;">
<span class="mask bg-gradient-primary opacity-6"></span> <span class="mask bg-gradient-primary opacity-6"></span>
</div> </div>
<div class="card card-body blur shadow-blur mx-4 mt-n6 overflow-hidden"> <div class="card card-body blur shadow-blur mx-4 mt-n6 overflow-hidden">
<div class="row gx-4"> <div class="row gx-4">
<% if(gIcon) { %> <% if(gIcon) { %>
<div class="col-auto"> <div class="col-auto">
<div class="avatar avatar-xl position-relative"> <div class="avatar avatar-xl position-relative">
<img id="img" src="<%= gIcon %>" alt="profile_image" <img id="img" src="<%= gIcon %>" alt="profile_image"
class="w-100 border-radius-lg shadow-sm"> class="w-100 border-radius-lg shadow-sm">
</div> </div>
</div> </div>
<% } %> <% } %>
<div class="col-auto my-auto"> <div class="col-auto my-auto">
<div class="h-100"> <div class="h-100">
<h5 id="title" class="mb-1"> <h5 id="title" class="mb-1">
<%= guild.name %> <%= guild.name %>
</h5> </h5>
<p id="desc" class="mb-0 font-weight-bold text-sm"> <p id="desc" class="mb-0 font-weight-bold text-sm">
<b>Server ID: </b> <b>Server ID: </b>
<%= guild.id %> <%= guild.id %>
</p> </p>
</div> </div>
</div> </div>
<% if (themeConfig.leaderboard) { %> <% if (themeConfig.leaderboard) { %>
<div class="col-lg-4 col-md-6 my-sm-auto ms-sm-auto me-sm-0 mx-auto mt-3"> <div class="col-lg-4 col-md-6 my-sm-auto ms-sm-auto me-sm-0 mx-auto mt-3">
<div class="nav-wrapper position-relative end-0"> <div class="nav-wrapper position-relative end-0">
<ul class="nav nav-pills nav-fill p-1 bg-transparent" role="tablist"> <ul class="nav nav-pills nav-fill p-1 bg-transparent" role="tablist">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link mb-0 px-0 py-1" <a class="nav-link mb-0 px-0 py-1"
href="/leaderboard/<%= req.params.id %>"> href="/leaderboard/<%= req.params.id %>">
<svg class="text-dark" width="16px" height="16px" <svg class="text-dark" width="16px" height="16px"
viewBox="0 0 42 42" version="1.1" viewBox="0 0 42 42" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<g stroke="none" stroke-width="1" fill="none" <g stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd"> fill-rule="evenodd">
<g transform="translate(-2319.000000, -291.000000)" <g transform="translate(-2319.000000, -291.000000)"
fill="#FFFFFF" fill-rule="nonzero"> fill="#FFFFFF" fill-rule="nonzero">
<g transform="translate(1716.000000, 291.000000)"> <g transform="translate(1716.000000, 291.000000)">
<g transform="translate(603.000000, 0.000000)"> <g transform="translate(603.000000, 0.000000)">
<path class="color-background" <path class="color-background"
d="M22.7597136,19.3090182 L38.8987031,11.2395234 C39.3926816,10.9925342 39.592906,10.3918611 39.3459167,9.89788265 C39.249157,9.70436312 39.0922432,9.5474453 38.8987261,9.45068056 L20.2741875,0.1378125 L20.2741875,0.1378125 C19.905375,-0.04725 19.469625,-0.04725 19.0995,0.1378125 L3.1011696,8.13815822 C2.60720568,8.38517662 2.40701679,8.98586148 2.6540352,9.4798254 C2.75080129,9.67332903 2.90771305,9.83023153 3.10122239,9.9269862 L21.8652864,19.3090182 C22.1468139,19.4497819 22.4781861,19.4497819 22.7597136,19.3090182 Z"> d="M22.7597136,19.3090182 L38.8987031,11.2395234 C39.3926816,10.9925342 39.592906,10.3918611 39.3459167,9.89788265 C39.249157,9.70436312 39.0922432,9.5474453 38.8987261,9.45068056 L20.2741875,0.1378125 L20.2741875,0.1378125 C19.905375,-0.04725 19.469625,-0.04725 19.0995,0.1378125 L3.1011696,8.13815822 C2.60720568,8.38517662 2.40701679,8.98586148 2.6540352,9.4798254 C2.75080129,9.67332903 2.90771305,9.83023153 3.10122239,9.9269862 L21.8652864,19.3090182 C22.1468139,19.4497819 22.4781861,19.4497819 22.7597136,19.3090182 Z">
</path> </path>
<path class="color-background" <path class="color-background"
d="M23.625,22.429159 L23.625,39.8805372 C23.625,40.4328219 24.0727153,40.8805372 24.625,40.8805372 C24.7802551,40.8805372 24.9333778,40.8443874 25.0722402,40.7749511 L41.2741875,32.673375 L41.2741875,32.673375 C41.719125,32.4515625 42,31.9974375 42,31.5 L42,14.241659 C42,13.6893742 41.5522847,13.241659 41,13.241659 C40.8447549,13.241659 40.6916418,13.2778041 40.5527864,13.3472318 L24.1777864,21.5347318 C23.8390024,21.7041238 23.625,22.0503869 23.625,22.429159 Z" d="M23.625,22.429159 L23.625,39.8805372 C23.625,40.4328219 24.0727153,40.8805372 24.625,40.8805372 C24.7802551,40.8805372 24.9333778,40.8443874 25.0722402,40.7749511 L41.2741875,32.673375 L41.2741875,32.673375 C41.719125,32.4515625 42,31.9974375 42,31.5 L42,14.241659 C42,13.6893742 41.5522847,13.241659 41,13.241659 C40.8447549,13.241659 40.6916418,13.2778041 40.5527864,13.3472318 L24.1777864,21.5347318 C23.8390024,21.7041238 23.625,22.0503869 23.625,22.429159 Z"
opacity="0.7"></path> opacity="0.7"></path>
<path class="color-background" <path class="color-background"
d="M20.4472136,21.5347318 L1.4472136,12.0347318 C0.953235098,11.7877425 0.352562058,11.9879669 0.105572809,12.4819454 C0.0361450918,12.6208008 6.47121774e-16,12.7739139 0,12.929159 L0,30.1875 L0,30.1875 C0,30.6849375 0.280875,31.1390625 0.7258125,31.3621875 L19.5528096,40.7750766 C20.0467945,41.0220531 20.6474623,40.8218132 20.8944388,40.3278283 C20.963859,40.1889789 21,40.0358742 21,39.8806379 L21,22.429159 C21,22.0503869 20.7859976,21.7041238 20.4472136,21.5347318 Z" d="M20.4472136,21.5347318 L1.4472136,12.0347318 C0.953235098,11.7877425 0.352562058,11.9879669 0.105572809,12.4819454 C0.0361450918,12.6208008 6.47121774e-16,12.7739139 0,12.929159 L0,30.1875 L0,30.1875 C0,30.6849375 0.280875,31.1390625 0.7258125,31.3621875 L19.5528096,40.7750766 C20.0467945,41.0220531 20.6474623,40.8218132 20.8944388,40.3278283 C20.963859,40.1889789 21,40.0358742 21,39.8806379 L21,22.429159 C21,22.0503869 20.7859976,21.7041238 20.4472136,21.5347318 Z"
opacity="0.7"></path> opacity="0.7"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</svg> </svg>
<span class="ms-1">Leaderboard</span> <span class="ms-1">Leaderboard</span>
</a> </a>
</li> </li>
</div> </div>
</div> </div>
<% } %> <% } %>
</div> </div>
</div> </div>
<style> <style>
.form-switch.larger .form-check-input:checked:after { .form-switch.larger .form-check-input:checked:after {
transform: scale(1.5) translate(23px, 3px); transform: scale(1.5) translate(23px, 3px);
} }
.form-switch.larger .form-check-input::after { .form-switch.larger .form-check-input::after {
transform: scale(1.5) translate(5px, 3px); transform: scale(1.5) translate(5px, 3px);
} }
</style> </style>
<% if (!req.params.category) { %> <% if (!req.params.category) { %>
<div class="container-fluid py-4 settings"> <div class="container-fluid py-4 settings">
<div class="row"> <div class="row">
<% settings.forEach(s=> { %> <% settings.forEach(s=> { %>
<a style="color: inherit; text-decoration: none;" href="/settings/<%- req.params.id %>/<%= s.categoryId %>"> <a style="color: inherit; text-decoration: none;" href="/settings/<%- req.params.id %>/<%= s.categoryId %>">
<div style="flex: 50%;" class="item" id="divtable"> <div style="flex: 50%;" class="item" id="divtable">
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header d-flex" <div class="card-header d-flex"
style="border-radius: 10px; justify-content: space-between;"> style="border-radius: 10px; justify-content: space-between;">
<div> <div>
<h4> <h4>
<%- s.categoryName %> <%- s.categoryName %>
</h4> </h4>
<p> <p>
<%- s.categoryDescription %> <%- s.categoryDescription %>
</p> </p>
</div> </div>
<div> <div>
<% if(s.toggleable) { %> <% if(s.toggleable) { %>
<span style="text-align: right; width: 100%;"> <span style="text-align: right; width: 100%;">
<div class="form-check form-switch ps-0 larger" <div class="form-check form-switch ps-0 larger"
style="float: right !important;"> style="float: right !important;">
<input name="<%- s.categoryId %>" <input name="<%- s.categoryId %>"
category="<%- s.categoryName %>" switch="true" category="<%- s.categoryName %>" switch="true"
class="form-check-input ms-auto category-toggle" class="form-check-input ms-auto category-toggle"
style="height: 20px !important; margin-left: 10px !important; height: 30px !important; width: 60px !important;" style="height: 20px !important; margin-left: 10px !important; height: 30px !important; width: 60px !important;"
type="checkbox" id="switch-<%= s.categoryId %>" type="checkbox" id="switch-<%= s.categoryId %>"
<%=toggle[s.categoryId] ? "checked" : "" %> <%=toggle[s.categoryId] ? "checked" : "" %>
> >
<label style="z-index: 100; position: relative;" <label style="z-index: 100; position: relative;"
class="form-check-label text-body ms-3 text-truncate w-80 mb-0 d-none" class="form-check-label text-body ms-3 text-truncate w-80 mb-0 d-none"
for="switch-<%= s.categoryId %>"></label> for="switch-<%= s.categoryId %>"></label>
</div> </div>
</span> </span>
<% } %> <% } %>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</a> </a>
<% }) %> <% }) %>
</div> </div>
</div> </div>
<% } %> <% } %>
</div> </div>
<div style="padding-bottom: 100px;"> <div style="padding-bottom: 100px;">
<% settings.forEach(s=> { <% settings.forEach(s=> {
if (s.categoryId !== req.params.category) return; if (s.categoryId !== req.params.category) return;
%> %>
<script> <script>
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
$(`#title`).html(`<%- s.categoryName %>`) $(`#title`).html(`<%- s.categoryName %>`)
$(`#desc`).html(`<%- s.categoryDescription %>`) $(`#desc`).html(`<%- s.categoryDescription %>`)
<% if(s.categoryImageURL) { %> <% if(s.categoryImageURL) { %>
$("#img").attr("src", `<%- s.categoryImageURL %>`); $("#img").attr("src", `<%- s.categoryImageURL %>`);
<% } %> <% } %>
}); });
</script> </script>
<div class="container-fluid settings mb-4" id="<%= s.categoryId %>div"> <div class="container-fluid settings mb-4" id="<%= s.categoryId %>div">
<% s.categoryOptionsList.forEach( option=> { <% s.categoryOptionsList.forEach( option=> {
let Allowed = canUseList[s.categoryId][option.optionId]; let Allowed = canUseList[s.categoryId][option.optionId];
%> %>
<% if (!option.themeOptions) option.themeOptions={}; let <% if (!option.themeOptions) option.themeOptions={}; let
themeOptions=option.themeOptions; %> themeOptions=option.themeOptions; %>
<% if (themeOptions?.startNewSection?.first || !themeOptions?.startNewSection) { %> <% if (themeOptions?.startNewSection?.first || !themeOptions?.startNewSection) { %>
<div class="mt-4"> <div class="mt-4">
<div class="col-12 item starting"> <div class="col-12 item starting">
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header pb-0"> <div class="card-header pb-0">
<% if(option.optionType.type !=="collapsable" && <% if(option.optionType.type !=="collapsable" &&
option.optionType.type !=="modal" ) { if option.optionType.type !=="modal" ) { if
(!option.themeOptions?.hideOptionName || !option.optionName) (!option.themeOptions?.hideOptionName || !option.optionName)
{ %> { %>
<% if (themeOptions?.startNewSection?.first && <% if (themeOptions?.startNewSection?.first &&
themeOptions?.startNewSection?.title ) { %> themeOptions?.startNewSection?.title ) { %>
<h4> <h4>
<%- themeOptions?.startNewSection?.title %> <%- themeOptions?.startNewSection?.title %>
</h4> </h4>
<% } else { %> <% } else { %>
<h4> <h4>
<%- option.optionName %> <%- option.optionName %>
</h4> </h4>
<% } %> <% } %>
<% } %> <% } %>
<% if (!option.themeOptions?.hideOptionDesc <% if (!option.themeOptions?.hideOptionDesc
|| !option.optionDescription) { %> || !option.optionDescription) { %>
<% if <% if
(themeOptions?.startNewSection?.first (themeOptions?.startNewSection?.first
&& &&
themeOptions?.startNewSection?.description) themeOptions?.startNewSection?.description)
{ %> { %>
<a> <a>
<%- themeOptions?.startNewSection?.description <%- themeOptions?.startNewSection?.description
%> %>
</a> </a>
<% } else { %> <% } else { %>
<a> <a>
<%- option.optionDescription <%- option.optionDescription
%> %>
</a> </a>
<% } %> <% } %>
<% } } %> <% } } %>
</div> </div>
<% if(option.optionType.type !=="collapsable" && <% if(option.optionType.type !=="collapsable" &&
option.optionType.type !=="modal" ) { %> option.optionType.type !=="modal" ) { %>
<hr> <hr>
<% } %> <% } %>
<div class="card-body px-0 pt-0 pb-2" <div class="card-body px-0 pt-0 pb-2"
style="padding: 0 1.5rem 1.5rem !important;"> style="padding: 0 1.5rem 1.5rem !important;">
<% } %> <% } %>
<div class="mt-3"> <div class="mt-3">
<%- include(`components/formTypes/${option.optionType.type}.ejs`, <%- include(`components/formTypes/${option.optionType.type}.ejs`,
{option, s, Allowed}); %> {option, s, Allowed}); %>
</div> </div>
<% if (!themeOptions?.startNewSection || <% if (!themeOptions?.startNewSection ||
themeOptions?.startNewSection && themeOptions?.startNewSection &&
themeOptions?.startNewSection?.last && themeOptions?.startNewSection?.last &&
!themeOptions?.startNewSection?.first) { %> !themeOptions?.startNewSection?.first) { %>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<% } %> <% } %>
<% }); %> <% }); %>
<% }); %> <% }); %>
</div> </div>
<div id="saveChanges" <div id="saveChanges"
class="animated card card-body blur shadow-blur mx-4 mt-n6 overflow-hidden"> class="animated card card-body blur shadow-blur mx-4 mt-n6 overflow-hidden">
<div class="row gx-4"> <div class="row gx-4">
<div class="col-auto my-auto"> <div class="col-auto my-auto">
<div class="h-100"> <div class="h-100">
<h5 class="mb-1"> <h5 class="mb-1">
Changes Detected! Changes Detected!
</h5> </h5>
</div> </div>
</div> </div>
<div class="buttons col-lg-4"> <div class="buttons col-lg-4">
<div class="nav-wrapper position-relative end-0" style="width: max-content;"> <div class="nav-wrapper position-relative end-0" style="width: max-content;">
<ul class="nav nav-pills nav-fill p-1 bg-transparent" role="tablist"> <ul class="nav nav-pills nav-fill p-1 bg-transparent" role="tablist">
<li class="nav-item" style="height: min-content;"> <li class="nav-item" style="height: min-content;">
<a style="float: right; margin: 0;" class="btn" data-bs-toggle="tab" <a style="float: right; margin: 0;" class="btn" data-bs-toggle="tab"
onclick="discardChanges()" role="tab" aria-selected="false"> onclick="discardChanges()" role="tab" aria-selected="false">
<span class="ms-1">Reset</span> <span class="ms-1">Reset</span>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a style="margin: 0 20px; float: right;" class="btn bg-gradient-primary" <a style="margin: 0 20px; float: right;" class="btn bg-gradient-primary"
data-bs-toggle="tab" onclick="saveChanges()" role="tab" data-bs-toggle="tab" onclick="saveChanges()" role="tab"
aria-selected="false"> aria-selected="false">
<span class="ms-1">Save Changes</span> <span class="ms-1">Save Changes</span>
</a> </a>
</li> </li>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
<!-- Core JS Files --> <!-- Core JS Files -->
<script id="helper" category="<%= req.params.category %>" gid="<%= req.params.id %>" refresh="<%= settings.find(s => s.categoryId === req.params?.category)?.refreshOnSave || false %>" <script id="helper" category="<%= req.params.category %>" gid="<%= req.params.id %>" refresh="<%= settings.find(s => s.categoryId === req.params?.category)?.refreshOnSave || false %>"
src="/js/dashboard/functions.js"></script> src="/js/dashboard/functions.js"></script>
<script src="../assets/js/core/popper.min.js"></script> <script src="../assets/js/core/popper.min.js"></script>
<script src="../assets/js/core/bootstrap.min.js"></script> <script src="../assets/js/core/bootstrap.min.js"></script>
<script src="../assets/js/plugins/perfect-scrollbar.min.js"></script> <script src="../assets/js/plugins/perfect-scrollbar.min.js"></script>
@ -454,35 +439,35 @@
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/bootstrap.tagsinput/0.4.2/bootstrap-tagsinput.min.js"></script> <script src="https://cdn.jsdelivr.net/bootstrap.tagsinput/0.4.2/bootstrap-tagsinput.min.js"></script>
<script> <script>
var win = navigator.platform.indexOf('Win') > -1; var win = navigator.platform.indexOf("Win") > -1;
if (win && document.querySelector('#sidenav-scrollbar')) { if (win && document.querySelector("#sidenav-scrollbar")) {
var options = { var options = {
damping: '0.5' damping: "0.5"
} }
Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options); Scrollbar.init(document.querySelector("#sidenav-scrollbar"), options);
} }
</script> </script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
<% if ( req.query.error === "premiumRequired" ) { %> <% if ( req.query.error === "premiumRequired" ) { %>
sweetalert("error", "<%= themeConfig?.sweetalert?.error?.requirePremium || 'Premium is required for this category' %>", 2000); sweetalert("error", "<%= themeConfig?.sweetalert?.error?.requirePremium || "Premium is required for this category" %>", 2000);
window.history.replaceState({}, title, window.location.href.split('?')[0]); window.history.replaceState({}, title, window.location.href.split("?")[0]);
<% } %> <% } %>
$('.multiSelect').select2({ closeOnSelect: true }); $(".multiSelect").select2({ closeOnSelect: true });
$(".tags").select2({ theme: "classic", tags: true }) $(".tags").select2({ theme: "classic", tags: true })
$(".select2-selection").addClass("form-control") $(".select2-selection").addClass("form-control")
$(".select2-search__field").attr('formType', 'tagInput'); $(".select2-search__field").attr("formType", "tagInput");
}); });
function updateSlider(slideAmount, id) { function updateSlider(slideAmount, id) {
var sliderDiv = document.getElementById(`value_${id}`); var sliderDiv = document.getElementById(`value_${id}`);
sliderDiv.innerHTML = slideAmount; sliderDiv.innerHTML = slideAmount;
} }
</script> </script>
<!-- Github buttons --> <!-- Github buttons -->
<script async defer src="https://buttons.github.io/buttons.js"></script> <script async defer src="https://buttons.github.io/buttons.js"></script>
<!-- Control Center for Soft Dashboard: parallax effects, scripts for the example pages etc --> <!-- Control Center for Soft Dashboard: parallax effects, scripts for the example pages etc -->
<%- include('partials/scripts.ejs', {now: "settings" }) %> <%- include("partials/scripts.ejs", {now: "settings" }) %>
</body> </body>
</html> </html>

View file

@ -1,18 +1,3 @@
<!--
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (https://www.creative-tim.com/license)
* Coded by Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<%- include('partials/preloader.ejs', {now:'index', req: req}) %> <%- include('partials/preloader.ejs', {now:'index', req: req}) %>
@ -24,120 +9,120 @@ let gradone;
let gradtwo; let gradtwo;
if (currentScheme == "blue") { if (currentScheme == "blue") {
colone = "#21d4fd"; colone = "#21d4fd";
coltwo = "#2152ff"; coltwo = "#2152ff";
gradone = "rgba(33,212,253,0.1)"; gradone = "rgba(33,212,253,0.1)";
gradtwo = "rgba(33,82,255,0.1)"; gradtwo = "rgba(33,82,255,0.1)";
} }
if (currentScheme == "pink") { if (currentScheme == "pink") {
colone = "#FF0080"; colone = "#FF0080";
coltwo = "#7928CA"; coltwo = "#7928CA";
gradone = "rgba(255,0,128,0.1)"; gradone = "rgba(255,0,128,0.1)";
gradtwo = "rgba(121,40,202,0.1)"; gradtwo = "rgba(121,40,202,0.1)";
} }
if (currentScheme == "red") { if (currentScheme == "red") {
colone = "#ea0606"; colone = "#ea0606";
coltwo = "#ff667c"; coltwo = "#ff667c";
gradone = "rgba(255,102,124,0.1)"; gradone = "rgba(255,102,124,0.1)";
gradtwo = "rgba(234,6,6,0.1)"; gradtwo = "rgba(234,6,6,0.1)";
} }
if (currentScheme == "green") { if (currentScheme == "green") {
colone = "#17ad37"; colone = "#17ad37";
coltwo = "#98ec2d"; coltwo = "#98ec2d";
gradone = "rgba(23,173,55,0.1)"; gradone = "rgba(23,173,55,0.1)";
gradtwo = "rgba(152,236,45,0.1)"; gradtwo = "rgba(152,236,45,0.1)";
} }
if (currentScheme == "yellow") { if (currentScheme == "yellow") {
colone = "#f53939"; colone = "#f53939";
coltwo = "#fbcf33"; coltwo = "#fbcf33";
gradone = "rgba(245,57,57,0.1)"; gradone = "rgba(245,57,57,0.1)";
gradtwo = "rgba(251,207,51,0.1)"; gradtwo = "rgba(251,207,51,0.1)";
} }
if (currentScheme == "dark") { if (currentScheme == "dark") {
colone = "#141727"; colone = "#141727";
coltwo = "#3A416F"; coltwo = "#3A416F";
gradone = "rgba(20,23,39,0.1)"; gradone = "rgba(20,23,39,0.1)";
gradtwo = "rgba(58,65,111,0.1)"; gradtwo = "rgba(58,65,111,0.1)";
} }
if (currentScheme == "custom") { if (currentScheme == "custom") {
colone = themeConfig.themeColors.primaryColor; colone = themeConfig.themeColors.primaryColor;
coltwo = themeConfig.themeColors.secondaryColor; coltwo = themeConfig.themeColors.secondaryColor;
gradone = hexToRgbA(themeConfig.themeColors.primaryColor, 0.1); gradone = hexToRgbA(themeConfig.themeColors.primaryColor, 0.1);
gradtwo = hexToRgbA(themeConfig.themeColors.secondaryColor, 0.1); gradtwo = hexToRgbA(themeConfig.themeColors.secondaryColor, 0.1);
} }
function hexToRgbA(hex){ function hexToRgbA(hex){
var c; var c;
if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){ if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){
c= hex.substring(1).split(''); c= hex.substring(1).split('');
if(c.length== 3){ if(c.length== 3){
c= [c[0], c[0], c[1], c[1], c[2], c[2]]; c= [c[0], c[0], c[1], c[1], c[2], c[2]];
} }
c= '0x'+c.join(''); c= '0x'+c.join('');
return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+',1)'; return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+',1)';
} }
throw new Error('Bad Hex'); throw new Error('Bad Hex');
} }
%> %>
<head> <head>
<style> <style>
.unselectable { .unselectable {
-webkit-user-select: none; -webkit-user-select: none;
-webkit-touch-callout: none; -webkit-touch-callout: none;
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
} }
</style> </style>
<%- themeConfig?.customHtml %> <%- themeConfig?.customHtml %>
</head> </head>
<body class="g-sidenav-show bg-gray-100" id="scroll"> <body class="g-sidenav-show bg-gray-100" id="scroll">
<%- include('partials/preload.ejs') %> <%- include('partials/preload.ejs') %>
<%- include('partials/sidebar.ejs', {config: config, now:'shards'}) %> <%- include('partials/sidebar.ejs', {config: config, now:'shards'}) %>
<div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100"> <div class="main-content position-relative bg-gray-100 max-height-vh-100 h-100">
<!-- Navbar --> <!-- Navbar -->
<%- include('partials/navbar.ejs', {now:'shards'}) %> <%- include('partials/navbar.ejs', {now:'shards'}) %>
<!-- End Navbar --> <!-- End Navbar -->
<% let image; if (themeConfig.shardspage.backgroundUrl) { image=themeConfig.shardspage.backgroundUrl } else { const images=["curved-1", "curved-2" , "curved-3" , "curved-4" , "curved-5" , "curved-6" , "curved-7" <% let image; if (themeConfig.shardspage.backgroundUrl) { image=themeConfig.shardspage.backgroundUrl } else { const images=["curved-1", "curved-2" , "curved-3" , "curved-4" , "curved-5" , "curved-6" , "curved-7"
, "curved-8" , "curved-9" , "curved-10" , "curved-11" , "curved-12" , "curved-13" , "curved-14" , "curved-8" , "curved-9" , "curved-10" , "curved-11" , "curved-12" , "curved-13" , "curved-14"
, "curved-15" , "curved-16" , "curved-17" , "curved-18" ]; image="/img/curved-images/" + images[Math.floor(Math.random() * , "curved-15" , "curved-16" , "curved-17" , "curved-18" ]; image="/img/curved-images/" + images[Math.floor(Math.random() *
images.length)]+ ".webp";} %> images.length)]+ ".webp";} %>
<div class="container-fluid"> <div class="container-fluid">
<div class="page-header min-height-300 border-radius-xl mt-4" <div class="page-header min-height-300 border-radius-xl mt-4"
style="background-image: url('<%- image %>'); background-position-y: 50%;"> style="background-image: url('<%- image %>'); background-position-y: 50%;">
<span class="mask bg-gradient-primary opacity-6"></span> <span class="mask bg-gradient-primary opacity-6"></span>
</div> </div>
<div class="card card-body blur shadow-blur mx-4 mt-n6 overflow-hidden"> <div class="card card-body blur shadow-blur mx-4 mt-n6 overflow-hidden">
<div class="row gx-4"> <div class="row gx-4">
<div class="col-auto"> <div class="col-auto">
<div class="avatar avatar-xl position-relative"> <div class="avatar avatar-xl position-relative">
<img id="img" src="<%- themeConfig.icons.sidebar.darkUrl %>" alt="profile_image" <img id="img" src="<%- themeConfig.icons.sidebar.darkUrl %>" alt="profile_image"
class="w-100 border-radius-lg shadow-sm"> class="w-100 border-radius-lg shadow-sm">
</div> </div>
</div> </div>
<div class="col-auto my-auto"> <div class="col-auto my-auto">
<div class="h-100"> <div class="h-100">
<h5 id="title" class="mb-1"> <h5 id="title" class="mb-1">
Bot Shards Status Bot Shards Status
</h5> </h5>
<p id="desc" class="mb-0 font-weight-bold text-sm"> <p id="desc" class="mb-0 font-weight-bold text-sm">
<b>Total Shards: </b> <b>Total Shards: </b>
<span id="totalshards">Loading</span> <span id="totalshards">Loading</span>
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row mt-4"> <div class="row mt-4">
<div class="container"> <div class="container">
<div class="row" style="row-gap: 1rem;" id="shardlist"> <div class="row" style="row-gap: 1rem;" id="shardlist">
<span> <span>
Loading... Loading...
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<%- include('partials/footer.ejs') %> <%- include('partials/footer.ejs') %>
</div> </div>
</main> </main>
</div> </div>
@ -145,169 +130,169 @@ function hexToRgbA(hex){
<%- include('partials/scripts.ejs', {now: "shards"}) %> <%- include('partials/scripts.ejs', {now: "shards"}) %>
<script> <script>
let graphs = {}; let graphs = {};
async function updateshards(first){ async function updateshards(first){
let timeout let timeout
await $.get("/shards/get", function(data, status){ await $.get("/shards/get", function(data, status){
if (first) if (first)
$('#shardlist').empty() $('#shardlist').empty()
data = data.sort((a, b) => a.id - b.id); data = data.sort((a, b) => a.id - b.id);
$('#totalshards').html(data.length) $('#totalshards').html(data.length)
if (!first) { if (!first) {
for (const shard in data) { for (const shard in data) {
const shardObj = data[shard]; const shardObj = data[shard];
$(`userCount-${shardObj.id}`).html(shardObj.users) $(`userCount-${shardObj.id}`).html(shardObj.users)
$(`serverCount-${shardObj.id}`).html(shardObj.servers) $(`serverCount-${shardObj.id}`).html(shardObj.servers)
$(`channelCount-${shardObj.id}`).html(shardObj.channels) $(`channelCount-${shardObj.id}`).html(shardObj.channels)
const graph = Chart.getChart(`chart-line-${shardObj.id}`) const graph = Chart.getChart(`chart-line-${shardObj.id}`)
graph.data.datasets[0].data = data[shard].ping; graph.data.datasets[0].data = data[shard].ping;
graph.update(); graph.update();
} }
} }
if (first) if (first)
for (const shard in data) { for (const shard in data) {
let row = $(` let row = $(`
<div class="col-sm-12 col-md-6"> <div class="col-sm-12 col-md-6">
<div class="card"> <div class="card">
<div class="card-body p-3"> <div class="card-body p-3">
<div class="d-flex flex-column h-100"> <div class="d-flex flex-column h-100">
<p class="mb-1 pt-2 text-bold">Shard - ${data[shard].id}</p> <p class="mb-1 pt-2 text-bold">Shard - ${data[shard].id}</p>
<div class="m-0 d-flex" style="gap: 5px;"> <div class="m-0 d-flex" style="gap: 5px;">
<i class="ni ni-circle-08 align-self-center"></i> Users: <span id="userCount-${data[shard].id}">${data[shard].users.toLocaleString()}</span><br> <i class="ni ni-circle-08 align-self-center"></i> Users: <span id="userCount-${data[shard].id}">${data[shard].users.toLocaleString()}</span><br>
</div> </div>
<div class="m-0 d-flex" style="gap: 5px;"> <div class="m-0 d-flex" style="gap: 5px;">
<i class="ni ni-laptop align-self-center"></i> Servers: <span id="serverCount-${data[shard].id}">${data[shard].guilds.toLocaleString()}</span><br> <i class="ni ni-laptop align-self-center"></i> Servers: <span id="serverCount-${data[shard].id}">${data[shard].guilds.toLocaleString()}</span><br>
</div> </div>
<div class="m-0 d-flex" style="gap: 5px;"> <div class="m-0 d-flex" style="gap: 5px;">
<i class="ni ni-collection align-self-center"></i> Channels: <span id="channelCount-${data[shard].id}">${data[shard].channels.toLocaleString()}</span><br> <i class="ni ni-collection align-self-center"></i> Channels: <span id="channelCount-${data[shard].id}">${data[shard].channels.toLocaleString()}</span><br>
</div> </div>
<div class="chart-container"> <div class="chart-container">
<canvas id="chart-line-${data[shard].id}" class="chart-canvas"></canvas> <canvas id="chart-line-${data[shard].id}" class="chart-canvas"></canvas>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
`) `)
$('#shardlist').append(row.clone(true)) $('#shardlist').append(row.clone(true))
} }
if (first) { if (first) {
for (const shard in data) { for (const shard in data) {
const graph = createGraph(data[shard]); const graph = createGraph(data[shard]);
graphs[data[shard].id] = graph; graphs[data[shard].id] = graph;
} }
} }
timeout = data[0].interval timeout = data[0].interval
}); });
return timeout return timeout
} }
window.onload = async function() { window.onload = async function() {
const interval = await updateshards(true) const interval = await updateshards(true)
setInterval(function(){ setInterval(function(){
updateshards(false) updateshards(false)
}, interval || 15000); }, interval || 15000);
}; };
</script> </script>
<script> <script>
function createGraph(shard) { function createGraph(shard) {
const { id, ping, interval } = shard; const { id, ping, interval } = shard;
const seconds = interval / 1000; const seconds = interval / 1000;
let labels = []; let labels = [];
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
labels.push(`${i * seconds}s`); labels.push(`${i * seconds}s`);
} }
let ctx = document.getElementById(`chart-line-${id}`).getContext("2d"); let ctx = document.getElementById(`chart-line-${id}`).getContext("2d");
var gradientStroke1 = ctx.createLinearGradient(0, 230, 0, 50); var gradientStroke1 = ctx.createLinearGradient(0, 230, 0, 50);
gradientStroke1.addColorStop(1, '<%= colone %>'); gradientStroke1.addColorStop(1, '<%= colone %>');
gradientStroke1.addColorStop(0.1, '<%= gradone %>'); gradientStroke1.addColorStop(0.1, '<%= gradone %>');
gradientStroke1.addColorStop(0, '<%= gradtwo %>'); //purple colors gradientStroke1.addColorStop(0, '<%= gradtwo %>'); //purple colors
const chart = new Chart(ctx, { const chart = new Chart(ctx, {
type: "line", type: "line",
data: { data: {
labels, labels,
datasets: [{ datasets: [{
label: "ping", label: "ping",
tension: 0.4, tension: 0.4,
borderWidth: 0, borderWidth: 0,
pointRadius: 0, pointRadius: 0,
borderColor: "<%- colone %>", borderColor: "<%- colone %>",
borderWidth: 3, borderWidth: 3,
backgroundColor: gradientStroke1, backgroundColor: gradientStroke1,
fill: true, fill: true,
data: ping, data: ping,
maxBarThickness: 6 maxBarThickness: 6
}, },
], ],
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
plugins: { plugins: {
legend: { legend: {
display: false, display: false,
} }
}, },
interaction: { interaction: {
intersect: false, intersect: false,
mode: 'index', mode: 'index',
}, },
scales: { scales: {
y: { y: {
suggestedMin: 0, suggestedMin: 0,
grid: { grid: {
drawBorder: false, drawBorder: false,
display: true, display: true,
drawOnChartArea: true, drawOnChartArea: true,
drawTicks: false, drawTicks: false,
borderDash: [5, 5] borderDash: [5, 5]
}, },
ticks: { ticks: {
display: true, display: true,
padding: 10, padding: 10,
color: '#b2b9bf', color: '#b2b9bf',
font: { font: {
size: 11, size: 11,
family: "Open Sans", family: "Open Sans",
style: 'normal', style: 'normal',
lineHeight: 2 lineHeight: 2
}, },
} }
}, },
x: { x: {
grid: { grid: {
drawBorder: false, drawBorder: false,
display: false, display: false,
drawOnChartArea: false, drawOnChartArea: false,
drawTicks: false, drawTicks: false,
borderDash: [5, 5] borderDash: [5, 5]
}, },
ticks: { ticks: {
display: true, display: true,
color: '#b2b9bf', color: '#b2b9bf',
padding: 20, padding: 20,
font: { font: {
size: 11, size: 11,
family: "Open Sans", family: "Open Sans",
style: 'normal', style: 'normal',
lineHeight: 2 lineHeight: 2
}, },
} }
}, },
}, },
}, },
}); });
return chart return chart
} }
</script> </script>
</body> </body>

View file

@ -14741,23 +14741,8 @@ fieldset:disabled .btn {
.d-print-none { .d-print-none {
display: none !important; display: none !important;
} }
} /*! }
=========================================================
* Soft UI Dashboard - v1.0.3
=========================================================
* Product Page: https://www.creative-tim.com/product/soft-ui-dashboard
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
* Licensed under MIT (site.license)
* Coded by www.creative-tim.com
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
.alert-primary { .alert-primary {
background-image: linear-gradient(310deg, #7928ca 0, #d6006c 100%); background-image: linear-gradient(310deg, #7928ca 0, #d6006c 100%);
} }

827
yarn.lock

File diff suppressed because it is too large Load diff