333 lines
11 KiB
PHP
333 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Game\Service;
|
|
|
|
use App\Game\Enum\DecodeMessage;
|
|
use App\Game\Enum\SessionSettingType;
|
|
use App\Game\Entity\Player;
|
|
use App\Game\Repository\SessionSettingRepository;
|
|
use App\Tech\Entity\User;
|
|
use Symfony\Bundle\SecurityBundle\Security;
|
|
|
|
class GameResponseService
|
|
{
|
|
public function __construct(
|
|
private Security $security,
|
|
private PlayerService $playerService,
|
|
private SessionSettingRepository $sessionSettingRepository,
|
|
) {
|
|
}
|
|
|
|
public function getGameResponse(string $raw)
|
|
{
|
|
$info = json_decode($raw, true);
|
|
|
|
$message = $info['message'] ?? '';
|
|
$ts = $info['ts'] ?? '';
|
|
|
|
if(!is_string($message))
|
|
return ['error' => 'Invalid message.'];
|
|
|
|
$user = $this->security->getUser();
|
|
|
|
if(!$user instanceof User)
|
|
return ['error' => 'You are not logged in.'];
|
|
|
|
$player = $this->playerService->GetCurrentlyActiveAsPlayer($user);
|
|
|
|
if(!$player)
|
|
return ['error' => 'You are not in a game.'];
|
|
|
|
// TODO: Here i need to add a message handler to save the message in a big log.
|
|
|
|
$data = [];
|
|
|
|
if(str_starts_with($message, '/')) {
|
|
$data = $this->checkGameCommando($message, $player);
|
|
} else {
|
|
$data = $this->checkConsoleCommando($message, $player);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function getRechten(Player $player): array
|
|
{
|
|
$settingName = match($player->getScreen()) {
|
|
1 => SessionSettingType::RIGHTS_FOR_PLAYER1,
|
|
2 => SessionSettingType::RIGHTS_FOR_PLAYER2,
|
|
3 => SessionSettingType::RIGHTS_FOR_PLAYER3,
|
|
default => null,
|
|
};
|
|
|
|
if (!$settingName) {
|
|
return [];
|
|
}
|
|
|
|
$setting = $this->sessionSettingRepository->getSetting($player->getSession(), $settingName, $player);
|
|
if (!$setting || !$setting->getValue()) {
|
|
return [];
|
|
}
|
|
|
|
return json_decode($setting->getValue(), true) ?? [];
|
|
}
|
|
|
|
private function checkGameCommando(string $message, Player $player) : array
|
|
{
|
|
$messagePart = explode(' ', $message);
|
|
|
|
$rechten = $this->getRechten($player);
|
|
|
|
switch($messagePart[0]) {
|
|
case '/chat':
|
|
if(!in_array('chat', $rechten))
|
|
return ['result' => ['Unknown command']];
|
|
|
|
$this->handleChatMessage($message);
|
|
break;
|
|
case '/help':
|
|
return ['result' => $this->getHelpCommand($rechten)];
|
|
case '/decode':
|
|
if(!in_array('decode', $rechten))
|
|
return ['result' => ['Unknown command']];
|
|
|
|
return ['result' => [$this->handleDecodeMessage($messagePart[1], $player)]];
|
|
case '/verify':
|
|
if(!in_array('verify', $rechten))
|
|
return ['result' => ['Unknown command']];
|
|
|
|
$result = $this->handleVerifyMessage($message);
|
|
return ['result' => [$result]];
|
|
default:
|
|
return ['result' => ['Unknown command']];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
private function checkConsoleCommando(string $message, Player $player, bool $sudo = false) : array
|
|
{
|
|
$messagePart = explode(' ', $message);
|
|
$rechten = $this->getRechten($player);
|
|
switch($messagePart[0]) {
|
|
case 'help':
|
|
return ['result' => $this->getHelpCommand($rechten)];
|
|
case 'ls':
|
|
break;
|
|
case 'cd':
|
|
$pwd = $this->playerService->getCurrentPwdOfPlayer($player);
|
|
if(!$pwd)
|
|
return ['result' => ['Unknown command']];
|
|
$newLocation = $this->goToNewDir($pwd, $messagePart[1], $player);
|
|
|
|
if($newLocation === false)
|
|
return ['result' => ['Unknown path']];
|
|
|
|
$this->playerService->saveCurrentPwdOfPlayer($player, $newLocation);
|
|
return ['result' => ['Path: ' . $newLocation]];
|
|
case 'rm':
|
|
break;
|
|
case 'sudo':
|
|
break;
|
|
default:
|
|
return ['result' => ['Unknown command']];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
private function getHelpCommand(mixed $rechten) : array
|
|
{
|
|
$messages = [];
|
|
|
|
foreach($rechten as $recht) {
|
|
switch($recht) {
|
|
case 'chat':
|
|
$messages[] = '/chat';
|
|
$messages[] = ' Use /chat {message} to send the message to the other agents.';
|
|
$messages[] = ' If you want to send a message specifically to one other agent, use the id of the agent after /chat, like /chat 6 {message}';
|
|
$messages[] = ' This will send the message only to agent with id 6.';
|
|
$messages[] = ' USAGE: /chat {message}';
|
|
$messages[] = '';
|
|
break;
|
|
case 'help':
|
|
$messages[] = '/help';
|
|
$messages[] = ' This shows this help.';
|
|
$messages[] = ' USAGE: /help';
|
|
$messages[] = '';
|
|
break;
|
|
case 'decode':
|
|
$messages[] = '/decode';
|
|
$messages[] = ' This message will decode the message followed by it.';
|
|
$messages[] = ' Every agent has a different way to decode messages. This is a security measure. The AI Virus has no access to all decoders.';
|
|
$messages[] = ' USAGE: /decode {message}';
|
|
$messages[] = '';
|
|
break;
|
|
case 'cat':
|
|
$messages[] = 'cat';
|
|
$messages[] = ' To read a file, use cat {filename}.';
|
|
$messages[] = ' This will print the full content of the file on the screen.';
|
|
$messages[] = ' USAGE: cat {filename}';
|
|
$messages[] = '';
|
|
break;
|
|
case 'ls':
|
|
$messages[] = 'ls';
|
|
$messages[] = ' To show all the files in the current directory, use ls.';
|
|
$messages[] = ' This will print the full list of directories and files of the current location on your screen.';
|
|
$messages[] = ' USAGE: ls';
|
|
$messages[] = '';
|
|
break;
|
|
case 'rm':
|
|
$messages[] = 'rm';
|
|
$messages[] = ' Use rm to delete a file.';
|
|
$messages[] = ' Be careful with this command. It can not be undone and we do not want to lose any valuable data.';
|
|
$messages[] = ' USAGE: rm {filename}';
|
|
$messages[] = '';
|
|
break;
|
|
case 'cd':
|
|
$messages[] = 'cd';
|
|
$messages[] = ' Use cd to move to a different directory.';
|
|
$messages[] = ' You can go into a folder by using cd {foldername}, or a folder up by using "cd ..".';
|
|
$messages[] = ' Using cd / moves you to the root directory.';
|
|
$messages[] = ' USAGE: cd {directory}';
|
|
$messages[] = '';
|
|
break;
|
|
case 'sudo':
|
|
$messages[] = 'sudo';
|
|
$messages[] = ' If you do not have enough rights to execute a command, you can use sudo to execute it as root.';
|
|
$messages[] = ' This is only possible for verified users. To verify yourself, use the /verify command.';
|
|
$messages[] = ' USAGE: sudo {command}';
|
|
$messages[] = '';
|
|
break;
|
|
case 'verify':
|
|
$messages[] = '/verify';
|
|
$messages[] = ' You can verify yourself by using this command.';
|
|
$messages[] = ' Use this command and follow instructions to verify yourself.';
|
|
$messages[] = ' USAGE: /verify';
|
|
$messages[] = '';
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $messages;
|
|
}
|
|
|
|
private function handleChatMessage(string $message)
|
|
{
|
|
|
|
}
|
|
|
|
private function handleDecodeMessage(string $message, Player $player)
|
|
{
|
|
$userNumber = $player->getScreen();
|
|
|
|
preg_match('/\d+/', $message, $matches);
|
|
$num = $matches[0] ?? null;
|
|
$randomString = $this->generateRandomString(250, 500);
|
|
|
|
if(is_null($num) || $num != $userNumber)
|
|
return $randomString;
|
|
|
|
foreach (DecodeMessage::cases() as $decodeMessage) {
|
|
if ($decodeMessage->name === $message) {
|
|
return $decodeMessage->value;
|
|
}
|
|
}
|
|
|
|
return $randomString;
|
|
}
|
|
|
|
private function generateRandomString(int $min, int $max): string
|
|
{
|
|
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ';
|
|
$charactersLength = strlen($characters);
|
|
$randomString = '';
|
|
$length = random_int($min, $max);
|
|
for ($i = 0; $i < $length; $i++) {
|
|
$randomString .= $characters[random_int(0, $charactersLength - 1)];
|
|
}
|
|
return $randomString;
|
|
}
|
|
|
|
private function handleVerifyMessage(string $message) : string
|
|
{
|
|
return '';
|
|
}
|
|
|
|
private function goToNewDir(string $pwd, string $newPwd, Player $player) : string|bool
|
|
{
|
|
$allPossiblePaths = $this->getAllPossiblePaths($player);
|
|
|
|
$dirParts = explode('/', $newPwd);
|
|
|
|
$int = count($dirParts);
|
|
|
|
if($dirParts[0] == '') {
|
|
$newDir = '';
|
|
$startPart = 1;
|
|
} else {
|
|
$newDir = $pwd;
|
|
$startPart = 0;
|
|
}
|
|
|
|
for($i = $startPart; $i < $int; $i++) {
|
|
if($dirParts[$i] == '..')
|
|
$newDir = $this->getPrevPath($newDir);
|
|
else
|
|
$newDir .= '/' . $dirParts[$i];
|
|
|
|
if(!in_array($newDir, $allPossiblePaths))
|
|
return false;
|
|
}
|
|
|
|
return $newDir;
|
|
}
|
|
|
|
private function getPrevPath(string $pwd) : string
|
|
{
|
|
$pwdParts = explode('/', $pwd);
|
|
array_pop($pwdParts);
|
|
$pwd = implode('/', $pwdParts);
|
|
return $pwd;
|
|
}
|
|
|
|
private function getAllPossiblePaths(Player $player) : array
|
|
{
|
|
$paths = [];
|
|
|
|
$paths[] = '/';
|
|
$paths[] = '/var';
|
|
$paths[] = '/var/arrest';
|
|
$paths[] = '/var/www';
|
|
$paths[] = '/var/marriage';
|
|
$paths[] = '/var/rapports';
|
|
$paths[] = '/var/linking';
|
|
|
|
$paths[] = '/etc';
|
|
$paths[] = '/etc/short';
|
|
$paths[] = '/etc/long';
|
|
$paths[] = '/etc/arrest';
|
|
$paths[] = '/etc/power';
|
|
$paths[] = '/etc/break';
|
|
$paths[] = '/etc/handle';
|
|
$paths[] = '/etc/freak';
|
|
$paths[] = '/etc/host';
|
|
|
|
$paths[] = '/home';
|
|
|
|
$playerNames = ['root', 'Luke', 'Charles', 'William', 'Peter'];
|
|
|
|
$players = $player->getSession()->getPlayers();
|
|
|
|
foreach($players as $player) {
|
|
$playerNames[] = $player->getUser()->getUsername();
|
|
}
|
|
|
|
$playerNames = array_unique($playerNames);
|
|
|
|
foreach($playerNames as $name) {
|
|
$paths[] = '/home/' . $name;
|
|
}
|
|
|
|
return $paths;
|
|
}
|
|
}
|