diff --git a/resources/lang/en/general.php b/resources/lang/en/general.php index 92ed656a..cb6ee4bf 100644 --- a/resources/lang/en/general.php +++ b/resources/lang/en/general.php @@ -15,4 +15,9 @@ 'last_updated' => 'Last updated :time', 'external_link' => 'External Link', 'external_link_disclaimer' => 'You are about to leave '.config('app.name').' to an external website. '.config('app.name').' has no control over the content of this site. Are you sure you wish to continue?', + + // Throttling + 'amount_hours' => ':amount hour|:amount hours', + 'amount_minutes' => ':amount minute|:amount minutes', + 'amount_seconds' => ':amount second|:amount seconds', ]; diff --git a/src/UserInterface/Components/ThrottledComponent.php b/src/UserInterface/Components/ThrottledComponent.php new file mode 100644 index 00000000..ffc2d7e8 --- /dev/null +++ b/src/UserInterface/Components/ThrottledComponent.php @@ -0,0 +1,74 @@ +getThrottlingKey(); + + $secondsUntilAvailable = RateLimiter::availableIn($this->getRateLimitKey($throttlingKey)); + + $parts = explode(':', gmdate('H:i', $secondsUntilAvailable)); + + $hours = (int) $parts[0]; + $minutes = (int) $parts[1]; + + if ($hours > 0) { + if ($minutes > 0) { + return sprintf( + '%s, %s', + trans_choice('ui::general.amount_hours', $hours, ['amount' => $hours]), + trans_choice('ui::general.amount_minutes', $minutes, ['amount' => $minutes]), + ); + } + + return trans_choice('ui::general.amount_hours', $hours, ['amount' => $hours]); + } + + if ($minutes > 0) { + return trans_choice('ui::general.amount_minutes', $minutes, ['amount' => $minutes]); + } + + return trans_choice('ui::general.amount_seconds', $secondsUntilAvailable, ['amount' => $secondsUntilAvailable]); + } + + protected function isThrottled(): bool + { + try { + $this->rateLimit( + $this->getThrottlingMaxAttempts(), + $this->getThrottlingTime(), + $this->getThrottlingKey() + ); + } catch (TooManyRequestsException) { + $this->toast($this->getThrottlingMessage($this->getThrottlingAvailableIn()), $this->throttledType); + + return true; + } + + return false; + } +}