From a5def62efa59934805cf3e1c8ac5280c770a72c3 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Sat, 17 Sep 2016 20:53:03 +0000 Subject: [PATCH] I just learned that URL unfurling is a thing, and now this chat client supports it (poorly). git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3335 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- core/client.js | 16 +++++-- packages/cory/chat/chat.js | 23 +++++++--- packages/cory/libunfurl/libunfurl.js | 67 ++++++++++++++++++++++++++++ packages/cory/libxml/libxml.js | 7 +++ 4 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 packages/cory/libunfurl/libunfurl.js diff --git a/core/client.js b/core/client.js index f9ccc6d5..938db2ae 100644 --- a/core/client.js +++ b/core/client.js @@ -280,8 +280,12 @@ function printStructured(container, data) { node.setAttribute("target", data.target || "_blank"); } else if (data.iframe) { node = document.createElement("iframe"); - node.setAttribute("srcdoc", data.iframe); - node.setAttribute("sandbox", "allow-forms allow-scripts allow-top-navigation"); + if (data.src) { + node.setAttribute("src", data.src); + } else { + node.setAttribute("srcdoc", data.iframe); + } + node.setAttribute("sandbox", "allow-forms allow-scripts allow-top-navigation allow-same-origin"); node.setAttribute("width", data.width || 320); node.setAttribute("height", data.height || 240); if (data.name) { @@ -519,7 +523,13 @@ function blur() { } function onMessage(event) { - send({event: "onWindowMessage", message: event.data}); + if (event.data && event.data.event == "resizeMe" && event.data.width && event.data.height) { + var iframe = document.getElementById("iframe_" + event.data.name); + iframe.setAttribute("width", event.data.width); + iframe.setAttribute("height", event.data.height); + } else { + send({event: "onWindowMessage", message: event.data}); + } } function submitButton() { diff --git a/packages/cory/chat/chat.js b/packages/cory/chat/chat.js index 0384e336..19d5c95d 100644 --- a/packages/cory/chat/chat.js +++ b/packages/cory/chat/chat.js @@ -250,8 +250,9 @@ function updateConversation() { terminal.clear(); printToConversation(gCurrentConversation, ["[", gCurrentConversation.name, "]"]); if (history) { + let previous = Promise.resolve(); for (let message of history) { - printToConversation(gCurrentConversation, message); + previous = previous.then(x => printToConversation(gCurrentConversation, message)); } } updateUsers(); @@ -326,10 +327,10 @@ function getConversation(session, conversationName) { return result; } -function printToConversation(conversation, message, notify) { +async function printToConversation(conversation, message, notify) { if (conversation == gCurrentConversation) { if (message.action == "message") { - printMessage(message.message); + await printMessage(message.message); } else if (message.action == "presence") { if (message.presence == "unavailable") { terminal.print(new Date().toString(), ": ", message.user, " has left the room."); @@ -405,7 +406,7 @@ function niceTime(lastTime, thisTime) { return result.join(" "); } -function formatMessage(message) { +async function formatMessage(message) { var result; if (typeof message == "string") { for (let i = 0; i < message.length; i++) { @@ -417,9 +418,17 @@ function formatMessage(message) { var regex = /(\w+:\/*\S+?)(?=(?:[\.!?])?(?:$|\s))/gi; var match; var lastIndex = 0; + let libunfurl; while ((match = regex.exec(message)) !== null) { + if (!libunfurl) { + libunfurl = await core.getService("libunfurl", "libunfurl"); + } result.push({class: "base1", value: message.substring(lastIndex, match.index)}); - result.push({href: match[0]}); + if (!libunfurl) { + result.push({href: match[0]}); + } else { + result.push(await libunfurl.postMessage(match[0])); + } lastIndex = regex.lastIndex; } result.push({class: "base1", value: message.substring(lastIndex)}); @@ -430,7 +439,7 @@ function formatMessage(message) { } var lastTimestamp = null; -function printMessage(message) { +async function printMessage(message) { var now = message.timestamp || new Date().toString(); var from = message.from || "unknown"; @@ -441,7 +450,7 @@ function printMessage(message) { {class: "base3", value: from}, {class: "base00", value: ">"}, " ", - formatMessage(message.message)); + await formatMessage(message.message)); lastTimestamp = now; } diff --git a/packages/cory/libunfurl/libunfurl.js b/packages/cory/libunfurl/libunfurl.js new file mode 100644 index 00000000..bb50298f --- /dev/null +++ b/packages/cory/libunfurl/libunfurl.js @@ -0,0 +1,67 @@ +"use strict"; + +//! {"category": "libraries", "require": ["libhttp", "libxml"], "permissions": ["network"]} + +let libxml = require("libxml"); +let libhttp = require("libhttp"); + +let gEmbedIndex = 0; + +async function unfurl(url) { + let result = {href: url}; + let response = await libhttp.get(url); + let parsed = libxml.StreamParser().parse(response.body); + let oEmbedUrl; + for (let node of parsed) { + if (node.type == "element" && node.value == "link" && node.attributes.type == "application/json+oembed") { + oEmbedUrl = node.attributes.href; + break; + } + } + + if (oEmbedUrl) { + response = await libhttp.get(oEmbedUrl); + let oEmbed = JSON.parse(response.body); + gEmbedIndex++; + result = [{href: url}, "\n", { + name: "oEmbed" + gEmbedIndex, + iframe: ` + + ${oEmbed.html} + + +`, + width: oEmbed.width || 320, + height: oEmbed.height || 120, + style: "margin: 0; padding: 0; border: 0; overflow: hidden", + }]; + } + + return result; +} + +async function test() { + terminal.print(await unfurl("https://twitter.com/511nyAlbany/status/777221230915096576")); + terminal.print(await unfurl("https://www.youtube.com/watch?v=pTA0DSfrGZ0")); +} + +//test().catch(terminal.print); + +core.register("onMessage", function(sender, message) { + return unfurl(message).catch(error => [message, "(error retrieving: ", error, ")"]); +}); \ No newline at end of file diff --git a/packages/cory/libxml/libxml.js b/packages/cory/libxml/libxml.js index 49bae864..28d871da 100644 --- a/packages/cory/libxml/libxml.js +++ b/packages/cory/libxml/libxml.js @@ -251,4 +251,11 @@ exports.StanzaParser = function(depth) { parse: parser.parse.bind(parser), reset: parser.reset.bind(parser), }; +} + +exports.StreamParser = function() { + let parser = new XmlStreamParser(); + return { + parse: parser.parse.bind(parser), + }; } \ No newline at end of file