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 1cd4ead..10c4833 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "coryd.dev",
- "version": "3.8.4",
+ "version": "4.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "coryd.dev",
- "version": "3.8.4",
+ "version": "4.0.0",
"license": "MIT",
"dependencies": {
"html-minifier-terser": "7.2.0",
diff --git a/package.json b/package.json
index de40494..b944893 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "coryd.dev",
- "version": "3.8.4",
+ "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/queries/views/media/shows/scheduled_shows.sql b/queries/views/media/shows/scheduled_shows.sql
index f015bf8..f921241 100644
--- a/queries/views/media/shows/scheduled_shows.sql
+++ b/queries/views/media/shows/scheduled_shows.sql
@@ -25,18 +25,18 @@ SELECT json_build_object(
THEN TO_CHAR(se.air_date, 'FMMM/FMDD/YY')
ELSE TO_CHAR(se.air_date, 'FMMM/FMDD')
END
- )
- FROM scheduled_episodes se
- WHERE se.show_id = s.id
- AND se.status IN ('upcoming', 'aired')
- AND NOT EXISTS (
- SELECT 1 FROM episodes e
- WHERE e.show = s.id
- AND e.season_number = se.season_number
- AND e.episode_number = se.episode_number
- )
- ORDER BY se.season_number ASC, se.episode_number ASC
- LIMIT 1),
+ )
+ FROM scheduled_episodes se
+ WHERE se.show_id = s.id
+ AND se.status IN ('upcoming', 'aired')
+ AND NOT EXISTS (
+ SELECT 1 FROM episodes e
+ WHERE e.show = s.id
+ AND e.season_number = se.season_number
+ AND e.episode_number = se.episode_number
+ )
+ ORDER BY se.season_number ASC, se.episode_number ASC
+ LIMIT 1),
(SELECT CONCAT(
'S', e.season_number, 'E', e.episode_number, ' • ',
CASE
@@ -44,11 +44,11 @@ SELECT json_build_object(
THEN TO_CHAR(e.last_watched_at, 'FMMM/FMDD/YY')
ELSE TO_CHAR(e.last_watched_at, 'FMMM/FMDD')
END
- )
- FROM episodes e
- WHERE e.show = s.id
- ORDER BY e.last_watched_at DESC, e.season_number DESC, e.episode_number DESC
- LIMIT 1),
+ )
+ FROM episodes e
+ WHERE e.show = s.id
+ ORDER BY e.last_watched_at DESC, e.season_number DESC, e.episode_number DESC
+ LIMIT 1),
s.year::text
)
) AS grid,
@@ -59,10 +59,10 @@ SELECT json_build_object(
WHERE se.show_id = s.id
AND se.status IN ('upcoming', 'aired')
AND NOT EXISTS (
- SELECT 1 FROM episodes e
- WHERE e.show = s.id
- AND e.season_number = se.season_number
- AND e.episode_number = se.episode_number
+ SELECT 1 FROM episodes e
+ WHERE e.show = s.id
+ AND e.season_number = se.season_number
+ AND e.episode_number = se.episode_number
)
ORDER BY se.season_number ASC, se.episode_number ASC
LIMIT 1
@@ -73,10 +73,10 @@ SELECT json_build_object(
WHERE se.show_id = s.id
AND se.status IN ('upcoming', 'aired')
AND NOT EXISTS (
- SELECT 1 FROM episodes e
- WHERE e.show = s.id
- AND e.season_number = se.season_number
- AND e.episode_number = se.episode_number
+ SELECT 1 FROM episodes e
+ WHERE e.show = s.id
+ AND e.season_number = se.season_number
+ AND e.episode_number = se.episode_number
)
ORDER BY se.season_number ASC, se.episode_number ASC
LIMIT 1
@@ -122,7 +122,24 @@ SELECT json_build_object(
'backdrop', CONCAT('/', df_backdrop.filename_disk),
'url', s.slug,
'alt', CONCAT('Poster from ', s.title),
- 'subtext', s.year::text
+ 'subtext', COALESCE(
+ (
+ SELECT CONCAT(
+ 'S', se.season_number, 'E', se.episode_number, ' • ',
+ CASE
+ WHEN EXTRACT(YEAR FROM se.air_date) < EXTRACT(YEAR FROM CURRENT_DATE)
+ THEN TO_CHAR(se.air_date, 'FMMM/FMDD/YY')
+ ELSE TO_CHAR(se.air_date, 'FMMM/FMDD')
+ END
+ )
+ FROM scheduled_episodes se
+ WHERE se.show_id = s.id
+ AND se.status IN ('upcoming', 'aired')
+ ORDER BY se.season_number ASC, se.episode_number ASC
+ LIMIT 1
+ ),
+ s.year::text
+ )
) AS grid
FROM shows s
LEFT JOIN directus_files df_art ON s.art = df_art.id
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 -%}