Greasy Fork is available in English.
Creates a window in YouTube's live chat window, that shows live translations and spanner comments.
// ==UserScript==
// @name YouTube Live Translation Collector
// @namespace https://github.com/Gestalte/youtube-live-translation-collector
// @version 1.2
// @description Creates a window in YouTube's live chat window, that shows live translations and spanner comments.
// @author https://github.com/Gestalte
// @match https://www.youtube.com/live_chat*
// @grant none
// @license WTFPL
// ==/UserScript==
var commentIdentifier = (function() {
// Final Regex: /^\/?((英訳|英訳\/en|en|tr|translation)\s?(:|-|\})|\[(英訳|英訳\/en|en|tr|translation)\]|(英訳|英訳\/en|en|tr|translation)\\s)/i
var basePattern = "^\\/?((§)\\s?(:|-|\\})|\\[(§)\\]|(§)\s)";
var thingsToMatch = ["英訳", "英訳\/en", "en", "tr", "translation"];
var pattern = basePattern.replace(/§/g, thingsToMatch.join('|'));
return {
isTranslation: function (txt) {
return RegExp(pattern, 'i').test(txt)
},
isSpecial: function(author) {
if (author === null ) {
return false;
}
return author.classList
? (author.classList.contains('moderator') || author.classList.contains('owner'))
: author.content.author.classes.indexOf('moderator') > -1;
},
identify: function(node) {
let authorElement = node.querySelector('#author-name');
let messageElement = node.querySelector('#message');
let message = messageElement.innerText.trim();
if(commentIdentifier.isSpecial(authorElement) || commentIdentifier.isTranslation(message)) {
monitor.stickComment(node);
}
}
}
}());
var monitor = (function(){
return {
setupWindow: function() {
// This creates a window at the top of the live chat window
// where translations and spanner comments will appear.
let sticky = document.createElement('div');
let ticker = document.getElementById('ticker');
sticky.id = 'sticky';
sticky.style.maxHeight = '30%';
sticky.style.overflow = 'auto';
ticker.parentNode.insertBefore(sticky, ticker);
},
init: function() {
let chatItems = document.querySelector('#items.style-scope.yt-live-chat-item-list-renderer');
// stick items that exist on load
chatItems.querySelectorAll('yt-live-chat-text-message-renderer').forEach(commentIdentifier.identify);
// stick mutations
let observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach(commentIdentifier.identify);
});
});
// start the observer
observer.observe(chatItems, { childList: true });
},
stickComment: function(node) {
let sticky = document.getElementById('sticky');
sticky.appendChild(node);
let chat = document.querySelector('#chat');
let itemScroller = chat.querySelector('#item-scroller');
itemScroller.scrollTop = itemScroller.scrollHeight;
sticky.scrollTop = sticky.scrollHeight;
}
}
}());
(function(){
monitor.setupWindow();
window.top.addEventListener('load', monitor.init());
})();