trypost/app/Support/UrlDetector.php
Paulo Castellano 8648ed9720 feat(bluesky): add link preview cards for posts
Bluesky does not hydrate link cards server-side, so build the app.bsky.embed.external embed at publish time: detect the first URL, scrape its OpenGraph metadata, and re-upload the og:image as the card thumb. Works for web, API and MCP. Adds a posts/link-preview endpoint so the editor renders the card live. The thumb download is SSRF-guarded and does not follow redirects.
2026-07-17 14:32:40 -03:00

38 lines
996 B
PHP

<?php
declare(strict_types=1);
namespace App\Support;
final class UrlDetector
{
/** PCRE matching bare http(s) URLs; shared with Bluesky link-facet parsing. */
public const string URL_PATTERN = '/(https?:\/\/[^\s]+)/u';
public static function firstUrl(string $text): ?string
{
if (preg_match(self::URL_PATTERN, $text, $matches) !== 1) {
return null;
}
return self::trimTrailingPunctuation($matches[0]);
}
/**
* Trailing sentence punctuation and an unmatched closing paren are almost
* never part of a URL (e.g. "see https://x.com)."). Mirrors the official
* atproto link tokenizer.
*/
public static function trimTrailingPunctuation(string $url): string
{
if (preg_match('/[.,;:!?]$/', $url)) {
$url = substr($url, 0, -1);
}
if (str_ends_with($url, ')') && ! str_contains($url, '(')) {
$url = substr($url, 0, -1);
}
return $url;
}
}