Compare commits

...

10 Commits

8 changed files with 56 additions and 28 deletions

View File

@@ -151,7 +151,7 @@ class ProfileController extends Controller
} }
// Update comments to deleted user // Update comments to deleted user
DB::table('comments')->where('commenter_id', '=', $user->id)->update(['commenter_id' => 1]); DB::table('comments')->where('user_id', '=', $user->id)->update(['user_id' => 1]);
// Delete Profile Picture // Delete Profile Picture
if ($user->avatar) { if ($user->avatar) {

View File

@@ -2,6 +2,7 @@
namespace App\Livewire; namespace App\Livewire;
use App\Models\Comment;
use Livewire\Component; use Livewire\Component;
use Livewire\WithPagination; use Livewire\WithPagination;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@@ -24,13 +25,19 @@ class AdminCommentSearch extends Component
$this->resetPage(); $this->resetPage();
} }
public function deleteComment($commentId)
{
$comment = Comment::where('id', (int) $commentId)->firstOrFail();
$comment->delete();
cache()->flush();
}
public function render() public function render()
{ {
$comments = DB::table('comments') $comments = Comment::when($this->search !== '', fn ($query) => $query->where('body', 'LIKE', "%$this->search%"))
->join('users', 'comments.commenter_id', '=', 'users.id') ->when($this->userSearch !== '', fn ($query) => $query->whereHas('user', fn ($query) => $query->where('name', 'LIKE', "%{$this->userSearch}%")))
->select('comments.*', 'users.name') ->orderBy('created_at', 'DESC')
->when($this->search !== '', fn ($query) => $query->where('comment', 'LIKE', "%$this->search%"))
->when($this->userSearch !== '', fn ($query) => $query->where('name', 'LIKE', "%$this->userSearch%"))
->paginate(12); ->paginate(12);
return view('livewire.admin-comment-search', [ return view('livewire.admin-comment-search', [

View File

@@ -2,14 +2,13 @@
namespace App\Livewire; namespace App\Livewire;
use App\Models\Comment;
use App\Models\User; use App\Models\User;
use Livewire\Component; use Livewire\Component;
use Livewire\WithPagination; use Livewire\WithPagination;
use Livewire\Attributes\Url; use Livewire\Attributes\Url;
use Illuminate\Support\Facades\DB;
class AdminUserSearch extends Component class AdminUserSearch extends Component
{ {
use WithPagination; use WithPagination;
@@ -31,8 +30,7 @@ class AdminUserSearch extends Component
$user = User::where('id', $userID) $user = User::where('id', $userID)
->firstOrFail(); ->firstOrFail();
DB::table('comments') Comment::where('user_id', $user->id)
->where('commenter_id', '=', $user->id)
->delete(); ->delete();
cache()->flush(); cache()->flush();

View File

@@ -4,8 +4,12 @@
namespace App\Livewire; namespace App\Livewire;
use App\Models\User; use App\Models\User;
use App\Models\Episode;
use App\Notifications\CommentNotification;
use Livewire\Component; use Livewire\Component;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\RateLimiter;
@@ -74,21 +78,23 @@ class Comment extends Component
public function postReply() public function postReply()
{ {
if (! $this->comment->depth() < 2) { if (!($this->comment->depth() < 2)) {
$this->addError('replyState.body', "Too many sub comments.");
return; return;
} }
$user = auth()->user(); $user = auth()->user();
$rateLimitKey = "send-comment:{$user->id}"; $rateLimitKey = "send-comment:{$user->id}";
$rateLimitMinutes = 60 * 5; // 5 minutes
if (RateLimiter::tooManyAttempts($rateLimitKey, 5)) { if (RateLimiter::tooManyAttempts($rateLimitKey, 1)) {
$seconds = RateLimiter::availableIn($rateLimitKey); $seconds = RateLimiter::availableIn($rateLimitKey);
$this->addError('replyState.body', "Too many comments. Try again in {$seconds} seconds."); $this->addError('replyState.body', "Too many comments. Try again in {$seconds} seconds.");
return; return;
} }
RateLimiter::hit($rateLimitKey, 60); RateLimiter::hit($rateLimitKey, $rateLimitMinutes);
$this->validate([ $this->validate([
'replyState.body' => 'required' 'replyState.body' => 'required'
@@ -100,6 +106,22 @@ class Comment extends Component
$reply->save(); $reply->save();
// Notify if Episode and if not the same user
if ($reply->commentable_type == Episode::class && $user->id !== $reply->parent->user->id) {
$episode = Episode::where('id', $reply->commentable_id)
->firstOrFail();
$url = route('hentai.index', ['title' => $episode->slug]);
$reply->parent->user->notify(
new CommentNotification(
"{$user->name} replied to your comment.",
Str::limit($reply->body, 50),
"{$url}#comment-{$reply->id}"
)
);
}
$this->replyState = [ $this->replyState = [
'body' => '' 'body' => ''
]; ];

View File

@@ -31,20 +31,18 @@ class Comments extends Component
'newCommentState.body' => 'required' 'newCommentState.body' => 'required'
]); ]);
$this->addError('newCommentState.body', "Too many comments. Try again in 1 seconds.");
return;
$user = auth()->user(); $user = auth()->user();
$rateLimitKey = "send-comment:{$user->id}"; $rateLimitKey = "send-comment:{$user->id}";
$rateLimitMinutes = 60 * 5; // 5 minutes
if (RateLimiter::tooManyAttempts($rateLimitKey, 5)) { if (RateLimiter::tooManyAttempts($rateLimitKey, 1)) {
$seconds = RateLimiter::availableIn($rateLimitKey); $seconds = RateLimiter::availableIn($rateLimitKey);
$this->addError('newCommentState.body', "Too many comments. Try again in {$seconds} seconds."); $this->addError('newCommentState.body', "Too many comments. Try again in {$seconds} seconds.");
return; return;
} }
RateLimiter::hit($rateLimitKey, 60); RateLimiter::hit($rateLimitKey, $rateLimitMinutes);
$comment = $this->model->comments()->make($this->newCommentState); $comment = $this->model->comments()->make($this->newCommentState);
$comment->user()->associate($user); $comment->user()->associate($user);

View File

@@ -296,8 +296,8 @@
<div class="pb-1 text-center w-full"> <div class="pb-1 text-center w-full">
<x-responsive-nav-link :href="route('login')"> <x-responsive-nav-link :href="route('login')">
<div <div
class="relative bg-blue-700 hover:bg-blue-600 text-white font-bold px-4 h-10 rounded text-center p-[10px]"> class="relative bg-rose-700 hover:bg-rose-600 text-white font-bold px-4 h-10 rounded text-center p-[10px]">
<i class="fa-brands fa-discord"></i> {{ __('nav.login') }} <i class="fa-solid fa-arrow-right-to-bracket"></i> {{ __('nav.login') }}
</div> </div>
</x-responsive-nav-link> </x-responsive-nav-link>
</div> </div>

View File

@@ -25,6 +25,8 @@
placeholder="Search..." placeholder="Search..."
> >
</th> </th>
<th scope="col" class="px-6 py-3">
</th>
<th scope="col" class="px-6 py-3"> <th scope="col" class="px-6 py-3">
Actions Actions
</th> </th>
@@ -34,17 +36,18 @@
@foreach($comments as $comment) @foreach($comments as $comment)
<tr wire:key="comment-{{ $comment->id }}" class="bg-white border-t dark:bg-neutral-800 dark:border-pink-700"> <tr wire:key="comment-{{ $comment->id }}" class="bg-white border-t dark:bg-neutral-800 dark:border-pink-700">
<td class="px-6 py-4"> <td class="px-6 py-4">
{{ $comment->name }} {{ $comment->user->name }}
</td> </td>
<th scope="row" class="px-6 py-4 font-medium text-gray-900 dark:text-white max-w-lg"> <th scope="row" class="px-6 py-4 font-medium text-gray-900 dark:text-white max-w-lg">
{{ $comment->comment }} {{ $comment->body }}
</th>
<th scope="row" class="px-6 py-4 font-medium text-gray-900 dark:text-white max-w-lg">
{{ $comment->created_at }}
</th> </th>
<td class="px-6 py-4"> <td class="px-6 py-4">
<a href="{{ route('comments.destroy', $comment->id) }}" onclick="event.preventDefault();document.getElementById('comment-delete-form-{{ $comment->id }}').submit();" class="inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 mt-2">@lang('comments::comments.delete')</a> <button wire:click="deleteComment({{$comment->id}})" type="button" class="inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 mt-2">
<form id="comment-delete-form-{{ $comment->id }}" action="{{ route('comments.destroy', $comment->id) }}" method="POST" style="display: none;"> Delete
@method('DELETE') </button>
@csrf
</form>
</td> </td>
</tr> </tr>
@endforeach @endforeach

View File

@@ -1,5 +1,5 @@
<div> <div>
<div class="flex"> <div class="flex" id="comment-{{ $comment->id }}">
<div class="flex-shrink-0 mr-4"> <div class="flex-shrink-0 mr-4">
<img class="h-10 w-10 rounded-full" src="{{ $comment->user->getAvatar() }}" alt="{{ $comment->user->name }}"> <img class="h-10 w-10 rounded-full" src="{{ $comment->user->getAvatar() }}" alt="{{ $comment->user->name }}">
</div> </div>