Skip to content

Instantly share code, notes, and snippets.

@simonpannek
Last active December 15, 2021 16:34
Show Gist options
  • Save simonpannek/30532c960fcdba163b0a915cb0d2389b to your computer and use it in GitHub Desktop.
Save simonpannek/30532c960fcdba163b0a915cb0d2389b to your computer and use it in GitHub Desktop.
This userscript replaces emojis in BBB in a Discord like style
// ==UserScript==
// @name Panikecke BBB Emoji Replacer
// @description This userscript replaces emojis in BBB in a Discord like style
// @author Simon Pannek
// @include https://node*.bbb.rbg.tum.de/html5client/*
// @version 1
// @grant none
// @run-at document-idle
// ==/UserScript==
// Timeout before starting to listen for new messages
const loadTimeout = 1500;
// List of all emojis and their image links
const emojis = {
// Not animated
":blobahyes:": "https://cdn.discordapp.com/emojis/744910241765916753.png?size=96",
":blobcomfy:": "https://cdn.discordapp.com/emojis/643897445519982622.png?size=96",
":blobcuddle:": "https://cdn.discordapp.com/emojis/643894932267991041.png?size=96",
":deepConcern:": "https://cdn.discordapp.com/emojis/710849017688359062.png?size=96",
":dogsmile:": "https://cdn.discordapp.com/emojis/836929374368038963.png?size=96",
":flush:": "https://cdn.discordapp.com/emojis/841433465207783445.png?size=96",
":flushy:": "https://cdn.discordapp.com/emojis/786203931139112981.png?size=96",
":happyJS:": "https://cdn.discordapp.com/emojis/664110317432733716.png?size=96",
":htpJS:": "https://cdn.discordapp.com/emojis/667720980965359626.png?size=96",
":iusearchbtw:": "https://cdn.discordapp.com/emojis/676951897772523572.png?size=96",
":lmuo:": "https://cdn.discordapp.com/emojis/668091545878003712.png?size=96",
":monkagiga:": "https://cdn.discordapp.com/emojis/643897519000256531.png?size=96",
":pinguassslap:": "https://cdn.discordapp.com/emojis/664110634207543326.png?size=96",
":sad:": "https://cdn.discordapp.com/emojis/856531263703613440.png?size=96",
// Animated
":catvibe:": "https://cdn.discordapp.com/emojis/908474162576773220.gif?size=96",
":pain:": "https://cdn.discordapp.com/emojis/905842315741003797.gif?size=96",
":pengudance:": "https://cdn.discordapp.com/emojis/816053259218976829.gif?size=96",
":plagiat:": "https://cdn.discordapp.com/emojis/816273958361628724.gif?size=96",
":thisisfine:": "https://cdn.discordapp.com/emojis/836929320244740138.gif?size=96",
};
// Wrap all emojis into image tags
for (const [key, value] of Object.entries(emojis)) {
emojis[key] = `<img src="${value} alt="${key}" title="${key}" style="width: 1.5rem" />`;
}
function replace(text = "") {
return text.replace(/:\w+:/g, match => emojis[match] || match);
}
function replaceChildren(messageNode) {
for (let child of messageNode.children) {
child.innerHTML = replace(escape(child.innerText));
}
}
// Escape HTML tags
const tags = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;'
};
function escape(text = "") {
return text.replace(/[&<>]/g, match => tags[match] || match);
}
let messagePreview;
// Listen to keydown events and update the message preview
document.addEventListener("keyup", e => {
// Get chat element
const chat = document.getElementsByTagName("textarea")[0];
// Check whether messagePreview element currently exists
if (messagePreview) {
if (chat && chat.value) {
// Update text
messagePreview.innerHTML = replace(escape(chat.value));
} else {
// Remove messagePreview, if chat does not exist anymore
messagePreview.remove();
messagePreview = null;
}
} else {
if (chat && chat.value) {
// If chat element exists and it contains text, create a message preview element
messagePreview = document.createElement("p");
messagePreview.innerHTML = replace(escape(chat.value));
chat.parentElement.insertAdjacentElement("beforebegin", messagePreview);
}
}
});
let subObserver;
setTimeout(() => {
const chatMessages = document.getElementById("chat-messages");
// Update existing chat messages
for (let messageList of chatMessages.children) {
// Filter out system messages
if (!messageList.classList[0].includes("item")) {
continue;
}
const messageNode = messageList.children[0].children[1].children[1];
replaceChildren(messageNode);
}
// Listen for new chat messages
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
// Replace content of new message
const messageNode = mutation.addedNodes[0].children[0].children[1].children[1];
replaceChildren(messageNode);
// Unregister current subObserver
if (subObserver) {
subObserver.disconnect();
}
// Register new subObserver
subObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
const child = mutation.addedNodes[0];
child.innerHTML = replace(escape(child.innerText));
});
});
subObserver.observe(messageNode, { childList: true });
});
});
observer.observe(chatMessages, { childList: true });
}, loadTimeout);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment