headers['signature'] ?? null; if (is_array($signature)) { $signature = $signature[0] ?? null; } if (! is_string($signature) || $signature === '') { return null; } $data = HttpSignature::parseSignatureHeader($signature); if (isset($data['error']) || empty($data['keyId'])) { return null; } $keyId = Helpers::validateUrl($data['keyId']); if (! $keyId) { return null; } return Profile::whereKeyId($keyId)->first(); } /** * Check if a profile has blocked the given domain. */ public function isDomainBlocked(int $profileId, ?string $domain): bool { if (! $domain) { return false; } return AccountService::blocksDomain($profileId, $domain) === true; } /** * Check if a profile has blocked a specific actor via user filters. */ public function isUserBlocked(int $profileId, int $actorId): bool { $blocks = UserFilterService::blocks($profileId); return $blocks && in_array($actorId, $blocks); } /** * Delete notifications matching the given criteria. * * @param array $criteria Column => value pairs for the query. */ public function deleteNotifications(array $criteria): void { $query = Notification::query(); foreach ($criteria as $column => $value) { $query->where($column, $value); } $query->get()->each(function ($notification) { $notification->forceDelete(); }); } /** * Clear cached profile follower/following counts for the given profile IDs. */ public function clearProfileCache(int ...$profileIds): void { foreach ($profileIds as $id) { Cache::forget('profile:follower_count:'.$id); Cache::forget('profile:following_count:'.$id); Cache::forget('profile:following:'.$id); Cache::forget('profile:followers:'.$id); } } /** * Strip a trailing '/activity' suffix from a URL. */ public function stripActivitySuffix(string $url): string { if (str_ends_with($url, '/activity')) { return substr($url, 0, -9); } return $url; } /** * Verify that the host of two URLs match (e.g. actor and object belong to same origin). */ public function hostsMatch(string $url1, string $url2): bool { return parse_url($url1, PHP_URL_HOST) === parse_url($url2, PHP_URL_HOST); } /** * Ensure payload has all required keys, returning false if any are missing. * * @param array $keys */ public function payloadHasKeys(array $keys): bool { foreach ($keys as $key) { if (! isset($this->payload[$key])) { return false; } } return true; } /** * Invalidate AccountService cache for the given profile IDs. */ public function clearAccountCache(int ...$profileIds): void { foreach ($profileIds as $id) { AccountService::del($id); } } }