├── pages ├── templates │ ├── login │ │ └── error.html │ ├── message │ │ ├── mention.html │ │ ├── first_message_content.html │ │ ├── merged_message_content.html │ │ └── message.html │ ├── icon.html │ ├── channellist │ │ ├── categorychannel.html │ │ └── textchannel.html │ ├── server │ │ ├── server_icon.html │ │ └── invalid_server.html │ ├── index │ │ ├── logged_out.html │ │ └── logged_in.html │ ├── channel │ │ ├── no_message_history.html │ │ ├── input.html │ │ └── input_disabled.html │ ├── server.html │ ├── forgot.html │ ├── guest.html │ ├── login.html │ ├── index.html │ ├── channel.html │ └── register.html ├── static │ ├── resources │ │ ├── logo.png │ │ ├── logo_old.png │ │ └── images │ │ │ ├── menu.png │ │ │ ├── refresh.png │ │ │ └── menuspacer.png │ ├── webapp.html │ └── connection.js ├── forgot.js ├── index.js ├── register.js ├── login.js ├── guest.js ├── send.js ├── server.js └── channel.js ├── .gitignore ├── README.md ├── package.json ├── bot.js ├── .github └── workflows │ └── codeql-analysis.yml ├── connectionHandler.js ├── index.js ├── authentication.js └── LICENSE.txt /pages/templates/login/error.html: -------------------------------------------------------------------------------- 1 | {$ERROR_MESSAGE}
-------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | secrets 4 | secrets-old 5 | start.sh 6 | getssl -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # discross 2 | A webhook bridge to send messages on Discord through a webpage 3 | -------------------------------------------------------------------------------- /pages/static/resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Heath123/discross/HEAD/pages/static/resources/logo.png -------------------------------------------------------------------------------- /pages/static/resources/logo_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Heath123/discross/HEAD/pages/static/resources/logo_old.png -------------------------------------------------------------------------------- /pages/templates/message/mention.html: -------------------------------------------------------------------------------- 1 | {$USERNAME} -------------------------------------------------------------------------------- /pages/static/resources/images/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Heath123/discross/HEAD/pages/static/resources/images/menu.png -------------------------------------------------------------------------------- /pages/static/resources/images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Heath123/discross/HEAD/pages/static/resources/images/refresh.png -------------------------------------------------------------------------------- /pages/templates/icon.html: -------------------------------------------------------------------------------- 1 | {$SERVER_NAME} -------------------------------------------------------------------------------- /pages/static/resources/images/menuspacer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Heath123/discross/HEAD/pages/static/resources/images/menuspacer.png -------------------------------------------------------------------------------- /pages/templates/message/first_message_content.html: -------------------------------------------------------------------------------- 1 | {$MESSAGE_TEXT} -------------------------------------------------------------------------------- /pages/templates/channellist/categorychannel.html: -------------------------------------------------------------------------------- 1 | 2 | {$CHANNEL_NAME} 3 | 4 |
-------------------------------------------------------------------------------- /pages/templates/message/merged_message_content.html: -------------------------------------------------------------------------------- 1 |
{$MESSAGE_TEXT}
2 | -------------------------------------------------------------------------------- /pages/templates/server/server_icon.html: -------------------------------------------------------------------------------- 1 | {$SERVER_NAME}

-------------------------------------------------------------------------------- /pages/templates/server/invalid_server.html: -------------------------------------------------------------------------------- 1 | Click on a server! Home -------------------------------------------------------------------------------- /pages/templates/channellist/textchannel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | #  {$CHANNEL_NAME} 4 | 5 | 6 |
-------------------------------------------------------------------------------- /pages/templates/index/logged_out.html: -------------------------------------------------------------------------------- 1 | Login   2 | Register   -------------------------------------------------------------------------------- /pages/templates/channel/no_message_history.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |           4 | You do not have permission to view the message history of this channel. 5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /pages/templates/channel/input.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pages/templates/index/logged_in.html: -------------------------------------------------------------------------------- 1 | Logged in as {$USER}   2 | Server list   3 | Logout   -------------------------------------------------------------------------------- /pages/templates/channel/input_disabled.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pages/templates/server.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Discross - Menu 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 27 | 28 | 29 |
19 | Home
20 |
21 | {$SERVER_LIST} 22 |
- 25 | {$CHANNEL_LIST} 26 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /pages/forgot.js: -------------------------------------------------------------------------------- 1 | var url = require('url'); 2 | var fs = require('fs'); 3 | var minify = require('html-minifier').minify; 4 | var escape = require('escape-html'); 5 | 6 | var auth = require('../authentication.js'); 7 | 8 | const forgot_template = minify(fs.readFileSync('pages/templates/forgot.html', 'utf-8')); 9 | const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8')); 10 | 11 | function strReplace(string, needle, replacement) { 12 | return string.split(needle).join(replacement||""); 13 | }; 14 | 15 | exports.processForgot = async function(bot, req, res, args) { 16 | parsedurl = url.parse(req.url, true); 17 | response = forgot_template; 18 | if (parsedurl.query.errortext) { 19 | response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "
"))); 20 | } else { 21 | response = strReplace(response, "{$ERROR}", ""); 22 | } 23 | res.write(response); 24 | res.end(); 25 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discross", 3 | "version": "0.9.0", 4 | "description": "A webhook bridge to send messages on Discord through a webpage", 5 | "main": "index.js", 6 | "dependencies": { 7 | "axios": "^0.21.2", 8 | "bcrypt": "^5.0.0", 9 | "discord.js": "github:discordjs/discord.js", 10 | "escape-html": "^1.0.3", 11 | "he": "^1.2.0", 12 | "html-minifier": "^4.0.0", 13 | "markdown-it": "^10.0.0", 14 | "mime-types": "^2.1.26", 15 | "owasp-password-strength-test": "^1.3.0", 16 | "sqlite3": "^4.1.1", 17 | "uuid": "^3.4.0" 18 | }, 19 | "devDependencies": { 20 | "standard": "^14.3.4" 21 | }, 22 | "scripts": { 23 | "test": "echo \"Error: no test specified\" && exit 1" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/Heath123/discross.git" 28 | }, 29 | "author": "Heath Mitchell, circuit10#0158, github.com/Heath123, heath.mitchell27@gmail.com", 30 | "license": "AGPL-3.0", 31 | "bugs": { 32 | "url": "https://github.com/Heath123/discross/issues" 33 | }, 34 | "homepage": "https://github.com/Heath123/discross#readme" 35 | } -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var minify = require('html-minifier').minify; 3 | var escape = require('escape-html'); 4 | 5 | var auth = require('../authentication.js'); 6 | 7 | const index_template = minify(fs.readFileSync('pages/templates/index.html', 'utf-8')); 8 | 9 | const logged_in_template = minify(fs.readFileSync('pages/templates/index/logged_in.html', 'utf-8')); 10 | const logged_out_template = minify(fs.readFileSync('pages/templates/index/logged_out.html', 'utf-8')); 11 | 12 | function strReplace(string, needle, replacement) { 13 | return string.split(needle).join(replacement||""); 14 | }; 15 | 16 | exports.processIndex = async function(bot, req, res, args) { 17 | discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page 18 | if (discordID) { 19 | response = strReplace(index_template, "{$MENU_OPTIONS}", 20 | strReplace(logged_in_template, "{$USER}", escape(await auth.getUsername(discordID))) 21 | ); 22 | } else { 23 | response = strReplace(index_template, "{$MENU_OPTIONS}", logged_out_template); 24 | } 25 | res.write(response); 26 | res.end(); 27 | } -------------------------------------------------------------------------------- /pages/templates/message/message.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 | 7 | 8 | 9 | 24 | 25 | 26 |
- 10 |
11 | 12 |
13 | {$MESSAGE_AUTHOR} 14 | {$MESSAGE_DATE}
15 |
16 | 17 |
18 | 19 | 20 | {$MESSAGE_CONTENT} 21 |
22 |
23 |
27 |
-------------------------------------------------------------------------------- /pages/register.js: -------------------------------------------------------------------------------- 1 | var url = require('url'); 2 | var fs = require('fs'); 3 | var minify = require('html-minifier').minify; 4 | var escape = require('escape-html'); 5 | 6 | var auth = require('../authentication.js'); 7 | 8 | const register_template = minify(fs.readFileSync('pages/templates/register.html', 'utf-8')); 9 | const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8')); 10 | 11 | function strReplace(string, needle, replacement) { 12 | return string.split(needle).join(replacement||""); 13 | }; 14 | 15 | exports.processRegister = async function(bot, req, res, args) { 16 | discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page 17 | if (discordID) { 18 | res.writeHead(302, {"Location": "/server/"}); 19 | res.write('Logged in! Click here to continue.'); 20 | } else { 21 | parsedurl = url.parse(req.url, true); 22 | response = register_template; 23 | if (parsedurl.query.errortext) { 24 | response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "
"))); 25 | } else { 26 | response = strReplace(response, "{$ERROR}", ""); 27 | } 28 | res.write(response); 29 | } 30 | res.end(); 31 | } -------------------------------------------------------------------------------- /pages/login.js: -------------------------------------------------------------------------------- 1 | var url = require('url'); 2 | var fs = require('fs'); 3 | var minify = require('html-minifier').minify; 4 | var escape = require('escape-html'); 5 | 6 | var auth = require('../authentication.js'); 7 | 8 | const login_template = minify(fs.readFileSync('pages/templates/login.html', 'utf-8')); 9 | const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8')); 10 | 11 | function strReplace(string, needle, replacement) { 12 | return string.split(needle).join(replacement||""); 13 | }; 14 | 15 | exports.processLogin = async function(bot, req, res, args) { 16 | discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page 17 | if (discordID) { 18 | // res.writeHead(200, {'Content-Type': 'text/html'}); 19 | res.writeHead(303, {"Location": "/server/", "Content-Type": "text/html"}); 20 | res.write('Logged in! Click here to continue.'); 21 | } else { 22 | parsedurl = url.parse(req.url, true); 23 | response = login_template; 24 | if (parsedurl.query.redirect) { 25 | response = strReplace(response, "{$REDIRECT_URL}", strReplace(parsedurl.query.redirect, '"', "%22")); 26 | } else { 27 | response = strReplace(response, "{$REDIRECT_URL}", "/server/"); 28 | } 29 | if (parsedurl.query.errortext) { 30 | response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "
"))); 31 | } else { 32 | response = strReplace(response, "{$ERROR}", ""); 33 | } 34 | res.write(response); 35 | } 36 | res.end(); 37 | } -------------------------------------------------------------------------------- /pages/guest.js: -------------------------------------------------------------------------------- 1 | var url = require('url'); 2 | var fs = require('fs'); 3 | var minify = require('html-minifier').minify; 4 | var escape = require('escape-html'); 5 | 6 | var auth = require('../authentication.js'); 7 | 8 | const guest_login_template = minify(fs.readFileSync('pages/templates/guest.html', 'utf-8')); 9 | const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8')); 10 | 11 | function strReplace(string, needle, replacement) { 12 | return string.split(needle).join(replacement||""); 13 | }; 14 | 15 | exports.processGuestLogin = async function(bot, req, res, args) { 16 | discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page 17 | if (discordID) { 18 | // res.writeHead(200, {'Content-Type': 'text/html'}); 19 | res.writeHead(303, {"Location": "/server/", "Content-Type": "text/html"}); 20 | res.write('Logged in! Click here to continue.'); 21 | } else { 22 | parsedurl = url.parse(req.url, true); 23 | response = guest_login_template; 24 | if (parsedurl.query.redirect) { 25 | response = strReplace(response, "{$REDIRECT_URL}", strReplace(parsedurl.query.redirect, '"', "%22")); 26 | } else { 27 | response = strReplace(response, "{$REDIRECT_URL}", "/server/"); 28 | } 29 | if (parsedurl.query.errortext) { 30 | response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "
"))); 31 | } else { 32 | response = strReplace(response, "{$ERROR}", ""); 33 | } 34 | res.write(response); 35 | } 36 | res.end(); 37 | } -------------------------------------------------------------------------------- /pages/static/webapp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Discross 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 31 | 32 | 33 | 34 |