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
This commit is contained in:
Cory McWilliams 2016-09-17 20:53:03 +00:00
parent c9b528f1dc
commit a5def62efa
4 changed files with 103 additions and 10 deletions

View File

@ -280,8 +280,12 @@ function printStructured(container, data) {
node.setAttribute("target", data.target || "_blank");
} else if (data.iframe) {
node = document.createElement("iframe");
if (data.src) {
node.setAttribute("src", data.src);
} else {
node.setAttribute("srcdoc", data.iframe);
node.setAttribute("sandbox", "allow-forms allow-scripts allow-top-navigation");
}
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,8 +523,14 @@ function blur() {
}
function onMessage(event) {
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() {
var inputs = document.getElementsByTagName("input");

View File

@ -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)});
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;
}

View File

@ -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: `
<span style="border: 0; padding: 0; margin: 0; overflow: hidden">
${oEmbed.html}
</span>
<script language="javascript">
let gResizeMeMessage = {
event: "resizeMe",
name: "oEmbed${gEmbedIndex}",
width: -1,
height: -1,
};
setInterval(function() {
if (document.body.scrollHeight != gResizeMeMessage.height
|| document.body.scrollWidth != gResizeMeMessage.width) {
gResizeMeMessage.width = document.body.scrollWidth;
gResizeMeMessage.height = document.body.scrollHeight;
parent.postMessage(gResizeMeMessage, "*");
}
}, 100);
</script>
`,
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, ")"]);
});

View File

@ -252,3 +252,10 @@ exports.StanzaParser = function(depth) {
reset: parser.reset.bind(parser),
};
}
exports.StreamParser = function() {
let parser = new XmlStreamParser();
return {
parse: parser.parse.bind(parser),
};
}