├── .gitignore
├── .gitattributes
├── router.js
├── config.json.example
├── routes
├── index.js
└── discord.js
├── views
├── partials
│ └── navbar.ejs
└── index.ejs
├── app.js
├── package.json
├── static
└── stylesheet.css
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | config.json
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/router.js:
--------------------------------------------------------------------------------
1 | module.exports = (app) => {
2 | // '/'
3 | app.use('/', require('./routes/index'));
4 |
5 | // '/authorize'
6 | app.use('/authorize', require('./routes/discord'));
7 | }
--------------------------------------------------------------------------------
/config.json.example:
--------------------------------------------------------------------------------
1 | {
2 | "port": 3000,
3 |
4 | "clientId": "",
5 | "clientSecret": "",
6 | "scopes": ["identify", "guilds"],
7 | "redirectUri": "http://localhost:3000/authorize/callback"
8 | }
--------------------------------------------------------------------------------
/routes/index.js:
--------------------------------------------------------------------------------
1 | const router = require('express').Router();
2 |
3 | router.get('/', (req, res) => {
4 | res.render('index', { pageTitle: 'Dashboard', user: req.session.user || null });
5 | });
6 |
7 | module.exports = router;
--------------------------------------------------------------------------------
/views/partials/navbar.ejs:
--------------------------------------------------------------------------------
1 |
16 |
Welcome
17 |
To get started, login by clicking Login on the navbar, then go to the servers page and choose a server to manage.
18 |
19 |
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "discord.js-dashboard",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app.js"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/caelinj/discord.js-dashboard.git"
13 | },
14 | "keywords": [],
15 | "author": "",
16 | "license": "ISC",
17 | "bugs": {
18 | "url": "https://github.com/caelinj/discord.js-dashboard/issues"
19 | },
20 | "homepage": "https://github.com/caelinj/discord.js-dashboard#readme",
21 | "dependencies": {
22 | "ejs": "^2.6.1",
23 | "express": "^4.16.3",
24 | "express-session": "^1.15.6",
25 | "form-data": "^2.3.2",
26 | "node-fetch": "^2.2.0",
27 | "uid-safe": "^2.1.5"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/static/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Roboto:300,500');
2 |
3 | body {
4 | background: #2C2F33;
5 | margin: 0 0;
6 | padding: 0 0;
7 | }
8 |
9 | .page-content {
10 | padding: 4px 42px;
11 | }
12 |
13 | .page-content h1 { margin-bottom: -10px; }
14 |
15 | h1, h2, h3, h4, h5, h6 {
16 | font-family: 'Roboto', sans-serif;
17 | font-weight: 500;
18 | color: #ffffff;
19 | }
20 |
21 | p, a {
22 | font-family: 'Roboto', sans-serif;
23 | font-weight: 300;
24 | color: #ffffff;
25 | }
26 |
27 | .navbar {
28 | background: #23272A;
29 | padding: 21px 42px;
30 | }
31 |
32 | .navbar a {
33 | transition: .25s ease;
34 | color: #ffffff;
35 | text-decoration: none;
36 | }
37 |
38 | .navbar a:hover {
39 | color: #7792f3;
40 | }
41 |
42 | .navbar a:not(:last-child) {
43 | margin-right: 12px;
44 | }
45 |
46 | .navbar .right {
47 | float: right;
48 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 caelinj
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/routes/discord.js:
--------------------------------------------------------------------------------
1 | const router = require('express').Router();
2 |
3 | const { clientId, clientSecret, scopes, redirectUri } = require('../config.json');
4 | const fetch = require('node-fetch');
5 | const FormData = require('form-data');
6 |
7 | const forceAuth = (req, res, next) => {
8 | if (!req.session.user) return res.redirect('/authorize')
9 | else return next();
10 | }
11 |
12 | router.get('/', (req, res) => {
13 | if (req.session.user) return res.redirect('/');
14 |
15 | const authorizeUrl = `https://discordapp.com/api/oauth2/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&scope=${scopes.join('%20')}`;
16 | res.redirect(authorizeUrl);
17 | });
18 |
19 | router.get('/callback', (req, res) => {
20 | if (req.session.user) return res.redirect('/');
21 |
22 | const accessCode = req.query.code;
23 | if (!accessCode) throw new Error('No access code returned frm Discord');
24 |
25 | const data = new FormData();
26 | data.append('client_id', clientId);
27 | data.append('client_secret', clientSecret);
28 | data.append('grant_type', 'authorization_code');
29 | data.append('redirect_uri', redirectUri);
30 | data.append('scope', scopes.join(' '));
31 | data.append('code', accessCode);
32 |
33 | fetch('https://discordapp.com/api/oauth2/token', {
34 | method: 'POST',
35 | body: data
36 | })
37 | .then(res => res.json())
38 | .then(response => {
39 | fetch('https://discordapp.com/api/users/@me', {
40 | method: 'GET',
41 | headers: {
42 | authorization: `${response.token_type} ${response.access_token}`
43 | },
44 | })
45 | .then(res2 => res2.json())
46 | .then(userResponse => {
47 | userResponse.tag = `${userResponse.username}#${userResponse.discriminator}`;
48 | userResponse.avatarURL = userResponse.avatar ? `https://cdn.discordapp.com/avatars/${userResponse.id}/${userResponse.avatar}.png?size=1024` : null;
49 |
50 | req.session.user = userResponse;
51 | res.redirect('/');
52 | });
53 | });
54 | });
55 |
56 | router.get('/logout', forceAuth, (req, res) => {
57 | req.session.destroy();
58 | });
59 |
60 | module.exports = router;
--------------------------------------------------------------------------------