youtube-herp-derp-browser-e.../index.js

119 lines
4.2 KiB
JavaScript

const RandomInt = max => Math.floor(Math.random() * max); // [1, max]
const DerpString = (length = 20) => {
const RandomDerp = () => {
let n = RandomInt(4);
let result = "";
if (n == 0) {
result = "blah";
}
else if (n == 1) {
result = "durr";
}
else if (n == 2) {
result = "herp";
}
else if (n == 3) {
result = "derp";
}
return result;
};
return Array.from({ length: (RandomInt(length) + 1) }, () => RandomDerp()).join(" ");
};
// Herp derps an comment.
const DerpComment = (commentNode, textNode) => {
commentNode.isDerped = true;
const c = textNode;
c.derpOrig = c.textContent; // Preserve the original contents.
c.onclick = () => {
c.derpClicked = !c.derpClicked;
c.textContent = c.derpClicked ? c.derpOrig : c.derpStr;
};
c.classList.add("isDerped");
c.derpStr = DerpString();
c.derpClicked = false;
c.textContent = c.derpStr; // Set the derp text.
};
const ValidatePreviouslyDerpedComments = comment => {
const c = comment;
if (c.derpClicked && c.textContent === c.derpOrig) return;
if (!c.derpClicked && c.textContent === c.derpStr) return;
// Fix the comment. The only case of malformed comments encountered so far
// are these two cases:
if (c.textContent.indexOf(c.derpStr) !== -1) {
// In the case of the new comment being appended after the derp string,
// just grab it and put it in the derpOrig variable
const idx = c.derpStr.length;
c.derpOrig = c.textContent.substring(idx);
c.textContent = c.textContent.substring(0, idx);
c.derpClicked = false;
return;
}
if (c.textContent.indexOf(c.derpOrig) !== -1) {
// Same issue, but the comment was appended after derpOrig.
const idx = c.derpOrig.length;
c.derpOrig = c.textContent.substring(idx);
c.textContent = c.derpStr;
c.derpClicked = false;
}
};
const Init = commentsSection => {
const commentTextId = "#content-text";
const derpedSelector = `${commentTextId}.isDerped`;
const commentRendererName = "YTD-COMMENT-RENDERER";
// Need to convert comments that were inserted before the mutation observer below runs.
commentsSection.querySelectorAll(commentRendererName).forEach(node => {
DerpComment(node, node.querySelector(commentTextId));
});
// Detect when comments are added to the DOM.
const observer = new MutationObserver(mutations => {
// Check that everything's fine with the already derped comments.
// This is necessary because youtube does a lot of wizardry with comments in-between videos.
document.querySelectorAll(derpedSelector).forEach(ValidatePreviouslyDerpedComments);
mutations.forEach((change, index) => {
console.assert(change.type === "childList");
change.addedNodes.forEach(node => {
if (node.nodeName === commentRendererName) {
if (!node.isDerped) {
DerpComment(node, node.querySelector(commentTextId));
}
}
});
});
});
// Only watch for child list changes, as we're watching the comments container.
observer.observe(commentsSection, { attributes: false, childList: true, subtree: true });
};
// Check every so often if comments are loaded or not. Once they are, the
// timeout stops until the user leaves youtube or reloads the page. This needs
// to be done since comments are added in the DOM through js at an undetermined
// point through Youtube's execution.
const CheckIfCommentsLoaded = () => {
setTimeout(() => {
const commentsSection = document.querySelector("ytd-comments #contents");
if (commentsSection !== null) {
Init(commentsSection);
}
else {
CheckIfCommentsLoaded();
}
// If the timeout is <= 1000 then Chrome sometimes fails to run the mutation observer.
// It'll create it and active it, but it doesn't run the callback on DOM changes...
// I'm seeing this in Chrome 110.
}, 2000);
};
CheckIfCommentsLoaded();