cs2-rcon-panel/routes/game.js
2024-11-16 18:08:04 +01:00

342 lines
13 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express');
const router = express.Router();
const readline = require('readline');
const fs = require('fs');
const rcon = require("../modules/rcon");
const is_authenticated = require("../modules/middleware");
const ALLOWED_STEAM_IDS = ['76561198154367261']
router.post('/api/setup-game', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const team1 = req.body.team1;
const team2 = req.body.team2;
const map = req.body.map;
const game = req.body.game.toString();
if (team1.trim() != "") {
await rcon.execute_command(server_id, `mp_teamname_1 "${team1}"`);
}
if (team2.trim() != "") {
await rcon.execute_command(server_id, `mp_teamname_2 "${team2}"`);
}
if (game == "1") { // Competitive Short
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 1`);
execute_cfg_on_server(server_id, './cfg/live_competitive_16.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "2") { // Competitive Long
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 1`);
execute_cfg_on_server(server_id, './cfg/live_competitive_24.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "3") { // Casual Short
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
execute_cfg_on_server(server_id, './cfg/live_casual_16.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "4") { // Casual Long
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
execute_cfg_on_server(server_id, './cfg/live_casual_24.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "5") { // Wingman
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 2`);
execute_cfg_on_server(server_id, './cfg/live_wingman.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "6") { // Arms race
await rcon.execute_command(server_id, `game_type 1`);
await rcon.execute_command(server_id, `game_mode 0`);
execute_cfg_on_server(server_id, './cfg/live_arms_race.cfg');
setTimeout(() => {
rcon.execute_command(server_id, `mp_restartgame 1`);
}, 20000)
}
await rcon.execute_command(server_id, `changelevel ${map}`);
// Adding 1 second delay in executing warmup.cfg to make it effective after map has been changed.
if (game == "1" || game == "3" || game == "5") {
setTimeout(() => {
execute_cfg_on_server(server_id, './cfg/warmup_16.cfg');
}, 1000)
} else if (game == "2" || game == "4") {
setTimeout(() => {
execute_cfg_on_server(server_id, './cfg/warmup_24.cfg');
}, 1000)
}
return res.status(200).json({ message: 'Game Created!' });
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/api/restart', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
await rcon.execute_command(server_id, `mp_restartgame 1`);
return res.status(200).json({ message: 'Game restarted' });
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/api/start-warmup', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
execute_cfg_on_server(server_id, './cfg/warmup.cfg');
execute_cfg_on_server(server_id, './cfg/warmup_restart.cfg');
return res.status(200).json({ message: 'Warmup started!' });
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/api/swap-team', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
await rcon.execute_command(server_id, `mp_swapteams`);
return res.status(200).json({ message: 'Teams Swapped!' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/api/go-live', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const res_mode = await rcon.execute_command(server_id, `game_mode`);
const game_mode = res_mode.split("=")[1].trim().toString();
const res_type = await rcon.execute_command(server_id, `game_type`);
const game_type = res_type.split("=")[1].trim().toString();
const res_rounds = await rcon.execute_command(server_id, `mp_maxrounds`);
const maxrounds = res_rounds.split("=")[1].trim().toString();
if (game_mode == "1" && maxrounds == "16") {
console.log("Executing live_competitive_16.cfg")
execute_cfg_on_server(server_id, './cfg/live_competitive_16.cfg');
} else if (game_mode == "1" && maxrounds == "24") {
console.log("Executing live_competitive_24.cfg")
execute_cfg_on_server(server_id, './cfg/live_competitive_24.cfg');
} else if (game_mode == "0" && maxrounds == "16") {
console.log("Executing live_casual_16.cfg")
execute_cfg_on_server(server_id, './cfg/live_casual_16.cfg');
} else if (game_mode == "0" && maxrounds == "24") {
console.log("Executing live_casual_24.cfg")
execute_cfg_on_server(server_id, './cfg/live_casual_24.cfg');
} else if (game_mode == "2") {
console.log("Executing live_wingman.cfg")
execute_cfg_on_server(server_id, './cfg/live_wingman.cfg');
}
execute_cfg_on_server(server_id, './cfg/live_restart.cfg');
return res.status(200).json({ message: 'Match is live!!' });
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
}
});
// List Round Backups API
router.post('/api/list-backups', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, "mp_backup_restore_list_files");
console.log('Server response:', response);
return res.status(200).json({ message: response });
} catch (error) {
console.log(error)
res.status(500).json({ error: 'Internal server error' });
}
});
// Restore Round API
router.post('/api/restore-round', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
let round_number = req.body.round_number.toString()
if (round_number.length == 1) {
round_number = "0" + round_number;
}
console.log(`SENDING mp_backup_restore_load_file backup_round${round_number}.txt`)
await rcon.execute_command(server_id, `mp_backup_restore_load_file backup_round${round_number}.txt`);
await rcon.execute_command(server_id, `mp_pause_match`);
return res.status(200).json({ message: 'Round Restored!' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/api/restore-latest-backup', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, `mp_backup_round_file_last`);
const last_round_file = response.split("=")[1].trim().toString();
if (last_round_file.includes('.txt')) {
await rcon.execute_command(server_id, `mp_backup_restore_load_file ${last_round_file}`);
await rcon.execute_command(server_id, `mp_pause_match`);
return res.status(200).json({ message: `Latest Round Restored! (${last_round_file})` });
} else {
return res.status(200).json({ message: 'No latest backup found!' });
}
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Pause Game API
router.post('/api/pause', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, 'mp_pause_match');
return res.status(200).json({ message: 'Game paused' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
// Unpause Game API
router.post('/api/unpause', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, 'mp_unpause_match');
return res.status(200).json({ message: 'Game unpaused' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/api/rcon', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const command = req.body.command;
const response = await rcon.execute_command(server_id, command);
if (response == 200) {
return res.status(200).json({ message: 'Command sent!' });
}
return res.status(200).json({ message: 'Command sent! Response received:\n' + response.toString() });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/api/say-admin', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const message = req.body.message;
const message_to_send = "say " + message;
await rcon.execute_command(server_id, message_to_send);
return res.status(200).json({ message: 'Message sent!' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
function check_whitelisted_players() {
rcon.rcons[server_id].execute('status_json')
.then((response) => {
console.log(response)
const server_status = JSON.parse(response)
const players = server_status['server']['clients']
for (var i = 0; i < players.length; i++) {
let player = players[i]
if (!player.bot && player.steamid64.includes('7656') && !ALLOWED_STEAM_IDS.includes(player.steamid64)) {
console.log(`kick ${player.name}`)
rcon.rcons[server_id].execute(`kick ${player.name}`);
}
}
return;
})
.catch(console.error);
}
function splitByByteLength(data, length) {
const lines = data;
const exportedLines = [];
const lineEndChar = '; '
let index = 0;
for(let item = 0; item < lines.length; item++) {
if(typeof exportedLines[index] === "undefined") {
exportedLines[index] = "";
}
const lineFormatted = `${lines[item]}${lineEndChar}`;
const lineBytes = Buffer.byteLength(lineFormatted, 'utf8');
const bufferBytes = Buffer.byteLength(exportedLines[index], 'utf8');
if((bufferBytes + lineBytes) < length) {
exportedLines[index] += lineFormatted;
} else {
index++;
}
}
return exportedLines;
}
async function execute_cfg_on_server(server_id, cfg_path) {
fs.readFile(cfg_path, 'utf8', (err, data) => {
if (err) {
throw err;
}
data = data.replace(/^\/\/.*$/m, '');
data = data.split("\n");
const new_data = [];
for (let i = 0; i < data.length; i += 1) {
const line = data[i].trim();
const segments = line.split(' ');
if(segments[0] === 'say' || segments.length == 1) {
new_data.push(line);
} else if (segments[0] !== '' && segments[0] !== '//') {
new_data.push(`${segments[0]} ${segments[1].split('\t')[0]}`);
}
}
const exported_lines = splitByByteLength(data, 512)
async function execute_next_item(item) {
try {
if (item < exported_lines.length) {
console.log("Executing on server:", exported_lines[item]);
await rcon.execute_command(server_id, exported_lines[item]);
// Wait for 100ms before moving to the next iteration
setTimeout(() => {
execute_next_item(item + 1);
}, 100);
}
} catch (error) {
console.log("[execute_next_item] Error:", error)
}
}
execute_next_item(0);
});
}
module.exports = {
router
};