소스 검색

add server selector page

Markus-Rost 4 년 전
부모
커밋
1eed566cdf
9개의 변경된 파일190개의 추가작업 그리고 108개의 파일을 삭제
  1. 4 0
      cmds/eval.js
  2. 3 3
      cmds/wiki/gamepedia/overview.js
  3. 55 22
      dashboard/guilds.js
  4. 12 16
      dashboard/index.html
  5. 15 12
      dashboard/login.html
  6. 14 14
      dashboard/oauth.js
  7. 1 1
      dashboard/src/channel.svg
  8. 78 32
      dashboard/src/index.css
  9. 8 8
      dashboard/util.js

+ 4 - 0
cmds/eval.js

@@ -6,6 +6,10 @@ const {limit: {verification: verificationLimit, rcgcdw: rcgcdwLimit}} = require(
 const newMessage = require('../util/newMessage.js');
 const newMessage = require('../util/newMessage.js');
 var db = require('../util/database.js');
 var db = require('../util/database.js');
 
 
+var allSites = [];
+const getAllSites = require('../util/allSites.js');
+getAllSites.then( sites => allSites = sites );
+
 /**
 /**
  * Processes the "eval" command.
  * Processes the "eval" command.
  * @param {import('../util/i18n.js')} lang - The user language.
  * @param {import('../util/i18n.js')} lang - The user language.

+ 3 - 3
cmds/wiki/gamepedia/overview.js

@@ -32,9 +32,9 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 		}
 		}
 		else {
 		else {
 			wiki.updateWiki(body.query.general);
 			wiki.updateWiki(body.query.general);
-			var site = false;
-			if ( allSites.some( site => site.wiki_domain === body.hostname ) ) {
-				site = allSites.find( site => site.wiki_domain === body.hostname );
+			var site = null;
+			if ( allSites.some( site => site.wiki_domain === wiki.hostname ) ) {
+				site = allSites.find( site => site.wiki_domain === wiki.hostname );
 				
 				
 				var name = [lang.get('overview.name'), site.wiki_display_name];
 				var name = [lang.get('overview.name'), site.wiki_display_name];
 				var created = [lang.get('overview.created'), new Date(parseInt(site.created + '000', 10)).toLocaleString(lang.get('dateformat'), timeoptions)];
 				var created = [lang.get('overview.created'), new Date(parseInt(site.created + '000', 10)).toLocaleString(lang.get('dateformat'), timeoptions)];

+ 55 - 22
dashboard/guilds.js

@@ -21,64 +21,60 @@ function dashboard_guilds(res, state, reqURL) {
 	var arguments = reqURL.pathname.split('/');
 	var arguments = reqURL.pathname.split('/');
 	var settings = settingsData.get(state);
 	var settings = settingsData.get(state);
 	var $ = cheerio.load(file);
 	var $ = cheerio.load(file);
-	let notice = '';
 	if ( process.env.READONLY ) {
 	if ( process.env.READONLY ) {
-		notice = createNotice($, {
+		createNotice($, {
 			title: 'Read-only database!',
 			title: 'Read-only database!',
 			text: 'You can currently only view your settings but not change them.'
 			text: 'You can currently only view your settings but not change them.'
-		});
+		}).prependTo('#text');
 	}
 	}
-	$('replace#notice').replaceWith(notice);
-	$('.navbar #logout img').attr('src', settings.user.avatar);
-	$('.navbar #logout span').text(`${settings.user.username} #${settings.user.discriminator}`);
+	$('#logout img').attr('src', settings.user.avatar);
+	$('#logout span').text(`${settings.user.username} #${settings.user.discriminator}`);
 	$('.guild#invite a').attr('href', oauth.generateAuthUrl( {
 	$('.guild#invite a').attr('href', oauth.generateAuthUrl( {
 		scope: ['identify', 'guilds', 'bot'],
 		scope: ['identify', 'guilds', 'bot'],
 		permissions: defaultPermissions, state
 		permissions: defaultPermissions, state
 	} ));
 	} ));
 	$('.guild#refresh a').attr('href', '/refresh?return=' + reqURL.pathname);
 	$('.guild#refresh a').attr('href', '/refresh?return=' + reqURL.pathname);
-	let guilds = $('<div>');
 	if ( settings.guilds.isMember.size ) {
 	if ( settings.guilds.isMember.size ) {
 		$('<div class="guild">').append(
 		$('<div class="guild">').append(
 			$('<div class="separator">')
 			$('<div class="separator">')
-		).appendTo(guilds);
+		).insertBefore('.guild#last-separator');
 		settings.guilds.isMember.forEach( guild => {
 		settings.guilds.isMember.forEach( guild => {
 			$('<div class="guild">').attr('id', guild.id).append(
 			$('<div class="guild">').attr('id', guild.id).append(
 				$('<div class="bar">'),
 				$('<div class="bar">'),
 				$('<a>').attr('href', `/guild/${guild.id}`).attr('alt', guild.name).append(
 				$('<a>').attr('href', `/guild/${guild.id}`).attr('alt', guild.name).append(
 					( guild.icon ? 
 					( guild.icon ? 
-						$('<img class="avatar" width="48" height="48">').attr('src', guild.icon).attr('alt', guild.name)
+						$('<img class="avatar">').attr('src', `${guild.icon}?size=64`).attr('alt', guild.name)
 					 : $('<div class="avatar noicon">').text(guild.acronym) )
 					 : $('<div class="avatar noicon">').text(guild.acronym) )
 				)
 				)
-			).appendTo(guilds);
+			).insertBefore('.guild#last-separator');
 		} );
 		} );
 	}
 	}
 	if ( settings.guilds.notMember.size ) {
 	if ( settings.guilds.notMember.size ) {
 		$('<div class="guild">').append(
 		$('<div class="guild">').append(
 			$('<div class="separator">')
 			$('<div class="separator">')
-		).appendTo(guilds);
+		).insertBefore('.guild#last-separator');
 		settings.guilds.notMember.forEach( guild => {
 		settings.guilds.notMember.forEach( guild => {
 			$('<div class="guild">').attr('id', guild.id).append(
 			$('<div class="guild">').attr('id', guild.id).append(
 				$('<div class="bar">'),
 				$('<div class="bar">'),
 				$('<a>').attr('href', `/guild/${guild.id}`).attr('alt', guild.name).append(
 				$('<a>').attr('href', `/guild/${guild.id}`).attr('alt', guild.name).append(
 					( guild.icon ? 
 					( guild.icon ? 
-						$('<img class="avatar" width="48" height="48">').attr('src', guild.icon).attr('alt', guild.name)
+						$('<img class="avatar">').attr('src', `${guild.icon}?size=64`).attr('alt', guild.name)
 					 : $('<div class="avatar noicon">').text(guild.acronym) )
 					 : $('<div class="avatar noicon">').text(guild.acronym) )
 				)
 				)
-			).appendTo(guilds);
+			).insertBefore('.guild#last-separator');
 		} );
 		} );
 	}
 	}
-	$('replace#guilds').replaceWith(guilds.children());
 
 
-	if ( reqURL.pathname.startsWith( '/guild/' ) ) {
-		let id = reqURL.pathname.replace( '/guild/', '' );
+	if ( arguments[1] === 'guild' ) {
+		let id = arguments[2];
 		if ( settings.guilds.isMember.has(id) ) {
 		if ( settings.guilds.isMember.has(id) ) {
 			$(`.guild#${id}`).addClass('selected');
 			$(`.guild#${id}`).addClass('selected');
 			let guild = settings.guilds.isMember.get(id);
 			let guild = settings.guilds.isMember.get(id);
 			$('head title').text(`${guild.name} – ` + $('head title').text());
 			$('head title').text(`${guild.name} – ` + $('head title').text());
 			res.setHeader('Set-Cookie', [`guild="${id}"; HttpOnly; Path=/`]);
 			res.setHeader('Set-Cookie', [`guild="${id}"; HttpOnly; Path=/`]);
-			$('replace#text').replaceWith(`${guild.permissions}`);
+			$('<a>').text(`${guild.permissions}`).appendTo('#text');
 		}
 		}
-		if ( settings.guilds.notMember.has(id) ) {
+		else if ( settings.guilds.notMember.has(id) ) {
 			$(`.guild#${id}`).addClass('selected');
 			$(`.guild#${id}`).addClass('selected');
 			let guild = settings.guilds.notMember.get(id);
 			let guild = settings.guilds.notMember.get(id);
 			$('head title').text(`${guild.name} – ` + $('head title').text());
 			$('head title').text(`${guild.name} – ` + $('head title').text());
@@ -88,12 +84,49 @@ function dashboard_guilds(res, state, reqURL) {
 				permissions: defaultPermissions,
 				permissions: defaultPermissions,
 				guild_id: id, state
 				guild_id: id, state
 			} );
 			} );
-			$('replace#text').replaceWith($('<a>').attr('href', url).text(guild.permissions));
+			$('<a>').attr('href', url).text(guild.permissions).appendTo('#text');
+		}
+		else {
+			$('<p>').text('You are missing the <code>MANAGE_GUILD</code> permission.').appendTo('#text');
 		}
 		}
-		$('replace#text').replaceWith('You are missing the <code>MANAGE_GUILD</code> permission.');
 	}
 	}
-
-	$('replace#text').replaceWith('Keks');
+	else {
+		$('#channellist').empty();
+		$('<div>').text('This is a list of all servers you can change settings on. Please select a server:').appendTo('#text');
+		if ( settings.guilds.isMember.size ) {
+			$('<h2 id="with-wikibot">').text('Server with Wiki-Bot').appendTo('#text');
+			$('<a class="channel">').attr('href', '#with-wikibot').append(
+				$('<img>').attr('src', '/src/channel.svg'),
+				$('<div>').text('Server with Wiki-Bot')
+			).appendTo('#channellist');
+			$('<div class="server-selector" id="isMember">').appendTo('#text');
+			settings.guilds.isMember.forEach( guild => {
+				$('<a class="server">').attr('href', `/guild/${guild.id}`).append(
+					( guild.icon ? 
+						$('<img class="avatar">').attr('src', `${guild.icon}?size=256`).attr('alt', guild.name)
+					 : $('<div class="avatar noicon">').text(guild.acronym) ),
+					$('<div class="server-name">').text(guild.name)
+				).appendTo('.server-selector#isMember');
+			} );
+		}
+		if ( settings.guilds.notMember.size ) {
+			$('<h2 id="without-wikibot">').text('Server without Wiki-Bot').appendTo('#text');
+			$('<a class="channel">').attr('href', '#without-wikibot').append(
+				$('<img>').attr('src', '/src/channel.svg'),
+				$('<div>').text('Server without Wiki-Bot')
+			).appendTo('#channellist');
+			$('<div class="server-selector" id="notMember">').appendTo('#text');
+			settings.guilds.notMember.forEach( guild => {
+				$('<a class="server">').attr('href', `/guild/${guild.id}`).append(
+					( guild.icon ? 
+						$('<img class="avatar">').attr('src', `${guild.icon}?size=256`).attr('alt', guild.name)
+					 : $('<div class="avatar noicon">').text(guild.acronym) ),
+					$('<div class="server-name">').text(guild.name)
+				).appendTo('.server-selector#notMember');
+			} );
+		}
+		$('#channellist:empty').remove();
+	}
 	let body = $.html();
 	let body = $.html();
 	res.writeHead(200, {'Content-Length': body.length});
 	res.writeHead(200, {'Content-Length': body.length});
 	res.write( body );
 	res.write( body );

+ 12 - 16
dashboard/index.html

@@ -12,24 +12,21 @@
 	<meta itemprop="author" content="MarkusRost">
 	<meta itemprop="author" content="MarkusRost">
 	<link rel="stylesheet" type="text/css" href="/src/index.css">
 	<link rel="stylesheet" type="text/css" href="/src/index.css">
 </head>
 </head>
-<body class="settings">
-	<div class="text">
-		<replace id="notice">Some text here</replace>
-		<replace id="text">Some text here</replace>
-	</div>
-	<div class="navbar">
+<body>
+	<div id="text"></div>
+	<div id="navbar">
 		<div style="width: 150px;"></div>
 		<div style="width: 150px;"></div>
 		<a id="support" href="https://discord.gg/v77RTk5" target="_blank" alt="Support server">
 		<a id="support" href="https://discord.gg/v77RTk5" target="_blank" alt="Support server">
-			<img class="avatar" src="https://cdn.discordapp.com/icons/464084451165732868/c6a8b9fc902b09545de8194a911e6045.png?size=128" alt="Support server" width="32" height="32">
+			<img class="avatar" src="https://cdn.discordapp.com/icons/464084451165732868/c6a8b9fc902b09545de8194a911e6045.png?size=128" alt="Support server">
 			<span>Support server</span>
 			<span>Support server</span>
 		</a>
 		</a>
 		<a id="logout" href="/logout" alt="Logout">
 		<a id="logout" href="/logout" alt="Logout">
-			<img class="avatar" src="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=64" alt="Logout" width="32" height="32">
+			<img class="avatar" src="https://cdn.discordapp.com/avatars/461189216198590464/f69cdc197791aed829882b64f9760dbb.png?size=64" alt="Logout">
 			<span>Wiki-Bot #2998</span>
 			<span>Wiki-Bot #2998</span>
 		</a>
 		</a>
 	</div>
 	</div>
-	<div class="sidebar">
-		<div class="guildlist">
+	<div class="scrollbar" id="sidebar">
+		<div id="guildlist">
 			<div class="guild" id="invite">
 			<div class="guild" id="invite">
 				<div class="bar"></div>
 				<div class="bar"></div>
 				<a href="https://discord.com/oauth2/authorize?client_id=461189216198590464&permissions=939912256&scope=bot" alt="Invite Wiki-Bot">
 				<a href="https://discord.com/oauth2/authorize?client_id=461189216198590464&permissions=939912256&scope=bot" alt="Invite Wiki-Bot">
@@ -40,8 +37,7 @@
 					</div>
 					</div>
 				</a>
 				</a>
 			</div>
 			</div>
-			<replace id="guilds">List of guilds here</replace>
-			<div class="guild">
+			<div class="guild" id="last-separator">
 				<div class="separator"></div>
 				<div class="separator"></div>
 			</div>
 			</div>
 			<div class="guild" id="refresh">
 			<div class="guild" id="refresh">
@@ -55,21 +51,21 @@
 				</a>
 				</a>
 			</div>
 			</div>
 		</div>
 		</div>
-		<div class="channellist">
+		<div class="scrollbar" id="channellist">
 			<a class="channel channel-header" id="settings">
 			<a class="channel channel-header" id="settings">
-				<svg width="24" height="24" viewBox="0 0 24 24">
+				<svg viewBox="0 0 24 24">
 					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"></path>
 					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"></path>
 				</svg>
 				</svg>
 				<div>Settings</div>
 				<div>Settings</div>
 			</a>
 			</a>
 			<a class="channel channel-header" id="verification">
 			<a class="channel channel-header" id="verification">
-				<svg width="24" height="24" viewBox="0 0 24 24">
+				<svg viewBox="0 0 24 24">
 					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"></path>
 					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"></path>
 				</svg>
 				</svg>
 				<div>Verifications</div>
 				<div>Verifications</div>
 			</a>
 			</a>
 			<a class="channel channel-header" id="rcgcdb">
 			<a class="channel channel-header" id="rcgcdb">
-				<svg width="24" height="24" viewBox="0 0 24 24">
+				<svg viewBox="0 0 24 24">
 					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"></path>
 					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"></path>
 				</svg>
 				</svg>
 				<div>Recent Changes</div>
 				<div>Recent Changes</div>

+ 15 - 12
dashboard/login.html

@@ -12,20 +12,17 @@
 	<meta itemprop="author" content="MarkusRost">
 	<meta itemprop="author" content="MarkusRost">
 	<link rel="stylesheet" type="text/css" href="/src/index.css">
 	<link rel="stylesheet" type="text/css" href="/src/index.css">
 </head>
 </head>
-<body class="settings">
-	<div class="text">
-		<replace id="notice">Some text here</replace>
-		<replace id="text">Some text here</replace>
-	</div>
-	<div class="navbar">
+<body>
+	<div id="text"></div>
+	<div id="navbar">
 		<div style="width: 150px;"></div>
 		<div style="width: 150px;"></div>
 		<a id="support" href="https://discord.gg/v77RTk5" target="_blank" alt="Support server">
 		<a id="support" href="https://discord.gg/v77RTk5" target="_blank" alt="Support server">
-			<img class="avatar" src="https://cdn.discordapp.com/icons/464084451165732868/c6a8b9fc902b09545de8194a911e6045.png?size=128" alt="Support server" width="32" height="32">
+			<img class="avatar" src="https://cdn.discordapp.com/icons/464084451165732868/c6a8b9fc902b09545de8194a911e6045.png?size=128" alt="Support server">
 			<span>Support server</span>
 			<span>Support server</span>
 		</a>
 		</a>
 	</div>
 	</div>
-	<div class="sidebar">
-		<div class="guildlist">
+	<div class="scrollbar" id="sidebar">
+		<div id="guildlist">
 			<div class="guild" id="invite">
 			<div class="guild" id="invite">
 				<div class="bar"></div>
 				<div class="bar"></div>
 				<a href="https://discord.com/oauth2/authorize?client_id=461189216198590464&permissions=939912256&scope=bot" alt="Invite Wiki-Bot">
 				<a href="https://discord.com/oauth2/authorize?client_id=461189216198590464&permissions=939912256&scope=bot" alt="Invite Wiki-Bot">
@@ -37,11 +34,17 @@
 				</a>
 				</a>
 			</div>
 			</div>
 		</div>
 		</div>
-		<div class="channellist">
-			<a class="channel" id="login">
-				<img src="/src/channel.svg" width="20" height="20">
+		<div class="scrollbar" id="channellist">
+			<a class="channel channel-header" id="login">
+				<svg viewBox="0 0 24 24">
+					<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"></path>
+				</svg>
 				<div>Login</div>
 				<div>Login</div>
 			</a>
 			</a>
+			<a class="channel" id="invite-wikibot">
+				<img src="/src/channel.svg" width="20" height="20">
+				<div>Invite Wiki-Bot</div>
+			</a>
 		</div>
 		</div>
 	</div>
 	</div>
 </body>
 </body>

+ 14 - 14
dashboard/oauth.js

@@ -27,33 +27,33 @@ function dashboard_login(res, state, action) {
 		res.setHeader('Set-Cookie', [`wikibot="${state}"; Max-Age=0; HttpOnly`]);
 		res.setHeader('Set-Cookie', [`wikibot="${state}"; Max-Age=0; HttpOnly`]);
 	}
 	}
 	var $ = cheerio.load(file);
 	var $ = cheerio.load(file);
-	$('.guild#invite a').attr('href', oauth.generateAuthUrl( {
+	let invite = oauth.generateAuthUrl( {
 		scope: ['identify', 'guilds', 'bot'],
 		scope: ['identify', 'guilds', 'bot'],
 		permissions: defaultPermissions, state
 		permissions: defaultPermissions, state
-	} ));
+	} );
+	$('.guild#invite a').attr('href', invite);
+	$('.channel#invite-wikibot').attr('href', invite);
 	let responseCode = 200;
 	let responseCode = 200;
-	let notice = '';
 	if ( action === 'failed' ) {
 	if ( action === 'failed' ) {
 		responseCode = 400;
 		responseCode = 400;
-		notice = createNotice($, {
+		createNotice($, {
 			title: 'Login failed!',
 			title: 'Login failed!',
 			text: 'An error occurred while logging you in, please try again.'
 			text: 'An error occurred while logging you in, please try again.'
-		});
+		}).prependTo('#text');
 	}
 	}
 	if ( action === 'unauthorized' ) {
 	if ( action === 'unauthorized' ) {
 		responseCode = 401;
 		responseCode = 401;
-		notice = createNotice($, {
+		createNotice($, {
 			title: 'Not logged in!',
 			title: 'Not logged in!',
 			text: 'Please login before you can change any settings.'
 			text: 'Please login before you can change any settings.'
-		});
+		}).prependTo('#text');
 	}
 	}
 	if ( action === 'logout' ) {
 	if ( action === 'logout' ) {
-		notice = createNotice($, {
+		createNotice($, {
 			title: 'Successfully logged out!',
 			title: 'Successfully logged out!',
 			text: 'You have been successfully logged out. To change any settings you need to login again.'
 			text: 'You have been successfully logged out. To change any settings you need to login again.'
-		});
+		}).prependTo('#text');
 	}
 	}
-	$('replace#notice').replaceWith(notice);
 	state = crypto.randomBytes(16).toString("hex");
 	state = crypto.randomBytes(16).toString("hex");
 	while ( settingsData.has(state) ) {
 	while ( settingsData.has(state) ) {
 		state = crypto.randomBytes(16).toString("hex");
 		state = crypto.randomBytes(16).toString("hex");
@@ -62,8 +62,8 @@ function dashboard_login(res, state, action) {
 		scope: ['identify', 'guilds'],
 		scope: ['identify', 'guilds'],
 		prompt: 'none', state
 		prompt: 'none', state
 	} );
 	} );
-	$('a#login').attr('href', url);
-	$('replace#text').replaceWith(`<a href="${url}">Login</a>`);
+	$('.channel#login').attr('href', url);
+	$('<a>').attr('href', url).text('Login').appendTo('#text');
 	let body = $.html();
 	let body = $.html();
 	res.writeHead(responseCode, {
 	res.writeHead(responseCode, {
 		'Set-Cookie': [`wikibot="${state}"; HttpOnly`],
 		'Set-Cookie': [`wikibot="${state}"; HttpOnly`],
@@ -106,7 +106,7 @@ function dashboard_oauth(res, state, searchParams, lastGuild) {
 					name: guild.name,
 					name: guild.name,
 					acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
 					acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
 					icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
 					icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
-					+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) + '?size=128' : null ),
+					+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) : null ),
 					permissions: guild.permissions
 					permissions: guild.permissions
 				};
 				};
 			} );
 			} );
@@ -177,7 +177,7 @@ function dashboard_refresh(res, state, returnLocation = '/') {
 				name: guild.name,
 				name: guild.name,
 				acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
 				acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
 				icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
 				icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
-				+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) + '?size=128' : null ),
+				+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) : null ),
 				permissions: guild.permissions
 				permissions: guild.permissions
 			};
 			};
 		} );
 		} );

+ 1 - 1
dashboard/src/channel.svg

@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
 	<path fill="#8e9297" 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>
 	<path fill="#8e9297" 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>
 </svg>

+ 78 - 32
dashboard/src/index.css

@@ -21,17 +21,17 @@ a[alt]:hover:after {
 	color: #dcddde;
 	color: #dcddde;
 	font-weight: bold;
 	font-weight: bold;
 	font-size: 90%;
 	font-size: 90%;
-	white-space: nowrap;
+	word-break: break-word;
 	border-radius: 4px;
 	border-radius: 4px;
 	padding: 8px;
 	padding: 8px;
 }
 }
-.text a {
+#text a {
 	color: #00b0f4;
 	color: #00b0f4;
 }
 }
-.text a:hover {
+#text a:hover {
 	text-decoration: underline;
 	text-decoration: underline;
 }
 }
-.text {
+#text {
 	position: relative;
 	position: relative;
 	padding: 8px;
 	padding: 8px;
 	width: calc(100% - 328px);
 	width: calc(100% - 328px);
@@ -47,7 +47,38 @@ a[alt]:hover:after {
 	background: #200;
 	background: #200;
 	border: 2px solid #500;
 	border: 2px solid #500;
 }
 }
-.navbar {
+.server-selector {
+	display: flex;
+	flex-wrap: wrap;
+}
+.server {
+	background-color: rgba(0,0,0,0.5);
+	text-align: center;
+	border-radius: 10%;
+	width: 200px;
+	margin: 5px;
+}
+.server-selector .server:hover {
+	background: rgba(0,0,0,0.3);
+	filter: brightness(1.2);
+	text-decoration: none;
+}
+.server .avatar {
+	border-radius: 10%;
+	width: 200px;
+	height: 200px;
+}
+.server .noicon {
+	font-size: 416%;
+	background-color: unset;
+}
+.server .server-name {
+	padding: 8px 12px;
+	word-break: break-word;
+	font-weight: bold;
+	font-size: 90%;
+}
+#navbar {
 	background: #2f3136;
 	background: #2f3136;
 	position: fixed;
 	position: fixed;
 	top: 0;
 	top: 0;
@@ -56,46 +87,62 @@ a[alt]:hover:after {
 	display: flex;
 	display: flex;
 	align-items: center;
 	align-items: center;
 	justify-content: space-between;
 	justify-content: space-between;
-	height: 48px;
+	height: 47px;
 	padding: 0 0 0 8px;
 	padding: 0 0 0 8px;
 	font-size: 16px;
 	font-size: 16px;
 	line-height: 20px;
 	line-height: 20px;
 	font-weight: bold;
 	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;
+	border-bottom: 1px solid rgba(4,4,5,0.2);
 }
 }
-.navbar a {
+:target::before {
+	content: "";
+	display: block;
+	height: 48px;
+	margin: -48px 0 0;
+}
+#navbar a {
 	display: flex;
 	display: flex;
 	align-items: center;
 	align-items: center;
 	height: 100%;
 	height: 100%;
 	padding-left: 10px;
 	padding-left: 10px;
 }
 }
-.navbar a:hover {
+#navbar a:hover {
 	background: #202225;
 	background: #202225;
 }
 }
-.navbar .avatar {
+#navbar a[alt]:hover:after {
+	top: 48px;
+}
+#navbar .avatar {
 	width: 32px;
 	width: 32px;
 	height: 32px;
 	height: 32px;
 }
 }
-.navbar span {
+#navbar span {
 	padding: 0 10px;
 	padding: 0 10px;
 }
 }
-.sidebar {
-	background: #202225;
-	position: absolute;
+.scrollbar {
+	-ms-overflow-style: none;
+	scrollbar-width: none;
+}
+.scrollbar::-webkit-scrollbar {
+	display: none;
+}
+#sidebar {
+	position: fixed;
+	display: flex;
 	top: 0;
 	top: 0;
 	left: 0;
 	left: 0;
-	min-height: calc(100% + 48px);
-	width: 72px;
-	display: flex;
+	bottom: 0;
+	width: 312px;
+	overflow: visible scroll;
 }
 }
-.guildlist {
+#guildlist {
+	background: #202225;
+	position: absolute;
 	padding: 12px 0;
 	padding: 12px 0;
-	position: relative;
 	flex: 1 1 auto;
 	flex: 1 1 auto;
-	z-index: 2;
+	min-height: calc(100% - 24px);
+	width: 72px;
+	z-index: 1;
 }
 }
 .guild {
 .guild {
 	margin: 0 0 8px;
 	margin: 0 0 8px;
@@ -110,14 +157,13 @@ a[alt]:hover:after {
 	display: flex;
 	display: flex;
 	align-items: center;
 	align-items: center;
 	justify-content: center;
 	justify-content: center;
-	font-weight: 500;
 	line-height: 1.2em;
 	line-height: 1.2em;
 	white-space: nowrap;
 	white-space: nowrap;
 	overflow: hidden;
 	overflow: hidden;
 	color: #dcddde;
 	color: #dcddde;
 	font-weight: bold;
 	font-weight: bold;
 }
 }
-.navbar a:hover .avatar,
+#navbar a:hover .avatar,
 .guild.selected .avatar,
 .guild.selected .avatar,
 .guild:hover .avatar {
 .guild:hover .avatar {
 	border-radius: 30%;
 	border-radius: 30%;
@@ -167,19 +213,19 @@ a[alt]:hover:after {
 .guild a[alt]:hover:after {
 .guild a[alt]:hover:after {
 	top: 20%;
 	top: 20%;
 	left: 72px;
 	left: 72px;
+	max-width: 224px;
+	width: max-content;
 }
 }
-.navbar a[alt]:hover:after {
-	top: 48px;
-}
-.channellist {
+#channellist {
 	background: #2f3136;
 	background: #2f3136;
-	position: absolute;
-	min-height: calc(100% - 80px);
+	position: fixed;
+	overflow: hidden scroll;
 	padding: 16px 0;
 	padding: 16px 0;
 	width: 240px;
 	width: 240px;
 	top: 48px;
 	top: 48px;
 	left: 72px;
 	left: 72px;
-	z-index: 1;
+	bottom: 0;
+	z-index: 0;
 }
 }
 .channel {
 .channel {
 	padding: 0 8px;
 	padding: 0 8px;

+ 8 - 8
dashboard/util.js

@@ -73,16 +73,16 @@ function sendMsg(message) {
 /**
 /**
  * Create a red notice
  * Create a red notice
  * @param {CheerioStatic} $ - The cheerio static
  * @param {CheerioStatic} $ - The cheerio static
- * @param {{title: String, text: String}[]} notices - The notices to create
+ * @param {Object} notice - The notices to create
+ * @param {String} notice.title - The title of the notice
+ * @param {String} notice.text - The text of the notice
  * @returns {Cheerio}
  * @returns {Cheerio}
  */
  */
-function createNotice($, ...notices) {
-	return notices.map( notice => {
-		return $('<div class="notice">').append(
-			$('<b>').text(notice.title),
-			$('<div>').text(notice.text)
-		);
-	} );
+function createNotice($, notice) {
+	return $('<div class="notice">').append(
+		$('<b>').text(notice.title),
+		$('<div>').text(notice.text)
+	);
 }
 }
 
 
 const permissions = {
 const permissions = {