mirror of https://github.com/YGGverse/HLState.git
ghost
11 months ago
8 changed files with 495 additions and 10 deletions
@ -0,0 +1,39 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
namespace DoctrineMigrations; |
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema; |
||||||
|
use Doctrine\Migrations\AbstractMigration; |
||||||
|
|
||||||
|
/** |
||||||
|
* Auto-generated Migration: Please modify to your needs! |
||||||
|
*/ |
||||||
|
final class Version20240106175257 extends AbstractMigration |
||||||
|
{ |
||||||
|
public function getDescription(): string |
||||||
|
{ |
||||||
|
return ''; |
||||||
|
} |
||||||
|
|
||||||
|
public function up(Schema $schema): void |
||||||
|
{ |
||||||
|
// this up() migration is auto-generated, please modify it to your needs |
||||||
|
$this->addSql('CREATE TABLE online (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, crc32server BIGINT NOT NULL, time BIGINT NOT NULL, total INTEGER NOT NULL, players INTEGER NOT NULL, bots INTEGER NOT NULL)'); |
||||||
|
$this->addSql('CREATE TABLE messenger_messages (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, body CLOB NOT NULL, headers CLOB NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at DATETIME NOT NULL --(DC2Type:datetime_immutable) |
||||||
|
, available_at DATETIME NOT NULL --(DC2Type:datetime_immutable) |
||||||
|
, delivered_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable) |
||||||
|
)'); |
||||||
|
$this->addSql('CREATE INDEX IDX_75EA56E0FB7336F0 ON messenger_messages (queue_name)'); |
||||||
|
$this->addSql('CREATE INDEX IDX_75EA56E0E3BD61CE ON messenger_messages (available_at)'); |
||||||
|
$this->addSql('CREATE INDEX IDX_75EA56E016BA31DB ON messenger_messages (delivered_at)'); |
||||||
|
} |
||||||
|
|
||||||
|
public function down(Schema $schema): void |
||||||
|
{ |
||||||
|
// this down() migration is auto-generated, please modify it to your needs |
||||||
|
$this->addSql('DROP TABLE online'); |
||||||
|
$this->addSql('DROP TABLE messenger_messages'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,137 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Controller; |
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface; |
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route; |
||||||
|
use Symfony\Component\HttpFoundation\Response; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
|
||||||
|
use App\Entity\Online; |
||||||
|
use Doctrine\ORM\EntityManagerInterface; |
||||||
|
|
||||||
|
class CrontabController extends AbstractController |
||||||
|
{ |
||||||
|
#[Route( |
||||||
|
'/crontab/online', |
||||||
|
name: 'crontab_online', |
||||||
|
methods: |
||||||
|
[ |
||||||
|
'GET' |
||||||
|
] |
||||||
|
)] |
||||||
|
public function online( |
||||||
|
?Request $request, |
||||||
|
EntityManagerInterface $entityManagerInterface |
||||||
|
): Response |
||||||
|
{ |
||||||
|
// Get HLServers config |
||||||
|
if ($hlservers = file_get_contents($this->getParameter('app.hlservers'))) |
||||||
|
{ |
||||||
|
$hlservers = json_decode($hlservers); |
||||||
|
} |
||||||
|
|
||||||
|
else |
||||||
|
{ |
||||||
|
$hlservers = []; |
||||||
|
} |
||||||
|
|
||||||
|
// Collect servers info |
||||||
|
$servers = []; |
||||||
|
|
||||||
|
foreach ($hlservers as $hlserver) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
$server = new \xPaw\SourceQuery\SourceQuery(); |
||||||
|
|
||||||
|
$server->Connect( |
||||||
|
$hlserver->host, |
||||||
|
$hlserver->port |
||||||
|
); |
||||||
|
|
||||||
|
if ($server->Ping()) |
||||||
|
{ |
||||||
|
if ($info = (array) $server->GetInfo()) |
||||||
|
{ |
||||||
|
// Filter response |
||||||
|
$bots = isset($info['Bots']) && $info['Bots'] > 0 ? (int) $info['Bots'] : 0; |
||||||
|
$players = isset($info['Players']) && $info['Players'] > 0 ? (int) $info['Players'] - $bots : 0; |
||||||
|
$total = $players + $bots; |
||||||
|
|
||||||
|
// Generate CRC32 server ID |
||||||
|
$crc32Server = crc32( |
||||||
|
$hlserver->host . ':' . $hlserver->port |
||||||
|
); |
||||||
|
|
||||||
|
// Get last online value |
||||||
|
$online = $entityManagerInterface->getRepository(Online::class)->findOneBy( |
||||||
|
[ |
||||||
|
'crc32server' => $crc32Server |
||||||
|
], |
||||||
|
[ |
||||||
|
'id' => 'DESC' // same as online.time but faster |
||||||
|
] |
||||||
|
); |
||||||
|
|
||||||
|
// Add new record if online changed |
||||||
|
if |
||||||
|
( |
||||||
|
is_null($online) |
||||||
|
|| |
||||||
|
$players !== $online->getPlayers() |
||||||
|
|| |
||||||
|
$bots !== $online->getBots() |
||||||
|
|| |
||||||
|
$total !== $online->getTotal() |
||||||
|
) |
||||||
|
{ |
||||||
|
$online = new Online(); |
||||||
|
|
||||||
|
$online->setCrc32server( |
||||||
|
$crc32Server |
||||||
|
); |
||||||
|
|
||||||
|
$online->setTime( |
||||||
|
time() |
||||||
|
); |
||||||
|
|
||||||
|
$online->setPlayers( |
||||||
|
$players |
||||||
|
); |
||||||
|
|
||||||
|
$online->setBots( |
||||||
|
$bots |
||||||
|
); |
||||||
|
|
||||||
|
$online->setTotal( |
||||||
|
$total |
||||||
|
); |
||||||
|
|
||||||
|
$entityManagerInterface->persist( |
||||||
|
$online |
||||||
|
); |
||||||
|
|
||||||
|
$entityManagerInterface->flush(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
catch (Exception $error) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
finally |
||||||
|
{ |
||||||
|
$server->Disconnect(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Render response |
||||||
|
return new Response(); // @TODO |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,109 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Controller; |
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface; |
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route; |
||||||
|
use Symfony\Component\HttpFoundation\Response; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
|
||||||
|
use App\Entity\Online; |
||||||
|
use Doctrine\ORM\EntityManagerInterface; |
||||||
|
|
||||||
|
class RssController extends AbstractController |
||||||
|
{ |
||||||
|
#[Route( |
||||||
|
'/rss/online/{crc32server}', |
||||||
|
name: 'rss_online', |
||||||
|
requirements: |
||||||
|
[ |
||||||
|
'crc32server' => '\d+', |
||||||
|
], |
||||||
|
methods: |
||||||
|
[ |
||||||
|
'GET' |
||||||
|
] |
||||||
|
)] |
||||||
|
public function online( |
||||||
|
?Request $request, |
||||||
|
EntityManagerInterface $entityManagerInterface |
||||||
|
): Response |
||||||
|
{ |
||||||
|
// Get HLServers config |
||||||
|
if ($hlservers = file_get_contents($this->getParameter('app.hlservers'))) |
||||||
|
{ |
||||||
|
$hlservers = json_decode($hlservers); |
||||||
|
} |
||||||
|
|
||||||
|
else |
||||||
|
{ |
||||||
|
$hlservers = []; |
||||||
|
} |
||||||
|
|
||||||
|
// Find server info |
||||||
|
foreach ($hlservers as $hlserver) |
||||||
|
{ |
||||||
|
// Generate CRC32 server ID |
||||||
|
$crc32server = crc32( |
||||||
|
$hlserver->host . ':' . $hlserver->port |
||||||
|
); |
||||||
|
|
||||||
|
// Skip servers not registered in HLServers |
||||||
|
if ($crc32server != $request->get('crc32server')) |
||||||
|
{ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Get last online value |
||||||
|
$online = $entityManagerInterface->getRepository(Online::class)->findBy( |
||||||
|
[ |
||||||
|
'crc32server' => $crc32server |
||||||
|
], |
||||||
|
[ |
||||||
|
'id' => 'DESC' // same as online.time but faster |
||||||
|
], |
||||||
|
10 |
||||||
|
); |
||||||
|
|
||||||
|
$result = []; |
||||||
|
|
||||||
|
foreach ($online as $value) |
||||||
|
{ |
||||||
|
$result[] = |
||||||
|
[ |
||||||
|
'id' => $value->getId(), |
||||||
|
'bots' => $value->getBots(), |
||||||
|
'players' => $value->getPlayers(), |
||||||
|
'total' => $value->getTotal(), |
||||||
|
'time' => $value->getTime() |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
// Response |
||||||
|
$response = new Response(); |
||||||
|
|
||||||
|
$response->headers->set( |
||||||
|
'Content-Type', |
||||||
|
'text/xml' |
||||||
|
); |
||||||
|
|
||||||
|
return $this->render( |
||||||
|
'default/rss/online.xml.twig', |
||||||
|
[ |
||||||
|
'server' => |
||||||
|
[ |
||||||
|
'crc32' => $crc32server, |
||||||
|
'host' => $hlserver->host, |
||||||
|
'port' => $hlserver->port, |
||||||
|
], |
||||||
|
'online' => $result |
||||||
|
], |
||||||
|
$response |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
throw $this->createNotFoundException(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,96 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Entity; |
||||||
|
|
||||||
|
use App\Repository\OnlineRepository; |
||||||
|
use Doctrine\DBAL\Types\Types; |
||||||
|
use Doctrine\ORM\Mapping as ORM; |
||||||
|
|
||||||
|
#[ORM\Entity(repositoryClass: OnlineRepository::class)] |
||||||
|
class Online |
||||||
|
{ |
||||||
|
#[ORM\Id] |
||||||
|
#[ORM\GeneratedValue] |
||||||
|
#[ORM\Column] |
||||||
|
private ?int $id = null; |
||||||
|
|
||||||
|
#[ORM\Column(type: Types::BIGINT)] |
||||||
|
private ?int $crc32server = null; |
||||||
|
|
||||||
|
#[ORM\Column(type: Types::BIGINT)] |
||||||
|
private ?int $time = null; |
||||||
|
|
||||||
|
#[ORM\Column] |
||||||
|
private ?int $total = null; |
||||||
|
|
||||||
|
#[ORM\Column] |
||||||
|
private ?int $players = null; |
||||||
|
|
||||||
|
#[ORM\Column] |
||||||
|
private ?int $bots = null; |
||||||
|
|
||||||
|
public function getId(): ?int |
||||||
|
{ |
||||||
|
return $this->id; |
||||||
|
} |
||||||
|
|
||||||
|
public function getCrc32server(): ?int |
||||||
|
{ |
||||||
|
return $this->crc32server; |
||||||
|
} |
||||||
|
|
||||||
|
public function setCrc32server(int $crc32server): static |
||||||
|
{ |
||||||
|
$this->crc32server = $crc32server; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
public function getTime(): ?int |
||||||
|
{ |
||||||
|
return $this->time; |
||||||
|
} |
||||||
|
|
||||||
|
public function setTime(int $time): static |
||||||
|
{ |
||||||
|
$this->time = $time; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
public function getTotal(): ?int |
||||||
|
{ |
||||||
|
return $this->total; |
||||||
|
} |
||||||
|
|
||||||
|
public function setTotal(int $total): static |
||||||
|
{ |
||||||
|
$this->total = $total; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
public function getPlayers(): ?int |
||||||
|
{ |
||||||
|
return $this->players; |
||||||
|
} |
||||||
|
|
||||||
|
public function setPlayers(int $players): static |
||||||
|
{ |
||||||
|
$this->players = $players; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
public function getBots(): ?int |
||||||
|
{ |
||||||
|
return $this->bots; |
||||||
|
} |
||||||
|
|
||||||
|
public function setBots(int $bots): static |
||||||
|
{ |
||||||
|
$this->bots = $bots; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Repository; |
||||||
|
|
||||||
|
use App\Entity\Online; |
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||||
|
use Doctrine\Persistence\ManagerRegistry; |
||||||
|
|
||||||
|
/** |
||||||
|
* @extends ServiceEntityRepository<Online> |
||||||
|
* |
||||||
|
* @method Online|null find($id, $lockMode = null, $lockVersion = null) |
||||||
|
* @method Online|null findOneBy(array $criteria, array $orderBy = null) |
||||||
|
* @method Online[] findAll() |
||||||
|
* @method Online[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) |
||||||
|
*/ |
||||||
|
class OnlineRepository extends ServiceEntityRepository |
||||||
|
{ |
||||||
|
public function __construct(ManagerRegistry $registry) |
||||||
|
{ |
||||||
|
parent::__construct($registry, Online::class); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> |
||||||
|
<channel> |
||||||
|
<atom:link href="{{ url('main_index') }}" rel="self" type="application/rss+xml"></atom:link> |
||||||
|
<title>{{ server.host }}:{{ server.port }} - {{ app.name }}</title> |
||||||
|
<link>{{ url('main_index') }}</link> |
||||||
|
{% for value in online %} |
||||||
|
<item> |
||||||
|
<title>{{ 'Online changed!' | trans }}</title> |
||||||
|
<guid>{{ value.id }}</guid> |
||||||
|
<description> |
||||||
|
{{ 'Players' | trans }}: {{ value.players }} |
||||||
|
{{ 'Bots' | trans }}: {{ value.bots }} |
||||||
|
{{ 'Total' | trans }}: {{ value.total }} |
||||||
|
</description> |
||||||
|
</item> |
||||||
|
{% endfor %} |
||||||
|
</channel> |
||||||
|
</rss> |
Loading…
Reference in new issue