Speed things up

This commit is contained in:
Michael Campagnaro 2023-02-15 15:50:14 -05:00
parent 829ebd0736
commit 6745b375a0
4 changed files with 116 additions and 91 deletions

View File

@ -13,7 +13,7 @@ Note: Ignores iframe embedded videos, including the chat replay iframe on YouTub
**Firefox** **Firefox**
* I have a signed xpi that you can immediately install. Open `build/` and drag the xpi into Firefox. * I have a signed xpi that you can immediately install. Open `build/` and drag the xpi into Firefox.
It may take a few seconds for the browser to display the extension installation dialog box. It may take a few seconds for the browser to display the extension installation dialog box.
* You can also find the signed Firefox files in the project's [Releases page](https://github.com/sir-pinecone/youtube-herp-derp-browser-extension/releases). * You can also find the signed Firefox files in the project's [Releases page](https://git.michael.is/michael/youtube-herp-derp-browser-extension/releases).
**Chrome** **Chrome**
* Go to Chrome extensions page. * Go to Chrome extensions page.
@ -31,10 +31,19 @@ Note: Ignores iframe embedded videos, including the chat replay iframe on YouTub
## Signing and Building ## Signing and Building
### Firefox ### Firefox
* Install web-ext with `$ npm install --global web-ext`
* Generate an unlisted xpi with: * Can either sign and upload from the CLI or manually upload. The former is easy but it triggers a human review?
* CLI Upload
* Install web-ext with `$ npm install --global web-ext`
* Generate an unlisted xpi with:
`web-ext sign --api-key <your JWT issuer> --api-secret <your JWT secret>` `web-ext sign --api-key <your JWT issuer> --api-secret <your JWT secret>`
* You can obtain these keys from https://addons.mozilla.org/en-US/developers/addon/api/key/ * You can obtain these keys from https://addons.mozilla.org/en-US/developers/addon/api/key/
* The signed xpi will be in `web-ext-artifacts/`. Drag this into Firefox to install it. * The signed xpi will be in `web-ext-artifacts/`. Drag this into Firefox to install it.
* Alternatively use the private sign-firefox-extension.sh script (not included in the repo) which places the xpi in `build/`. * Alternatively use the private sign-firefox-extension.sh script (not included in the repo) which places the xpi in `build/`.
* Manual Upload
* Go to https://addons.mozilla.org/en-US/developers, open the extension and then click on `Upload new version`.
* Pack the manifest, js script and icons directory into a zip and upload this file.
* To download the signed xpi, click on `view all` (versions), then the name of the new version, then the xpi filename.

Binary file not shown.

129
index.js
View File

@ -1,88 +1,97 @@
// [1, max] const RandomInt = max => Math.floor(Math.random() * max); // [1, max]
const RandomInt = max => Math.floor(Math.random() * max);
const DerpString = (length = 20) => { const DerpString = (length = 20) => {
const RandomDerp = () => { const RandomDerp = () => {
let n = RandomInt(4); let n = RandomInt(4);
let result = ""; let result = "";
if (n == 0) if (n == 0) {
result = "blah"; result = "blah";
else if (n == 1) }
else if (n == 1) {
result = "durr"; result = "durr";
else if (n == 2) }
else if (n == 2) {
result = "herp"; result = "herp";
else if (n == 3) }
else if (n == 3) {
result = "derp"; result = "derp";
}
return result; return result;
}; };
return Array.from({ length: (RandomInt(length) + 1) }, () => RandomDerp()).join(" "); return Array.from({ length: (RandomInt(length) + 1) }, () => RandomDerp()).join(" ");
}; };
// Herp derps an element. // Herp derps an comment.
const DerpElement = element => { const DerpComment = (commentNode, textNode) => {
const c = element; commentNode.isDerped = true;
c.derpOriginal = c.textContent; // Preserve the original contents. const c = textNode;
c.derpOrig = c.textContent; // Preserve the original contents.
c.onclick = () => { c.onclick = () => {
c.clicked = !c.clicked; c.derpClicked = !c.derpClicked;
c.textContent = c.clicked ? c.derpOriginal : c.derp_str; c.textContent = c.derpClicked ? c.derpOrig : c.derpStr;
}; };
c.classList.add("derped"); c.classList.add("isDerped");
c.derp_str = DerpString(); c.derpStr = DerpString();
c.textContent = c.derp_str; c.derpClicked = false;
c.clicked = false; c.textContent = c.derpStr; // Set the derp text.
}; };
const ValidatePreviouslyDerpedComments = comment => { const ValidatePreviouslyDerpedComments = comment => {
const c = comment; const c = comment;
if (c.clicked && c.textContent === c.derpOriginal) return; if (c.derpClicked && c.textContent === c.derpOrig) return;
if (!c.clicked && c.textContent === c.derp_str) return; if (!c.derpClicked && c.textContent === c.derpStr) return;
// Fix the comment. The only case of malformed comments encountered so far // Fix the comment. The only case of malformed comments encountered so far
// are these two cases: // are these two cases:
if (c.textContent.indexOf(c.derp_str) !== -1) { if (c.textContent.indexOf(c.derpStr) !== -1) {
// In the case of the new comment being appended after the derp string, // In the case of the new comment being appended after the derp string,
// just grab it and put it in the derpOriginal variable // just grab it and put it in the derpOrig variable
const idx = c.derp_str.length; const idx = c.derpStr.length;
c.derpOriginal = c.textContent.substring(idx); c.derpOrig = c.textContent.substring(idx);
c.textContent = c.textContent.substring(0, idx); c.textContent = c.textContent.substring(0, idx);
c.clicked = false; c.derpClicked = false;
return; return;
} }
if (c.textContent.indexOf(c.derpOriginal) !== -1) { if (c.textContent.indexOf(c.derpOrig) !== -1) {
// Same issue, but the comment was appended after derpOriginal. // Same issue, but the comment was appended after derpOrig.
const idx = c.derpOriginal.length; const idx = c.derpOrig.length;
c.derpOriginal = c.textContent.substring(idx); c.derpOrig = c.textContent.substring(idx);
c.textContent = c.derp_str; c.textContent = c.derpStr;
c.clicked = false; c.derpClicked = false;
} }
}; };
const Init = commentsSection => { const Init = commentsSection => {
const commentContentSelector = ["#content-text"]; // Comment text content. const commentTextId = "#content-text";
const derpedSelector = `${commentTextId}.isDerped`;
const commentRendererName = "YTD-COMMENT-RENDERER";
const notDerpedSelector = commentContentSelector // Need to convert comments that were inserted before the mutation observer below runs.
.map(sel => `${sel}:not(.derped)`) commentsSection.querySelectorAll(commentRendererName).forEach(node => {
.join(", "); DerpComment(node, node.querySelector(commentTextId));
const derpedSelector = commentContentSelector.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 };
// Detect when comments are added to the DOM.
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);
}); });
observer.observe(commentsSection, mutationConfig); // 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 // Check every so often if comments are loaded or not. Once they are, the
@ -90,18 +99,20 @@ const Init = commentsSection => {
// to be done since comments are added in the DOM through js at an undetermined // to be done since comments are added in the DOM through js at an undetermined
// point through Youtube's execution. // point through Youtube's execution.
const CheckIfCommentsLoaded = () => { const CheckIfCommentsLoaded = () => {
const commentSectionSelector = "html body ytd-app ytd-comments ytd-item-section-renderer #contents";
setTimeout(() => { setTimeout(() => {
// This selector is awful, but Youtube re-uses a lot of the DOM (the const commentsSection = document.querySelector("ytd-comments #contents");
// selector for the comments is re-used across a bunch of pages) so we need
// the exact path to the comments to match if (commentsSection !== null) {
const commentsSection = document.querySelector(commentSectionSelector);
if (commentsSection !== null)
Init(commentsSection); Init(commentsSection);
else }
else {
CheckIfCommentsLoaded(); CheckIfCommentsLoaded();
}, 500); }
// 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(); CheckIfCommentsLoaded();

View File

@ -1,13 +1,18 @@
{ {
"manifest_version": 2, "manifest_version": 3,
"name": "YouTube Herp Derp", "name": "YouTube Herp Derp",
"description": "Replaces YouTube comments with herp derps. Forked from github.com/twstokes/herpderp", "description": "Replaces YouTube comments with herp derps. Forked from github.com/twstokes/herpderp",
"homepage_url": "https://github.com/sir-pinecone/youtube-herp-derp-browser-extension", "homepage_url": "https://git.michael.is/michael/youtube-herp-derp-browser-extension",
"version": "1.0.3", "version": "1.0.4.2",
"icons": { "icons": {
"48": "icons/herp48.png", "48": "icons/herp48.png",
"128": "icons/herp128.png" "128": "icons/herp128.png"
}, },
"browser_specific_settings": {
"gecko": {
"id": "{8460883e-a350-4e55-8c07-eed5eefdc2b5}"
}
},
"content_scripts": [ "content_scripts": [
{ {
"run_at": "document_idle", "run_at": "document_idle",