diff --git a/migrations/Version20240106175257.php b/migrations/Version20240106175257.php
new file mode 100644
index 0000000..89ee6dc
--- /dev/null
+++ b/migrations/Version20240106175257.php
@@ -0,0 +1,39 @@
+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');
+ }
+}
diff --git a/src/Controller/CrontabController.php b/src/Controller/CrontabController.php
new file mode 100644
index 0000000..d95faf5
--- /dev/null
+++ b/src/Controller/CrontabController.php
@@ -0,0 +1,137 @@
+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
+ }
+}
\ No newline at end of file
diff --git a/src/Controller/MainController.php b/src/Controller/MainController.php
index db8f21a..988eadb 100644
--- a/src/Controller/MainController.php
+++ b/src/Controller/MainController.php
@@ -9,6 +9,9 @@ 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 MainController extends AbstractController
{
#[Route(
@@ -20,7 +23,8 @@ class MainController extends AbstractController
]
)]
public function index(
- ?Request $request
+ ?Request $request,
+ EntityManagerInterface $entityManagerInterface
): Response
{
// Get HLServers config
@@ -52,15 +56,49 @@ class MainController extends AbstractController
{
if ($info = (array) $server->GetInfo())
{
+ // Generate CRC32 ID
+ $crc32server = crc32(
+ $hlserver->host . ':' . $hlserver->port
+ );
+
+ // Get session
+ $session = empty($info['Players']) ? [] : (array) $server->GetPlayers();
+
+ // Sort by players by frags
+ if ($session)
+ {
+ array_multisort(
+ array_column(
+ $session,
+ 'Frags'
+ ),
+ SORT_DESC,
+ $session
+ );
+ }
+
+ // Get online
+ $online = $entityManagerInterface->getRepository(Online::class)->findBy(
+ [
+ 'crc32server' => $crc32server
+ ],
+ [
+ 'id' => 'DESC' // same as online.time but faster
+ ],
+ 10
+ );
+
+ // Add server
$servers[] = [
- 'host' => $hlserver->host,
- 'port' => $hlserver->port,
- 'alias' => $hlserver->alias,
- 'info' => $info,
- 'online' => empty($info['Players']) ? [] : (array) $server->GetPlayers()
+ 'crc32server' => $crc32server,
+ 'host' => $hlserver->host,
+ 'port' => $hlserver->port,
+ 'alias' => $hlserver->alias,
+ 'info' => $info,
+ 'session' => $session,
+ 'online' => $online
];
}
-
}
}
diff --git a/src/Controller/RssController.php b/src/Controller/RssController.php
new file mode 100644
index 0000000..4098025
--- /dev/null
+++ b/src/Controller/RssController.php
@@ -0,0 +1,109 @@
+ '\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();
+ }
+}
\ No newline at end of file
diff --git a/src/Entity/Online.php b/src/Entity/Online.php
new file mode 100644
index 0000000..17932d6
--- /dev/null
+++ b/src/Entity/Online.php
@@ -0,0 +1,96 @@
+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;
+ }
+}
diff --git a/src/Repository/OnlineRepository.php b/src/Repository/OnlineRepository.php
new file mode 100644
index 0000000..7e37dfe
--- /dev/null
+++ b/src/Repository/OnlineRepository.php
@@ -0,0 +1,23 @@
+
+ *
+ * @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);
+ }
+}
diff --git a/templates/default/main/index.html.twig b/templates/default/main/index.html.twig
index 552fe68..8ee462c 100644
--- a/templates/default/main/index.html.twig
+++ b/templates/default/main/index.html.twig
@@ -27,15 +27,15 @@
{% endfor %}
{% endif %}
- {% if server.online %}
-
{{ 'Online' | trans }}
+ {% if server.session %}
+ {{ 'Session' | trans }}
{{ 'Name' | trans }} |
{{ 'Frags' | trans }} |
{{ 'Time' | trans }} |
- {% for player in server.online %}
+ {% for player in server.session %}
{{ player.Name }} |
{{ player.Frags }} |
@@ -52,6 +52,30 @@
{% endfor %}
{% endif %}
+ {% if server.online %}
+
+ {{ 'Online' | trans }}
+
+
+
+
+ {{ 'Time' | trans }} |
+ {{ 'Players' | trans }} |
+ {{ 'Bots' | trans }} |
+ {{ 'Total' | trans }} |
+
+ {% for online in server.online %}
+
+ {{ online.time | format_datetime }} |
+ {{ online.players }} |
+ {{ online.bots }} |
+ {{ online.total }} |
+
+ {% endfor %}
+
+ {% endif %}
{% endfor %}
{% endblock %}
\ No newline at end of file
diff --git a/templates/default/rss/online.xml.twig b/templates/default/rss/online.xml.twig
new file mode 100644
index 0000000..9bfa0f3
--- /dev/null
+++ b/templates/default/rss/online.xml.twig
@@ -0,0 +1,19 @@
+
+
+
+
+ {{ server.host }}:{{ server.port }} - {{ app.name }}
+ {{ url('main_index') }}
+ {% for value in online %}
+ -
+ {{ 'Online changed!' | trans }}
+ {{ value.id }}
+
+ {{ 'Players' | trans }}: {{ value.players }}
+ {{ 'Bots' | trans }}: {{ value.bots }}
+ {{ 'Total' | trans }}: {{ value.total }}
+
+
+ {% endfor %}
+
+
\ No newline at end of file