Skip to content

Commit 5fc9d01

Browse files
committed
fix: ✨ Feature for player intel, resync player on delete server, playerbase graphs, upsert fix, critical player intel permission
1 parent 3ff910f commit 5fc9d01

25 files changed

+1365
-557
lines changed

Diff for: .env.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ MARK_USER_VERIFYED_ON_ACCOUNT_LINK=true
110110
USE_USERNAME_FOR_SKINS=false
111111
FETCH_AVATAR_FROM_URL_USING_CURL=false
112112

113-
PLAYER_FETCHER_CRON_INTERVAL=hourly
113+
PLAYER_FETCHER_CRON_INTERVAL=everyThirtyMinutes
114114

115115
ALLOW_ANY_PROVIDER_SOCIAL_AUTH=false
116116

Diff for: app/Http/Controllers/Admin/CustomPageController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public function update(UpdateCustomPageRequest $request, CustomPage $customPage)
104104
$customPage->updated_by = $request->user()->id;
105105
$customPage->save();
106106

107-
return redirect()->route('admin.custom-page.index')
107+
return redirect()->back()
108108
->with(['toast' => ['type' => 'success', 'title' => __('Updated Successfully'), 'body' => __('Custom Page updated successfully')]]);
109109
}
110110

Diff for: app/Http/Controllers/Admin/GraphController.php

+199-15
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function getOnlinePlayersOverTime(Request $request)
4141
}
4242
$sqlData = $query->get();
4343
$sqlData = $sqlData->map(function ($item) {
44-
$item->created_at_5min = (int) $item->created_at_5min;
44+
$item->created_at_5min = (int)$item->created_at_5min;
4545

4646
return array_values(get_object_vars($item));
4747
})->toArray();
@@ -265,7 +265,7 @@ public function getServerPerformanceOverTime(Request $request)
265265
->whereIn('server_id', $servers->pluck('id'));
266266
$sqlData = $query->get();
267267
$sqlData = $sqlData->map(function ($item) {
268-
$item->created_at_5min = (int) $item->created_at_5min;
268+
$item->created_at_5min = (int)$item->created_at_5min;
269269
$item->used_memory = round($item->used_memory / 1024); // Convert to MB
270270

271271
return array_values(get_object_vars($item));
@@ -308,7 +308,7 @@ public function getServerOnlineActivityOverTime(Request $request)
308308
->whereIn('server_id', $servers->pluck('id'));
309309
$sqlData = $query->get();
310310
$sqlData = $sqlData->map(function ($item) {
311-
$item->created_at_5min = (int) $item->created_at_5min;
311+
$item->created_at_5min = (int)$item->created_at_5min;
312312

313313
return array_values(get_object_vars($item));
314314
})->toArray();
@@ -320,39 +320,223 @@ public function getServerOnlineActivityOverTime(Request $request)
320320
]);
321321
}
322322

323-
public function getPlayerMinecraftVersions()
323+
public function getPlayerMinecraftVersions(Request $request)
324324
{
325-
$this->authorize('view admin_dashboard');
325+
$isAuthorized = $request->user()->can('view admin_dashboard') || $request->user()->can('view server_intel');
326+
if (!$isAuthorized) {
327+
abort(403);
328+
}
329+
330+
$request->validate([
331+
'servers' => 'sometimes|nullable|array',
332+
'servers.*' => 'sometimes|nullable|integer|exists:servers,id',
333+
]);
334+
335+
$servers = $request->query('servers') ?? null;
336+
if ($servers) {
337+
$servers = Server::where('type', '!=', ServerType::Bungee())->whereIn('id', $servers)->get();
338+
} else {
339+
$servers = Server::where('type', '!=', ServerType::Bungee())->get();
340+
}
326341

327-
$data = DB::table('players')
328-
->selectRaw('COUNT(*) AS count, last_minecraft_version')
329-
->groupBy('last_minecraft_version')
342+
$data = DB::table('minecraft_player_sessions')
343+
->selectRaw('COUNT(*) AS count, minecraft_version')
344+
->whereIn('server_id', $servers->pluck('id'))
345+
->groupBy('minecraft_version')
346+
->orderBy('count', 'desc')
330347
->get()
331348
->map(function ($item) {
332349
return [
333-
'name' => $item->last_minecraft_version,
350+
'name' => $item->minecraft_version,
334351
'value' => $item->count,
335352
];
336353
});
337354

338355
return response()->json($data);
339356
}
340357

