104 lines
3.6 KiB
JavaScript
104 lines
3.6 KiB
JavaScript
|
// returns a random int from 1 to max
|
||
|
const randomInt = max => Math.floor(Math.random() * max);
|
||
|
|
||
|
// builds a string with random herps and derps
|
||
|
const derpString = (length = 20) => {
|
||
|
const randomLength = randomInt(length) + 1;
|
||
|
const randomDerp = randomInt(2) ? "herp" : "derp";
|
||
|
|
||
|
return Array.from({ length: randomLength }, () => randomDerp).join(" ");
|
||
|
};
|
||
|
|
||
|
// herp derps an element
|
||
|
const derpElement = element => {
|
||
|
const c = element;
|
||
|
// preserve the original contents
|
||
|
c.derpOriginal = c.textContent;
|
||
|
// swap between the two when clicked
|
||
|
c.onclick = () => {
|
||
|
c.clicked = !c.clicked;
|
||
|
c.textContent = c.clicked ? c.derpOriginal : c.derpString;
|
||
|
};
|
||
|
|
||
|
// add derped class
|
||
|
c.classList.add("derped");
|
||
|
// create a derp string for this comment
|
||
|
c.derpString = derpString();
|
||
|
// change the contents
|
||
|
c.textContent = c.derpString;
|
||
|
c.clicked = false;
|
||
|
};
|
||
|
|
||
|
const checkComment = commentElement => {
|
||
|
const c = commentElement;
|
||
|
// if everything is fine, return
|
||
|
if (c.clicked && c.textContent === c.derpOriginal) return;
|
||
|
if (!c.clicked && c.textContent === c.derpString) return;
|
||
|
|
||
|
// otherwise, fix the comment
|
||
|
// the only case of malformed comment encountered so far are these two cases:
|
||
|
if (c.textContent.indexOf(c.derpString) !== -1) {
|
||
|
// in the case of the new comment being appended after the derp string,
|
||
|
// just grab it and put it in the derpOriginal variable
|
||
|
const idx = c.derpString.length;
|
||
|
c.derpOriginal = c.textContent.substring(idx);
|
||
|
c.textContent = c.textContent.substring(0, idx);
|
||
|
c.clicked = false;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (c.textContent.indexOf(c.derpOriginal) !== -1) {
|
||
|
// Same issue but the comment was appended after derpOriginal
|
||
|
const idx = c.derpOriginal.length;
|
||
|
c.derpOriginal = c.textContent.substring(idx);
|
||
|
c.textContent = c.derpString;
|
||
|
c.clicked = false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const init = commentsSection => {
|
||
|
// selectors for comments
|
||
|
const selectors = ["#content-text"];
|
||
|
// build the full selector string
|
||
|
const derpSelectorString = selectors
|
||
|
.map(sel => `${sel}:not(.derped)`)
|
||
|
.join(", ");
|
||
|
const checkSelectorString = selectors.map(sel => `${sel}.derped`).join(", ");
|
||
|
|
||
|
// Only watch for child list changes, as we're watching the comments container
|
||
|
const mutationConfig = { attributes: false, childList: true, subtree: true };
|
||
|
|
||
|
// Create a MutationObserver
|
||
|
// This object will monitor the comments for DOM changes
|
||
|
const observer = new MutationObserver(() => {
|
||
|
// 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(checkSelectorString).forEach(checkComment);
|
||
|
// Derp all un-derped comments
|
||
|
document.querySelectorAll(derpSelectorString).forEach(derpElement);
|
||
|
});
|
||
|
|
||
|
observer.observe(commentsSection, mutationConfig);
|
||
|
};
|
||
|
|
||
|
// 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 checkCommentsLoaded = () => {
|
||
|
setTimeout(() => {
|
||
|
// This selector is awful, but Youtube re-uses a lot of the DOM (the
|
||
|
// selector for the comments is re-used across a bunch of pages) so we need
|
||
|
// the exact path to the comments to match
|
||
|
const commentsSection = document.querySelector("html body ytd-app ytd-comments ytd-item-section-renderer #contents");
|
||
|
if (commentsSection !== null) {
|
||
|
init(commentsSection);
|
||
|
}
|
||
|
else {
|
||
|
checkCommentsLoaded();
|
||
|
}
|
||
|
}, 500);
|
||
|
};
|
||
|
|
||
|
checkCommentsLoaded();
|