Skip to content

Instantly share code, notes, and snippets.

@bertiebaggio
Forked from ItsCinnabar/preview.user.js
Last active December 16, 2024 13:13
Show Gist options
  • Save bertiebaggio/9ffe0e6e54d903c3be82cb2137aa5b3b to your computer and use it in GitHub Desktop.
Save bertiebaggio/9ffe0e6e54d903c3be82cb2137aa5b3b to your computer and use it in GitHub Desktop.
Element youtube preview fix
// ==UserScript==
// @name Element YouTube Preview
// @namespace http://tampermonkey.net/
// @version 0.3
// @description Fix YouTube embeds in Element client-side to keep description (instead of oembed, which does not)
// @author Cinnabar (original script) / bertiebaggio (for images & updates)
// @match https://example.com/
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant GM.xmlHttpRequest
// @connect youtube.com
// @connect youtu.be
// ==/UserScript==
/*
Change example.com in @match to Element client URL, eg https://element.yourdomain if self-hosting
Alternatively, you can reconfigure your homeserver to use oembed data, see link below for details.
This script will make requests from your browser to YouTube via xmlHttpRequest.
See also:
- https://github.com/matrix-org/synapse/issues/9733#issuecomment-819488067 (Cinnarbar's comment on original issue, Apr 2021)
- https://github.com/element-hq/synapse/issues/17462 (more recent issue with oembed info, Dec 2024)
Note: This userscript has been tested with Greasemonkey on a self-hosted Element & homeserver combo. YMMV
*/
(function() {
'use strict';
const checkForPreviewsInterval = 2000; // 2s, feel free to increase / decrease
const checkTitle = "- YouTube";
const checkDescription = "Enjoy the videos and music that you love, upload original content and share it all with friends, family and the world on YouTube.";
function previewEditor() {
const allPreviews = document.getElementsByClassName('mx_LinkPreviewWidget');
for (const preview of allPreviews) {
const previewImg = preview.getElementsByClassName("mx_LinkPreviewWidget_image")[0];
const caption = preview.getElementsByClassName("mx_LinkPreviewWidget_caption")[0];
if (!caption) { continue; }
const linkTitle = caption.getElementsByClassName("mx_LinkPreviewWidget_title")[0];
if (!linkTitle) { continue; }
const linkDesc = caption.getElementsByClassName("mx_LinkPreviewWidget_description")[0];
if (!linkDesc) { continue; }
if (linkTitle.textContent == checkTitle && linkDesc.textContent == checkDescription) {
const linkHref = linkTitle.childNodes[0].href; // first child is <a>
console.log("YT Preview: fetching " + linkHref);
GM.xmlHttpRequest({
method: "GET",
url: linkHref,
onload: function(response) {
if (response.status == 200) {
const title = response.responseText.match(/<title[^>]*>([^<]+)<\/title>/)[1];
const desc = response.responseText.match(/<meta name="description" content="(.*?)">/)[1];
const imgsrc = response.responseText.match(/<meta property="og:image" content="(.*?)">/)[1];
linkTitle.childNodes[0].textContent = title;
linkDesc.textContent = desc;
previewImg.childNodes[0].src = imgsrc; // first child is <img>
}
}
});
}
}
}
setInterval(previewEditor,checkForPreviewsInterval);
})();
@bertiebaggio
Copy link
Author

As noted in the original gist, remember to update the @match line with the URL of your Element client -- eg // @match https://app.element.io -- and refresh the page after saving/enabling the script.

@ItsCinnabar
Copy link

Great work!

@bertiebaggio
Copy link
Author

Updated as YT previews stopped working again

image

See: element-hq/synapse#17462

.text was not working so this now uses .textContent 🤷

Further improvements welcome :)

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment