New Docker Structure

This commit is contained in:
Starystars67 2023-12-06 12:08:49 +00:00
parent 691c8afe87
commit 97cd0c9444
36 changed files with 1972 additions and 1072 deletions

25
Dockerfile Normal file
View File

@ -0,0 +1,25 @@
FROM node:18.16.0-alpine3.17
# Create app directory
WORKDIR /app
RUN apk --no-cache add curl
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json /app
# General Install of Deps
# RUN npm install
# If you are building your code for production
RUN npm ci --only=production
# Bundle app source
COPY . /app
EXPOSE 3599
HEALTHCHECK CMD curl --fail http://localhost:3599/ping || exit 1
CMD [ "node", "index.js" ]

View File

@ -1,22 +0,0 @@
var express = require('express');
var router = express.Router();
module.exports = function(){
router.get('/forum', function(req, res) {
res.redirect('https://forum.beammp.com/');
});
router.get('/servers', function(req, res) {
res.render('servers.ejs');
});
router.get('/stats', function(req, res) {
res.render('stats.ejs');
});
router.get('/keymaster', function(req, res) {
res.redirect('https://forum.beammp.com/');
});
return router;
}

3
example.env Normal file
View File

@ -0,0 +1,3 @@
INSTANCES=3
DEBUG=false
PORT=3000

129
index.js
View File

@ -1,56 +1,93 @@
// Define all Items we require
var express = require('express');
var express = require('express');
var bodyParser = require('body-parser');
#!/usr/bin/env node
const chalk = require('chalk');
const error = chalk.bold.keyword('red');
const warn = chalk.keyword('orange');
const good = chalk.keyword('lime');
/*
* oooooooooo. ooo ooooo ooooooooo.
* `888' `Y8b `88. .888' `888 `Y88.
* 888 888 .ooooo. .oooo. ooo. .oo. .oo. 888b d'888 888 .d88'
* 888oooo888' d88' `88b `P )88b `888P"Y88bP"Y88b 8 Y88. .P 888 888ooo88P'
* 888 `88b 888ooo888 .oP"888 888 888 888 8 `888' 888 888
* 888 .88P 888 .o d8( 888 888 888 888 8 Y 888 888
* o888bood8P' `Y8bod8P' `Y888""8o o888o o888o o888o o8o o888o o888o
* ========================================================================
* Copyright (c) 2019-2023 BeamMP Ltd. All rights reserved.
*/
// Setup Webserver
var app = express();
require('dotenv').config()
const pkg = require('./package.json')
const chalk = require('chalk');
const cluster = require('cluster');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const error = chalk.bold.keyword('red');
const warn = chalk.keyword('orange');
const good = chalk.keyword('lime');
// PROXY HANDLING
app.set('trust proxy', true);
// set the view engine to ejs
app.set('view engine', 'ejs');
app.use(express.static('static'))
app.set("views", "./views")
// use res.render to load up an ejs view file
// index page
app.get('/', function(req, res) {
res.render('index');
process.on('warning', (warning) => {
console.log(warning.stack);
});
var routes = require('./app/routes.js');
app.use('/', routes);
if (cluster.isMaster) {
app.get('/builds/launcher', function(req, res) {
if (req.query.download == 'true') {
const file = `${__dirname}/builds/launcher/launcher.exe`;
res.download(file); // Set disposition and send it.
} else if (req.query.version == 'true') {
const file = `${__dirname}/builds/launcher/version.json`;
res.download(file); // Set disposition and send it.
} else {
//res.sendStatus(403)
res.send("Not Found!")
const env = process.env.NODE_ENV || 'development'
console.log('oooooooooo. ooo ooooo ooooooooo. ')
console.log('`888\' `Y8b `88. .888\' `888 `Y88. ')
console.log(' 888 888 .ooooo. .oooo. ooo. .oo. .oo. 888b d\'888 888 .d88\' ')
console.log(' 888oooo888\' d88\' `88b `P )88b `888P"Y88bP"Y88b 8 Y88. .P 888 888ooo88P\' ')
console.log(' 888 `88b 888ooo888 .oP"888 888 888 888 8 `888\' 888 888 ')
console.log(' 888 .88P 888 .o d8( 888 888 888 888 8 Y 888 888 ')
console.log('o888bood8P\' `Y8bod8P\' `Y888""8o o888o o888o o888o o8o o888o o888o ')
console.log('=================================================================================')
console.log('Website v' + pkg.version + ' Copyright (C) 2019-2024 BeamMP Ltd')
console.log('')
console.log('Running in: ' + env)
console.log('Server Time: ' + new Date())
function start() {
process.title = pkg.name + "@" + pkg.version;
if (cluster.isMaster) {
console.log(`Master PID: ${process.pid}`)
console.log(`Creating ${process.env.INSTANCES} Instances of the Website Backend`)
for (let i = 0; i < process.env.INSTANCES; i++) {
cluster.fork();
}
// set console's directory so we can see output from workers
console.dir(cluster.workers, { depth: 0 });
cluster.on('exit', (worker, code) => {
// Good exit code is 0 :))
// exitedAfterDisconnect ensures that it is not killed by master cluster or manually
// if we kill it via .kill or .disconnect it will be set to true
// \x1b[XXm represents a color, and [0m represent the end of this
//color in the console ( 0m sets it to white again )
if (code !== 0 && !worker.exitedAfterDisconnect) {
console.error(`\x1b[34mWorker ${worker.process.pid} crashed... Starting a new worker...\x1b[0m`);
const nw = cluster.fork();
console.error(`\x1b[32mWorker ${nw.process.pid} will replace him \x1b[0m`);
}
});
} else {
console.error('FATAL: This script can only be run as a master process.')
}
}
});
app.get('/builds/server', function(req, res) {
console.log(req.params)
const file = `${__dirname}/builds/server/server.zip`;
res.download(file); // Set disposition and send it.
});
start()
} else {
const ws = require('./src/webserver')
app.listen(3599);
console.log('3599 is the magic port');
try {
ws.init(function (err) {
if (err) {
console.error(err)
return
}
ws.listen(function () {
console.info('BeamMP Website Ready')
})
})
} catch (e) {
throw e;
}
}

1305
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,29 @@
{
"name": "beammp-website",
"version": "1.0.0",
"description": "",
"description": "BeamMP Website",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"docker-build": "docker build -t 192.168.100.6:5000/beammp/website:latest -t 192.168.100.6:5000/beammp/website:1.0.0 .",
"docker-push": "docker push 192.168.100.6:5000/beammp/website:latest"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Starystars67/BeamMP-Website.git"
"url": "git+https://github.com/BeamMP/BeamMP-Website.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/Starystars67/BeamMP-Website/issues"
"url": "https://github.com/BeamMP/BeamMP-Website/issues"
},
"homepage": "https://github.com/Starystars67/BeamMP-Website#readme",
"homepage": "https://github.com/BeamMP/BeamMP-Website#readme",
"dependencies": {
"body-parser": "^1.19.0",
"chalk": "^3.0.0",
"dotenv": "^16.0.3",
"ejs": "^3.0.1",
"express": "^4.17.1"
"express": "^4.17.1",
"helmet": "^6.1.5",
"morgan": "^1.10.0"
}
}

72
src/routes.js Normal file
View File

@ -0,0 +1,72 @@
var express = require('express');
var router = express.Router();
function mainRoutes(router) {
router.get('/', function (req, res) {
res.render('index.ejs');
});
router.get('/servers', function (req, res) {
res.render('servers.ejs');
});
router.get('/stats', function (req, res) {
res.render('stats.ejs');
});
router.get('/ping', function (req, res) {
res.send('OK');
});
}
module.exports = function (app) {
try {
mainRoutes(router)
} catch (e) {
console.error(e)
}
app.use('/', router)
app.use(handle404)
app.use(handleErrors)
app.use(clientErrorHandler)
}
function handleErrors(err, req, res) {
const status = err.status || 500
res.status(err.status)
if (status === 429) {
res.render('429', { layout: false })
return
}
if (status === 500) {
res.render('500', { layout: false })
return
}
if (status === 503) {
res.render('503', { layout: false })
return
}
winston.warn(err.stack)
res.json({
message: err.message,
error: err,
})
}
function handle404(req, res) {
return res.status(404).send('404')
}
function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something failed!' })
} else {
next(err)
}
}

View File

@ -134,9 +134,9 @@ nav li {
.logo-image {
width: 200px;
height: 200px;
/*height: 200px;*/
/*border-radius: 50%;*/
margin-top: -57px;
/*margin-top: -57px;*/
}
.burger-menu {

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
src/static/img/flags.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

362
src/static/js/scripts.js Normal file
View File

@ -0,0 +1,362 @@
$(function () {
$.getJSON("https://backend.beammp.com/servers-info", function (data) {
$('#Servers-List').empty();
//console.log("Data Received:")
//console.log(data)
$.each(data, function (k, v) {
//var v = data[k][Object.keys(data[k])[0]]
//console.log(v)
$('#Servers-List').append(`
<tr>
<td>${getCountryName(v.location)}</td>
<td>${formatServerName(v.sname)}</td>
<td>${SmoothMapName(v.map)}</td>
<td>${v.players}/${v.maxplayers}</td>
</tr>`
);
});
$('#dataTable').DataTable();
});
});
var styleMap = {
'^0': 'color:#000000',
'^1': 'color:#0000AA',
'^2': 'color:#00AA00',
'^3': 'color:#00AAAA',
'^4': 'color:#AA0000',
'^5': 'color:#AA00AA',
'^6': 'color:#FFAA00',
'^7': 'color:#AAAAAA',
'^8': 'color:#555555',
'^9': 'color:#5555FF',
'^a': 'color:#55FF55',
'^b': 'color:#55FFFF',
'^c': 'color:#FF5555',
'^d': 'color:#FF55FF',
'^e': 'color:#FFFF55',
'^f': 'color:#FFFFFF',
'^l': 'font-weight:bold',
'^m': 'text-decoration:line-through',
'^n': 'text-decoration:underline',
'^o': 'font-style:italic',
};
function applyCode(string, codes) {
var elem = document.createElement('span');
string = string.replace(/\x00*/g, '');
for (var i = 0, len = codes.length; i < len; i++) {
elem.style.cssText += styleMap[codes[i]] + ';';
}
elem.innerHTML = string;
return elem;
}
function formatServerName(string) {
var codes = string.match(/\^.{1}/g) || [],
indexes = [],
apply = [],
tmpStr,
deltaIndex,
noCode,
final = document.createDocumentFragment(),
i;
for (i = 0, len = codes.length; i < len; i++) {
indexes.push(string.indexOf(codes[i]));
string = string.replace(codes[i], '\x00\x00');
}
if (indexes[0] !== 0) {
final.appendChild(applyCode(string.substring(0, indexes[0]), []));
}
for (i = 0; i < len; i++) {
indexDelta = indexes[i + 1] - indexes[i];
if (indexDelta === 2) {
while (indexDelta === 2) {
apply.push(codes[i]);
i++;
indexDelta = indexes[i + 1] - indexes[i];
}
apply.push(codes[i]);
} else {
apply.push(codes[i]);
}
if (apply.lastIndexOf('^r') > -1) {
apply = apply.slice(apply.lastIndexOf('^r') + 1);
}
tmpStr = string.substring(indexes[i], indexes[i + 1]);
final.appendChild(applyCode(tmpStr, apply));
}
$('#TEMPAREA').html(final);
return $('#TEMPAREA').html();;
}
function SmoothMapName(map) {
if (map != "Any Map") {
map = map.replace("/info.json", "")
map = map.split('/').pop().replace(/\s*/g, '')
map = map.replace(/_/g, " ")
map = map.replace(/-/g, " ")
map = toTitleCase(map)
}
return map
}
function toTitleCase(str) {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
var isoCountries = {
'AF': 'Afghanistan',
'AX': 'Aland Islands',
'AL': 'Albania',
'DZ': 'Algeria',
'AS': 'American Samoa',
'AD': 'Andorra',
'AO': 'Angola',
'AI': 'Anguilla',
'AQ': 'Antarctica',
'AG': 'Antigua And Barbuda',
'AR': 'Argentina',
'AM': 'Armenia',
'AW': 'Aruba',
'AU': 'Australia',
'AT': 'Austria',
'AZ': 'Azerbaijan',
'BS': 'Bahamas',
'BH': 'Bahrain',
'BD': 'Bangladesh',
'BB': 'Barbados',
'BY': 'Belarus',
'BE': 'Belgium',
'BZ': 'Belize',
'BJ': 'Benin',
'BM': 'Bermuda',
'BT': 'Bhutan',
'BO': 'Bolivia',
'BA': 'Bosnia And Herzegovina',
'BW': 'Botswana',
'BV': 'Bouvet Island',
'BR': 'Brazil',
'IO': 'British Indian Ocean Territory',
'BN': 'Brunei Darussalam',
'BG': 'Bulgaria',
'BF': 'Burkina Faso',
'BI': 'Burundi',
'KH': 'Cambodia',
'CM': 'Cameroon',
'CA': 'Canada',
'CV': 'Cape Verde',
'KY': 'Cayman Islands',
'CF': 'Central African Republic',
'TD': 'Chad',
'CL': 'Chile',
'CN': 'China',
'CX': 'Christmas Island',
'CC': 'Cocos (Keeling) Islands',
'CO': 'Colombia',
'KM': 'Comoros',
'CG': 'Congo',
'CD': 'Congo, Democratic Republic',
'CK': 'Cook Islands',
'CR': 'Costa Rica',
'CI': 'Cote D\'Ivoire',
'HR': 'Croatia',
'CU': 'Cuba',
'CY': 'Cyprus',
'CZ': 'Czech Republic',
'DK': 'Denmark',
'DJ': 'Djibouti',
'DM': 'Dominica',
'DO': 'Dominican Republic',
'EC': 'Ecuador',
'EG': 'Egypt',
'SV': 'El Salvador',
'GQ': 'Equatorial Guinea',
'ER': 'Eritrea',
'EE': 'Estonia',
'ET': 'Ethiopia',
'FK': 'Falkland Islands (Malvinas)',
'FO': 'Faroe Islands',
'FJ': 'Fiji',
'FI': 'Finland',
'FR': 'France',
'GF': 'French Guiana',
'PF': 'French Polynesia',
'TF': 'French Southern Territories',
'GA': 'Gabon',
'GM': 'Gambia',
'GE': 'Georgia',
'DE': 'Germany',
'GH': 'Ghana',
'GI': 'Gibraltar',
'GR': 'Greece',
'GL': 'Greenland',
'GD': 'Grenada',
'GP': 'Guadeloupe',
'GU': 'Guam',
'GT': 'Guatemala',
'GG': 'Guernsey',
'GN': 'Guinea',
'GW': 'Guinea-Bissau',
'GY': 'Guyana',
'HT': 'Haiti',
'HM': 'Heard Island & Mcdonald Islands',
'VA': 'Holy See (Vatican City State)',
'HN': 'Honduras',
'HK': 'Hong Kong',
'HU': 'Hungary',
'IS': 'Iceland',
'IN': 'India',
'ID': 'Indonesia',
'IR': 'Iran, Islamic Republic Of',
'IQ': 'Iraq',
'IE': 'Ireland',
'IM': 'Isle Of Man',
'IL': 'Israel',
'IT': 'Italy',
'JM': 'Jamaica',
'JP': 'Japan',
'JE': 'Jersey',
'JO': 'Jordan',
'KZ': 'Kazakhstan',
'KE': 'Kenya',
'KI': 'Kiribati',
'KR': 'Korea',
'KW': 'Kuwait',
'KG': 'Kyrgyzstan',
'LA': 'Lao People\'s Democratic Republic',
'LV': 'Latvia',
'LB': 'Lebanon',
'LS': 'Lesotho',
'LR': 'Liberia',
'LY': 'Libyan Arab Jamahiriya',
'LI': 'Liechtenstein',
'LT': 'Lithuania',
'LU': 'Luxembourg',
'MO': 'Macao',
'MK': 'Macedonia',
'MG': 'Madagascar',
'MW': 'Malawi',
'MY': 'Malaysia',
'MV': 'Maldives',
'ML': 'Mali',
'MT': 'Malta',
'MH': 'Marshall Islands',
'MQ': 'Martinique',
'MR': 'Mauritania',
'MU': 'Mauritius',
'YT': 'Mayotte',
'MX': 'Mexico',
'FM': 'Micronesia, Federated States Of',
'MD': 'Moldova',
'MC': 'Monaco',
'MN': 'Mongolia',
'ME': 'Montenegro',
'MS': 'Montserrat',
'MA': 'Morocco',
'MZ': 'Mozambique',
'MM': 'Myanmar',
'NA': 'Namibia',
'NR': 'Nauru',
'NP': 'Nepal',
'NL': 'Netherlands',
'AN': 'Netherlands Antilles',
'NC': 'New Caledonia',
'NZ': 'New Zealand',
'NI': 'Nicaragua',
'NE': 'Niger',
'NG': 'Nigeria',
'NU': 'Niue',
'NF': 'Norfolk Island',
'MP': 'Northern Mariana Islands',
'NO': 'Norway',
'OM': 'Oman',
'PK': 'Pakistan',
'PW': 'Palau',
'PS': 'Palestinian Territory, Occupied',
'PA': 'Panama',
'PG': 'Papua New Guinea',
'PY': 'Paraguay',
'PE': 'Peru',
'PH': 'Philippines',
'PN': 'Pitcairn',
'PL': 'Poland',
'PT': 'Portugal',
'PR': 'Puerto Rico',
'QA': 'Qatar',
'RE': 'Reunion',
'RO': 'Romania',
'RU': 'Russian Federation',
'RW': 'Rwanda',
'BL': 'Saint Barthelemy',
'SH': 'Saint Helena',
'KN': 'Saint Kitts And Nevis',
'LC': 'Saint Lucia',
'MF': 'Saint Martin',
'PM': 'Saint Pierre And Miquelon',
'VC': 'Saint Vincent And Grenadines',
'WS': 'Samoa',
'SM': 'San Marino',
'ST': 'Sao Tome And Principe',
'SA': 'Saudi Arabia',
'SN': 'Senegal',
'RS': 'Serbia',
'SC': 'Seychelles',
'SL': 'Sierra Leone',
'SG': 'Singapore',
'SK': 'Slovakia',
'SI': 'Slovenia',
'SB': 'Solomon Islands',
'SO': 'Somalia',
'ZA': 'South Africa',
'GS': 'South Georgia And Sandwich Isl.',
'ES': 'Spain',
'LK': 'Sri Lanka',
'SD': 'Sudan',
'SR': 'Suriname',
'SJ': 'Svalbard And Jan Mayen',
'SZ': 'Swaziland',
'SE': 'Sweden',
'CH': 'Switzerland',
'SY': 'Syrian Arab Republic',
'TW': 'Taiwan',
'TJ': 'Tajikistan',
'TZ': 'Tanzania',
'TH': 'Thailand',
'TL': 'Timor-Leste',
'TG': 'Togo',
'TK': 'Tokelau',
'TO': 'Tonga',
'TT': 'Trinidad And Tobago',
'TN': 'Tunisia',
'TR': 'Turkey',
'TM': 'Turkmenistan',
'TC': 'Turks And Caicos Islands',
'TV': 'Tuvalu',
'UG': 'Uganda',
'UA': 'Ukraine',
'AE': 'United Arab Emirates',
'GB': 'United Kingdom',
'US': 'United States',
'UM': 'United States Outlying Islands',
'UY': 'Uruguay',
'UZ': 'Uzbekistan',
'VU': 'Vanuatu',
'VE': 'Venezuela',
'VN': 'Viet Nam',
'VG': 'Virgin Islands, British',
'VI': 'Virgin Islands, U.S.',
'WF': 'Wallis And Futuna',
'EH': 'Western Sahara',
'YE': 'Yemen',
'ZM': 'Zambia',
'ZW': 'Zimbabwe'
};
function getCountryName(countryCode) {
if (isoCountries.hasOwnProperty(countryCode)) {
return isoCountries[countryCode];
} else {
return countryCode;
}
}

View File

@ -0,0 +1,46 @@
<footer class="py-5">
<div class="container">
<div class="row">
<div class="col-6 col-sm-4 text-xs-center order-sm-2">
<a class="text-white" target="_blank" href="https://www.reddit.com/user/BeamNG-MP_Mod_Team">
<i class="fab fa-reddit"></i>
</a>
<a class="text-white" target="_blank" href="https://twitter.com/BeamMP_Mod_Team">
<i class="fab fa-twitter"></i>
</a>
<a class="text-white" target="_blank" href="https://www.facebook.com/BeamNGMP">
<i class="fab fa-facebook"></i>
</a>
</div>
<div class="col-6 justify-content-between col-sm-4 text-right text-xs-center order-sm-3">
<a class="text-white" target="_blank" href="https://github.com/BeamMP">
<i class="fab fa-github"></i>
</a>
<a class="text-white" target="_blank" href="https://discord.gg/beammp">
<i class="fab fa-discord"></i>
</a>
<a class="text-white" target="_blank" href="https://www.beamng.com/threads/beamng-drive-multiplayer-beamng-mp-formally-local-multiplayer-lua-based.63052/">
<i class="fa fa-envelope"></i>
</a>
</div>
</div>
<div class="col-12 col-sm-4 text-center py-4 order-sm-2">
<small class="text-white">&#xA9; 2020 - Present | BeamMP Mod Team All Rights Reserved</small>
<small class="ml-1">
<a href="https://forum.beammp.com/topic/95/privacy-policy-v1-0" target="_blank">Privacy Policy</a>
&middot;
<a href="https://forum.beammp.com/topic/94/terms-of-use-v1-0">Terms &amp; Conditions</a>
</small>
</div>
</div>
</footer>

View File

@ -1,20 +1,11 @@
<div class="container">
<div class="row center-xs">
<div class="col-md-4 col-sm-4">
<!-- <a href class="logo-link">-->
<!-- <span class="logo-text">BeamMP</span>-->
<!-- <a href="../img/Logo_Black_4K"></a>-->
<!-- </a>-->
<a class="logo-img" href="/">
<div class="logo-image">
<!-- <img src="../static/img/Logo_Black_4K.png" alt="BeamMP" class="img-fluid">-->
<img src="../img/mainlogo.png" alt="BeamMP" class="img-fluid"/>
<img src="../img/beammp-logo.png" alt="BeamMP Logo" class="img-fluid"/>
</div>
</a>
<!-- "Hamburger menu" / "Bar icon" to toggle the navigation links -->
<!-- <img class="navbutton" src="../static/img/nav-button.svg" alt="">-->
</div>
<div class="col-md-8 col-sm-8">
<div class="burger-menu">
@ -27,7 +18,7 @@
<div class="mobile-container">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/forum">Forum <span class="sr-only">(current)</span></a>
<a class="nav-link" href="https://forum.beammp.com">Forum</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://wiki.beammp.com">Wiki</a>
@ -52,7 +43,7 @@
<div class="topnav mobile-links">
<div id="burger-links">
<a href="/forum">Forum</a>
<a href="https://forum.beammp.com">Forum</a>
<a href="https://wiki.beammp.com">Docs</a>
<a href="/servers">Servers</a>
<a href="/stats">Statistics</a>
@ -68,7 +59,7 @@
<div class="navbar-links">
<ul class="links">
<li>
<a href="/forum">
<a href="https://forum.beammp.com">
<span class="text">Forum</span>
</a>
</li>

View File

@ -24,7 +24,6 @@
<body>
<nav class="nav">
<%- include('includes/nav.ejs') %>
</nav>
<header class="main-content" style="background-position: center center, center 0px;">
@ -46,7 +45,7 @@
<div class="buttons mt-3">
<button class="download-client js-show-story" onclick="downloadserver()" href="beamMP.zip" download style="background: radial-gradient(circle,rgb(255 179 38 / 80%),rgb(255 176 0 / 65%)) center/100%;">
<span class="text">Download Server</span>
<span class="description"> BeamMP_Server.zip</span>
<span class="description"> BeamMP-Server</span>
</button>
</div>
</div>
@ -112,74 +111,22 @@
<h3 id="faq-heading"> Does this work with pirated versions of BeamNG.drive?</h3>
<p>We dont know if it works with pirated versions of BeamNG.drive, but we <b>will not</b> provide any support to non legit copies of the game. Nor will we change to support it.</p>
<h3 id="faq-heading">How do I host a server?</h3>
<p>The server files required for hosting your own server can be found at the top of this page below the client download. You will also require a authentication key which can be found from <a href="https://beammp.com/k/keys">keymaster</a>. Further information around the setup can be found on our <a href="https://wiki.beammp.com/en/home/server-installation">wiki</a>.</p>
<p>The server files required for hosting your own server can be found at the top of this page below the client download. You will also require a authentication key which can be found from <a href="https://beammp.com/k/keys">keymaster</a>. Further information around the setup can be found on our <a href="https://wiki.beammp.com/en/home/Server_Mod">wiki</a>.</p>
<h3 id="faq-heading">Can I use mods?</h3>
<p>Mods are supported, These are installed on the server. See our <a href="https://wiki.beammp.com/en/home/server-installation">wiki</a> for more infomation.</p>
<p>Mods are supported, These are installed on the server. See our <a href="https://wiki.beammp.com/en/home/Server_Mod">wiki</a> for more infomation.</p>
</div>
<!--Start of Tawk.to Script
<script type="text/javascript">
var Tawk_API=Tawk_API||{}, Tawk_LoadStart=new Date();
(function(){
var s1=document.createElement("script"),s0=document.getElementsByTagName("script")[0];
s1.async=true;
s1.src='https://embed.tawk.to/5f875a212901b92076937d66/default';
s1.charset='UTF-8';
s1.setAttribute('crossorigin','*');
s0.parentNode.insertBefore(s1,s0);
})();
</script>
End of Tawk.to Script-->
</div>
</div>
</div>
</section>
<footer class="py-5">
<div class="container">
<div class="row">
<div class="col-6 col-sm-4 text-xs-center order-sm-2">
<a class="text-white" target="_blank" href="https://www.reddit.com/r/BeamMP">
<i class="fab fa-reddit"></i>
</a>
<a class="text-white" target="_blank" href="https://twitter.com/BeamMP_Mod_Team">
<i class="fab fa-twitter"></i>
</a>
<a class="text-white" target="_blank" href="https://www.facebook.com/BeamMPTeam">
<i class="fab fa-facebook"></i>
</a>
</div>
<div class="col-6 justify-content-between col-sm-4 text-right text-xs-center order-sm-3">
<a class="text-white" target="_blank" href="https://github.com/BeamMP/BeamMP">
<i class="fab fa-github"></i>
</a>
<a class="text-white" target="_blank" href="https://discord.gg/beammp">
<i class="fab fa-discord"></i>
</a>
<a class="text-white" target="_blank" href="https://www.beamng.com/threads/beamng-drive-multiplayer-beamng-mp-formally-local-multiplayer-lua-based.63052/">
<i class="fa fa-envelope"></i>
</a>
</div>
</div>
<div class="col-12 col-sm-4 text-center py-4 order-sm-2">
<small class="text-white">© 2020 BeamMP Mod Team All Rights Reserved</small>
<small class="ml-1"><a href="https://forum.beammp.com/t/privacy-policy/6" target="_blank">Privacy Policy</a></small>
</div>
</div>
</footer>
<%- include('includes/footer.ejs') %>
<!-- <footer class="">
<div class="col-1 justify-content-between socials-left">
<ul class="list-inline">
<li class="col-xs-4 list-inline-item h3" data-toggle="tooltip" data-placement="top" title="" aria-label="Reddit" data-original-title="Reddit">
<a class="text-white" target="_blank" href="https://www.reddit.com/r/BeamMP">
<a class="text-white" target="_blank" href="https://www.reddit.com/user/BeamNG-MP_Mod_Team">
<i class="fab fa-reddit"></i>
</a>
</li>
@ -191,7 +138,7 @@ End of Tawk.to Script-->
</li>
<li class="col-xs-4 list-inline-item h3" data-toggle="tooltip" data-placement="top" title="" aria-label="Facebook" data-original-title="Facebook">
<a class="text-white" target="_blank" href="https://www.facebook.com/BeamMPTeam">
<a class="text-white" target="_blank" href="https://www.facebook.com/BeamNGMP">
<i class="fab fa-facebook"></i>
</a>
</li>
@ -200,11 +147,11 @@ End of Tawk.to Script-->
<div class="row middle-xs">
<hr>
<div class="col-lg-8 col-md-7 col-sm-6">
<p>BeamNG-MP is not affiliated by BeamNG.Drive, Any trademarks belong to the respective owners.
<p>BeamMP is not affiliated by BeamNG.Drive, Any trademarks belong to their respective owners.
</p>
</div>
<div class="copyright col-lg-4 col-md-5 col-sm-6">
<p class="righty"> © 2020 BeamMP Mod Team All Rights Reserved.
<p class="righty"> © 2021 BeamMP Mod Team All Rights Reserved.
</p>
</div>
</div>
@ -216,7 +163,7 @@ function downloadinstaller() {
}
function downloadserver() {
document.location.href ="/server/BeamMP_Server.zip";
document.location.href ="https://github.com/BeamMP/BeamMP-Server/releases/latest";
//alert("Sorry this is coming soon, Therefore it is not available just yet. Please join the discord to get the latest version: https://discord.gg/beammp")
}

68
src/views/servers.ejs Normal file
View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>BeamNG-MP-Servers</title>
<link rel="stylesheet" type="text/css" href="css/styles.css"/>
<link href="css/servers-styles.css" rel="stylesheet" />
<link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/js/all.min.js" crossorigin="anonymous"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-160071688-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-160071688-1');
</script>
</head>
<body class="sb-nav-fixed">
<span id="TEMPAREA" style="display:none;"></span>
<nav class="nav" style="position: unset !important;">
<%- include('includes/nav.ejs') %>
</nav>
<div class="container-fluid">
<div id="layoutSidenav_content">
<h1 class="mt-4" style="color:white;">Server List</h1>
<div class="card mb-4">
<div class="card-header"><i class="fas fa-server mr-1"></i>BeamMP Server List</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Location</th>
<th>Server Name</th>
<th>Map</th>
<th>Players</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Location</th>
<th>Server Name</th>
<th>Map</th>
<th>Players</th>
</tr>
</tfoot>
<tbody id="Servers-List">
</tbody>
</table>
</div>
</div>
</div>
</div>
<%- include('includes/footer.ejs') %>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js" crossorigin="anonymous"></script>
</body>
</html>

View File

@ -5,8 +5,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>BeamMP-Statistics</title>
<meta name="author" content="BeamMP Mod Team" />
<title>BeamMP | Statistics</title>
<link rel="stylesheet" type="text/css" href="css/styles.css"/>
<link href="css/servers-styles.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"/>
@ -14,7 +14,6 @@
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/js/all.min.js" crossorigin="anonymous"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-160071688-1"></script>
@ -32,48 +31,48 @@
<%- include('includes/nav.ejs') %>
</nav>
<div class="container-fluid">
<div id="layoutSidenav_content">
<div class="row">
<div class="col-md-12">
<h1 class="mt-4" style="color:white;"><i class="fas fa-server mr-1"></i>BeamMP Statistics <h3 id="LivePlayerCount" style="color:white;"></h3></h1>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Highest Recorded Players</h5>
<p class="card-text text-muted" id="MAXPLAYERS">100</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Highest Recorded Servers</h5>
<p class="card-text text-muted" id="MAXSERVERS">100</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Something</h5>
<p class="card-text">-</p
</div>
<div id="layoutSidenav_content">
<div class="row">
<div class="col-md-12">
<h1 class="mt-4" style="color:white;"><i class="fas fa-server mr-1"></i>BeamMP Statistics <h3 id="LivePlayerCount" style="color:white;"></h3></h1>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Highest Recorded Players</h5>
<p class="card-text text-muted" id="MAXPLAYERS"></p>
</div>
</div>
</div>
<div class="col-md-12">
<canvas id="myChart" width="100vw" height="770"></canvas>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Highest Recorded Servers</h5>
<p class="card-text text-muted" id="MAXSERVERS"></p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Todays Average Players</h5>
<p class="card-text text-muted" id="AVERAGES"></p
</div>
</div>
</div>
</div>
<div class="col-md-12">
<canvas id="myChart" width="100vw" height="770"></canvas>
</div>
</div>
<footer class="py-4 bg-light mt-auto">
<div class="container-fluid">
<div class="d-flex align-items-center justify-content-between small">
<div class="text-muted">Copyright &copy; BeamMP Development Team 2020</div>
<div class="text-muted">Copyright &copy; BeamMP Development Team 2021</div>
<div>
<a href="https://forum.beammp.com/topic/95/privacy-policy-v1-0">Privacy Policy</a>
&middot;
<a href="#">Terms &amp; Conditions</a>
<a href="https://forum.beammp.com/topic/94/terms-of-use-v1-0">Terms &amp; Conditions</a>
</div>
</div>
</div>
@ -87,31 +86,45 @@
<script type="text/javascript">
var chartData = {};
var GetChartData = function () {
var GetChartData = function (period) {
$.ajax({
type: 'POST',
url: '/stats',
type: 'GET',
url: 'https://backend.beammp.com/stats-info',
data: {
period: 'today',
period: (period) ? period : 'today',
},
dataType: 'json',
success: function (d) {
console.log(d)
var average = 0;
var Data = {}
Data.Players = []
Data.Servers = []
Data.v2Players = []
Data.v2Servers = []
Data.Labels = []
console.log(d.maxp, d.maxs)
console.log(d.history)
d.history.forEach(function(item, index) {
Data.Players.push(item.players)
Data.Servers.push(item.servers)
Data.Labels.push(item.datetime)
});
console.log(d.maxp, d.maxs)
console.log(d.v2history)
if (d.v2history) {
var count = 0
var tot = 0
d.v2history.forEach(function(item, index) {
Data.Labels.push(item.datetime)
Data.v2Players.push(item.players)
if (typeof(item.servers) == 'number') Data.v2Servers.push(item.servers);
if (typeof(item.servers) == 'object') Data.v2Servers.push(item.servers.count);
tot += parseInt(item.players)
count++;
});
average = tot / count
}
$('#MAXPLAYERS').text(d.maxp);
$('#MAXSERVERS').text(d.maxs);
$('#LivePlayerCount').text(`Currently Online: ${d.history[d.history.length-1].players}`)
$('#AVERAGES').text(Math.floor(average));
$('#LivePlayerCount').text(`Currently Online: ${d.v2history[d.v2history.length-1].players}`)
console.log(Data)
document.getElementById('myChart').innerHTML = '';
var ctx = document.getElementById('myChart').getContext('2d');
ctx.height = 770;
var myChart = new Chart(ctx, {
@ -122,14 +135,14 @@
label: 'Servers',
backgroundColor: 'rgba(255,0,0,0.1)',
borderColor: 'rgba(255,0,0,0.4)',
data: Data.Servers,
data: Data.v2Servers,
fill: false,
}, {
label: 'Players',
fill: false,
backgroundColor: 'rgba(0,0,255,0.1)',
borderColor: 'rgba(0,0,255,0.4)',
data: Data.Players,
data: Data.v2Players,
}]
},
options: {

117
src/webserver.js Normal file
View File

@ -0,0 +1,117 @@
/*
* oooooooooo. ooo ooooo ooooooooo.
* `888' `Y8b `88. .888' `888 `Y88.
* 888 888 .ooooo. .oooo. ooo. .oo. .oo. 888b d'888 888 .d88'
* 888oooo888' d88' `88b `P )88b `888P"Y88bP"Y88b 8 Y88. .P 888 888ooo88P'
* 888 `88b 888ooo888 .oP"888 888 888 888 8 `888' 888 888
* 888 .88P 888 .o d8( 888 888 888 888 8 Y 888 888
* o888bood8P' `Y8bod8P' `Y888""8o o888o o888o o888o o8o o888o o888o
* ========================================================================
* Updated: 2/11/22 22:17
* Copyright (c) 2019-2022 BeamMP Ltd. All rights reserved.
*/
require('dotenv').config()
const helmet = require("helmet");
var morgan = require('morgan');
const express = require('express')
const WebServer = express()
const routes = require('./routes')
const server = require('http').createServer(WebServer)
//////////////////////////////////////////////////////////////////////
// Cluster Handling
//////////////////////////////////////////////////////////////////////
const cluster = require('cluster');
if (!cluster.isMaster) {
cluster.worker.on('disconnect', function() {
console.log('Worker disconnected, closing server');
server.close(() => {
console.log('HTTP server closed')
})
});
}
//////////////////////////////////////////////////////////////////////
// Main Webserver
//////////////////////////////////////////////////////////////////////
;(app => {
'use strict'
module.exports.server = server
module.exports.app = app
module.exports.init = async (callback) => {
app.disable('x-powered-by')
if (process.env.DEBUG == "true") {
console.log('Request Logging Enabled.')
app.use(morgan('dev', {
/*skip: function (req, res) {
return res.statusCode == 200 || res.statusCode == 401
}*/
}))
}
app.use(helmet());
// CORS
app.use(allowCrossDomain)
// PROXY HANDLING
app.set('trust proxy', true);
// set the view engine to ejs
app.set('view engine', 'ejs');
app.use(express.static(require('path').join(__dirname, 'static')))
app.set("views", "./src/views")
routes(app)
if (typeof callback === 'function') callback()
}
module.exports.listen = (callback) => {
server.on('error', err => {
if (err.code === 'EADDRINUSE') {
console.error('Address in use, exiting...')
server.close()
} else {
console.error(err.message)
throw err
}
})
server.listen(process.env.PORT, '0.0.0.0', () => {
console.log('Backend is now listening on port: ' + process.env.PORT)
if (typeof callback === 'function') return callback()
})
}
})(WebServer)
function allowCrossDomain (req, res, next) {
const allowedOrigins = ['http://127.0.0.1:3599', 'http://localhost:3599', 'https://beammp.com', 'https://backend.beammp.com'];
const origin = req.headers['origin'];
console.log(origin)
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
//res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000') // TODO: Update this to the keymaster domain
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
res.setHeader(
'Access-Control-Allow-Headers',
'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,authorization,X-RToken,X-Token,Origin'
)
res.setHeader('Content-Security-Policy', "frame-ancestors 'none';")
if (req.method === 'OPTIONS') {
res.sendStatus(200)
} else {
next()
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 514 KiB

View File

@ -1,354 +0,0 @@
$(function() {
$.getJSON("/servers-info", function( data ) {
$('#Servers-List').empty();
console.log("Data Received:")
console.log(data)
$.each(data, function(k, v) {
var v = data[k][Object.keys(data[k])[0]]
$('#Servers-List').append(`<tr><td>${getCountryName(v.location)}</td><td>${formatServerName(v.sname)}</td><td>${SmoothMapName(v.map)}</td><td>---</td><td>---</td><td>${v.players}/${v.maxplayers}</td></tr>`);
});
$('#dataTable').DataTable();
});
});
var styleMap = {
'^0': 'color:#000000',
'^1': 'color:#0000AA',
'^2': 'color:#00AA00',
'^3': 'color:#00AAAA',
'^4': 'color:#AA0000',
'^5': 'color:#AA00AA',
'^6': 'color:#FFAA00',
'^7': 'color:#AAAAAA',
'^8': 'color:#555555',
'^9': 'color:#5555FF',
'^a': 'color:#55FF55',
'^b': 'color:#55FFFF',
'^c': 'color:#FF5555',
'^d': 'color:#FF55FF',
'^e': 'color:#FFFF55',
'^f': 'color:#FFFFFF',
'^l': 'font-weight:bold',
'^m': 'text-decoration:line-through',
'^n': 'text-decoration:underline',
'^o': 'font-style:italic',
};
function applyCode(string, codes) {
var elem = document.createElement('span');
string = string.replace(/\x00*/g, '');
for(var i = 0, len = codes.length; i < len; i++) {
elem.style.cssText += styleMap[codes[i]] + ';';
}
elem.innerHTML = string;
return elem;
}
function formatServerName(string) {
var codes = string.match(/\^.{1}/g) || [],
indexes = [],
apply = [],
tmpStr,
deltaIndex,
noCode,
final = document.createDocumentFragment(),
i;
for(i = 0, len = codes.length; i < len; i++) {
indexes.push( string.indexOf(codes[i]) );
string = string.replace(codes[i], '\x00\x00');
}
if(indexes[0] !== 0) {
final.appendChild( applyCode( string.substring(0, indexes[0]), [] ) );
}
for(i = 0; i < len; i++) {
indexDelta = indexes[i + 1] - indexes[i];
if(indexDelta === 2) {
while(indexDelta === 2) {
apply.push ( codes[i] );
i++;
indexDelta = indexes[i + 1] - indexes[i];
}
apply.push ( codes[i] );
} else {
apply.push( codes[i] );
}
if( apply.lastIndexOf('^r') > -1) {
apply = apply.slice( apply.lastIndexOf('^r') + 1 );
}
tmpStr = string.substring( indexes[i], indexes[i + 1] );
final.appendChild( applyCode(tmpStr, apply) );
}
$('#TEMPAREA').html(final);
return $('#TEMPAREA').html();;
}
function SmoothMapName(map) {
if (map != "Any Map") {
map = map.replace("/info.json","")
map = map.split('/').pop().replace(/\s*/g,'')
map = map.replace(/_/g," ")
map = map.replace(/-/g," ")
map = toTitleCase(map)
}
return map
}
function toTitleCase(str) {
return str.replace(/\w\S*/g, function(txt){
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
var isoCountries = {
'AF' : 'Afghanistan',
'AX' : 'Aland Islands',
'AL' : 'Albania',
'DZ' : 'Algeria',
'AS' : 'American Samoa',
'AD' : 'Andorra',
'AO' : 'Angola',
'AI' : 'Anguilla',
'AQ' : 'Antarctica',
'AG' : 'Antigua And Barbuda',
'AR' : 'Argentina',
'AM' : 'Armenia',
'AW' : 'Aruba',
'AU' : 'Australia',
'AT' : 'Austria',
'AZ' : 'Azerbaijan',
'BS' : 'Bahamas',
'BH' : 'Bahrain',
'BD' : 'Bangladesh',
'BB' : 'Barbados',
'BY' : 'Belarus',
'BE' : 'Belgium',
'BZ' : 'Belize',
'BJ' : 'Benin',
'BM' : 'Bermuda',
'BT' : 'Bhutan',
'BO' : 'Bolivia',
'BA' : 'Bosnia And Herzegovina',
'BW' : 'Botswana',
'BV' : 'Bouvet Island',
'BR' : 'Brazil',
'IO' : 'British Indian Ocean Territory',
'BN' : 'Brunei Darussalam',
'BG' : 'Bulgaria',
'BF' : 'Burkina Faso',
'BI' : 'Burundi',
'KH' : 'Cambodia',
'CM' : 'Cameroon',
'CA' : 'Canada',
'CV' : 'Cape Verde',
'KY' : 'Cayman Islands',
'CF' : 'Central African Republic',
'TD' : 'Chad',
'CL' : 'Chile',
'CN' : 'China',
'CX' : 'Christmas Island',
'CC' : 'Cocos (Keeling) Islands',
'CO' : 'Colombia',
'KM' : 'Comoros',
'CG' : 'Congo',
'CD' : 'Congo, Democratic Republic',
'CK' : 'Cook Islands',
'CR' : 'Costa Rica',
'CI' : 'Cote D\'Ivoire',
'HR' : 'Croatia',
'CU' : 'Cuba',
'CY' : 'Cyprus',
'CZ' : 'Czech Republic',
'DK' : 'Denmark',
'DJ' : 'Djibouti',
'DM' : 'Dominica',
'DO' : 'Dominican Republic',
'EC' : 'Ecuador',
'EG' : 'Egypt',
'SV' : 'El Salvador',
'GQ' : 'Equatorial Guinea',
'ER' : 'Eritrea',
'EE' : 'Estonia',
'ET' : 'Ethiopia',
'FK' : 'Falkland Islands (Malvinas)',
'FO' : 'Faroe Islands',
'FJ' : 'Fiji',
'FI' : 'Finland',
'FR' : 'France',
'GF' : 'French Guiana',
'PF' : 'French Polynesia',
'TF' : 'French Southern Territories',
'GA' : 'Gabon',
'GM' : 'Gambia',
'GE' : 'Georgia',
'DE' : 'Germany',
'GH' : 'Ghana',
'GI' : 'Gibraltar',
'GR' : 'Greece',
'GL' : 'Greenland',
'GD' : 'Grenada',
'GP' : 'Guadeloupe',
'GU' : 'Guam',
'GT' : 'Guatemala',
'GG' : 'Guernsey',
'GN' : 'Guinea',
'GW' : 'Guinea-Bissau',
'GY' : 'Guyana',
'HT' : 'Haiti',
'HM' : 'Heard Island & Mcdonald Islands',
'VA' : 'Holy See (Vatican City State)',
'HN' : 'Honduras',
'HK' : 'Hong Kong',
'HU' : 'Hungary',
'IS' : 'Iceland',
'IN' : 'India',
'ID' : 'Indonesia',
'IR' : 'Iran, Islamic Republic Of',
'IQ' : 'Iraq',
'IE' : 'Ireland',
'IM' : 'Isle Of Man',
'IL' : 'Israel',
'IT' : 'Italy',
'JM' : 'Jamaica',
'JP' : 'Japan',
'JE' : 'Jersey',
'JO' : 'Jordan',
'KZ' : 'Kazakhstan',
'KE' : 'Kenya',
'KI' : 'Kiribati',
'KR' : 'Korea',
'KW' : 'Kuwait',
'KG' : 'Kyrgyzstan',
'LA' : 'Lao People\'s Democratic Republic',
'LV' : 'Latvia',
'LB' : 'Lebanon',
'LS' : 'Lesotho',
'LR' : 'Liberia',
'LY' : 'Libyan Arab Jamahiriya',
'LI' : 'Liechtenstein',
'LT' : 'Lithuania',
'LU' : 'Luxembourg',
'MO' : 'Macao',
'MK' : 'Macedonia',
'MG' : 'Madagascar',
'MW' : 'Malawi',
'MY' : 'Malaysia',
'MV' : 'Maldives',
'ML' : 'Mali',
'MT' : 'Malta',
'MH' : 'Marshall Islands',
'MQ' : 'Martinique',
'MR' : 'Mauritania',
'MU' : 'Mauritius',
'YT' : 'Mayotte',
'MX' : 'Mexico',
'FM' : 'Micronesia, Federated States Of',
'MD' : 'Moldova',
'MC' : 'Monaco',
'MN' : 'Mongolia',
'ME' : 'Montenegro',
'MS' : 'Montserrat',
'MA' : 'Morocco',
'MZ' : 'Mozambique',
'MM' : 'Myanmar',
'NA' : 'Namibia',
'NR' : 'Nauru',
'NP' : 'Nepal',
'NL' : 'Netherlands',
'AN' : 'Netherlands Antilles',
'NC' : 'New Caledonia',
'NZ' : 'New Zealand',
'NI' : 'Nicaragua',
'NE' : 'Niger',
'NG' : 'Nigeria',
'NU' : 'Niue',
'NF' : 'Norfolk Island',
'MP' : 'Northern Mariana Islands',
'NO' : 'Norway',
'OM' : 'Oman',
'PK' : 'Pakistan',
'PW' : 'Palau',
'PS' : 'Palestinian Territory, Occupied',
'PA' : 'Panama',
'PG' : 'Papua New Guinea',
'PY' : 'Paraguay',
'PE' : 'Peru',
'PH' : 'Philippines',
'PN' : 'Pitcairn',
'PL' : 'Poland',
'PT' : 'Portugal',
'PR' : 'Puerto Rico',
'QA' : 'Qatar',
'RE' : 'Reunion',
'RO' : 'Romania',
'RU' : 'Russian Federation',
'RW' : 'Rwanda',
'BL' : 'Saint Barthelemy',
'SH' : 'Saint Helena',
'KN' : 'Saint Kitts And Nevis',
'LC' : 'Saint Lucia',
'MF' : 'Saint Martin',
'PM' : 'Saint Pierre And Miquelon',
'VC' : 'Saint Vincent And Grenadines',
'WS' : 'Samoa',
'SM' : 'San Marino',
'ST' : 'Sao Tome And Principe',
'SA' : 'Saudi Arabia',
'SN' : 'Senegal',
'RS' : 'Serbia',
'SC' : 'Seychelles',
'SL' : 'Sierra Leone',
'SG' : 'Singapore',
'SK' : 'Slovakia',
'SI' : 'Slovenia',
'SB' : 'Solomon Islands',
'SO' : 'Somalia',
'ZA' : 'South Africa',
'GS' : 'South Georgia And Sandwich Isl.',
'ES' : 'Spain',
'LK' : 'Sri Lanka',
'SD' : 'Sudan',
'SR' : 'Suriname',
'SJ' : 'Svalbard And Jan Mayen',
'SZ' : 'Swaziland',
'SE' : 'Sweden',
'CH' : 'Switzerland',
'SY' : 'Syrian Arab Republic',
'TW' : 'Taiwan',
'TJ' : 'Tajikistan',
'TZ' : 'Tanzania',
'TH' : 'Thailand',
'TL' : 'Timor-Leste',
'TG' : 'Togo',
'TK' : 'Tokelau',
'TO' : 'Tonga',
'TT' : 'Trinidad And Tobago',
'TN' : 'Tunisia',
'TR' : 'Turkey',
'TM' : 'Turkmenistan',
'TC' : 'Turks And Caicos Islands',
'TV' : 'Tuvalu',
'UG' : 'Uganda',
'UA' : 'Ukraine',
'AE' : 'United Arab Emirates',
'GB' : 'United Kingdom',
'US' : 'United States',
'UM' : 'United States Outlying Islands',
'UY' : 'Uruguay',
'UZ' : 'Uzbekistan',
'VU' : 'Vanuatu',
'VE' : 'Venezuela',
'VN' : 'Viet Nam',
'VG' : 'Virgin Islands, British',
'VI' : 'Virgin Islands, U.S.',
'WF' : 'Wallis And Futuna',
'EH' : 'Western Sahara',
'YE' : 'Yemen',
'ZM' : 'Zambia',
'ZW' : 'Zimbabwe'
};
function getCountryName (countryCode) {
if (isoCountries.hasOwnProperty(countryCode)) {
return isoCountries[countryCode];
} else {
return countryCode;
}
}

View File

@ -1,8 +0,0 @@
<footer>
<div class="container-fluid">
<p class="text-gray-dark">
<strong class="m-r-1">BeamMP Mod Team </strong>
<span class="text-gray-dark">&#xA9; 2020 - Present.</span>
</p>
</div>
</footer>

View File

@ -1,17 +0,0 @@
<div>
<div class="initial-loader-top">
<img class="initial-loader-logo" src="../images/beammp-logo.png" alt="Loader" style="width: 100px;">
<div class="loader loader--style1">
<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="30px" height="30px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">
<g>
<path fill="#2d2d2d" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"></path>
<path fill="#2c97de" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0C22.32,8.481,24.301,9.057,26.013,10.047z"></path>
</g>
</svg>
</div>
</div>
<div class="initial-loader-bottom">
Loading. Please Wait. <i class="fa fa-cricle" style="opacity: 0"></i>
</div>
</div>

View File

@ -1,141 +0,0 @@
<div class="navbar-inverse navbar navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="current navbar-brand" href="/dashboard">
<img alt="BeamMP Logo" class="h-20" src="../images/beammp-logo.png">
</a>
<button class="action-right-sidebar-toggle navbar-toggle collapsed" data-target="#navdbar" data-toggle="collapse" type="button">
<i class="fa fa-fw fa-align-right text-white"></i>
</button>
<button class="navbar-toggle collapsed" data-target="#navbar" data-toggle="collapse" type="button">
<i class="fa fa-fw fa-user text-white"></i>
</button>
<button class="action-sidebar-open navbar-toggle collapsed" type="button">
<i class="fa fa-fw fa-bars text-white"></i>
</button>
</div>
<div class="collapse navbar-collapse" id="navbar">
<!-- START Left Side Navbar -->
<ul class="nav navbar-nav navbar-left clearfix yamm">
<!-- START Switch Sidebar ON/OFF -->
<li id="sidebar-switch" class="hidden-xs">
<a class="action-toggle-sidebar-slim" data-placement="bottom" data-toggle="tooltip" href="#" title="Slim sidebar on/off">
<i class="fa fa-lg fa-bars fa-fw"></i>
</a>
</li>
<!-- END Switch Sidebar ON/OFF -->
</ul>
<!-- START Left Side Navbar -->
<!-- START Right Side Navbar -->
<ul class="nav navbar-nav navbar-right">
<li role="separator" class="divider hidden-lg hidden-md hidden-sm"></li>
<li class="dropdown-header hidden-lg hidden-md hidden-sm text-gray-lighter text-uppercase">
<strong>Your Profile</strong>
</li>
<!-- START Notification -->
<li class="dropdown">
<!-- START Icon Notification with Badge (10)-->
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button">
<i class="fa fa-lg fa-fw fa-bell hidden-xs"></i>
<span class="hidden-sm hidden-md hidden-lg">
Notifications <span class="badge badge-primary m-l-1"></span>
</span>
<span class="label label-primary label-pill label-with-icon hidden-xs"></span>
<span class="fa fa-fw fa-angle-down hidden-lg hidden-md hidden-sm"></span>
</a>
<!-- END Icon Notification with Badge (10)-->
<!-- START Notification Dropdown Menu -->
<ul class="dropdown-menu dropdown-menu-right p-t-0 b-t-0 p-b-0 b-b-0 b-a-0">
<li>
<div class="yamm-content p-t-0 p-r-0 p-l-0 p-b-0">
<ul class="list-group m-b-0 b-b-0">
<li class="list-group-item b-r-0 b-l-0 b-r-0 b-t-r-0 b-t-l-0 b-b-2 w-350">
<small class="text-uppercase">
<strong>Notifications</strong>
</small>
<!--<a role="button" href="#" class="btn m-t-0 btn-xs btn-default pull-right">
<i class="fa fa-fw fa-gear"></i>
</a>-->
</li>
<!-- START Scroll Inside Panel -->
<li class="list-group-item b-a-0 p-x-0 p-y-0 b-t-0">
<div class="scroll-300 custom-scrollbar">
<!--<a href="../pages/timeline.html" class="list-group-item b-r-0 b-t-0 b-l-0">
<div class="media">
<div class="media-left">
<span class="fa-stack fa-lg">
<i class="fa fa-circle-thin fa-stack-2x text-danger"></i>
<i class="fa fa-close fa-stack-1x fa-fw text-danger"></i>
</span>
</div>
<div class="media-body">
<h5 class="m-t-0">
<span>We need to compress the open-source SAS protocol!</span>
</h5>
<p class="text-nowrap small m-b-0">
<span>24-Jan-2020, 09:41</span>
</p>
</div>
</div>
</a>-->
</div>
</li>
<!-- END Scroll Inside Panel -->
<li class="list-group-item b-a-0 p-x-0 p-y-0 r-a-0 b-b-0">
<a class="list-group-item text-center b-r-0 b-b-0 b-l-0 b-r-b-r-0 b-r-b-l-0" href="/notifications">
See All Notifications <i class="fa fa-angle-right"></i>
</a>
</li>
</ul>
</div>
</li>
</ul>
<!-- END Notification Dropdown Menu -->
</li>
<!-- END Notification -->
<li class="dropdown">
<a class="dropdown-toggle user-dropdown" data-toggle="dropdown" href="#" role="button">
<span class="m-r-1"><%= user.username %>#<%= user.discriminator%></span>
<div class="avatar avatar-image avatar-sm avatar-inline">
<img alt="User" src="https://cdn.discordapp.com/avatars/<%= user.discord.id %>/<%= user.discord.avatar %>.png">
</div>
</a>
<ul class="dropdown-menu">
<li class="dropdown-header text-gray-lighter">
<strong class="text-uppercase">Account</strong>
</li>
<li role="separator" class="divider"></li>
<li>
<a href="/profile-details">Your Profile</a>
</li>
<li>
<a href="#">Settings <span class="label label-danger label-outline">Coming Soon</span></a>
</li>
<li>
<a href="https://wiki.beammp.com/">Wiki <span class="label label-primary label-outline">In-Progress</span></a>
</li>
<li role="separator" class="divider"></li>
<li>
<a href="/logout">Sign Out</a>
</li>
</ul>
</li>
</ul>
<!-- END Right Side Navbar -->
</div>
</div>
</div>

View File

@ -1,70 +0,0 @@
<aside class="navbar-default sidebar">
<div class="sidebar-content">
<div class="add-on-container">
<div class="sidebar-container-default sidebar-section">
<div class="media">
<div class="media-body">
<div class="avatar avatar-image avatar-lg center-block">
<img src="https://cdn.discordapp.com/avatars/<%= user.discord.id %>/<%= user.discord.avatar %>.png" alt="Avatar">
<i class="avatar-status bg-success avatar-status-bottom"></i>
</div>
<h5 class="media-heading text-center m-t-2 m-b-0"><span><%= user.username %>#<%= user.discriminator%></span></h5>
<p class="text-center small"><%= user.email%></p>
</div>
</div>
<ul class="nav nav-pills">
<li role="presentation">
<a href="#">
<span class="f-w-300 text-center h1 m-b-0 m-t-0"><%= keyTotal %></span><br>
<small class="text-white">Keys</small>
</a>
</li>
<li role="presentation">
<a href="#">
<span class="f-w-300 h1 text-center m-b-0 m-t-0">00</span><br>
<small class="text-white">Servers</small>
</a>
</li>
<li role="presentation">
<a href="#">
<span class="f-w-300 h1 text-center m-b-0 m-t-0">00</span><br>
<small class="text-white">Players</small>
</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-default-visible text-muted small text-uppercase sidebar-section p-y-2">
<strong>Navigation</strong>
</div>
<!-- START Tree Sidebar Common -->
<ul class="side-menu">
<li <% if (page == "dashboard") {%>class="active"<%}%>>
<a href="/k/dashboard">
<i class="fa fa-home fa-lg fa-fw"></i><span class="nav-label">Dashboard</span>
</a>
</li>
<li <% if (page == "servers" && page == "server") {%>class="active"<%}%>>
<a href="/k/servers">
<i class="fa fa-server fa-lg fa-fw"></i><span class="nav-label">Servers</span>
</a>
</li>
<li <% if (page == "keys") {%>class="active"<%}%>>
<a href="/k/keys">
<i class="fa fa-key fa-lg fa-fw"></i><span class="nav-label">Keys</span>
</a>
</li>
</ul>
<!-- END Tree Sidebar Common -->
<div class="sidebar-default-visible">
<hr>
</div>
</div>
</aside>

View File

@ -1,88 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>BeamNG-MP-Servers</title>
<link href="css/servers-styles.css" rel="stylesheet" />
<link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/js/all.min.js" crossorigin="anonymous"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-160071688-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-160071688-1');
</script>
</head>
<body class="sb-nav-fixed">
<span id="TEMPAREA" style="display:none;"></span>
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
<%- include('includes/nav.ejs') %>
</nav>
<div id="layoutSidenav_content">
<main>
<br>
<br>
<div class="container-fluid">
<h1 class="mt-4">Server List</h1>
<div class="card mb-4">
<div class="card-header"><i class="fas fa-server mr-1"></i>BeamNG-MP Server List</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Location</th>
<th>Server Name</th>
<th>Map</th>
<th>Ping</th>
<th>Online Since</th>
<th>Players</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Location</th>
<th>Server Name</th>
<th>Map</th>
<th>Ping</th>
<th>Online Since</th>
<th>Players</th>
</tr>
</tfoot>
<tbody id="Servers-List">
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container-fluid">
<div class="d-flex align-items-center justify-content-between small">
<div class="text-muted">Copyright &copy; BeamNG-MP Development Team 2020</div>
<div>
<a href="#">Privacy Policy</a>
&middot;
<a href="#">Terms &amp; Conditions</a>
</div>
</div>
</div>
</footer>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js" crossorigin="anonymous"></script>
<script src="js/datatables-demo.js"></script>
</body>
</html>