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

108 lines
3.6 KiB
JavaScript
Raw Normal View History

// [1, max]
const RandomInt = max => Math.floor(Math.random() * max);
2019-03-20 02:54:00 +00:00
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(" ");
2019-03-20 02:54:00 +00:00
};
// Herp derps an element.
const DerpElement = element => {
2019-03-20 02:54:00 +00:00
const c = element;
c.derpOriginal = c.textContent; // Preserve the original contents.
2019-03-20 02:54:00 +00:00
c.onclick = () => {
c.clicked = !c.clicked;
c.textContent = c.clicked ? c.derpOriginal : c.derp_str;
2019-03-20 02:54:00 +00:00
};
c.classList.add("derped");
c.derp_str = DerpString();
c.textContent = c.derp_str;
2019-03-20 02:54:00 +00:00
c.clicked = false;
};
const ValidatePreviouslyDerpedComments = comment => {
const c = comment;
2019-03-20 02:54:00 +00:00
if (c.clicked && c.textContent === c.derpOriginal) return;
if (!c.clicked && c.textContent === c.derp_str) return;
2019-03-20 02:54:00 +00:00
// Fix the comment. The only case of malformed comments encountered so far
// are these two cases:
if (c.textContent.indexOf(c.derp_str) !== -1) {
// In the case of the new comment being appended after the derp string,
2019-03-20 02:54:00 +00:00
// just grab it and put it in the derpOriginal variable
const idx = c.derp_str.length;
2019-03-20 02:54:00 +00:00
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.
2019-03-20 02:54:00 +00:00
const idx = c.derpOriginal.length;
c.derpOriginal = c.textContent.substring(idx);
c.textContent = c.derp_str;
2019-03-20 02:54:00 +00:00
c.clicked = false;
}
};
const Init = commentsSection => {
const commentContentSelector = ["#content-text"]; // Comment text content.
const notDerpedSelector = commentContentSelector
2019-03-20 02:54:00 +00:00
.map(sel => `${sel}:not(.derped)`)
.join(", ");
const derpedSelector = commentContentSelector.map(sel => `${sel}.derped`).join(", ");
// Only watch for child list changes, as we're watching the comments
// container.
2019-03-20 02:54:00 +00:00
const mutationConfig = { attributes: false, childList: true, subtree: true };
// Detect when comments are added to the DOM.
2019-03-20 02:54:00 +00:00
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(derpedSelector).forEach(ValidatePreviouslyDerpedComments);
// Derp all un-derped comments.
document.querySelectorAll(notDerpedSelector).forEach(DerpElement);
2019-03-20 02:54:00 +00:00
});
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 CheckIfCommentsLoaded = () => {
const commentSectionSelector = "html body ytd-app ytd-comments ytd-item-section-renderer #contents";
2019-03-20 02:54:00 +00:00
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(commentSectionSelector);
if (commentsSection !== null)
Init(commentsSection);
else
CheckIfCommentsLoaded();
2019-03-20 02:54:00 +00:00
}, 500);
};
CheckIfCommentsLoaded();