diff --git a/api/oembed.php b/api/oembed.php new file mode 100644 index 0000000..5cea468 --- /dev/null +++ b/api/oembed.php @@ -0,0 +1,68 @@ +sendErrorResponse('Missing url parameter', 400); + + $parsed = parse_url($requestUrl); + $relativePath = $parsed['path'] ?? null; + if (!$relativePath) $this->sendErrorResponse('Invalid url', 400); + if ($relativePath !== '/' && str_ends_with($relativePath, '/')) $relativePath = rtrim($relativePath, '/'); + + $globals = $this->fetchGlobals(); + + $results = $this->fetchFromApi('optimized_oembed', 'url=eq.' . urlencode($relativePath)); + if (!empty($results)) { + $item = $results[0]; + $this->sendResponse([ + 'version' => '1.0', + 'type' => 'link', + 'title' => $item['title'], + 'author_name' => $globals['author'], + 'provider_name' => $globals['site_name'], + 'provider_url' => $globals['url'], + 'thumbnail_url' => $globals['url'] . $item['image_url'], + 'html' => '' . htmlspecialchars($item['title']) . '', + ]); + } + + $segments = explode('/', trim($relativePath, '/')); + if (count($segments) === 1 && $segments[0] !== '') { + $title = ucwords(str_replace('-', ' ', $segments[0])) . ' • ' . $globals['author']; + $this->sendResponse([ + 'version' => '1.0', + 'type' => 'link', + 'title' => $title, + 'author_name' => $globals['author'], + 'provider_name' => $globals['site_name'], + 'provider_url' => $globals['url'], + 'thumbnail_url' => $globals['url'] . $globals['avatar'], + 'html' => '' . htmlspecialchars($title) . '', + ]); + } + + $this->sendErrorResponse('No match found', 404); + } + + private function fetchGlobals(): array + { + $globals = $this->fetchFromApi('optimized_globals', 'limit=1'); + return $globals[0] ?? [ + 'author' => 'Cory Dransfeldt', + 'site_name' => 'coryd.dev', + 'url' => 'https://www.coryd.dev', + 'avatar' => '' + ]; + } +} + +$handler = new OembedHandler(); +$handler->handleRequest(); diff --git a/package-lock.json b/package-lock.json index 0876f18..10c4833 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "coryd.dev", - "version": "3.9.0", + "version": "4.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "coryd.dev", - "version": "3.9.0", + "version": "4.0.0", "license": "MIT", "dependencies": { "html-minifier-terser": "7.2.0", diff --git a/package.json b/package.json index a56b593..b944893 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coryd.dev", - "version": "3.9.0", + "version": "4.0.0", "description": "The source for my personal site. Built using 11ty (and other tools).", "type": "module", "engines": { diff --git a/queries/views/feeds/oembed.sql b/queries/views/feeds/oembed.sql new file mode 100644 index 0000000..f07f3ff --- /dev/null +++ b/queries/views/feeds/oembed.sql @@ -0,0 +1,87 @@ +CREATE OR REPLACE VIEW optimized_oembed AS +WITH oembed_data AS ( + SELECT + 'post' AS type, + p.url::TEXT AS url, + p.title AS title, + p.description AS description, + CASE + WHEN df.filename_disk IS NOT NULL AND df.filename_disk != '' AND df.filename_disk != '/' THEN df.filename_disk + ELSE (SELECT g.avatar FROM optimized_globals g LIMIT 1) + END AS image_url, + p.date AS content_date + FROM optimized_posts p + LEFT JOIN directus_files df ON p.image = df.filename_disk + UNION ALL + SELECT + 'book' AS type, + b.url::TEXT AS url, + b.title AS title, + b.description AS description, + CASE + WHEN b.image IS NOT NULL AND b.image != '' THEN b.image + ELSE (SELECT g.avatar FROM optimized_globals g LIMIT 1) + END AS image_url, + b.date_finished AS content_date + FROM optimized_books b + UNION ALL + SELECT + 'artist' AS type, + ar.url::TEXT AS url, + ar.name AS title, + ar.description AS description, + CASE + WHEN ar.image IS NOT NULL AND ar.image != '' THEN ar.image + ELSE (SELECT g.avatar FROM optimized_globals g LIMIT 1) + END AS image_url, + CURRENT_TIMESTAMP AS content_date + FROM optimized_artists ar + UNION ALL + SELECT + 'genre' AS type, + g.url::TEXT AS url, + g.name AS title, + g.description AS description, + CASE + WHEN top_artist.image IS NOT NULL AND top_artist.image != '' THEN top_artist.image + ELSE (SELECT g.avatar FROM optimized_globals g LIMIT 1) + END AS image_url, + CURRENT_TIMESTAMP AS content_date + FROM optimized_genres g + LEFT JOIN LATERAL ( + SELECT ar.image + FROM optimized_artists ar + WHERE (ar.genre->>'id')::bigint = g.id + ORDER BY ar.total_plays DESC + LIMIT 1 + ) top_artist ON true + UNION ALL + SELECT + 'show' AS type, + s.url::TEXT AS url, + s.title AS title, + s.description AS description, + CASE + WHEN s.image IS NOT NULL AND s.image != '' THEN s.image + ELSE (SELECT g.avatar FROM optimized_globals g LIMIT 1) + END AS image_url, + s.last_watched_at AS content_date + FROM optimized_shows s + UNION ALL + SELECT + 'movie' AS type, + m.url::TEXT AS url, + m.title AS title, + m.description AS description, + CASE + WHEN m.image IS NOT NULL AND m.image != '' THEN m.image + ELSE (SELECT g.avatar FROM optimized_globals g LIMIT 1) + END AS image_url, + m.last_watched AS content_date + FROM optimized_movies m +) +SELECT + ROW_NUMBER() OVER (ORDER BY url) AS id, + * +FROM + oembed_data; diff --git a/src/includes/fetchers/artist.php.liquid b/src/includes/fetchers/artist.php.liquid index 056fd26..d120e80 100644 --- a/src/includes/fetchers/artist.php.liquid +++ b/src/includes/fetchers/artist.php.liquid @@ -75,6 +75,7 @@ ), 250); $ogImage = htmlspecialchars($artist["image"], ENT_QUOTES, "UTF-8"); $fullUrl = "https://www.coryd.dev" . $requestUri; + $oembedUrl = "https://www.coryd.dev/oembed" . $requestUri; ob_start(); diff --git a/src/includes/fetchers/book.php.liquid b/src/includes/fetchers/book.php.liquid index 0409024..3818280 100644 --- a/src/includes/fetchers/book.php.liquid +++ b/src/includes/fetchers/book.php.liquid @@ -98,6 +98,7 @@ ), 250); $ogImage = htmlspecialchars($book["image"], ENT_QUOTES, "UTF-8"); $fullUrl = "https://www.coryd.dev" . $requestUri; + $oembedUrl = "https://www.coryd.dev/oembed" . $requestUri; ob_start(); diff --git a/src/includes/fetchers/genre.php.liquid b/src/includes/fetchers/genre.php.liquid index 7da6908..3f0c5ad 100644 --- a/src/includes/fetchers/genre.php.liquid +++ b/src/includes/fetchers/genre.php.liquid @@ -66,6 +66,7 @@ $pageDescription = truncateText(htmlspecialchars(strip_tags($genre["description"]), ENT_QUOTES, "UTF-8"), 250); $ogImage = htmlspecialchars($genre["artists"][0]["image"], ENT_QUOTES, "UTF-8"); $fullUrl = "https://www.coryd.dev" . $requestUri; + $oembedUrl = "https://www.coryd.dev/oembed" . $requestUri; ob_start(); diff --git a/src/includes/fetchers/movie.php.liquid b/src/includes/fetchers/movie.php.liquid index d22d732..02dd36b 100644 --- a/src/includes/fetchers/movie.php.liquid +++ b/src/includes/fetchers/movie.php.liquid @@ -75,6 +75,7 @@ ), 250); $ogImage = htmlspecialchars($movie["backdrop"], ENT_QUOTES, "UTF-8"); $fullUrl = "https://www.coryd.dev" . $requestUri; + $oembedUrl = "https://www.coryd.dev/oembed" . $requestUri; ob_start(); diff --git a/src/includes/fetchers/show.php.liquid b/src/includes/fetchers/show.php.liquid index f88d764..1466f4a 100644 --- a/src/includes/fetchers/show.php.liquid +++ b/src/includes/fetchers/show.php.liquid @@ -66,6 +66,7 @@ $pageDescription = truncateText(htmlspecialchars(strip_tags($show["description"]), ENT_QUOTES, "UTF-8"), 250); $ogImage = htmlspecialchars($show["image"], ENT_QUOTES, "UTF-8"); $fullUrl = "https://www.coryd.dev" . $requestUri; + $oembedUrl = "https://www.coryd.dev/oembed" . $requestUri; ob_start(); diff --git a/src/includes/fetchers/tags.php.liquid b/src/includes/fetchers/tags.php.liquid index 97212ed..3eba3d2 100644 --- a/src/includes/fetchers/tags.php.liquid +++ b/src/includes/fetchers/tags.php.liquid @@ -99,6 +99,7 @@ $pagination = [ $pageTitle = "#" . strtolower(ucfirst($tag)) . ""; $pageDescription = "All content tagged with #" . strtolower(ucfirst($tag)) . "."; $fullUrl = "https://www.coryd.dev" . $requestUri; +$oembedUrl = "https://www.coryd.dev/oembed" . $requestUri; ob_start(); diff --git a/src/includes/metadata/base.liquid b/src/includes/metadata/base.liquid index 7a70da6..a42d23b 100644 --- a/src/includes/metadata/base.liquid +++ b/src/includes/metadata/base.liquid @@ -2,6 +2,7 @@ + diff --git a/src/includes/metadata/dynamic.php.liquid b/src/includes/metadata/dynamic.php.liquid index 4dda7db..9c6cd7f 100644 --- a/src/includes/metadata/dynamic.php.liquid +++ b/src/includes/metadata/dynamic.php.liquid @@ -4,6 +4,7 @@ " /> + diff --git a/src/includes/metadata/index.liquid b/src/includes/metadata/index.liquid index 67ec255..4d1993c 100644 --- a/src/includes/metadata/index.liquid +++ b/src/includes/metadata/index.liquid @@ -1,4 +1,5 @@ {%- assign fullUrl = globals.url | append: page.url -%} +{%- assign oembedUrl = globals.url | append: "/oembed" | append: page.url -%} {%- capture pageTitle -%} {%- if page.title -%} {{ page.title | append: ' • ' | append: globals.site_name }} @@ -74,6 +75,7 @@ {%- if type == 'dynamic' -%} {% render "metadata/dynamic.php.liquid" fullUrl:fullUrl, + oembedUrl:oembedUrl, pageTitle:pageTitle, pageDescription:pageDescription, ogImage:ogImage, @@ -82,6 +84,7 @@ {%- else -%} {% render "metadata/static.liquid" fullUrl:fullUrl, + oembedUrl:oembedUrl, pageTitle:pageTitle, pageDescription:pageDescription, ogImage:ogImage, diff --git a/src/includes/metadata/static.liquid b/src/includes/metadata/static.liquid index 1a4035e..0308047 100644 --- a/src/includes/metadata/static.liquid +++ b/src/includes/metadata/static.liquid @@ -5,5 +5,6 @@ + diff --git a/src/meta/htaccess.liquid b/src/meta/htaccess.liquid index 1ad2896..ccc620f 100644 --- a/src/meta/htaccess.liquid +++ b/src/meta/htaccess.liquid @@ -50,6 +50,9 @@ RewriteRule ^tags/([^/]+)(?:/([0-9]+))?/?$ tags/index.php [L] ## open graph assets RewriteRule ^og/([a-z0-9\-]+)/([\d\.]+)/([a-f0-9\-]+)\.([a-z0-9]+)$ /api/og-image.php?id=$3&class=$1&v=$2&extension=$4 [L] +## oembed +RewriteRule ^oembed/(.*)$ /api/oembed.php?url=https://www.coryd.dev/$1 [L,QSA] + {% for redirect in redirects -%} Redirect {{ redirect.status_code | default: "301" }} {{ redirect.source_url }} {{ redirect.destination_url }} {% endfor -%}