Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Facebook.tv
- // @namespace smhdale
- // @description Twitch.tv emotes in Facebook.com & Messenger.com!
- // @include https://www.messenger.com
- // @include https://www.messenger.com/*
- // @include https://www.facebook.com
- // @include https://www.facebook.com/*
- // @version 1.0.0
- // @grant GM_xmlhttpRequest
- // ==/UserScript==
- var loads = 0;
- window.addEventListener("load", LocalMain, false);
- var emotes = {};
- var chatSwitchObs, messageGroupObs, newMessageObs;
- var curAddr = window.location.href;
- var messenger = (curAddr.indexOf("messenger.com") > -1 ? true : false);
- //
- // FETCH AND CREATE EMOTE LISTS
- //
- GM_xmlhttpRequest({
- method: "GET",
- url: "https://twitchemotes.com",
- onload: function(response) {
- var emoteHTML = response.responseText;
- // Manipulate twitchemotes.com page to pull emotes and images
- if (emoteHTML !== "") {MakeEmoteList(emoteHTML);}
- // Load BTTV emotes afterwards
- GM_xmlhttpRequest({
- method: "GET",
- url: "https://api.betterttv.net/emotes",
- onload: function(response) {
- var emoteHTML = response.responseText;
- // Manipulate twitchemotes.com page to pull emotes and images
- if (emoteHTML !== "") {MakeBTTVEmoteList(emoteHTML);}
- },
- onerror: function(response) {
- console.log("Failed loading BTTV emote set");
- }
- });
- },
- onerror: function(response) {
- console.log("Failed loading base emote set");
- }
- });
- function MakeEmoteList(html) {
- // DEFAULT TWITCH.TV EMOTES
- var emoteRe = /emote-name.*/g;
- var emoteHTMLArr = html.match(emoteRe);
- // Create key-value dict for every emote
- var emoteID, emoteName;
- var reID = /data-image-id="([\d]+)"/;
- var reName = /data-regex="([\w]+)"/;
- for (var i = 0; i < emoteHTMLArr.length; i++) {
- // Get emote ID and name
- emoteID = reID.exec(emoteHTMLArr[i])[1];
- emoteName = reName.exec(emoteHTMLArr[i])[1];
- // Add emote info to emote dict
- emotes[emoteName] = emoteID;
- }
- }
- function MakeBTTVEmoteList(html) {
- // BETTER TTV EMOTES
- var emoteObj = JSON.parse(html);
- var emoteObjArr = emoteObj.emotes;
- var reID = /\/([\w]+?)\/1x/;
- for (var i = 0; i < emoteObjArr.length; i++) {
- //var emoteURL
- var emoteID = "$" + reID.exec(emoteObjArr[i].url)[1];
- var emoteName = emoteObjArr[i].regex;
- // Add emote info to emote dict
- emotes[emoteName] = emoteID;
- }
- // Load all the emote stuff!
- LocalMain();
- }
- function GetEmoteAsTag(emoteName, valign) {
- var imgSrc;
- var id = emotes[emoteName];
- // Detect BTTV emotes
- if (id.charAt(0) == "$") {
- // BTTV emote
- imgSrc = "https://cdn.betterttv.net/emote/" + id.slice(1) + "/1x";
- } else {
- // Normal emote
- imgSrc = "https://static-cdn.jtvnw.net/emoticons/v1/" + id + "/1.0";
- }
- // If valign specified, add it in
- var valignStyle = "vertical-align:" + (valign !== undefined ? valign.toString() : "middle") + "px;";
- var tag = '<img src="' + imgSrc + '" style="' + valignStyle + '" />';
- //console.log(tag);
- return tag;
- }
- //
- // ADDING EMOTES TO CHAT MESSAGES
- //
- function LocalMain() {
- loads++;
- if (loads == 2) {
- // Identify chat window
- var selector = (messenger ? "div._4_j4" : "div.fbNubGroup div.fbNubGroup");
- var threadWindow = document.querySelector(selector);
- // Init observer to run event on chat thread switch
- chatSwitchObs = new MutationObserver( ObserveChat );
- chatSwitchObs.observe(threadWindow, {childList: true});
- messageGroupObs = new MutationObserver(function(mutations) {
- obsLatestMessageGroup();
- });
- newMessageObs = new MutationObserver(function(mutations) {
- var nodes = mutations[mutations.length-1].addedNodes;
- var selector = (messenger ? "span._3oh-" : "span._5yl5 span");
- var latest = nodes[nodes.length-1].querySelector(selector);
- AddEmotesToMessage(latest);
- // Loading previous messages (facebook.com only)
- if (!messenger && mutations.length > 3) {
- AddEmotesToAll();
- addBrowserBtns();
- }
- });
- ObserveChat();
- // Add Twitch emote browser to message bar
- CreateEmoteBrowser();
- }
- }
- function ObserveChat() {
- if (messenger) {
- var chatWindow = document.querySelector("#js_1");
- if (chatWindow !== null) {
- // Initial message group tracking
- obsLatestMessageGroup();
- // Track future changes
- messageGroupObs.observe(chatWindow, { childList: true });
- }
- } else {
- var chatWindows = document.querySelectorAll("div.conversation > div");
- if (chatWindows !== null) {
- // Initial message tracking
- AddEmotesToAll();
- addBrowserBtns();
- // Track future changes
- for (var i = 0; i < chatWindows.length; i++) {
- // Add an emote browser button to each alive chat window
- // (if it doesn't already have one)
- // Observe the chat window
- newMessageObs.observe(chatWindows[i], { childList: true });
- }
- }
- }
- }
- function obsLatestMessageGroup() {
- var msgGroups = document.querySelectorAll("#js_1 > div._1t_p > div._1t_s");
- // Initial message update
- AddEmotesToAll();
- if (messenger) {
- var latestGroup = msgGroups[msgGroups.length - 1];
- // Track future changes
- newMessageObs.observe(latestGroup, { childList: true });
- }
- }
- function AddEmotes(message) {
- // Split message into words
- var words = message.replace(/\n/g, " ").split(" ");
- var arrLen = words.length;
- if (arrLen > 0 && !Object.isEmpty(emotes)) {
- var key, keyDec, emoteImg;
- // Check each word in message for emote phrase
- for (var i = 0; i < arrLen; i++) {
- key = words[i];
- keyDec = DecodeHTML(key);
- if (emotes[keyDec] !== undefined && emotes.hasOwnProperty(keyDec)) {
- // Replace text with emote
- emoteImg = GetEmoteAsTag(keyDec, -7);
- message = message.replace(key, emoteImg);
- }
- }
- }
- // Return message with emote images added
- return message;
- }
- function AddEmotesToMessage(node) {
- node.innerHTML = AddEmotes(node.innerHTML);
- }
- function AddEmotesToAll() {
- var selector = (messenger ? "div > span._3oh-" : "span._5yl5 span");
- var messages = document.querySelectorAll(selector);
- for (var i = 0; i < messages.length; i++) {
- AddEmotesToMessage(messages[i]);
- }
- }
- //
- // MISC FUNCTIONS
- //
- Object.isEmpty = function(obj) {
- var empty = true, key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- empty = false;
- break;
- }
- }
- return empty;
- };
- function DecodeHTML(text) {
- var txtBox = document.createElement("TEXTAREA");
- txtBox.innerHTML = text;
- return txtBox.value;
- }
- function CopyTextToClipboard(text) {
- var textArea = document.createElement("textarea");
- // Place off-screen
- textArea.style.position = 'fixed';
- textArea.style.top = -100;
- textArea.style.left = -100;
- // Add textarea to document and fill with text to copy
- textArea.value = text;
- document.body.appendChild(textArea);
- textArea.select();
- try {
- document.execCommand('copy');
- } catch (err) {
- alert("The emote couldn't be copied.");
- }
- // Delete textarea
- document.body.removeChild(textArea);
- }
- //
- // INTERACTIVE EMOTE BROWSER
- //
- // SPOILERS ON THIS LINE. DON'T BE A BISH AND LOOK AT THEM.
- var headers = ["Click an emote to copy it to your clipboard!","If you don't see any emotes, refresh the page.","Twitch memes get!","If your message is over 50% emotes, you're doing it wrong","Don't use them all at once!","Why are you reading this? Just use the emotes!","A nice fresh box of Twitch emote memes","Your memes, sir.","Click one to get cummies from daddy","GIVE ME THE MEMEmotes","Fuck I'm running out of things to put here","Fuck tha police comin' str8 from the underground","Ey b0ss, cooked up some spicy emotes","SOMETIMES I LIKE TO PLAY WITH MY BALL-","Oooh yes, you know this - I have a big emote collection, like Moses","If you borrow my emotes, then you owe me","Disregard uni assignments, acquire Twitch emotes","Brought to you by Dr. F. Frank, professor in internet retardation.","These emotes are sponsored by my student debt!","Please meme responsibly. Don't emote and drive!","I'm not sure why I wrote so many of these","Try not to meme all over the message you're writing pls","There's a secret string with a 0.001% chance of appearing. This isn't it.","The secret title string doesn't exist. Stop looking."];
- function GetHeader() {
- var min, max, chance = Math.random();
- if (chance < 0.25) {
- // Group 1 (Main title)
- min = 0;
- max = 1;
- } else if (chance < 0.55) {
- // Group 2 (describes what's in the box)
- min = 2;
- max = 5;
- } else if (chance < 0.99) {
- // Group 3 (maximum shitpost tier)
- min = 6;
- max = headers.length - 3;
- } else {
- // Group 4 (conspiracy theory tier)
- min = headers.length - 2;
- max = headers.length - 1;
- }
- return headers[Math.floor(Math.random()*(max-min+1)+min)];
- }
- function ToggleEmoteBrowser(chatName) {
- var emoteHeader = document.querySelector("#emote_header");
- var emoteBrowser = document.querySelector("#emote_browser");
- if (emoteBrowser.style.opacity == "0") {
- // Choose a random header
- emoteHeader.innerHTML = GetHeader();
- // Show emote browser
- emoteBrowser.style.display = "block";
- emoteBrowser.style.opacity = "1";
- emoteBrowser.style.transform = "translate3D(-50%, -50%, 0)";
- emoteBrowser.style.pointerEvents = "auto";
- // Remember who opened the browser
- if (chatName !== undefined) {
- emoteBrowser.setAttribute("data-sender", chatName);
- }
- } else {
- // Hide emote browser
- emoteBrowser.style.opacity = "0";
- emoteBrowser.style.transform = "translate3D(-50%, -43%, 0)";
- emoteBrowser.style.pointerEvents = "none";
- // Clear sender attribute and focus input
- emoteBrowser.setAttribute("data-sender", "");
- }
- }
- function FindCurrentChatBox() {
- // Get chat that opened emote browser
- var emoteBrowser = document.querySelector("#emote_browser");
- var chatName = emoteBrowser.getAttribute("data-sender");
- // Get correct textarea to paste into
- var parents = document.querySelectorAll("div.fbNub._50mz");
- for (var i = 0; i < parents.length; i++) {
- var header = parents[i].querySelector("h4.titlebarTextWrapper a");
- if (chatName == header.getAttribute("href")) {
- // Correct parent, paste here
- return parents[i].querySelector("textarea");
- }
- }
- return null;
- }
- function AddEmoteClickEvent(node, emoteName) {
- node.addEventListener("click", function() {
- // Click event
- var clickEvent = new MouseEvent("click", { bubbles: true, cancelable: false });
- // Set focus to input area (messenger)
- if (messenger) {
- // Copy emote name to clipboard
- CopyTextToClipboard(emoteName + " ");
- // Send click event to input area
- var inputArea = document.querySelector("div._kmc");
- inputArea.dispatchEvent(clickEvent);
- // Hide emote browser
- ToggleEmoteBrowser();
- } else {
- // Arrow key event
- var arrowEvent = new KeyboardEvent("keydown", { key: "ArrowDown" });
- var textArea = FindCurrentChatBox();
- if (textArea !== null) {
- textArea.value += emoteName + " ";
- textArea.dispatchEvent(clickEvent);
- textArea.dispatchEvent(arrowEvent);
- }
- }
- });
- }
- function CreateEmoteBrowser() {
- // Emote browser header
- var emoteHeader = document.createElement("DIV");
- emoteHeader.id = "emote_header";
- emoteHeader.style.width = "calc(100% - 38px)";
- emoteHeader.style.backgroundColor = "#6441A5";
- emoteHeader.style.color = "#FFF";
- emoteHeader.style.padding = "4px 0px 4px 0px";
- emoteHeader.style.fontSize = "22px";
- emoteHeader.style.textAlign = "center";
- emoteHeader.style.height = "30px";
- emoteHeader.style.position = "relative";
- emoteHeader.style.float = "left";
- var closeBtn = document.createElement("DIV");
- closeBtn.style.backgroundColor = "#6441A5";
- closeBtn.style.fontSize = "22px";
- closeBtn.style.color = "#FFF";
- closeBtn.innerHTML = "[x]";
- closeBtn.style.width = "38px";
- closeBtn.style.height = "30px";
- closeBtn.style.textAlign = "left";
- closeBtn.style.padding = "4px 0px 4px 0px";
- closeBtn.style.position = "relative";
- closeBtn.style.float = "right";
- closeBtn.style.cursor = "pointer";
- closeBtn.addEventListener("click", function() {
- if (!messenger) {
- // Set focus
- var textArea = FindCurrentChatBox();
- if (textArea !== null) {
- var clickEvent = new MouseEvent("click", { bubbles: true, cancelable: false });
- textArea.dispatchEvent(clickEvent);
- }
- }
- ToggleEmoteBrowser();
- });
- // Emote browser emote area
- var emoteArea = document.createElement("DIV");
- emoteArea.style.padding = "4px";
- var emoteSections = ["Default Twitch.tv set", "Better TTV set"];
- var emoteSection = 0;
- var breakDiv = document.createElement("DIV");
- breakDiv.className = "section_header";
- breakDiv.style.width = "100%";
- breakDiv.style.fontSize = "18px";
- breakDiv.style.textAlign = "center";
- breakDiv.style.clear = "both";
- // Populate emote area
- emoteArea.appendChild(breakDiv.cloneNode(false));
- for (var key in emotes) {
- if (emotes.hasOwnProperty(key)) {
- // Check if in BTTV section yet
- if (emotes[key].slice(0, 1) == "$" && emoteSection === 0) {
- // Add break div
- emoteArea.appendChild(breakDiv.cloneNode(false));
- emoteSection++;
- }
- // Create clickable emote div
- var emoteImg = document.createElement("DIV");
- emoteImg.setAttribute("title", key);
- // Make it clickable
- AddEmoteClickEvent(emoteImg, key);
- // Style it
- emoteImg.style.cursor = "pointer";
- emoteImg.style.padding = "4px";
- emoteImg.style.display = "inline-block";
- emoteImg.style.textAlign = "center";
- // Add the image
- emoteImg.innerHTML = GetEmoteAsTag(key, -1);
- // Append it to the emote area
- emoteArea.appendChild(emoteImg);
- }
- }
- // Add break div title sections
- var breakDivs = emoteArea.querySelectorAll("div.section_header");
- for (var i = 0; i < breakDivs.length; i++) {
- breakDivs[i].innerHTML = emoteSections[i];
- }
- // Create the emote browser div
- var emoteBrowser = document.createElement("DIV");
- emoteBrowser.id = "emote_browser";
- emoteBrowser.style.width = "60%";
- //emoteBrowser.style.height = "50%";
- emoteBrowser.style.top = "50%";
- emoteBrowser.style.left = "50%";
- emoteBrowser.style.backgroundColor = "#fff";
- emoteBrowser.style.position = "fixed";
- emoteBrowser.style.zIndex = "1000";
- emoteBrowser.style.borderRadius = "10px";
- emoteBrowser.style.boxShadow = "0px 0px 10px #888888";
- emoteBrowser.style.transform = "translate3D(-50%, -43%, 0)";
- emoteBrowser.style.overflow = "hidden";
- emoteBrowser.style.display = "block";
- emoteBrowser.style.opacity = "0";
- emoteBrowser.style.pointerEvents = "none";
- emoteBrowser.style.transition = "opacity 0.25s, transform 0.25s";
- emoteBrowser.appendChild(emoteHeader);
- emoteBrowser.appendChild(closeBtn);
- emoteBrowser.appendChild(emoteArea);
- document.body.appendChild(emoteBrowser);
- if (messenger) {
- // Create a button to open the emote browser
- var iconArea = document.querySelector("ul._4rv4");
- // Create button to open browser
- var openBrowser = document.createElement("LI");
- openBrowser.setAttribute("title", "Twitch emote browser");
- // Add image
- openBrowser.innerHTML = GetEmoteAsTag("Kappa", 2);
- // Add onclick event
- openBrowser.addEventListener("click", ToggleEmoteBrowser);
- // Style it
- openBrowser.style.cursor = "pointer";
- openBrowser.style.paddingRight = "9px";
- // Add to button area
- iconArea.appendChild(openBrowser);
- }
- }
- // Add emote browser button to every chat window
- function addBrowserBtns() {
- // Create button
- var openBrowser = document.createElement("DIV");
- openBrowser.setAttribute("title", "Twitch emote browser");
- openBrowser.className = "_5g2o open_browser";
- openBrowser.style.width = "18px";
- openBrowser.style.height = "18px";
- openBrowser.style.padding = "5px 6px 5px 0px";
- openBrowser.style.cursor = "pointer";
- openBrowser.style.transition = "opacity 0.2s";
- openBrowser.innerHTML = GetEmoteAsTag("Kappa", 2);
- var chats = document.querySelectorAll("div._552n");
- var re = /<img/, btn;
- for (var i = 0; i < chats.length; i++) {
- if (chats[i].querySelector("div.open_browser") === null) {
- chats[i].appendChild(openBrowser.cloneNode(true));
- chats[i].innerHTML = chats[i].innerHTML.replace(re, '<img style="max-height:100%;"');
- // Add event listener to each button
- btn = chats[i].querySelector("div.open_browser");
- AddEventListeners(btn);
- }
- }
- // Fix padding on input areas
- var inputs = document.querySelectorAll("div._552h._n4k");
- for (i = 0; i < inputs.length; i++) {
- inputs[i].style.paddingRight = "100px";
- }
- }
- function AddEventListeners(node) {
- // Get parent node
- var parents = document.querySelectorAll("div.fbNub._50mz");
- var chatName;
- for (var i = 0; i < parents.length; i++) {
- if (parents[i].contains(node)) {
- var header = parents[i].querySelector("h4.titlebarTextWrapper a");
- chatName = header.getAttribute("href");
- break;
- }
- }
- node.addEventListener("click", function() {
- ToggleEmoteBrowser(chatName);
- });
- node.addEventListener("mouseenter", function(){
- node.style.opacity = "0.6";
- });
- node.addEventListener("mouseleave", function(){
- node.style.opacity = "1";
- });
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement