85 |
Page <%= page %> of <%= maxpages %>
86 |
Back
87 |
Next
88 |
89 |
90 | <%- include('../blocks/footer') %>
91 |
92 |
145 |
146 |
--------------------------------------------------------------------------------
/dynamic/servers/404.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Void Servers - Error 404
4 | <%- include('../blocks/header') %>
5 |
6 |
7 | <%- include('../blocks/navbar', { bot, user }) %>
8 |
9 |
10 |
13 |
14 |
Error 404 Server not found!
15 |
16 |
17 |
18 |
19 | <%- include('../blocks/footer') %>
20 |
21 |
22 |
--------------------------------------------------------------------------------
/dynamic/servers/bump.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Void Servers - Bump <%= guild.name %>
4 | <%- include('../blocks/header') %>
5 |
6 | <%- include('../blocks/navbar', { bot, user }) %>
7 |
8 | <%- include('../blocks/guildtop', { bot, user, guild }) %>
9 |
24 | <%- include('../blocks/footer') %>
25 |
26 |
27 |
--------------------------------------------------------------------------------
/dynamic/servers/edit.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Void Servers - Edit <%= guild.name %>
4 | <%- include('../blocks/header') %>
5 |
6 | <%- include('../blocks/navbar', { bot, user }) %>
7 |
8 | <%- include('../blocks/guildtop', { bot, user, guild }) %>
9 |
10 | <% if((server.description == "Short Description") || (server.long == "Long Description") || (server.invite == null)) { %>
11 |
12 |
Unfinished!
13 |
14 |
15 | <%- server.description == "Short Description" ? `Make sure to set your Short Description ! ` : '' %>
16 | <%- server.long == "Long Description" ? ` Make sure to set your Long Description ! ` : '' %>
17 | <%- server.invite == null ? ` Make sure to set your Server Invite ! ` : '' %>
18 |
19 |
20 |
21 |
22 |
23 | <% } %>
24 |
25 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
139 |
140 |
141 | Action
142 |
143 | Select One
144 | >Join Server
145 | >Server Page
146 |
147 |
148 |
149 | Save
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
166 |
167 |
168 |
169 | Modal body..
170 |
171 |
172 |
173 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
186 |
187 |
188 |
189 | Modal body..
190 |
191 |
192 |
193 |
196 |
197 |
198 |
199 | <%- include('../blocks/footer') %>
200 |
201 |
206 |
283 |
284 |
--------------------------------------------------------------------------------
/dynamic/servers/join.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Void Servers - Join <%= guild.name %>
4 | <%- include('../blocks/header') %>
5 | <%- server.invite ? `
` : '' %>
6 |
7 |
8 |
9 |
Online ⚫ <%= guild.members.cache.size %> Members" />
12 |
Online ⚫ <%= guild.members.cache.size %> Members" />
15 |
16 |
17 |
18 | <%- include('../blocks/navbar', { bot, user }) %>
19 |
20 | <%- include('../blocks/guildtop', { bot, user, guild }) %>
21 | <% if (server.password && server.invite) { %>
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | <% } else if (!server.password && server.invite) { %>
37 |
38 |
39 |
40 |
41 |
42 |
43 | Redirecting you to the discord server.
44 |
45 |
46 |
47 |
48 |
49 | <% } else if (!server.invite) { %>
50 |
51 |
52 |
53 |
54 |
55 |
56 | Please tell an administator in the server to setup the server's invite.
57 |
Back
58 |
59 |
60 |
61 |
62 |
63 | <% } %>
64 | <%- include('../blocks/footer') %>
65 |
66 |
67 |
--------------------------------------------------------------------------------
/dynamic/servers/view.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Void Servers - <%= guild.name %>
8 | <%- include('../blocks/header') %>
9 |
10 |
11 |
12 |
13 |
Online ⚫ <%= guild.memberCount %> Members" />
16 |
Online ⚫ <%= guild.memberCount %> Members" />
19 |
20 |
21 |
22 | <%- include('../blocks/navbar', { bot, user }) %>
23 |
24 | <%- include('../blocks/guildtop', { bot, user, guild }) %>
25 |
26 |
Successfully copied https://di.scord.xyz/<%= server.vanity.code %> to your clipboard!
27 |
Successfully updated your server page!
28 |
29 |
30 |
31 |
32 |
33 | Owner: <%= guild.owner.user.tag %>
34 | Members: <%= guild.memberCount %> (More)
35 |
36 |
Humans: <%= guild.members.cache.filter(m => !m.user.bot).size %>
37 | Bots: <%= guild.members.cache.filter(m => m.user.bot).size %>
38 | <%- guild.premiumSubscriptionCount != 0 ? `Boosters: ${guild.premiumSubscriptionCount} ` : '' %>
39 |
40 | Emojis: <%= guild.emojis.cache.size %> (Show)
41 |
42 | <%- guild.emojis.cache.size == 0 ? `This server has no emojis
` : '' %>
43 | <% guild.emojis.cache.forEach((e,i) => { %>
44 |
45 | <% }) %>
46 |
47 | <% if (server.categories.length != 0) { %>
48 | Categories:
49 | <% server.categories.forEach((m,i) => { %>
50 | <%- m.toProperCase() %>
51 | <% }) %>
52 |
53 | <% } %>
54 | <%- server.vanity.code ? `Vanity: di.scord.xyz/${server.vanity.code} ` : '' %>
55 | Last Bumped: <%= moment(server.lastbumped).fromNow() %>
56 | Join <%- isManaged ? `` : `Bump ` %>
57 |
58 |
59 |
71 |
72 |
78 |
79 |
80 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
Too early! Please come back in
100 |
104 |
105 |
106 |
Minutes
107 |
108 |
109 |
110 |
Seconds
111 |
112 |
(Servers can be bumped every 2 hours)
113 |
114 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
🎉 Successfully bumped <%= guild.name %> 🎉
126 |
127 |
130 |
131 |
132 |
133 |
134 |
Copied Vanity Link!
https://di.scord.xyz/<%= server.vanity.code %>
135 |
146 |
173 |
233 |
262 | <%- include('../blocks/footer') %>
263 |
264 |
265 |
--------------------------------------------------------------------------------
/dynamic/terms.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%- include('./blocks/header') %>
4 |
Void Servers - Terms
5 |
6 |
7 |
8 |
9 |
10 |
11 | <%- include('./blocks/navbar', { bot, user }) %>
12 |
13 |
14 |
17 |
18 |
Terms and Conditions Legal stuff ¯\_(ツ)_/¯
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
You agree to be bound by our website rules and any laws which may apply to this website and your participation.
29 | The website administration have the right to ban your account or guild at any time, delete any content you may have posted, and use your IP address and any data you input to the website to assist the site staff with their moderation duties.
30 | The site administration have the right to change these terms and conditions, and any site rules, at any point without warning. Whilst you may be informed of any changes, it is your responsibility to check these terms and the rules at any point.
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | <%- include('./blocks/footer') %>
39 |
40 |
41 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 | require("module-alias/register");
3 |
4 | process.env.ADMIN_USERS = String(process.env.ADMIN_USERS);
5 |
6 | const VoidClient = require('@bot/base/BotClass.js');
7 | const client = new VoidClient();
8 |
9 | client.login(process.env.DISCORD_TOKEN).catch(err => console.log(err));
10 |
11 | client.levelCache = {};
12 | client.perms = require('@bot/base/Level');
13 | for (let i = 0; i < client.perms.length; i++) {
14 | const thisLevel = client.perms[i];
15 | client.levelCache[thisLevel.name] = thisLevel.level;
16 | }
17 |
18 | String.prototype.toProperCase = function () {
19 | return this.replace(/([^\W_]+[^\s-]*) */g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
20 | };
21 |
--------------------------------------------------------------------------------
/models/reboot.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const rebootSchema = new mongoose.Schema({
4 | channelid: String,
5 | rebooted: String,
6 | messageid: String,
7 | ranuser: String,
8 | });
9 |
10 | module.exports = mongoose.model("reboot", rebootSchema);
11 |
--------------------------------------------------------------------------------
/models/servers.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const serversSchema = new mongoose.Schema({
4 | addedAt: {
5 | default: () => new Date(),
6 | type: Date
7 | },
8 | guildid: {
9 | type: String,
10 | required: true,
11 | unique: true
12 | },
13 | invite: {
14 | type: String
15 | },
16 | description: {
17 | type: String,
18 | required: true
19 | },
20 | long: {
21 | type: String,
22 | required: true
23 | },
24 | state: {
25 | type: String,
26 | default: "setup"
27 | },
28 | lastbumped: {
29 | default: () => new Date(),
30 | type: Date,
31 | },
32 | nsfw: {
33 | type: Boolean,
34 | default: false
35 | },
36 | categories: {
37 | type: Array,
38 | default: [],
39 | },
40 | password: {
41 | type: String,
42 | },
43 | vanity: {
44 | code: { type: String, default: null },
45 | action: { type: String, default: null },
46 | },
47 | styles: {
48 | background: { type: String, default: "default" },
49 | }
50 | });
51 |
52 | module.exports = mongoose.model("servers", serversSchema);
53 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "voidservers",
3 | "version": "1.0.0",
4 | "description": "A discord server list made by TheVoid.",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node index.js",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "beautify": "0.0.8",
14 | "body-parser": "^1.19.0",
15 | "colors": "^1.4.0",
16 | "cookie-parser": "^1.4.5",
17 | "discord.js": "^12.3.1",
18 | "dotenv": "^8.2.0",
19 | "ejs": "^3.1.5",
20 | "express": "^4.17.1",
21 | "klaw": "^3.0.0",
22 | "markdown-it": "^11.0.1",
23 | "module-alias": "^2.2.2",
24 | "moment": "^2.29.0",
25 | "mongoose": "^5.10.7",
26 | "node-fetch": "^2.6.1",
27 | "unirest": "^0.6.0"
28 | },
29 | "_moduleAliases": {
30 | "@root": ".",
31 | "@bot": "./bot/",
32 | "@routes": "./routes/",
33 | "@models": "./models/",
34 | "@structures": "./structures/"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/public/arc-sw.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=100)}({100:function(e,t,n){"use strict";n.r(t);var r=n(3);if("undefined"!=typeof ServiceWorkerGlobalScope){var o="https://arc.io"+r.j;importScripts(o)}else if("undefined"!=typeof SharedWorkerGlobalScope){var c="https://arc.io"+r.h;importScripts(c)}else if("undefined"!=typeof DedicatedWorkerGlobalScope){var i="https://arc.io"+r.b;importScripts(i)}},3:function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"f",function(){return c}),n.d(t,"i",function(){return i}),n.d(t,"h",function(){return a}),n.d(t,"b",function(){return d}),n.d(t,"j",function(){return f}),n.d(t,"c",function(){return p}),n.d(t,"d",function(){return s}),n.d(t,"e",function(){return l}),n.d(t,"g",function(){return m});var r={images:["bmp","jpeg","jpg","ttf","pict","svg","webp","eps","svgz","gif","png","ico","tif","tiff","bpg"],video:["mp4","3gp","webm","mkv","flv","f4v","f4p","f4bogv","drc","avi","mov","qt","wmv","amv","mpg","mp2","mpeg","mpe","m2v","m4v","3g2","gifv","mpv"],audio:["mid","midi","aac","aiff","flac","m4a","m4p","mp3","ogg","oga","mogg","opus","ra","rm","wav","webm","f4a","pat"],documents:["pdf","ps","doc","docx","ppt","pptx","xls","otf","xlsx"],other:["swf"]},o="arc:",c={COMLINK_INIT:"".concat(o,"comlink:init"),NODE_ID:"".concat(o,":nodeId"),CDN_CONFIG:"".concat(o,"cdn:config"),P2P_CLIENT_READY:"".concat(o,"cdn:ready"),STORED_FIDS:"".concat(o,"cdn:storedFids"),SW_HEALTH_CHECK:"".concat(o,"cdn:healthCheck"),SW_DEBUG:"".concat(o,"cdn:debug"),WIDGET_CONFIG:"".concat(o,"widget:config"),WIDGET_INIT:"".concat(o,"widget:init"),WIDGET_UI_LOAD:"".concat(o,"widget:load"),BROKER_LOAD:"".concat(o,"broker:load"),RENDER_FILE:"".concat(o,"inlay:renderFile"),FILE_RENDERED:"".concat(o,"inlay:fileRendered")},i="serviceWorker",a="/".concat("shared-worker",".js"),d="/".concat("dedicated-worker",".js"),f="/".concat("arc-sw-core",".js"),u="".concat("arc-sw",".js"),p=("/".concat(u),"/".concat("arc-sw"),"arc-db"),s="key-val-store",l=2**17,m="".concat("https://warden.arc.io","/mailbox/propertySession")}});
2 |
--------------------------------------------------------------------------------
/public/prismjs/prism.css:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.21.0
2 | https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+ejs+json+markup-templating */
3 | /**
4 | * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
5 | * Based on https://github.com/chriskempson/tomorrow-theme
6 | * @author Rose Pritchard
7 | */
8 |
9 | code[class*="language-"],
10 | pre[class*="language-"] {
11 | color: #ccc;
12 | background: none;
13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
14 | font-size: 1em;
15 | text-align: left;
16 | white-space: pre;
17 | word-spacing: normal;
18 | word-break: normal;
19 | word-wrap: normal;
20 | line-height: 1.5;
21 |
22 | -moz-tab-size: 4;
23 | -o-tab-size: 4;
24 | tab-size: 4;
25 |
26 | -webkit-hyphens: none;
27 | -moz-hyphens: none;
28 | -ms-hyphens: none;
29 | hyphens: none;
30 |
31 | }
32 |
33 | /* Code blocks */
34 | pre[class*="language-"] {
35 | padding: 1em;
36 | margin: .5em 0;
37 | overflow: auto;
38 | }
39 |
40 | :not(pre) > code[class*="language-"],
41 | pre[class*="language-"] {
42 | background: #2d2d2d;
43 | }
44 |
45 | /* Inline code */
46 | :not(pre) > code[class*="language-"] {
47 | padding: .1em;
48 | border-radius: .3em;
49 | white-space: normal;
50 | }
51 |
52 | .token.comment,
53 | .token.block-comment,
54 | .token.prolog,
55 | .token.doctype,
56 | .token.cdata {
57 | color: #999;
58 | }
59 |
60 | .token.punctuation {
61 | color: #ccc;
62 | }
63 |
64 | .token.tag,
65 | .token.attr-name,
66 | .token.namespace,
67 | .token.deleted {
68 | color: #e2777a;
69 | }
70 |
71 | .token.function-name {
72 | color: #6196cc;
73 | }
74 |
75 | .token.boolean,
76 | .token.number,
77 | .token.function {
78 | color: #f08d49;
79 | }
80 |
81 | .token.property,
82 | .token.class-name,
83 | .token.constant,
84 | .token.symbol {
85 | color: #f8c555;
86 | }
87 |
88 | .token.selector,
89 | .token.important,
90 | .token.atrule,
91 | .token.keyword,
92 | .token.builtin {
93 | color: #cc99cd;
94 | }
95 |
96 | .token.string,
97 | .token.char,
98 | .token.attr-value,
99 | .token.regex,
100 | .token.variable {
101 | color: #7ec699;
102 | }
103 |
104 | .token.operator,
105 | .token.entity,
106 | .token.url {
107 | color: #67cdcc;
108 | }
109 |
110 | .token.important,
111 | .token.bold {
112 | font-weight: bold;
113 | }
114 | .token.italic {
115 | font-style: italic;
116 | }
117 |
118 | .token.entity {
119 | cursor: help;
120 | }
121 |
122 | .token.inserted {
123 | color: green;
124 | }
125 |
126 |
--------------------------------------------------------------------------------
/public/prismjs/prism.js:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.21.0
2 | https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+ejs+json+markup-templating */
3 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=l.reach);k+=y.value.length,y=y.next){var b=y.value;if(t.length>n.length)return;if(!(b instanceof W)){var x=1;if(h&&y!=t.tail.prev){m.lastIndex=k;var w=m.exec(n);if(!w)break;var A=w.index+(f&&w[1]?w[1].length:0),P=w.index+w[0].length,S=k;for(S+=y.value.length;S<=A;)y=y.next,S+=y.value.length;if(S-=y.value.length,k=S,y.value instanceof W)continue;for(var E=y;E!==t.tail&&(S
l.reach&&(l.reach=j);var C=y.prev;L&&(C=I(t,C,L),k+=L.length),z(t,C,x);var _=new W(o,g?M.tokenize(O,g):O,v,O);y=I(t,C,_),N&&I(t,y,N),1"+a.content+""+a.tag+">"},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var e=M.util.currentScript();function t(){M.manual||M.highlightAll()}if(e&&(M.filename=e.src,e.hasAttribute("data-manual")&&(M.manual=!0)),!M.manual){var r=document.readyState;"loading"===r||"interactive"===r&&e&&e.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)}return M}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
4 | Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var t={};t[a]={pattern:RegExp("(<__[^]*?>)(?:))*\\]\\]>|(?!)".replace(/__/g,function(){return a}),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",t)}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;
5 | !function(e){var s=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+s.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+s.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+s.source+")*?(?=\\s*\\{)"),string:{pattern:s,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var t=e.languages.markup;t&&(t.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:t.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},t.tag))}(Prism);
6 | Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
7 | Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-flags":/[a-z]+$/,"regex-delimiter":/^\/|\/$/}},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript;
8 | !function(h){function v(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(h.languages["markup-templating"]={},{buildPlaceholders:{value:function(a,r,e,o){if(a.language===r){var c=a.tokenStack=[];a.code=a.code.replace(e,function(e){if("function"==typeof o&&!o(e))return e;for(var n,t=c.length;-1!==a.code.indexOf(n=v(r,t));)++t;return c[t]=e,n}),a.grammar=h.languages.markup}}},tokenizePlaceholders:{value:function(p,k){if(p.language===k&&p.tokenStack){p.grammar=h.languages[k];var m=0,d=Object.keys(p.tokenStack);!function e(n){for(var t=0;t=d.length);t++){var a=n[t];if("string"==typeof a||a.content&&"string"==typeof a.content){var r=d[m],o=p.tokenStack[r],c="string"==typeof a?a:a.content,i=v(k,r),u=c.indexOf(i);if(-1$/,alias:"punctuation"},comment:/^#[\s\S]*/,"language-javascript":{pattern:/[\s\S]+/,inside:e.languages.javascript}},e.hooks.add("before-tokenize",function(a){e.languages["markup-templating"].buildPlaceholders(a,"ejs",/<%(?!%)[\s\S]+?%>/g)}),e.hooks.add("after-tokenize",function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"ejs")}),e.languages.eta=e.languages.ejs}(Prism);
10 | Prism.languages.json={property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json;
11 |
--------------------------------------------------------------------------------
/public/style/style.css:
--------------------------------------------------------------------------------
1 | /* TEXT HIGHLIGHT COLOR *//* TEXT HIGHLIGHT COLOR */
2 | ::-moz-selection {
3 | color: #fff;
4 | background: rgba(160, 40, 105, 1);
5 | }
6 |
7 | ::selection {
8 | color: #fff;
9 | background: rgba(160, 40, 105, 1);
10 | }
11 | /* TEXT HIGHLIGHT COLOR *//* TEXT HIGHLIGHT COLOR */
12 |
13 | /* SCROLL BAR *//* SCROLL BAR *//* SCROLL BAR */
14 | ::-webkit-scrollbar {
15 | width: 10px;
16 | }
17 | ::-webkit-scrollbar-track {
18 | background: #F6F6F6;
19 | }
20 | ::-webkit-scrollbar-thumb {
21 | background: #aaa;
22 | }
23 | ::-webkit-scrollbar-thumb:hover {
24 | background: #989898;
25 | }
26 | /* SCROLL BAR *//* SCROLL BAR *//* SCROLL BAR */
27 |
--------------------------------------------------------------------------------
/routes/apiroutes.js:
--------------------------------------------------------------------------------
1 | const { Router } = require("express");
2 | const Servers = require("@models/servers");
3 |
4 | const route = Router();
5 |
6 | route.get('/server/:id', async (req, res) => {
7 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
8 | if (!server) return res.json({ code: 404, error: "Server does not exist" });
9 |
10 | res.json({ code: 200, server });
11 | });
12 |
13 | route.post('/run/', async (req, res) => {
14 | if(req.headers.authorization != "Debug0N") return res.status(401).json({code: 401, error: "Unauthorized"});
15 | // Route is for debugging issues.
16 | try {
17 | let e = eval(req.body.code);
18 | res.status(200).json({ code: 200, evaled: e });
19 | } catch (err) {
20 | res.status(400).json({ code: 400, error: err.message });
21 | }
22 | });
23 |
24 | module.exports = route;
25 |
--------------------------------------------------------------------------------
/routes/authroutes.js:
--------------------------------------------------------------------------------
1 | const { Router } = require("express");
2 |
3 | const Servers = require("@models/servers");
4 | const { getUser, addUser } = require("@structures/discordApi");
5 |
6 | const route = Router();
7 |
8 | route.get("/login", async (req, res, next) => {
9 | res.redirect(`https://discord.com/api/oauth2/authorize?client_id=${process.env.CLIENT_ID}&response_type=code&scope=identify%20guilds%20guilds.join&prompt=none&redirect_uri=${encodeURIComponent(process.env.DOMAIN)}/callback`)
10 | });
11 |
12 | route.get("/callback", async (req, res, next) => {
13 | if (!req.query.code) {
14 | if (req.cookies.backURL) {
15 | const url = decodeURIComponent(req.cookies.backURL);
16 | res.clearCookie("backURL");
17 | return res.redirect(url);
18 | } else {
19 | return res.redirect('/');
20 | }
21 | }
22 | const code = req.query.code;
23 | const result = await getUser({ code });
24 | if (!result) return res.redirect('/login');
25 | const [{ username, discriminator, avatar, id }, { refresh_token, access_token }] = result;
26 | res.cookie("refresh_token", refresh_token, { httpOnly: true })
27 | res.cookie("access_token", access_token, { httpOnly: true })
28 | // await addUser({client: req.app.get('client'), accessToken: access_token, userId: id}).catch(err => console.error(err));
29 | req.app.get('client').users.fetch(id);
30 | if (req.cookies.backURL) {
31 | const url = decodeURIComponent(req.cookies.backURL);
32 | res.clearCookie("backURL");
33 | res.redirect(url);
34 | } else {
35 | res.redirect('/');
36 | }
37 | });
38 |
39 | route.get("/logout", async (req, res, next) => {
40 | res.clearCookie("access_token");
41 | res.clearCookie("refresh_token");
42 | res.redirect(`/?ref=logout`);
43 | });
44 |
45 | module.exports = route;
46 |
--------------------------------------------------------------------------------
/routes/index.js:
--------------------------------------------------------------------------------
1 | const { Router } = require("express");
2 | const moment = require('moment');
3 | const Servers = require("@models/servers");
4 | const { renderTemplate } = require('@structures/middleware');
5 |
6 | const route = Router();
7 |
8 | const servers = require("@routes/serversroutes");
9 | route.use("/server", servers);
10 |
11 | const authroutes = require("@routes/authroutes");
12 | route.use("/", authroutes);
13 |
14 | const tagroutes = require("@routes/tagroutes");
15 | route.use("/", tagroutes);
16 |
17 | const meroutes = require("@routes/meroutes");
18 | route.use("/me", meroutes);
19 |
20 | const apiroutes = require("@routes/apiroutes");
21 | route.use("/api", apiroutes);
22 |
23 | route.get('/', async (req, res) => {
24 | if (req.headers.host == process.env.VANITY_DOMAIN.toString().replace(/(http(s?)):\/\//i, '')) return res.redirect(process.env.DOMAIN);
25 | let servers = await Servers.find({}, { _id: false })
26 | servers = servers.filter(server => server.state != "setup");
27 | let data = {
28 | servers: servers,
29 | };
30 | renderTemplate(res, req, 'index', data);
31 | });
32 |
33 | route.get("/join", async (req, res, next) => {
34 | res.redirect(process.env.GUILD_INVITE);
35 | });
36 |
37 | route.get("/terms", async (req, res, next) => {
38 | renderTemplate(res, req, 'terms');
39 | });
40 | route.get("/partners", async (req, res, next) => {
41 | renderTemplate(res, req, 'partners');
42 | });
43 | route.get("/privacy", async (req, res, next) => {
44 | renderTemplate(res, req, 'privacy');
45 | });
46 | route.get("/markdown", async (req, res, next) => {
47 | renderTemplate(res, req, 'markdown');
48 | });
49 |
50 | const vanityroutes = require("@routes/vanity");
51 | route.use("/", vanityroutes);
52 |
53 | Array.prototype.shuffle = function () {
54 | let a = this;
55 | for (let i = a.length - 1; i > 0; i--) {
56 | const j = Math.floor(Math.random() * (i + 1));
57 | [a[i], a[j]] = [a[j], a[i]];
58 | }
59 | return a;
60 | }
61 |
62 | module.exports = route;
63 |
--------------------------------------------------------------------------------
/routes/meroutes.js:
--------------------------------------------------------------------------------
1 | const { Router } = require("express");
2 |
3 | const Servers = require("@models/servers");
4 | const { renderTemplate } = require("@structures/middleware.js");
5 | const { getUser } = require("@structures/discordApi");
6 |
7 | const route = Router();
8 |
9 | route.get('/', async (req, res) => {
10 | res.redirect('/me/servers')
11 | })
12 |
13 | route.get('/servers', async (req, res) => {
14 | let servers = await Servers.find({}, { _id: false })
15 | servers = servers.filter(server => server.state != "deleted");
16 |
17 | let data = {
18 | servers: servers
19 | };
20 | renderTemplate(res, req, 'me/servers', data);
21 | });
22 |
23 | route.get('/settings', async (req, res) => {
24 | renderTemplate(res, req, 'me/settings');
25 | });
26 |
27 | route.get('/add', async (req, res) => {
28 | res.render('me/add');
29 | });
30 |
31 | route.get('/admin', async (req, res) => {
32 | let user;
33 | let { refresh_token, access_token } = req.cookies;
34 | if (!refresh_token) {
35 | res.cookie("backURL", req.originalUrl);
36 | return res.redirect('/login');
37 | }
38 |
39 | let result = await getUser({ access_token, refresh_token });
40 | if (!result) return res.redirect("/login");
41 | [user, { refresh_token, access_token }] = result;
42 |
43 | if (!process.env.ADMIN_USERS.includes(user.id)) return renderTemplate(res, req, 'errors/403');
44 |
45 | let servers = await Servers.find({}, { _id: false });
46 | servers = servers.filter(server => server.state != "deleted");
47 |
48 | let data = {
49 | cards: servers
50 | };
51 | renderTemplate(res, req, 'me/admin', data);
52 | });
53 |
54 | module.exports = route;
55 |
--------------------------------------------------------------------------------
/routes/serversroutes.js:
--------------------------------------------------------------------------------
1 | const { Router } = require("express");
2 |
3 | const Servers = require("@models/servers");
4 | const moment = require('moment');
5 | const { getUser } = require('@structures/discordApi');
6 | const { renderTemplate } = require("@structures/middleware.js");
7 | const md = require('markdown-it')({
8 | breaks: true
9 | });
10 |
11 | const route = Router();
12 |
13 | route.get('/:id', async (req, res, next) => {
14 | let user;
15 | let { refresh_token, access_token } = req.cookies;
16 | if (refresh_token) {
17 | let result = await getUser({ access_token, refresh_token });
18 | if (!result) return res.redirect("/login");
19 | [user, { refresh_token, access_token }] = result;
20 | }
21 |
22 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
23 | if (!server) return renderTemplate(res, req, "servers/404");
24 | if (server.state === "deleted") return renderTemplate(res, req, "servers/404");
25 |
26 | const guild = req.app.get('client').guilds.cache.get(req.params.id);
27 |
28 | var desc = `This server's description was corrupted, most likely due to an image.`;
29 | if (server.long != null) desc = md.render(server.long);
30 | server.long = desc;
31 |
32 | let isManaged = false;
33 | if (user != null) {
34 | isManaged = guild && !!guild.member(user.id) ? guild.member(user.id).permissions.has('MANAGE_GUILD') : false;
35 | if (process.env.ADMIN_USERS.includes(user.id)) isManaged = true;
36 | }
37 |
38 | let data = {
39 | server,
40 | guild,
41 | moment,
42 | isManaged,
43 | };
44 | renderTemplate(res, req, "servers/view", data);
45 | });
46 |
47 | route.get("/:id/edit", async (req, res, next) => {
48 | let user;
49 | let { refresh_token, access_token } = req.cookies;
50 | if (!refresh_token) {
51 | res.cookie("backURL", req.originalUrl);
52 | return res.redirect('/login');
53 | }
54 |
55 | let result = await getUser({ access_token, refresh_token });
56 | if (!result) return res.redirect("/login");
57 | [user, { refresh_token, access_token }] = result;
58 |
59 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
60 | if (!server) return renderTemplate(res, req, "servers/404");
61 |
62 | const guild = req.app.get('client').guilds.cache.get(req.params.id);
63 | const isManaged = guild && !!guild.member(user.id) ? guild.member(user.id).permissions.has('MANAGE_GUILD') : false;
64 | if (!isManaged && !process.env.ADMIN_USERS.includes(user.id)) return renderTemplate(res, req, 'errors/403');
65 |
66 | const categories = ["advertising", "giveaway", "meme", "bots", "developer", "fun", "social", "emotes", "support-server", "music", "stream", "roleplay", "art", "gaming", "economy", "chill", "events", "friends", "teen", "community", "new", "comedy", "youtube", "twitch"]
67 |
68 | renderTemplate(res, req, "servers/edit", { server: server, guild: guild, categories });
69 | });
70 |
71 | route.post("/:id/edit", async (req, res, next) => {
72 | let user;
73 | let { refresh_token, access_token } = req.cookies;
74 | if (!refresh_token) return res.status(403).json({ code: "NO_PERMISSION", message: "You do not have permission to access this." });
75 |
76 | let result = await getUser({ access_token, refresh_token });
77 | if (!result) return res.status(403).json({ code: "NO_PERMISSION", message: "You do not have permission to access this." });
78 | [user, { refresh_token, access_token }] = result;
79 |
80 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
81 | if (!server) return res.status(404).json({ code: "NOT_FOUND", message: "The server you tried to access was non-existant. Please check the url and try again." });
82 |
83 | const guild = req.app.get('client').guilds.cache.get(req.params.id);
84 | const isManaged = guild && !!guild.member(user.id) ? guild.member(user.id).permissions.has('MANAGE_GUILD') : false;
85 | if (!isManaged && !process.env.ADMIN_USERS.includes(user.id)) return res.status(403).json({ code: "NO_PERMISSION", message: "You do not have permission to access this." });
86 | const body = req.body;
87 | if (Object.keys(body).length == 0) return res.status(400).json({ code: "EMPTY_RESPONSE", message: "No data received. The server closed the connection without receiving any data." });
88 |
89 |
90 | if (body.vanityURL && body.vanityAction) {
91 | let servervenity = await Servers.findOne({ "vanity.code": body.vanityURL }, { _id: false })
92 | if (servervenity != null) return res.status(409).json({ code: "CONFLICT", message: "The selected vanity code already exists for another server. Please select another one, and try again." });
93 | await Servers.updateOne({ guildid: server.guildid }, { $set: { vanity: { code: body.vanityURL, action: body.vanityAction } } })
94 | return res.status(201).json({ message: "Successfully updated your vanity settings!", code: "SUCCESS", redirect: `/server/${req.params.id}/?type=edited` });
95 | }
96 | if (body.shortdesc && body.longdesc && body.invitelink) {
97 | const tags = body.tags || [];
98 | await Servers.updateOne({ guildid: server.guildid }, { $set: { state: "default", description: body.shortdesc, long: body.longdesc, invite: body.invitelink, categories: tags, styles: { background: body.backgroundStyle } } })
99 | return res.status(201).json({ message: "Successfully updated your server settings!", code: "SUCCESS", redirect: `/server/${req.params.id}/?type=edited` });
100 | }
101 | if (!body.shortdesc || !body.longdesc || !body.invitelink || !body.vanityURL || !body.vanityAction || !body.backgroundStyle) {
102 | res.status(400).json({ message: "One or more fields are missing.", code: "EMPTY_RESPONSE" });
103 | }
104 |
105 | res.status(400).json({ message: "An unexpected error occurred.", code: "UNEXPECTED_ERR" });
106 | });
107 |
108 | route.get("/:id/join", async (req, res, next) => {
109 | let user;
110 | let { refresh_token, access_token } = req.cookies;
111 | if (refresh_token) {
112 | let result = await getUser({ access_token, refresh_token });
113 | if (!result) return res.redirect("/login");
114 | [user, { refresh_token, access_token }] = result;
115 | }
116 |
117 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
118 | if (!server) return renderTemplate(res, req, "servers/404");
119 |
120 | const guild = req.app.get('client').guilds.cache.get(req.params.id);
121 |
122 | renderTemplate(res, req, "servers/join", { server: server, guild: guild });
123 | });
124 |
125 | route.get("/:id/bump", async (req, res, next) => {
126 | let user;
127 | let { refresh_token, access_token } = req.cookies;
128 | if (!refresh_token) {
129 | res.cookie("backURL", req.originalUrl);
130 | return res.redirect('/login');
131 | }
132 |
133 | let result = await getUser({ access_token, refresh_token });
134 | if (!result) return res.redirect("/login");
135 | [user, { refresh_token, access_token }] = result;
136 |
137 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
138 | if (!server) return res.sendStatus(404);
139 | const guild = req.app.get('client').guilds.cache.get(req.params.id);
140 | renderTemplate(res, req, "servers/bump", { server: server, guild: guild });
141 | });
142 |
143 | route.post('/:id/bump', async (req, res, next) => {
144 | let user;
145 | let { refresh_token, access_token } = req.cookies;
146 | if (!refresh_token) { res.cookie("backURL", req.originalUrl); return res.redirect("/login"); }
147 |
148 | let result = await getUser({ access_token, refresh_token });
149 | if (!result) return res.redirect("/login");
150 | [user, { refresh_token, access_token }] = result;
151 |
152 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
153 | if (!server) return renderTemplate(res, req, "servers/404");
154 |
155 | const timeremain = getTimeRemaining(server.lastbumped)
156 | if (timeremain.days == 0) {
157 | if (timeremain.hours < 2) return res.redirect(`/server/${server.guildid}/?type=cooldown`);
158 | }
159 | await Servers.updateOne({ guildid: server.guildid }, { $set: { lastbumped: new Date(Date.parse(new Date())) } })
160 | res.redirect(`/server/${server.guildid}/?type=success`)
161 | });
162 |
163 | route.get("/:id/delete", async (req, res, next) => {
164 | let user;
165 | let { refresh_token, access_token } = req.cookies;
166 | if (!refresh_token) {
167 | res.cookie("backURL", req.originalUrl);
168 | return res.redirect('/login');
169 | }
170 |
171 | let result = await getUser({ access_token, refresh_token });
172 | if (!result) return res.redirect("/login");
173 | [user, { refresh_token, access_token }] = result;
174 |
175 | let server = await Servers.findOne({ guildid: req.params.id }, { _id: false })
176 | if (!server) return renderTemplate(res, req, "servers/404");
177 |
178 | const guild = req.app.get('client').guilds.cache.get(req.params.id);
179 | const isManaged = guild && guild.ownerID === user.id ? true : false;
180 | if (!isManaged && !process.env.ADMIN_USERS.includes(user.id)) return renderTemplate(res, req, 'errors/403');
181 |
182 | await Servers.findOneAndDelete({ guildid: guild.id });
183 | await guild.leave();
184 |
185 | res.redirect(`/me/servers?deleted=${guild.id}`);
186 | });
187 |
188 | function getTimeRemaining(endtime) {
189 | const total = Date.parse(new Date()) - Date.parse(endtime);
190 | const seconds = Math.floor((total / 1000) % 60);
191 | const minutes = Math.floor((total / 1000 / 60) % 60);
192 | const hours = Math.floor((total / (1000 * 60 * 60)) % 24);
193 | const days = Math.floor(total / (1000 * 60 * 60 * 24));
194 | return { total, days, hours, minutes, seconds };
195 | }
196 |
197 | module.exports = route;
198 |
--------------------------------------------------------------------------------
/routes/tagroutes.js:
--------------------------------------------------------------------------------
1 | const { Router } = require("express");
2 |
3 | const Servers = require("@models/servers");
4 | const { renderTemplate } = require("@structures/middleware.js");
5 |
6 | const allcategories = ["advertising", "giveaway", "meme", "bots", "developer", "fun", "social", "emotes", "support-server", "music", "stream", "roleplay", "art", "gaming", "economy", "chill", "events", "friends", "teen", "community", "new", "comedy", "youtube", "twitch"];
7 |
8 | const route = Router();
9 |
10 | route.get("/search", async (req, res, next) => {
11 | let search = req.query.q;
12 | if (!search) search = "";
13 | search = search.toLowerCase();
14 | let servers = await Servers.find({}, { _id: false });
15 | let found = servers.filter(server => {
16 | if (server.state == "setup") return false;
17 | else if (server.description.toLowerCase().includes(search)) return true;
18 | else if (server.long.toLowerCase().includes(search)) return true;
19 | else return false;
20 | });
21 |
22 | let pg = parseInt(req.query.page);
23 | if (pg != Math.floor(pg)) pg = 1;
24 | if (!pg) pg = 1;
25 | let end = pg * 12;
26 | let start = pg * 12 - 12;
27 | const array = [];
28 | if (found.length === 0) {
29 | //return res.render('tag/nobots', {category: req.params.category});
30 | } else if (found.length <= start) {
31 | //return res.redirect('/tags/');
32 | } else if (found.length <= end) {
33 | for (let i = start; i < found.length; i++) {
34 | array.push(found[i]);
35 | //console.log(array.join(", "));
36 | }
37 | } else {
38 | for (let i = start; i < end; i++) {
39 | array.push(found[i]);
40 | }
41 | }
42 |
43 | if (!found) return res.send({ error: "No servers found for this search" });
44 | let data = {
45 | cards: array,
46 | search: search,
47 | page: pg,
48 | maxpages: Math.ceil(found.length / 12),
49 | };
50 | renderTemplate(res, req, "search/search", data);
51 | });
52 |
53 | route.get('/tags/', async (req, res, next) => {
54 | renderTemplate(res, req, "search/alltags", { allcategories })
55 | });
56 |
57 | route.get('/tag/:category', async (req, res, next) => {
58 | if (!allcategories.includes(req.params.category)) return res.redirect('/tags');
59 |
60 |
61 | let leaderboard = await Servers.find({ state: "default" }, { _id: false });
62 | leaderboard = leaderboard.filter(m => m.categories.includes(req.params.category));
63 | const sorted = leaderboard.sort((a, b) => b.lastbumped - a.lastbumped);
64 |
65 | // if (sorted.length === 0) return res.redirect('/tag/'+req.params.category);
66 |
67 | let pg = parseInt(req.query.page);
68 | if (pg != Math.floor(pg)) pg = 1;
69 | if (!pg) pg = 1;
70 | let end = pg * 12;
71 | let start = pg * 12 - 12;
72 | const array = [];
73 | if (sorted.length === 0) {
74 | //return res.render('tag/nobots', {category: req.params.category});
75 | } else if (sorted.length <= start) {
76 | //return res.redirect('/list/'+req.params.category);
77 | } else if (sorted.length <= end) {
78 | for (let i = start; i < sorted.length; i++) {
79 | array.push(sorted[i]);
80 | //console.log(array.join(", "));
81 | }
82 | } else {
83 | for (let i = start; i < end; i++) {
84 | array.push(sorted[i]);
85 | }
86 | }
87 |
88 | let data = {
89 | category: req.params.category,
90 | categoryformatted: req.params.category.toProperCase(),
91 | page: pg,
92 | maxpages: Math.ceil(sorted.length / 12),
93 | cards: array,
94 | };
95 | if (array == []) return res.redirect("/tags");
96 | renderTemplate(res, req, "search/category", data);
97 | });
98 |
99 | route.get('/list/:category', async (req, res, next) => {
100 | if (!["bumped", "members", "added", "vanity"].includes(req.params.category)) return res.redirect('/tags');
101 |
102 |
103 | let leaderboard = await Servers.find({ state: "default" }, { _id: false });
104 | let sorted = leaderboard.sort((a, b) => b.lastbumped - a.lastbumped);
105 | if (req.params.category == "members") sorted = leaderboard.sort((a, b) => req.app.get('client').guilds.cache.get(b.guildid).members.cache.size - req.app.get('client').guilds.cache.get(a.guildid).members.cache.size);
106 | if (req.params.category == "added") sorted = leaderboard.sort((a, b) => b.addedAt - a.addedAt);
107 | if (req.params.category == "vanity") sorted = leaderboard.filter(m => m.vanity.code).sort((a, b) => b.addedAt - a.addedAt);
108 |
109 | // if (sorted.length === 0) return res.redirect('/tag/'+req.params.category);
110 |
111 | let pg = parseInt(req.query.page);
112 | if (pg != Math.floor(pg)) pg = 1;
113 | if (!pg) pg = 1;
114 | let end = pg * 12;
115 | let start = pg * 12 - 12;
116 | const array = [];
117 | if (sorted.length === 0) {
118 | //return res.render('tag/nobots', {category: req.params.category});
119 | } else if (sorted.length <= start) {
120 | //return res.redirect('/list/'+req.params.category);
121 | } else if (sorted.length <= end) {
122 | for (let i = start; i < sorted.length; i++) {
123 | array.push(sorted[i]);
124 | //console.log(array.join(", "));
125 | }
126 | } else {
127 | for (let i = start; i < end; i++) {
128 | array.push(sorted[i]);
129 | }
130 | }
131 |
132 | let data = {
133 | category: req.params.category,
134 | categoryformatted: req.params.category.toProperCase(),
135 | page: pg,
136 | maxpages: Math.ceil(sorted.length / 12),
137 | cards: array,
138 | };
139 | renderTemplate(res, req, "search/list", data);
140 | });
141 |
142 | module.exports = route;
143 |
--------------------------------------------------------------------------------
/routes/vanity.js:
--------------------------------------------------------------------------------
1 | const { Router } = require("express");
2 | const Servers = require("@models/servers");
3 |
4 | const route = Router();
5 |
6 | route.get('/:vanity', async (req, res, next) => {
7 | if(req.headers.host == process.env.DOMAIN.toString().replace(/(http(s?)):\/\//i, '')) return next();
8 | const vanityuri = req.params.vanity;
9 |
10 | let server = await Servers.findOne({ "vanity.code": vanityuri }, { _id: false })
11 | if(!server) return res.redirect(process.env.DOMAIN)
12 | if(server.vanity.action == "join") {
13 | return res.redirect(process.env.DOMAIN + "/server/" + server.guildid + "/join")
14 | }
15 |
16 | res.redirect(process.env.DOMAIN + "/server/" + server.guildid)
17 | });
18 |
19 | module.exports = route;
20 |
--------------------------------------------------------------------------------
/structures/app.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const express = require("express");
3 | const cookieParser = require('cookie-parser')
4 |
5 | const getFilesSync = require("@structures/fileWalk");
6 | const { renderTemplate } = require('@structures/middleware');
7 |
8 | class App {
9 | constructor(client) {
10 | this.express = express();
11 | this.express.set('views', './dynamic');
12 | this.express.set('view engine', 'ejs');
13 | this.express.set('client', client);
14 | this.express.use(cookieParser());
15 | this.express.use(express.json());
16 | this.express.use(express.urlencoded({ extended: false }));
17 | this.express.use(express.static(__dirname + "/../public"));
18 |
19 | this.loadRoutes().loadErrorHandler().loadNotFound();
20 | }
21 |
22 | listen(port) {
23 | return new Promise((resolve) => this.express.listen(port, resolve));
24 | }
25 |
26 |
27 | loadRoutes() {
28 | const routesPath = path.join(__dirname, "../routes");
29 | const routes = getFilesSync(routesPath);
30 |
31 | if (!routes.length) return this;
32 |
33 | routes.forEach((filename) => {
34 | const route = require(path.join(routesPath, filename));
35 |
36 | const routePath = filename === "index.js" ? "/" : `/${filename.slice(0, -3)}`;
37 |
38 | try {
39 | this.express.use(routePath, route);
40 | } catch (error) {
41 | console.error(`Error occured with the route "${filename}"\n\n${error}`);
42 | }
43 | });
44 |
45 | return this;
46 | }
47 |
48 |
49 | loadErrorHandler() {
50 | this.express.use(async (error, _req, res, _next) => {
51 | const { message, statusCode = 500 } = error;
52 |
53 | if (statusCode >= 500) {
54 | console.error(error);
55 | let data = {
56 | message: message,
57 | status: statusCode,
58 | error
59 | };
60 | return renderTemplate(res, _req, "errors/express", data);
61 | }
62 | return res.json(error);
63 | });
64 |
65 | return this;
66 | }
67 |
68 | loadNotFound() {
69 | this.express.use(async (_req, res, _next) => {
70 | renderTemplate(res, _req, 'errors/404');
71 | });
72 | }
73 | }
74 |
75 | module.exports = App;
76 |
--------------------------------------------------------------------------------
/structures/discordApi.js:
--------------------------------------------------------------------------------
1 | const unirest = require("unirest");
2 | const fetch = require('node-fetch');
3 | const { CLIENT_ID, CLIENT_SECRET, DOMAIN } = process.env;
4 |
5 | module.exports.refreshUser = async (opts) => {
6 | const params = new URLSearchParams();
7 | params.append("client_id", CLIENT_ID);
8 | params.append("client_secret", CLIENT_SECRET);
9 | params.append("redirect_uri", `${DOMAIN}/callback`);
10 | params.append("scope", "identify%20guilds%20guilds.join");
11 |
12 | if (opts.code) {
13 | params.append("grant_type", "authorization_code");
14 | params.append("code", opts.code);
15 | } else if (opts.refresh_token) {
16 | params.append("grant_type", "refresh_token");
17 | params.append("code", opts.refresh_token);
18 | }
19 |
20 | const response = await fetch(`https://discord.com/api/oauth2/token`, {
21 | method: "POST",
22 | headers: {
23 | "Content-Type": "application/x-www-form-urlencoded",
24 | },
25 | body: params,
26 | });
27 | let json = await response.json();
28 |
29 | return json;
30 | }
31 |
32 | module.exports.getUser = async (opts) => {
33 | let access_token, refresh_token;
34 | if (!opts.access_token) {
35 | let json = await module.exports.refreshUser(opts);
36 | access_token = json.access_token;
37 | refresh_token = json.refresh_token
38 | } else {
39 | access_token = opts.access_token;
40 | refresh_token = opts.refresh_token;
41 | }
42 |
43 | let data = [];
44 | let user = await fetch(`https://discord.com/api/users/@me`, {
45 | headers: {
46 | Authorization: `Bearer ${access_token}`,
47 | },
48 | });
49 | user = await user.json();
50 | user.guilds = await module.exports.getGuilds();
51 |
52 | if (user.code === 0) return false;
53 | data.push(user);
54 | data.push({ refresh_token, access_token });
55 | return data;
56 | };
57 |
58 | module.exports.getGuilds = () => {
59 | return new Promise(function (resolve, reject) {
60 | let data = [];
61 | unirest
62 | .get(`https://discord.com/api/users/@me/guilds`)
63 | .headers({
64 | Authorization: `Bot ${process.env.DISCORD_TOKEN}`,
65 | })
66 | .end(function (user) {
67 | if (user["raw_body"].error) return resolve(false);
68 | data.push(JSON.parse(user["raw_body"]));
69 | resolve(data);
70 | });
71 | });
72 | };
73 |
74 | module.exports.getBot = (id) => {
75 | return new Promise(function (resolve, reject) {
76 | let data = [];
77 | unirest
78 | .get(`https://discord.com/api/users/${id}`)
79 | .headers({
80 | Authorization: `Bot ${process.env.DISCORD_TOKEN}`,
81 | })
82 | .end(function (user) {
83 | if (user["raw_body"].error) return resolve(false);
84 | data.push(JSON.parse(user["raw_body"]));
85 | resolve(data);
86 | });
87 | });
88 | };
89 |
90 | module.exports.addUser = async (opts) => {
91 | return await opts.client.guilds.cache.get(process.env.GUILD_ID).addMember(opts.userId, { accessToken: opts.accessToken });
92 | };
93 |
--------------------------------------------------------------------------------
/structures/fileWalk.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 |
3 | module.exports = (filepath) => {
4 | if (!filepath) throw new Error("No file path provided!");
5 |
6 | if (!fs.existsSync(filepath)) fs.mkdirSync(filepath);
7 |
8 | const files = fs.readdirSync(filepath, { withFileTypes: true })
9 | .filter((entry) => !entry.isDirectory())
10 | .map((entry) => entry.name);
11 |
12 | return files;
13 | };
14 |
--------------------------------------------------------------------------------
/structures/middleware.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const templateDir = path.resolve(`${process.cwd()}${path.sep}dynamic`);
3 | const { getUser } = require("@structures/discordApi");
4 |
5 | module.exports.renderTemplate = async (res, req, template, data = {}) => {
6 | if(!res.render) return console.error('TypeError: res was not defined');
7 | if(!req.cookies) return console.error('TypeError: req was not defined');
8 |
9 |
10 | // Setup user variable
11 | let user = null;
12 | let {refresh_token, access_token} = req.cookies;
13 | if (refresh_token) {
14 | let result = await getUser({access_token, refresh_token});
15 | if (!result) return res.redirect("/login");
16 | [user, {refresh_token, access_token}, userguilds] = result;
17 | res.cookie("refresh_token", refresh_token, {httpOnly: true});
18 | res.cookie("access_token", access_token, {httpOnly: true});
19 | }
20 |
21 | if(user != null) user.isAdmin = process.env.ADMIN_USERS.includes(user.id);
22 |
23 | const baseData = {
24 | bot: req.app.get('client'),
25 | path: req.path,
26 | user: user,
27 | };
28 | res.render(path.resolve(`${templateDir}${path.sep}${template}`), Object.assign(baseData, data));
29 | };
30 |
--------------------------------------------------------------------------------