From 84052a2f1c04834ec68259ef2985a935b1d6bd9d Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Sat, 13 Jun 2026 20:04:40 -0300 Subject: [PATCH] Tidy BlueskyPublisher conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Import Exception instead of referencing it inline, read the blob via data_get, source the web-app host from config (new bluesky.web_app key) instead of hardcoding bsky.app, and drop the getUtf8ByteOffset no-op — the PREG /u offset is already in bytes, so the call sites use it directly. --- app/Services/Social/BlueskyPublisher.php | 22 ++++++++++------------ config/trypost.php | 2 ++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/Services/Social/BlueskyPublisher.php b/app/Services/Social/BlueskyPublisher.php index b117ac62..23d83bdb 100644 --- a/app/Services/Social/BlueskyPublisher.php +++ b/app/Services/Social/BlueskyPublisher.php @@ -10,6 +10,7 @@ use App\Models\SocialAccount; use App\Services\Media\MediaOptimizer; use App\Services\Social\Concerns\HasSocialHttpClient; +use Exception; use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; @@ -114,7 +115,7 @@ private function uploadBlob(SocialAccount $account, string $service, string $url $downloadResponse = Http::withOptions(['sink' => $tempFile])->timeout(600)->get($url); if ($downloadResponse->failed()) { - throw new \Exception('Failed to download media: HTTP '.$downloadResponse->status()); + throw new Exception('Failed to download media: HTTP '.$downloadResponse->status()); } $fileSize = filesize($tempFile); @@ -154,8 +155,8 @@ private function uploadBlob(SocialAccount $account, string $service, string $url return null; } - return $response->json()['blob']; - } catch (\Exception $e) { + return data_get($response->json(), 'blob'); + } catch (Exception $e) { Log::error('Bluesky blob upload exception', [ 'error' => $e->getMessage(), 'url' => $url, @@ -181,7 +182,7 @@ private function parseFacets(string $text): array foreach ($urlMatches[0] as $match) { $url = $this->trimTrailingUrlPunctuation($match[0]); - $start = $this->getUtf8ByteOffset($text, (int) $match[1]); + $start = (int) $match[1]; $end = $start + strlen($url); $facets[] = [ @@ -221,7 +222,7 @@ private function parseFacets(string $text): array continue; } - $start = $this->getUtf8ByteOffset($text, (int) $match[1]); + $start = (int) $match[1]; $end = $start + strlen($mention); $facets[] = [ @@ -249,7 +250,7 @@ private function parseFacets(string $text): array foreach ($hashtagMatches[0] as $match) { $hashtag = $match[0]; $tag = substr($hashtag, 1); // Remove # - $start = $this->getUtf8ByteOffset($text, (int) $match[1]); + $start = (int) $match[1]; $end = $start + strlen($hashtag); $facets[] = [ @@ -294,11 +295,6 @@ private function resolveHandleToDid(string $handle): ?string } } - private function getUtf8ByteOffset(string $text, int $charOffset): int - { - return strlen(substr($text, 0, $charOffset)); - } - /** * Trailing sentence punctuation and an unmatched closing paren are almost * never part of a URL (e.g. "see https://x.com)."). Mirrors the official @@ -319,7 +315,9 @@ private function trimTrailingUrlPunctuation(string $url): string private function buildPostUrl(string $handle, string $postId): string { - return "https://bsky.app/profile/{$handle}/post/{$postId}"; + $webApp = (string) config('trypost.platforms.bluesky.web_app'); + + return "{$webApp}/profile/{$handle}/post/{$postId}"; } private function handleApiError(Response $response): never diff --git a/config/trypost.php b/config/trypost.php index 082e1357..2ebdf592 100644 --- a/config/trypost.php +++ b/config/trypost.php @@ -145,6 +145,8 @@ 'public_appview' => env('BLUESKY_PUBLIC_APPVIEW', 'https://public.api.bsky.app'), // Default PDS used when the account has no `meta.service` override. 'default_service' => env('BLUESKY_DEFAULT_SERVICE', 'https://bsky.social'), + // Web client where published posts are viewed (profile/post URLs). + 'web_app' => env('BLUESKY_WEB_APP', 'https://bsky.app'), ], 'mastodon' => [ 'enabled' => env('MASTODON_ENABLED', true),