Skip to content

Commit f7fc851

Browse files
committed
add simple api for query
1 parent 72e486a commit f7fc851

3 files changed

Lines changed: 120 additions & 0 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
use App\Http\Middleware\Activity\ServerSubject;
4+
use App\Http\Middleware\Api\Client\Server\AuthenticateServerAccess;
5+
use App\Http\Middleware\Api\Client\Server\ResourceBelongsToServer;
6+
use Boy132\PlayerCounter\Http\Controllers\Api\Client\Servers\PlayerCounterController;
7+
use Boy132\PlayerCounter\Providers\PlayerCounterRoutesProvider;
8+
use Illuminate\Routing\Middleware\ThrottleRequests;
9+
use Illuminate\Support\Facades\Route;
10+
11+
Route::prefix('/servers/{server:uuid}')->middleware([ServerSubject::class, AuthenticateServerAccess::class, ResourceBelongsToServer::class])->group(function () {
12+
Route::prefix('/query')->middleware(ThrottleRequests::using(PlayerCounterRoutesProvider::QUERY_THROTTLE_KEY))->group(function () {
13+
Route::get('/', [PlayerCounterController::class, 'query']);
14+
Route::get('/players', [PlayerCounterController::class, 'players']);
15+
});
16+
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Boy132\PlayerCounter\Http\Controllers\Api\Client\Servers;
4+
5+
use App\Http\Controllers\Api\Client\ClientApiController;
6+
use App\Models\Server;
7+
use Boy132\PlayerCounter\Models\GameQuery;
8+
use Dedoc\Scramble\Attributes\Group;
9+
use Illuminate\Http\JsonResponse;
10+
use Illuminate\Http\Response;
11+
use Symfony\Component\HttpKernel\Exception\HttpException;
12+
13+
#[Group('Server - Players')]
14+
class PlayerCounterController extends ClientApiController
15+
{
16+
/**
17+
* Get query
18+
*
19+
* Returns query information.
20+
*
21+
* @throws HttpException
22+
*/
23+
public function query(Server $server): JsonResponse
24+
{
25+
$data = $this->runQuery($server);
26+
27+
return response()->json([
28+
'hostname' => (string) $data['gq_hostname'],
29+
'current_players' => (int) $data['gq_numplayers'],
30+
'max_players' => (int) $data['gq_maxplayers'],
31+
'map' => (string) $data['gq_mapname'],
32+
]);
33+
}
34+
35+
/**
36+
* Get players
37+
*
38+
* Returns the names of the current players.
39+
*
40+
* @throws HttpException
41+
*/
42+
public function players(Server $server): JsonResponse
43+
{
44+
$data = $this->runQuery($server);
45+
46+
/** @var string[] $players */
47+
$players = array_map(fn ($player) => $player['gq_name'], $data['players']);
48+
49+
return response()->json($players);
50+
}
51+
52+
/** @return array<mixed> */
53+
private function runQuery(Server $server): array
54+
{
55+
if (!$server->allocation || $server->allocation->ip === '0.0.0.0' || $server->allocation->ip === '::') {
56+
abort(Response::HTTP_NOT_ACCEPTABLE, 'Server has invalid allocation');
57+
}
58+
59+
if ($server->retrieveStatus()->isOffline()) {
60+
abort(Response::HTTP_NOT_ACCEPTABLE, 'Server is offline');
61+
}
62+
63+
/** @var ?GameQuery $gameQuery */
64+
$gameQuery = $server->egg->gameQuery; // @phpstan-ignore property.notFound
65+
66+
if (!$gameQuery) {
67+
abort(Response::HTTP_NOT_ACCEPTABLE, 'Server has no query');
68+
}
69+
70+
return $gameQuery->runQuery($server->allocation);
71+
}
72+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Boy132\PlayerCounter\Providers;
4+
5+
use App\Models\Server;
6+
use Illuminate\Cache\RateLimiting\Limit;
7+
use Illuminate\Foundation\Support\Providers\RouteServiceProvider;
8+
use Illuminate\Http\Request;
9+
use Illuminate\Support\Facades\RateLimiter;
10+
use Illuminate\Support\Facades\Route;
11+
use Webmozart\Assert\Assert;
12+
13+
class PlayerCounterRoutesProvider extends RouteServiceProvider
14+
{
15+
const QUERY_THROTTLE_KEY = 'api.client:server-resource:query';
16+
17+
public function boot(): void
18+
{
19+
$this->routes(function () {
20+
Route::middleware(['api', 'client-api', 'throttle:api.client'])
21+
->prefix('/api/client')
22+
->scopeBindings()
23+
->group(plugin_path('player-counter', 'routes/api-client.php'));
24+
});
25+
26+
RateLimiter::for(self::QUERY_THROTTLE_KEY, function (Request $request) {
27+
Assert::isInstanceOf($server = $request->route()->parameter('server'), Server::class);
28+
29+
return Limit::perMinute(2)->by($server->uuid);
30+
});
31+
}
32+
}

0 commit comments

Comments
 (0)