Skip to content

Commit

Permalink
add ban list and unban option
Browse files Browse the repository at this point in the history
  • Loading branch information
LoV432 committed Jan 9, 2024
1 parent 84c697a commit b8b284e
Show file tree
Hide file tree
Showing 7 changed files with 387 additions and 7 deletions.
7 changes: 6 additions & 1 deletion .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@ SERVER_IP=1.1.1.1
SERVER_PORT=27015
RCON_PORT=27015
RCON_PASSWORD=supersecurepassword
ADMIN_PLUGIN_INSTALLED=false # Change this to true if you have this plugin installed: https://github.com/daffyyyy/CS2-SimpleAdmin
ADMIN_PLUGIN_INSTALLED=false # Change this to true if you have this plugin installed: https://github.com/daffyyyy/CS2-SimpleAdmin
# DB values used for CS2-SimpleAdmin
SQL_HOST=
SQL_USER=
SQL_DB=
SQL_PASSWORD=
223 changes: 223 additions & 0 deletions app/components/BanList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
'use client';
import { useEffect, useRef, useState } from 'react';
import { getBans, dbAllBansReturn } from '../lib/get-bans';

export default function BanListButton() {
const [banList, setBanlist] = useState([] as dbAllBansReturn);
const banListModal = useRef() as React.MutableRefObject<HTMLDialogElement>;
async function updateBanList() {
const banList = await getBans();
if ('error' in banList) return;
setBanlist(banList);
}
useEffect(() => {
updateBanList();
}, []);
return (
<>
<div
onClick={() => {
updateBanList();
banListModal.current.showModal();
}}
>
Show all bans
</div>
<BanListModal
banListModal={banListModal}
banList={banList}
updateBanList={updateBanList}
/>
</>
);
}

function BanListModal({
banListModal,
banList,
updateBanList
}: {
banListModal: React.MutableRefObject<HTMLDialogElement>;
banList: dbAllBansReturn;
updateBanList: () => Promise<void>;
}) {
const [selectedPlayer, setSelectedPlayer] = useState<
dbAllBansReturn[0] | undefined
>();
const unbanPlayerModal =
useRef() as React.MutableRefObject<HTMLDialogElement>;
function closePopUp() {
banListModal.current.close();
}
return (
<dialog ref={banListModal} className="modal">
<div className="modal-box h-3/4 w-11/12 max-w-[70rem] bg-zinc-900 md:w-2/3">
{/* Dummy element to remove auto focus */}
<a href="#" className="opacity-0"></a>
<p className="pb-5 text-xl font-bold">All Active Bans</p>
<div className="overflow-x-auto">
<table className="table">
<thead className="text-slate-300">
<tr className="border-slate-300 border-opacity-30">
<th>Name</th>
<th>IP</th>
<th>Reason</th>
<th>Ends on</th>
</tr>
</thead>
<tbody>
{banList.map((ban) => {
return (
<BanItemList
key={ban.id}
banItem={ban}
setSelectedPlayer={setSelectedPlayer}
unbanPlayerModal={unbanPlayerModal}
/>
);
})}
</tbody>
</table>
</div>
<button
onClick={closePopUp}
className="btn btn-circle btn-ghost btn-sm absolute right-2 top-2"
>
</button>
</div>
<div className="modal-backdrop bg-zinc-700 opacity-30">
<button onClick={closePopUp}>close</button>
</div>
<UnbanPlayerPopUp
player={selectedPlayer}
unbanPlayerModal={unbanPlayerModal}
updateBanList={updateBanList}
/>
</dialog>
);
}

