Speed things up
This commit is contained in:
parent
829ebd0736
commit
6745b375a0
11
README.md
11
README.md
|
@ -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,6 +31,10 @@ Note: Ignores iframe embedded videos, including the chat replay iframe on YouTub
|
||||||
## Signing and Building
|
## Signing and Building
|
||||||
|
|
||||||
### Firefox
|
### Firefox
|
||||||
|
|
||||||
|
* 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`
|
* Install web-ext with `$ npm install --global web-ext`
|
||||||
* Generate an unlisted xpi with:
|
* 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>`
|
||||||
|
@ -38,3 +42,8 @@ Note: Ignores iframe embedded videos, including the chat replay iframe on YouTub
|
||||||
* 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.
|
||||||
|
|
||||||
|
|
BIN
build/Firefox_youtube_herp_derp-1.0.4.2.xpi
Normal file
BIN
build/Firefox_youtube_herp_derp-1.0.4.2.xpi
Normal file
Binary file not shown.
129
index.js
129
index.js
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user