Add viewer display
This commit is contained in:
parent
3a1fb4dfbb
commit
085f7af8f7
@ -47,7 +47,6 @@ class AddChannelPermissions extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
// Give the user a list of channels to choose from.
|
|
||||||
$channels = TraceChannel::all();
|
$channels = TraceChannel::all();
|
||||||
$channel = $this->choice('Which channel would you like to add permissions to?', $channels->pluck('channel_login')->toArray());
|
$channel = $this->choice('Which channel would you like to add permissions to?', $channels->pluck('channel_login')->toArray());
|
||||||
$channel = $channels->where('channel_login', $channel)->first();
|
$channel = $channels->where('channel_login', $channel)->first();
|
||||||
@ -64,7 +63,6 @@ public function handle()
|
|||||||
|
|
||||||
$users = array_values($users);
|
$users = array_values($users);
|
||||||
|
|
||||||
// Get the user details from the Twitch API.
|
|
||||||
$response = Http::get($this->usersApi, [
|
$response = Http::get($this->usersApi, [
|
||||||
'login' => $users,
|
'login' => $users,
|
||||||
]);
|
]);
|
||||||
|
@ -21,10 +21,11 @@ public function index(Request $request)
|
|||||||
public function channel(ChannelActionsRequest $request, Channel $channel)
|
public function channel(ChannelActionsRequest $request, Channel $channel)
|
||||||
{
|
{
|
||||||
$limit = $request->input('limit', 50);
|
$limit = $request->input('limit', 50);
|
||||||
|
$actions = $channel->actions()->orderBy('timestamp', 'desc')->paginate($limit);
|
||||||
|
|
||||||
return view('dashboard.channel', [
|
return view('dashboard.channel', [
|
||||||
'channel' => $channel,
|
'channel' => $channel,
|
||||||
'actions' => $channel->actions()->orderBy('timestamp', 'desc')->paginate($limit),
|
'actions' => $actions,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
app/Http/Controllers/ViewerController.php
Normal file
39
app/Http/Controllers/ViewerController.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
use App\Models\Trace\Message;
|
||||||
|
|
||||||
|
class ViewerController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request, string $viewerId)
|
||||||
|
{
|
||||||
|
// Check if viewerId is numeric
|
||||||
|
if (!is_numeric($viewerId)) {
|
||||||
|
$message = Message::orderBy('timestamp', 'desc')
|
||||||
|
->where('author_login', $viewerId)
|
||||||
|
->firstOrFail();
|
||||||
|
$viewerId = $message->author_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if viewerId exists
|
||||||
|
$initialMessage = Message::orderBy('timestamp', 'desc')
|
||||||
|
->where('author_id', $viewerId)
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
// Get distinct author_login based on author_id
|
||||||
|
$usernames = Message::where('author_id', $viewerId)
|
||||||
|
->distinct('author_login')
|
||||||
|
->get()
|
||||||
|
->pluck('author_login')
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return view('viewer.index', [
|
||||||
|
'id' => $viewerId,
|
||||||
|
'username' => $initialMessage->author_login,
|
||||||
|
'usernames' => $usernames,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ class ModeratorAction extends Model
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function formatted() : string
|
public function formatted($asHtml = false) : string
|
||||||
{
|
{
|
||||||
$cmd = $this->action;
|
$cmd = $this->action;
|
||||||
$discriminator = $this->discriminator;
|
$discriminator = $this->discriminator;
|
||||||
@ -38,7 +38,12 @@ public function formatted() : string
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($cmd === 'delete') {
|
if ($cmd === 'delete') {
|
||||||
return sprintf('/%s %s %s %s', $cmd, $this->targetName(), $this->message, $this->message_id);
|
$message = $this->message;
|
||||||
|
if ($asHtml) {
|
||||||
|
$message = htmlspecialchars($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('/%s %s %s %s', $cmd, $this->targetName(), $message, $this->message_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,11 +51,21 @@ public function formatted() : string
|
|||||||
*/
|
*/
|
||||||
if ($cmd === 'timeout') {
|
if ($cmd === 'timeout') {
|
||||||
$duration = $this->timeout_duration;
|
$duration = $this->timeout_duration;
|
||||||
return sprintf('/%s %s %s %s', $cmd, $this->targetName(), $duration, $this->timeout_reason ?? '');
|
$reason = $this->timeout_reason;
|
||||||
|
if ($asHtml) {
|
||||||
|
$reason = htmlspecialchars($reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('/%s %s %s %s', $cmd, $this->targetName(), $duration, $reason ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($discriminator === 'TermAction') {
|
if ($discriminator === 'TermAction') {
|
||||||
return sprintf('/%s %s %s', $cmd, $this->text, $this->term_id);
|
$text = $this->text;
|
||||||
|
if ($asHtml) {
|
||||||
|
$text = htmlspecialchars($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('/%s %s %s', $cmd, $text, $this->term_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return trim(sprintf('/%s %s', $cmd, $this->targetName()));
|
return trim(sprintf('/%s %s', $cmd, $this->targetName()));
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@if ($actions->hasPages())
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="border px-4 py-2">
|
<td colspan="3" class="border px-4 py-2">
|
||||||
@ -39,6 +40,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
|
@endif
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||||
</head>
|
</head>
|
||||||
<body class="font-sans antialiased">
|
<body class="font-sans antialiased bg-gray-900">
|
||||||
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
|
<div class="flex flex-col h-screen justify-between">
|
||||||
<livewire:layout.navigation />
|
<livewire:layout.navigation />
|
||||||
|
|
||||||
<!-- Page Heading -->
|
<!-- Page Heading -->
|
||||||
@ -34,13 +34,14 @@
|
|||||||
<p>This is the initial implementation of this project. A few different things that are planned:</p>
|
<p>This is the initial implementation of this project. A few different things that are planned:</p>
|
||||||
|
|
||||||
<ul class="list-disc list-inside mt-2">
|
<ul class="list-disc list-inside mt-2">
|
||||||
<li>Channels that are tracked where you have moderator access will be <a href="https://twitch.uservoice.com/forums/310213-developers/suggestions/38203849-add-endpoint-to-return-channels-where-the-user-is" class="underline text-amber-400">automatically retrieved from Twitch's API</a>. At the moment you have to be manually added to the database.</li>
|
<li>Channels that are tracked where you have moderator access will be <a href="https://twitch.uservoice.com/forums/310213-developers/suggestions/38203849-add-endpoint-to-return-channels-where-the-user-is" class="underline text-amber-400">automatically retrieved from Twitch's API upon login</a>. At the moment I have to manually give permissions via the database.</li>
|
||||||
<li>Different filtering options: Type of action (timeout, raid etc.), moderator (whodunit), user/viewer (next point).</li>
|
<li>Different filtering options: Type of action (timeout, raid etc.), moderator (whodunit), user/viewer (next point).</li>
|
||||||
<li>See related moderation actions, for example if a specific viewer has been timed out or banned multiple times.</li>
|
<li>See related moderation actions, for example if a specific viewer has been timed out or banned multiple times.</li>
|
||||||
<li>Searching by text.</li>
|
<li>Searching by text.</li>
|
||||||
<li>Linking any affected viewer's to their Twitch viewer card.</li>
|
<li>Linking any affected viewer's to their Twitch viewer card.</li>
|
||||||
<li>Automatic conversion to local time. Currently it's displayed in UTC.</li>
|
<li>Automatic conversion to local time. Currently it's displayed in UTC.</li>
|
||||||
<li>Ability to see a viewer's chat messages at the time of action, alongside messages before/after to see context.</li>
|
<li>Ability to see a viewer's chat messages at the time of action, alongside messages before/after to see context.</li>
|
||||||
|
<li>Username history of a user</li>
|
||||||
<li>... and probably more I'll figure out as I go along.</li>
|
<li>... and probably more I'll figure out as I go along.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -49,9 +50,25 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Page Content -->
|
<!-- Page Content -->
|
||||||
<main>
|
<main class="mb-auto bg-white dark:bg-gray-800 mt-4">
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="bg-white dark:bg-gray-800 shadow bottom-0 mt-4">
|
||||||
|
<div class="max-w-full mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<div class="text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
<p>TraceDash — v0.0.2 [Pre-Alpha Early Access™]</p>
|
||||||
|
<p>Powered by an unhealthy amount of caffeine</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-sm text-gray-500 dark:text-gray-400 text-right">
|
||||||
|
<p>Please send any feedback or bug reports to @Decicus on Discord</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
{{-- "Three Dots" Separator --}}
|
{{-- "Three Dots" Separator --}}
|
||||||
@if (is_string($element))
|
@if (is_string($element))
|
||||||
<span aria-disabled="true">
|
<span aria-disabled="true">
|
||||||
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-800 dark:text-gray-200 bg-white border border-gray-300 cursor-default leading-5">{{ $element }}</span>
|
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5">{{ $element }}</span>
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
28
resources/views/viewer/index.blade.php
Normal file
28
resources/views/viewer/index.blade.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<x-slot name="header">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||||
|
{{ __('Viewer Details') }}
|
||||||
|
</h2>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div class="py-12">
|
||||||
|
<div class="max-w-full mx-auto sm:px-6 lg:px-8">
|
||||||
|
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
||||||
|
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||||
|
Viewer details for: {{ $username }} [{{ $id }}]
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="mt-4">Seen under the following usernames:</p>
|
||||||
|
|
||||||
|
<!-- List style dots -->
|
||||||
|
<ul class="mt-2 list-disc list-inside">
|
||||||
|
@foreach ($usernames as $username)
|
||||||
|
<li>{{ $username }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use App\Http\Controllers\Auth\TwitchController;
|
use App\Http\Controllers\Auth\TwitchController;
|
||||||
use App\Http\Controllers\DashboardController;
|
use App\Http\Controllers\DashboardController;
|
||||||
|
use App\Http\Controllers\ViewerController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::middleware('guest')->group(function () {
|
Route::middleware('guest')->group(function () {
|
||||||
@ -16,6 +17,9 @@
|
|||||||
Route::get('/channel/{channel}', [DashboardController::class, 'channel'])
|
Route::get('/channel/{channel}', [DashboardController::class, 'channel'])
|
||||||
->name('dashboard.channel');
|
->name('dashboard.channel');
|
||||||
|
|
||||||
|
Route::get('/viewer/{viewerId}', [ViewerController::class, 'index'])
|
||||||
|
->name('viewer');
|
||||||
|
|
||||||
Route::post('logout', [TwitchController::class, 'logout'])
|
Route::post('logout', [TwitchController::class, 'logout'])
|
||||||
->name('logout');
|
->name('logout');
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user