function BanItemList({
banItem,
setSelectedPlayer,
unbanPlayerModal
}: {
banItem: dbAllBansReturn[0];
setSelectedPlayer: (player: dbAllBansReturn[0]) => void;
unbanPlayerModal: React.MutableRefObject<HTMLDialogElement>;
}) {
return (
<tr className="border-slate-300 border-opacity-30 text-base">
<th>
<a
className="link link-primary"
target={'_blank'}
href={`https://steamcommunity.com/profiles/${banItem.player_steamid}/`}
>
{banItem.player_name}
</a>
</th>
<td className="font-semibold">
<a
className="link link-primary"
target={'_blank'}
href={`https://whatismyipaddress.com/ip/${banItem.player_ip}/`}
>
{banItem.player_ip}
</a>
</td>
<td className="font-semibold">{banItem.reason}</td>
{banItem.duration == 0 ? (
<td className="font-semibold">Permanent</td>
) : (
<td className="font-semibold">
{new Date(banItem.ends).toLocaleString('en-US', {
day: '2-digit',
month: 'short',
hour: 'numeric',
minute: '2-digit'
})}
</td>
)}

<td>
<button
onClick={() => {
setSelectedPlayer(banItem);
unbanPlayerModal.current.showModal();
}}
className="btn btn-error h-9 min-h-0"
>
Unban
</button>
</td>
</tr>
);
}

function UnbanPlayerPopUp({
player,
unbanPlayerModal,
updateBanList
}: {
player: dbAllBansReturn[0] | undefined;
unbanPlayerModal: React.MutableRefObject<HTMLDialogElement>;
updateBanList: () => Promise<void>;
}) {
const unbanPlayer = (e: React.MouseEvent<HTMLButtonElement>) => {
if (player?.player_steamid) {
fetch('/api/rcon', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
command: `css_unban ${player.player_steamid}`
})
});
} else {
fetch('/api/rcon', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
command: `css_unban ${player?.player_ip}`
})
});
}
closePopUp();
setTimeout(() => {
updateBanList();
}, 500);
};

function closePopUp() {
unbanPlayerModal.current.close();
}

return (
<dialog ref={unbanPlayerModal} className="modal">
<div className="modal-box bg-zinc-900">
<h3 className="pb-5 text-lg font-bold">Unban Player</h3>
<p>Are you sure you want to unban "{player?.player_name}"?</p>
<button onClick={unbanPlayer} className="btn btn-error mt-5 w-full">
UNBAN
</button>
<button onClick={closePopUp} className="btn btn-ghost mt-5 w-full">
Cancel
</button>
<button
onClick={closePopUp}
className="btn btn-circle btn-ghost btn-sm absolute right-2 top-2"
>
</button>
</div>
<div className="modal-backdrop bg-zinc-700 opacity-30">
<button onClick={closePopUp}>close</button>
</div>
</dialog>
);
}
16 changes: 10 additions & 6 deletions app/components/ServerInfoPanel.Server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { rconInit } from '@/app/lib/rcon';
import { parsePlayerData } from '@/app/lib/parse-players';
import ServerInfo from './ServerInfo';
import ServerPlayers from './ServerPlayers';
import BanList from './BanList';

export default async function ServerInfoPanel() {
const csServer = await csServerInit();
Expand All @@ -20,12 +21,15 @@ export default async function ServerInfoPanel() {
rcon.destroy();
csServer.disconnect();
return (
<div className="m-5 h-fit rounded-md bg-zinc-800 p-4">
<ServerInfo serverInfoPreRender={serverInfo} />
<ServerPlayers
playersPreRendered={allPlayers}
featureFlags={featureFlags}
/>
<div>
<div className="m-5 h-fit rounded-md bg-zinc-800 p-4">
<ServerInfo serverInfoPreRender={serverInfo} />
<ServerPlayers
playersPreRendered={allPlayers}
featureFlags={featureFlags}
/>
</div>
<BanList />
</div>
);
}
8 changes: 8 additions & 0 deletions app/lib/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import mysql from 'mysql2';

export const db = mysql.createPool({
host: process.env.SQL_HOST,
user: process.env.SQL_USER,
database: process.env.SQL_DB,
password: process.env.SQL_PASSWORD
}).promise();
27 changes: 27 additions & 0 deletions app/lib/get-bans.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use server';
import { db } from '@/app/lib/db';

export type dbAllBansReturn = {
id: number;
player_steamid: string;
player_name: string;
player_ip: string;
admin_steamid: string;
admin_name: string;
reason: string;
duration: number;
ends: string;
created: string;
status: string;
}[];

export async function getBans() {
try {
const dbRes = await db.query('SELECT * FROM sa_bans WHERE status="ACTIVE"');
const res = dbRes[0] as dbAllBansReturn;
return res;
} catch (err) {
console.log(err);
return { error: true };
}
}
Loading

0 comments on commit b8b284e

Please sign in to comment.