Przeglądaj źródła

move css to own file

close #85
close #86
close #87
Markus-Rost 4 lat temu
rodzic
commit
bd01269fe4
6 zmienionych plików z 288 dodań i 355 usunięć
  1. 4 4
      bot.js
  2. 17 171
      dashboard/index.html
  3. 40 7
      dashboard/index.js
  4. 11 171
      dashboard/login.html
  5. 209 0
      dashboard/src/index.css
  6. 7 2
      main.js

+ 4 - 4
bot.js

@@ -344,13 +344,13 @@ global.log_warn = function(warning, api = true) {
  * End the process gracefully.
  * @param {NodeJS.Signals} signal - The signal received.
  */
-async function graceful(signal) {
+function graceful(signal) {
 	isStop = true;
 	console.log( '- ' + shardId + ': ' + signal + ': Preparing to close...' );
-	setTimeout( async () => {
+	setTimeout( () => {
 		console.log( '- ' + shardId + ': ' + signal + ': Destroying client...' );
-		await client.destroy();
-		await db.close( dberror => {
+		client.destroy();
+		db.close( dberror => {
 			if ( dberror ) {
 				console.log( '- ' + shardId + ': ' + signal + ': Error while closing the database connection: ' + dberror );
 				return dberror;

+ 17 - 171
dashboard/index.html

@@ -5,180 +5,12 @@
 	<title>Wiki-Bot Settings</title>
 	<link rel="shortcut icon" href="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=64">
 	<meta name="description" content="Wiki-Bot is a bot with the purpose to easily search for and link to wiki pages. Wiki-Bot shows short descriptions and additional info about pages and is able to resolve redirects and follow interwiki links.">
+	<meta property="og:description" content="Wiki-Bot is a bot with the purpose to easily search for and link to wiki pages. Wiki-Bot shows short descriptions and additional info about pages and is able to resolve redirects and follow interwiki links.">
 	<meta property="og:image" content="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=1024">
 	<meta property="og:title" content="Wiki-Bot Settings">
 	<meta property="og:site_name" content="Wiki-Bot Settings">
 	<meta itemprop="author" content="MarkusRost">
-	<style>
-		html {
-			height: calc(100% - 48px);
-		}
-		body {
-			font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
-			text-rendering: optimizeLegibility;
-			background: #36393f;
-			color: #dcddde;
-			position: relative;
-			min-height: 100%;
-			margin: 0;
-		}
-		a {
-			text-decoration: none;
-			color: inherit;
-		}
-		.text a {
-			color: #00b0f4;
-		}
-		.text a:hover {
-			text-decoration: underline;
-		}
-		.text {
-			position: relative;
-			padding: 8px;
-			width: calc(100% - 88px);
-			top: 48px;
-			left: 72px;
-		}
-		.notice {
-			padding: 5px 10px;
-			line-height: 1.6;
-			text-align: center;
-			margin: 0 auto 1em;
-			width: fit-content;
-			background: #200;
-			border: 2px solid #500;
-		}
-		.navbar {
-			background: #2f3136;
-			position: fixed;
-			top: 0;
-			left: 72px;
-			right: 0;
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			height: 48px;
-			padding: 0 0 0 8px;
-			font-size: 16px;
-			line-height: 20px;
-			font-weight: bold;
-		}
-		.navbar a {
-			display: flex;
-			align-items: center;
-			height: 100%;
-			padding-left: 10px;
-		}
-		.navbar a:hover {
-			background: #202225;
-		}
-		.navbar .avatar {
-			width: 32px;
-			height: 32px;
-		}
-		.navbar span {
-			padding: 0 10px;
-		}
-		.sidebar {
-			background: #202225;
-			position: absolute;
-			top: 0;
-			left: 0;
-			min-height: calc(100% + 48px);
-			width: 72px;
-			display: flex;
-		}
-		.guildlist {
-			padding: 12px 0;
-			position: relative;
-			flex: 1 1 auto;
-		}
-		.guild {
-			margin: 0 0 8px;
-			position: relative;
-			display: flex;
-			justify-content: center;
-		}
-		.avatar {
-			border-radius: 50%;
-			width: 48px;
-			height: 48px;
-			display: flex;
-			align-items: center;
-			justify-content: center;
-			font-weight: 500;
-			line-height: 1.2em;
-			white-space: nowrap;
-			overflow: hidden;
-			color: #dcddde;
-			font-weight: bold;
-		}
-		.navbar a:hover .avatar,
-		.guild.selected .avatar,
-		.guild:hover .avatar {
-			border-radius: 30%;
-			color: #ffffff;
-		}
-		.noicon {
-			width: 48px;
-			height: 48px;
-			background: #36393f;
-		}
-		.guild.selected .noicon,
-		.guild:hover .noicon {
-			background-color: #7289da;
-		}
-		.svg-avatar {
-			color: #43b581;
-			background: #36393f;
-		}
-		.guild:hover .svg-avatar {
-			color: #ffffff;
-			background-color: #43b581;
-		}
-		.separator {
-			height: 2px;
-			width: 32px;
-			border-radius: 1px;
-			background-color: rgba(255,255,255,0.06);;
-		}
-		.bar {
-			position: absolute;
-			left: 0;
-			top: 0;
-			display: block;
-			width: 8px;
-			border-radius: 0 4px 4px 0;
-			margin-left: -4px;
-			background-color: #ffffff;
-		}
-		.guild:hover .bar {
-			margin-top: 14px;
-			height: 20px;
-		}
-		.guild.selected .bar {
-			margin-top: 4px;
-			height: 40px;
-		}
-		a[alt]:hover:after {
-			content: attr(alt);
-			position: absolute;
-			background: #000000;
-			color: #dcddde;
-			font-weight: bold;
-			font-size: 90%;
-			white-space: nowrap;
-			border-radius: 4px;
-			padding: 8px;
-		}
-		.guild a[alt]:hover:after {
-			top: 20%;
-			left: 72px;
-		}
-		.navbar a[alt]:hover:after {
-			top: 48px;
-		}
-	</style>
+	<link rel="stylesheet" type="text/css" href="/src/index.css">
 </head>
 <body class="settings">
 	<div class="text">
@@ -188,7 +20,7 @@
 	<div class="navbar">
 		<div style="width: 150px;"></div>
 		<a id="support" href="https://discord.gg/v77RTk5" target="_blank" alt="Support server">
-			<img class="avatar" src="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=64" alt="Support server" width="32" height="32">
+			<img class="avatar" src="https://cdn.discordapp.com/icons/464084451165732868/c6a8b9fc902b09545de8194a911e6045.png?size=128" alt="Support server" width="32" height="32">
 			<span>Support server</span>
 		</a>
 		<a id="logout" href="/logout" alt="Logout">
@@ -223,6 +55,20 @@
 				</a>
 			</div>
 		</div>
+		<div class="channellist">
+			<a class="channel">
+				<svg width="20" height="20" viewBox="0 0 24 24">
+					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M5.88657 21C5.57547 21 5.3399 20.7189 5.39427 20.4126L6.00001 17H2.59511C2.28449 17 2.04905 16.7198 2.10259 16.4138L2.27759 15.4138C2.31946 15.1746 2.52722 15 2.77011 15H6.35001L7.41001 9H4.00511C3.69449 9 3.45905 8.71977 3.51259 8.41381L3.68759 7.41381C3.72946 7.17456 3.93722 7 4.18011 7H7.76001L8.39677 3.41262C8.43914 3.17391 8.64664 3 8.88907 3H9.87344C10.1845 3 10.4201 3.28107 10.3657 3.58738L9.76001 7H15.76L16.3968 3.41262C16.4391 3.17391 16.6466 3 16.8891 3H17.8734C18.1845 3 18.4201 3.28107 18.3657 3.58738L17.76 7H21.1649C21.4755 7 21.711 7.28023 21.6574 7.58619L21.4824 8.58619C21.4406 8.82544 21.2328 9 20.9899 9H17.41L16.35 15H19.7549C20.0655 15 20.301 15.2802 20.2474 15.5862L20.0724 16.5862C20.0306 16.8254 19.8228 17 19.5799 17H16L15.3632 20.5874C15.3209 20.8261 15.1134 21 14.8709 21H13.8866C13.5755 21 13.3399 20.7189 13.3943 20.4126L14 17H8.00001L7.36325 20.5874C7.32088 20.8261 7.11337 21 6.87094 21H5.88657ZM9.41045 9L8.35045 15H14.3504L15.4104 9H9.41045Z"></path>
+				</svg>
+				<div>Keks</div>
+			</a>
+			<a class="channel">
+				<svg width="20" height="20" viewBox="0 0 24 24">
+					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M5.88657 21C5.57547 21 5.3399 20.7189 5.39427 20.4126L6.00001 17H2.59511C2.28449 17 2.04905 16.7198 2.10259 16.4138L2.27759 15.4138C2.31946 15.1746 2.52722 15 2.77011 15H6.35001L7.41001 9H4.00511C3.69449 9 3.45905 8.71977 3.51259 8.41381L3.68759 7.41381C3.72946 7.17456 3.93722 7 4.18011 7H7.76001L8.39677 3.41262C8.43914 3.17391 8.64664 3 8.88907 3H9.87344C10.1845 3 10.4201 3.28107 10.3657 3.58738L9.76001 7H15.76L16.3968 3.41262C16.4391 3.17391 16.6466 3 16.8891 3H17.8734C18.1845 3 18.4201 3.28107 18.3657 3.58738L17.76 7H21.1649C21.4755 7 21.711 7.28023 21.6574 7.58619L21.4824 8.58619C21.4406 8.82544 21.2328 9 20.9899 9H17.41L16.35 15H19.7549C20.0655 15 20.301 15.2802 20.2474 15.5862L20.0724 16.5862C20.0306 16.8254 19.8228 17 19.5799 17H16L15.3632 20.5874C15.3209 20.8261 15.1134 21 14.8709 21H13.8866C13.5755 21 13.3399 20.7189 13.3943 20.4126L14 17H8.00001L7.36325 20.5874C7.32088 20.8261 7.11337 21 6.87094 21H5.88657ZM9.41045 9L8.35045 15H14.3504L15.4104 9H9.41045Z"></path>
+				</svg>
+				<div>Keks</div>
+			</a>
+		</div>
 	</div>
 </body>
 </html>

+ 40 - 7
dashboard/index.js

@@ -21,9 +21,34 @@ const oauth = new DiscordOauth2( {
 } );
 
 const fs = require('fs');
+const path = require('path');
 const files = {
 	index: fs.readFileSync('./dashboard/index.html'),
-	login: fs.readFileSync('./dashboard/login.html')
+	login: fs.readFileSync('./dashboard/login.html'),
+	src: new Map(fs.readdirSync( './dashboard/src' ).map( file => {
+		let contentType = 'text/html';
+		switch ( path.extname(file) ) {
+			case '.css':
+				contentType = 'text/css';
+				break;
+			case '.js':
+				contentType = 'text/javascript';
+				break;
+			case '.json':
+				contentType = 'application/json';
+				break;
+			case '.png':
+				contentType = 'image/png';
+				break;
+			case '.jpg':
+				contentType = 'image/jpg';
+				break;
+		}
+		return [`/src/${file}`, {
+			name: file, contentType,
+			path: `./dashboard/src/${file}`
+		}];
+	} ))
 }
 
 /**
@@ -96,11 +121,19 @@ const server = http.createServer((req, res) => {
 		return res.end();
 	}
 
-	if ( req.url === '/favicon.ico' ) {
+	var reqURL = new URL(req.url, process.env.dashboard);
+
+	if ( reqURL.pathname === '/favicon.ico' ) {
 		res.writeHead(302, {Location: 'https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=64'});
 		return res.end();
 	}
 
+	if ( files.src.has(reqURL.pathname) ) {
+		let file = files.src.get(reqURL.pathname);
+		res.writeHead(200, {'Content-Type': file.contentType});
+		return fs.createReadStream(file.path).pipe(res);
+	}
+
 	res.setHeader('Content-Type', 'text/html');
 	res.setHeader('Content-Language', ['en']);
 
@@ -113,8 +146,6 @@ const server = http.createServer((req, res) => {
 		return cookie.split('=')[0] === 'wikibot';
 	} )?.map( cookie => cookie.replace( /^wikibot="(\w+(?:-\d+)?)"$/, '$1' ) )?.join();
 
-	var reqURL = new URL(req.url, process.env.dashboard);
-
 	if ( reqURL.pathname === '/login' ) {
 		if ( settingsData.has(state) ) {
 			res.writeHead(302, {Location: '/'});
@@ -157,6 +188,7 @@ const server = http.createServer((req, res) => {
 			scope: ['identify', 'guilds'],
 			prompt: 'none', state
 		} );
+		$('a#login').attr('href', url);
 		$('replace#text').replaceWith(`<a href="${url}">Login</a>`);
 		let body = $.html();
 		res.writeHead(responseCode, {
@@ -441,17 +473,18 @@ function hasPerm(all, permission, admin = true) {
  * End the process gracefully.
  * @param {NodeJS.Signals} signal - The signal received.
  */
-async function graceful(signal) {
+function graceful(signal) {
 	console.log( '- Dashboard: ' + signal + ': Closing the dashboard...' );
-	await server.close( () => {
+	server.close( () => {
 		console.log( '- Dashboard: ' + signal + ': Closed the dashboard server.' );
 	} );
-	await db.close( dberror => {
+	db.close( dberror => {
 		if ( dberror ) {
 			console.log( '- Dashboard: ' + signal + ': Error while closing the database connection: ' + dberror );
 			return dberror;
 		}
 		console.log( '- Dashboard: ' + signal + ': Closed the database connection.' );
+		process.exit(0);
 	} );
 }
 

+ 11 - 171
dashboard/login.html

@@ -5,180 +5,12 @@
 	<title>Login – Wiki-Bot Settings</title>
 	<link rel="shortcut icon" href="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=64">
 	<meta name="description" content="Wiki-Bot is a bot with the purpose to easily search for and link to wiki pages. Wiki-Bot shows short descriptions and additional info about pages and is able to resolve redirects and follow interwiki links.">
+	<meta property="og:description" content="Wiki-Bot is a bot with the purpose to easily search for and link to wiki pages. Wiki-Bot shows short descriptions and additional info about pages and is able to resolve redirects and follow interwiki links.">
 	<meta property="og:image" content="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=1024">
 	<meta property="og:title" content="Login – Wiki-Bot Settings">
 	<meta property="og:site_name" content="Wiki-Bot Settings">
 	<meta itemprop="author" content="MarkusRost">
-	<style>
-		html {
-			height: calc(100% - 48px);
-		}
-		body {
-			font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
-			text-rendering: optimizeLegibility;
-			background: #36393f;
-			color: #dcddde;
-			position: relative;
-			min-height: 100%;
-			margin: 0;
-		}
-		a {
-			text-decoration: none;
-			color: inherit;
-		}
-		.text a {
-			color: #00b0f4;
-		}
-		.text a:hover {
-			text-decoration: underline;
-		}
-		.text {
-			position: relative;
-			padding: 8px;
-			width: calc(100% - 88px);
-			top: 48px;
-			left: 72px;
-		}
-		.notice {
-			padding: 5px 10px;
-			line-height: 1.6;
-			text-align: center;
-			margin: 0 auto 1em;
-			width: fit-content;
-			background: #200;
-			border: 2px solid #500;
-		}
-		.navbar {
-			background: #2f3136;
-			position: fixed;
-			top: 0;
-			left: 72px;
-			right: 0;
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			height: 48px;
-			padding: 0 0 0 8px;
-			font-size: 16px;
-			line-height: 20px;
-			font-weight: bold;
-		}
-		.navbar a {
-			display: flex;
-			align-items: center;
-			height: 100%;
-			padding-left: 10px;
-		}
-		.navbar a:hover {
-			background: #202225;
-		}
-		.navbar .avatar {
-			width: 32px;
-			height: 32px;
-		}
-		.navbar span {
-			padding: 0 10px;
-		}
-		.sidebar {
-			background: #202225;
-			position: absolute;
-			top: 0;
-			left: 0;
-			min-height: calc(100% + 48px);
-			width: 72px;
-			display: flex;
-		}
-		.guildlist {
-			padding: 12px 0;
-			position: relative;
-			flex: 1 1 auto;
-		}
-		.guild {
-			margin: 0 0 8px;
-			position: relative;
-			display: flex;
-			justify-content: center;
-		}
-		.avatar {
-			border-radius: 50%;
-			width: 48px;
-			height: 48px;
-			display: flex;
-			align-items: center;
-			justify-content: center;
-			font-weight: 500;
-			line-height: 1.2em;
-			white-space: nowrap;
-			overflow: hidden;
-			color: #dcddde;
-			font-weight: bold;
-		}
-		.navbar a:hover .avatar,
-		.guild.selected .avatar,
-		.guild:hover .avatar {
-			border-radius: 30%;
-			color: #ffffff;
-		}
-		.noicon {
-			width: 48px;
-			height: 48px;
-			background: #36393f;
-		}
-		.guild.selected .noicon,
-		.guild:hover .noicon {
-			background-color: #7289da;
-		}
-		.svg-avatar {
-			color: #43b581;
-			background: #36393f;
-		}
-		.guild:hover .svg-avatar {
-			color: #ffffff;
-			background-color: #43b581;
-		}
-		.separator {
-			height: 2px;
-			width: 32px;
-			border-radius: 1px;
-			background-color: rgba(255,255,255,0.06);;
-		}
-		.bar {
-			position: absolute;
-			left: 0;
-			top: 0;
-			display: block;
-			width: 8px;
-			border-radius: 0 4px 4px 0;
-			margin-left: -4px;
-			background-color: #ffffff;
-		}
-		.guild:hover .bar {
-			margin-top: 14px;
-			height: 20px;
-		}
-		.guild.selected .bar {
-			margin-top: 4px;
-			height: 40px;
-		}
-		a[alt]:hover:after {
-			content: attr(alt);
-			position: absolute;
-			background: #000000;
-			color: #dcddde;
-			font-weight: bold;
-			font-size: 90%;
-			white-space: nowrap;
-			border-radius: 4px;
-			padding: 8px;
-		}
-		.guild a[alt]:hover:after {
-			top: 20%;
-			left: 72px;
-		}
-		.navbar a[alt]:hover:after {
-			top: 48px;
-		}
-	</style>
+	<link rel="stylesheet" type="text/css" href="/src/index.css">
 </head>
 <body class="settings">
 	<div class="text">
@@ -188,7 +20,7 @@
 	<div class="navbar">
 		<div style="width: 150px;"></div>
 		<a id="support" href="https://discord.gg/v77RTk5" target="_blank" alt="Support server">
-			<img class="avatar" src="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=64" alt="Support server" width="32" height="32">
+			<img class="avatar" src="https://cdn.discordapp.com/icons/464084451165732868/c6a8b9fc902b09545de8194a911e6045.png?size=128" alt="Support server" width="32" height="32">
 			<span>Support server</span>
 		</a>
 	</div>
@@ -205,6 +37,14 @@
 				</a>
 			</div>
 		</div>
+		<div class="channellist">
+			<a class="channel" id="login">
+				<svg width="20" height="20" viewBox="0 0 24 24">
+					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M5.88657 21C5.57547 21 5.3399 20.7189 5.39427 20.4126L6.00001 17H2.59511C2.28449 17 2.04905 16.7198 2.10259 16.4138L2.27759 15.4138C2.31946 15.1746 2.52722 15 2.77011 15H6.35001L7.41001 9H4.00511C3.69449 9 3.45905 8.71977 3.51259 8.41381L3.68759 7.41381C3.72946 7.17456 3.93722 7 4.18011 7H7.76001L8.39677 3.41262C8.43914 3.17391 8.64664 3 8.88907 3H9.87344C10.1845 3 10.4201 3.28107 10.3657 3.58738L9.76001 7H15.76L16.3968 3.41262C16.4391 3.17391 16.6466 3 16.8891 3H17.8734C18.1845 3 18.4201 3.28107 18.3657 3.58738L17.76 7H21.1649C21.4755 7 21.711 7.28023 21.6574 7.58619L21.4824 8.58619C21.4406 8.82544 21.2328 9 20.9899 9H17.41L16.35 15H19.7549C20.0655 15 20.301 15.2802 20.2474 15.5862L20.0724 16.5862C20.0306 16.8254 19.8228 17 19.5799 17H16L15.3632 20.5874C15.3209 20.8261 15.1134 21 14.8709 21H13.8866C13.5755 21 13.3399 20.7189 13.3943 20.4126L14 17H8.00001L7.36325 20.5874C7.32088 20.8261 7.11337 21 6.87094 21H5.88657ZM9.41045 9L8.35045 15H14.3504L15.4104 9H9.41045Z"></path>
+				</svg>
+				<div>Login</div>
+			</a>
+		</div>
 	</div>
 </body>
 </html>

+ 209 - 0
dashboard/src/index.css

@@ -0,0 +1,209 @@
+html {
+	height: calc(100% - 48px);
+}
+body {
+	font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
+	text-rendering: optimizeLegibility;
+	background: #36393f;
+	color: #dcddde;
+	position: relative;
+	min-height: 100%;
+	margin: 0;
+}
+a {
+	text-decoration: none;
+	color: inherit;
+}
+a[alt]:hover:after {
+	content: attr(alt);
+	position: absolute;
+	background: #000000;
+	color: #dcddde;
+	font-weight: bold;
+	font-size: 90%;
+	white-space: nowrap;
+	border-radius: 4px;
+	padding: 8px;
+}
+.text a {
+	color: #00b0f4;
+}
+.text a:hover {
+	text-decoration: underline;
+}
+.text {
+	position: relative;
+	padding: 8px;
+	width: calc(100% - 328px);
+	top: 48px;
+	left: 312px;
+}
+.notice {
+	padding: 5px 10px;
+	line-height: 1.6;
+	text-align: center;
+	margin: 0 auto 1em;
+	width: fit-content;
+	background: #200;
+	border: 2px solid #500;
+}
+.navbar {
+	background: #2f3136;
+	position: fixed;
+	top: 0;
+	left: 72px;
+	right: 0;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	height: 48px;
+	padding: 0 0 0 8px;
+	font-size: 16px;
+	line-height: 20px;
+	font-weight: bold;
+	box-shadow: 0 1px 0 rgba(4,4,5,0.2),
+				0 1.5px 0 rgba(6,6,7,0.05),
+				0 2px 0 rgba(4,4,5,0.05);
+	z-index: 2;
+}
+.navbar a {
+	display: flex;
+	align-items: center;
+	height: 100%;
+	padding-left: 10px;
+}
+.navbar a:hover {
+	background: #202225;
+}
+.navbar .avatar {
+	width: 32px;
+	height: 32px;
+}
+.navbar span {
+	padding: 0 10px;
+}
+.sidebar {
+	background: #202225;
+	position: absolute;
+	top: 0;
+	left: 0;
+	min-height: calc(100% + 48px);
+	width: 72px;
+	display: flex;
+}
+.guildlist {
+	padding: 12px 0;
+	position: relative;
+	flex: 1 1 auto;
+	z-index: 2;
+}
+.guild {
+	margin: 0 0 8px;
+	position: relative;
+	display: flex;
+	justify-content: center;
+}
+.avatar {
+	border-radius: 50%;
+	width: 48px;
+	height: 48px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	font-weight: 500;
+	line-height: 1.2em;
+	white-space: nowrap;
+	overflow: hidden;
+	color: #dcddde;
+	font-weight: bold;
+}
+.navbar a:hover .avatar,
+.guild.selected .avatar,
+.guild:hover .avatar {
+	border-radius: 30%;
+	color: #ffffff;
+}
+.noicon {
+	width: 48px;
+	height: 48px;
+	background: #36393f;
+}
+.guild.selected .noicon,
+.guild:hover .noicon {
+	background-color: #7289da;
+}
+.svg-avatar {
+	color: #43b581;
+	background: #36393f;
+}
+.guild:hover .svg-avatar {
+	color: #ffffff;
+	background-color: #43b581;
+}
+.separator {
+	height: 2px;
+	width: 32px;
+	border-radius: 1px;
+	background-color: rgba(255,255,255,0.06);
+}
+.bar {
+	position: absolute;
+	left: 0;
+	top: 0;
+	display: block;
+	width: 8px;
+	border-radius: 0 4px 4px 0;
+	margin-left: -4px;
+	background-color: #ffffff;
+}
+.guild:hover .bar {
+	margin-top: 14px;
+	height: 20px;
+}
+.guild.selected .bar {
+	margin-top: 4px;
+	height: 40px;
+}
+.guild a[alt]:hover:after {
+	top: 20%;
+	left: 72px;
+}
+.navbar a[alt]:hover:after {
+	top: 48px;
+}
+.channellist {
+	background: #2f3136;
+	position: absolute;
+	min-height: calc(100% - 80px);
+	padding: 16px 0;
+	width: 240px;
+	top: 48px;
+	left: 72px;
+	z-index: 1;
+}
+.channel {
+	padding: 0 8px;
+	margin: 0 8px 2px;
+	height: 32px;
+	border-radius: 4px;
+	display: flex;
+	align-items: center;
+	color: #8e9297;
+}
+.channel:hover {
+	background: rgba(79,84,92,0.16);
+}
+.channel svg {
+	margin-right: 6px;
+	width: 20;
+	height: 20;
+}
+.channel div {
+	font-size: 16px;
+	line-height: 20px;
+	text-shadow: 0 0 1px;
+	white-space: nowrap;
+}
+.channel:hover div {
+	color: #dcddde;
+}

+ 7 - 2
main.js

@@ -35,6 +35,7 @@ manager.on( 'shardCreate', shard => {
 		if ( message === 'SIGKILL' ) {
 			console.log( '\n- Killing all shards!\n\n' );
 			manager.shards.forEach( shard => shard.kill() );
+			if ( typeof server !== 'undefined' ) server.kill();
 		}
 		if ( message === 'postStats' && process.env.botlist ) postStats();
 	} );
@@ -157,7 +158,7 @@ function postStats(botList = JSON.parse(process.env.botlist), shardCount = manag
  * End the process gracefully.
  * @param {NodeJS.Signals} signal - The signal received.
  */
-async function graceful(signal) {
+function graceful(signal) {
 	console.log( '- ' + signal + ': Disabling respawn...' );
 	manager.respawn = false;
 }
@@ -175,6 +176,10 @@ if ( isDebug && process.argv[3]?.startsWith( '--timeout:' ) ) {
 	setTimeout( () => {
 		console.log( `\n- Running for ${timeout} seconds, closing process!\n` );
 		manager.shards.forEach( shard => shard.kill() );
-		if ( typeof server !== 'undefined' ) server.kill('SIGTERM');
+		if ( typeof server !== 'undefined' ) server.kill();
+		setTimeout( () => {
+			console.log( `\n- Process stayed open, exiting maually!\n` );
+			process.exit(0);
+		}, timeout  * 1000 ).unref();
 	}, timeout  * 1000 ).unref();
 }