*/ protected $fillable = ['id', 'users_id', 'request', 'hosthash', 'timestamp']; /** * @return BelongsTo */ public function user(): BelongsTo { return $this->belongsTo(User::class, 'users_id'); } /** * @throws \Throwable */ public static function delApiRequests(mixed $userID): void { DB::transaction(function () use ($userID) { self::query()->where('users_id', $userID)->delete(); }, 3); } /** * Get the quantity of API requests in the last day for the users_id. * Note: Old request cleanup is no longer done inline to avoid blocking API responses. * Use clearApiRequests() via a scheduled command or queue job instead. * * @throws \Exception * @throws \Throwable */ public static function getApiRequests(int $userID): int { $requests = self::query() ->where('users_id', $userID) ->where('timestamp', '>', now()->subDay()) ->count('id'); return $requests ?: 0; } /** * Get hourly API request counts for the last 24 hours. * * @return array Array of hourly counts indexed by hour * * @throws \Exception */ public static function getHourlyApiRequests(int $userID): array { $hourlyData = []; $now = now(); // Initialize all 24 hours with 0 for ($i = 23; $i >= 0; $i--) { $hour = $now->copy()->subHours($i); $hourlyData[$hour->format('H:00')] = 0; } // Get API requests from the last 24 hours grouped by hour $requests = self::query() ->where('users_id', $userID) ->where('timestamp', '>', $now->subDay()) ->get(); foreach ($requests as $request) { $hourKey = Carbon::parse($request->timestamp)->format('H:00'); if (isset($hourlyData[$hourKey])) { $hourlyData[$hourKey]++; } } return $hourlyData; } /** * If a user accesses the API, log it. * * @param string|int $tokenOrUserId API token string or user ID integer * @param string $request The API request. */ public static function addApiRequest(string|int $tokenOrUserId, string $request): void { if (is_int($tokenOrUserId)) { $userID = $tokenOrUserId; } else { $userID = User::query()->select(['id'])->where('api_token', $tokenOrUserId)->value('id'); } self::recordApiRequest((int) $userID, $request, now()->toDateTimeString()); } public static function recordApiRequest(int $userId, string $request, string $occurredAt): void { self::query()->insert([ 'users_id' => $userId, 'request' => $request, 'timestamp' => $occurredAt, ]); } /** * Delete api requests older than a day. * * @param int|bool $userID * int The users ID. * bool false do all user ID's.. * * @throws \Exception * @throws \Throwable */ public static function clearApiRequests($userID): void { DB::transaction(function () use ($userID) { if ($userID === false) { self::query()->where('timestamp', '<', now()->subDay())->delete(); } else { self::query()->where('users_id', $userID)->where('timestamp', '<', now()->subDay())->delete(); } }, 3); } }