341-
public function getPlayerJoinAddresses()
358+
public function getPlayerJoinAddresses(Request $request)
342359
{
343-
$this->authorize('view admin_dashboard');
360+
$isAuthorized = $request->user()->can('view admin_dashboard') || $request->user()->can('view server_intel');
361+
if (!$isAuthorized) {
362+
abort(403);
363+
}
364+
365+
$request->validate([
366+
'servers' => 'sometimes|nullable|array',
367+
'servers.*' => 'sometimes|nullable|integer|exists:servers,id',
368+
]);
344369

345-
$data = DB::table('players')
346-
->selectRaw('COUNT(*) AS count, last_join_address')
347-
->groupBy('last_join_address')
370+
$servers = $request->query('servers') ?? null;
371+
if ($servers) {
372+
$servers = Server::where('type', '!=', ServerType::Bungee())->whereIn('id', $servers)->get();
373+
} else {
374+
$servers = Server::where('type', '!=', ServerType::Bungee())->get();
375+
}
376+
377+
$data = DB::table('minecraft_player_sessions')
378+
->selectRaw('COUNT(*) AS count, join_address')
379+
->whereIn('server_id', $servers->pluck('id'))
380+
->groupBy('join_address')
381+
->orderBy('count', 'desc')
348382
->get()
349383
->map(function ($item) {
350384
return [
351-
'name' => $item->last_join_address,
385+
'name' => $item->join_address,
352386
'value' => $item->count,
353387
];
354388
});
355389

356390
return response()->json($data);
357391
}
392+
393+
public function getPlayerJoinAddressesOverTime(Request $request)
394+
{
395+
$this->authorize('view server_intel');
396+
397+
$request->validate([
398+
'servers' => 'sometimes|nullable|array',
399+
'servers.*' => 'sometimes|nullable|integer|exists:servers,id',
400+
'from_date' => 'sometimes|nullable|date',
401+
'to_date' => 'sometimes|nullable|date',
402+
]);
403+
404+
$servers = $request->query('servers') ?? null;
405+
if ($servers) {
406+
$servers = Server::where('type', '!=', ServerType::Bungee())->whereIn('id', $servers)->get();
407+
} else {
408+
$servers = Server::where('type', '!=', ServerType::Bungee())->get();
409+
}
410+
411+
$fromDate = $request->query('from_date') ?? now()->subMonth();
412+
$toDate = $request->query('to_date') ?? now();
413+
$query = DB::table('minecraft_player_sessions')
414+
->selectRaw('UNIX_TIMESTAMP(DATE(created_at)) AS unix_day')
415+
->selectRaw('join_address')
416+
->selectRaw('COUNT(*) AS count')
417+
->groupBy(['join_address', 'unix_day'])
418+
->orderBy('unix_day')
419+
->where('created_at', '>=', $fromDate)
420+
->where('created_at', '<=', $toDate)
421+
->whereIn('server_id', $servers->pluck('id'));
422+
$sqlData = $query->get();
423+
424+
// Generate DataSet for Chart.
425+
$dataSets = [];
426+
$seriesName = [];
427+
$uniqueDates = $sqlData->unique('unix_day');
428+
429+
foreach ($sqlData as $data) {
430+
$day = $data->unix_day * 1000;
431+
$address = $data->join_address;
432+
$count = $data->count;
433+
434+
$dataSets[$address][$day] = $count;
435+
}
436+
437+
// Fill in missing data.
438+
foreach ($dataSets as $address => $dataSet) {
439+
foreach ($uniqueDates as $date) {
440+
$day = $date->unix_day * 1000;
441+
if (!isset($dataSet[$day])) {
442+
$dataSets[$address][$day] = 0;
443+
}
444+
}
445+
}
446+
447+
$finalDataSet = [];
448+
foreach ($dataSets as $address => $dataSet) {
449+
$seriesName[] = $address;
450+
451+
$dataSet = \Arr::sort($dataSet, function ($value, $key) {
452+
return $key;
453+
});
454+
$convertedArray = array_map(function ($key, $value) {
455+
return [$key, $value];
456+
}, array_keys($dataSet), $dataSet);
457+
$convertedArray = array_values($convertedArray);
458+
$finalDataSet[]['source'] = $convertedArray;
459+
}
460+
461+
return response()->json([
462+
'filters' => request()->all(['servers', 'from_date', 'to_date']),
463+
'data' => $finalDataSet,
464+
'series' => $seriesName,
465+
]);
466+
}
467+
468+
public function getPlayerMinecraftVersionsOverTime(Request $request)
469+
{
470+
$this->authorize('view server_intel');
471+
472+
$request->validate([
473+
'servers' => 'sometimes|nullable|array',
474+
'servers.*' => 'sometimes|nullable|integer|exists:servers,id',
475+
'from_date' => 'sometimes|nullable|date',
476+
'to_date' => 'sometimes|nullable|date',
477+
]);
478+
479+
$servers = $request->query('servers') ?? null;
480+
if ($servers) {
481+
$servers = Server::where('type', '!=', ServerType::Bungee())->whereIn('id', $servers)->get();
482+
} else {
483+
$servers = Server::where('type', '!=', ServerType::Bungee())->get();
484+
}
485+
486+
$fromDate = $request->query('from_date') ?? now()->subMonth();
487+
$toDate = $request->query('to_date') ?? now();
488+
$query = DB::table('minecraft_player_sessions')
489+
->selectRaw('UNIX_TIMESTAMP(DATE(created_at)) AS unix_day')
490+
->selectRaw('minecraft_version')
491+
->selectRaw('COUNT(*) AS count')
492+
->groupBy(['minecraft_version', 'unix_day'])
493+
->orderBy('unix_day')
494+
->where('created_at', '>=', $fromDate)
495+
->where('created_at', '<=', $toDate)
496+
->whereIn('server_id', $servers->pluck('id'));
497+
$sqlData = $query->get();
498+
499+
// Generate DataSet for Chart.
500+
$dataSets = [];
501+
$seriesName = [];
502+
$uniqueDates = $sqlData->unique('unix_day');
503+
504+
foreach ($sqlData as $data) {
505+
$day = $data->unix_day * 1000;
506+
$version = $data->minecraft_version;
507+
$count = $data->count;
508+
509+
$dataSets[$version][$day] = $count;
510+
}
511+
512+
// Fill in missing data.
513+
foreach ($dataSets as $version => $dataSet) {
514+
foreach ($uniqueDates as $date) {
515+
$day = $date->unix_day * 1000;
516+
if (!isset($dataSet[$day])) {
517+
$dataSets[$version][$day] = 0;
518+
}
519+
}
520+
}
521+
522+
$finalDataSet = [];
523+
foreach ($dataSets as $version => $dataSet) {
524+
$seriesName[] = $version;
525+
526+
$dataSet = \Arr::sort($dataSet, function ($value, $key) {
527+
return $key;
528+
});
529+
$convertedArray = array_map(function ($key, $value) {
530+
return [$key, $value];
531+
}, array_keys($dataSet), $dataSet);
532+
$convertedArray = array_values($convertedArray);
533+
$finalDataSet[]['source'] = $convertedArray;
534+
}
535+
536+
return response()->json([
537+
'filters' => request()->all(['servers', 'from_date', 'to_date']),
538+
'data' => $finalDataSet,
539+
'series' => $seriesName,
540+
]);
541+
}
358542
}

Diff for: app/Http/Controllers/Admin/ServerController.php

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use App\Http\Requests\CreateServerRequest;
99
use App\Http\Requests\UpdateServerRequest;
1010
use App\Jobs\CalculatePlayersJob;
11+
use App\Jobs\ResyncPlayersTableJob;
1112
use App\Models\MinecraftPlayer;
1213
use App\Models\Server;
1314
use App\Queries\Filters\FilterMultipleFields;
@@ -319,6 +320,9 @@ public function destroy(Server $server)
319320
$this->authorize('delete', $server);
320321

321322
$server->delete();
323+
324+
ResyncPlayersTableJob::dispatch();
325+
322326
return redirect()->back()
323327
->with(['toast' => ['type' => 'success', 'title' => __('Deleted Successfully'), 'body' => __('Server has been deleted permanently')]]);
324328
}

0 commit comments

Comments
 (0)