aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/transport.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/transport.js27
1 files changed, 27 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js
index 9f85ee1..1a146ce 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js
@@ -847,6 +847,20 @@ class MeshBayTransport {
}
/**
+ * Unfurl a URL pasted in chat. The node fetches it (the browser cannot —
+ * CSP and CORS — and would leak every reader's IP), parses an OpenGraph
+ * card, and caches any image in its thumb store; `image_thumb_hash` then
+ * rides the normal file_req path like a poster. `ok: false` means "no
+ * preview" (blocked, unreachable, not HTML) — the caller just shows the
+ * bare link. Keyed by url: a message with several links fires one each.
+ */
+ async fetchLinkPreview(url) {
+ const msg = await this._sendAndWait({ type: 'link_preview_req', v: '0.6', url });
+ if (msg.type === 'error') throw new Error(msg.detail);
+ return msg;
+ }
+
+ /**
* One season's own overview/air_date/poster (docs/mediacenter.md §5.4's
* per-season view) — a show's own tmdb_meta is one static field that does
* not necessarily describe every season alike, found live: a 3-season
@@ -1854,6 +1868,9 @@ class MeshBayTransport {
? `chunk:${obj.file_id}:${obj.chunk_index}`
: obj.type === 'ping' ? `ping:${obj.token}`
: obj.type === 'media_meta_req' ? `media_meta:${obj.file_id}`
+ // One chat message can carry several links, each unfurled on its
+ // own; matching by arrival order would swap two cards.
+ : obj.type === 'link_preview_req' ? `link_preview:${obj.url}`
// Same reordering hazard as media_meta_req: an album grid fires
// one music_meta_req per visible tile, several at a time.
: obj.type === 'music_meta_req' ? `music_meta:${obj.file_id}`
@@ -2171,6 +2188,16 @@ class MeshBayTransport {
return;
}
+ // Same reasoning as media_meta_resp: keyed by url, and "nobody's waiting"
+ // must not fall through.
+ if (msg.type === 'link_preview_resp') {
+ const key = `link_preview:${msg.url}`;
+ for (const [, handler] of this._pending) {
+ if (handler._key === key) { handler.resolve(msg); return; }
+ }
+ return;
+ }
+
// Same reasoning as media_meta_resp: keyed, not arrival-order, and
// "nobody's waiting any more" must not fall through either.
if (msg.type === 'music_meta_resp') {