10 days ago I did a Show HN post about a Chrome extension to speed up YouTube ads, which was open sourced under MIT license.
A member of HN who is also the admin of a developer community saw & commented on the project. Rather than support it as a contributor, they functionally copied it, created their own Chrome Web Store posting and shared it on r/webdev with zero acknowledgement or inclusion of the original MIT license.
I've documented in detail the whole experience.[1]
They now have an order of magnitude more traction with 10k+ users.
Although I'm happy that our project now has contributors it's hard not to think any work we do won't just continue to be copied.
Any advice would be appreciated.
[1] https://github.com/rkk3/ad-accelerator/blob/main/lessons_post.md_post.md
"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software."
Assuming the full license (I omitted about 892 characters) were in the original the derivative work omitting the original notice violates the license. In USA, you register your copyrighted work and can sue for statutory damages.
Patent protects an original idea (reduced to practice) and one precept is that the idea got independently used only after it was disclosed to the public. Obtaining a patent from the PTO is not a trivial matter and then you can sue for your lost profits, damages based on the defendant's profits, or prohibit use by anyone. All of this assumes you really care.
The MIT license is for the code artifact; if you want to control the IDEA you'd need much stronger measures like a patent.
As you point out they have an order of magnitude more users. Evidently they have some skills in marketing and distribution.
This seems like the main mistake. Try AGPLv3 instead.
function waitForVideoAndObserve() {
const video = document.querySelector('video');
if (video) {
video.playbackRate = 16;
video.autoplay = true;
video.muted = true;
const player = document.querySelector('ytd-player #movie_player[aria-label="YouTube Video Player"]');
if (player) {
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
clickButton();
adjustPlaybackForAds(mutation.target);
}
});
});
observer.observe(player, { attributes: true });
}
} else {
setTimeout(waitForVideoAndObserve, 500);
}
}
waitForVideoAndObserve();
})();
4. Hard work. What a joke, this took me 4 hours tops to convert from idea to bookmarklet to extension . It’s about 60 lines of code in a content script that a monkey could write! I’m that monkey! And it only took that long because I had to keep pinging YouTube to get an ad to play! Wait for video element, then increase playback and mute! That’s it! Yet you are under the impression this is some arcane knowledge that must be copied to be believed.
5. I actually DID look at your code after thesr accusations appeared, I even posted both our code in the server for others to come to their own conclusions! Additionally you use background scripts and content scripts - I just use a content script because … why would you even need a background script? You don’t.
5. You are discussing legal advice - cute. Now HARASSMENT and slander, those are legal discussions
6. You and the other user who have been harassing me have been doing so with alt accounts, across platforms, now harassment does fall under legal eyes. Yes i have begun taking action on this.
7. This guy thought telling me my real name would scare me and all this stuff about “karma”. Ooo clever. He just got it from the license text by reverse engineering my extension, but it was meant to scare me. Yet he is the one with the very public profile and VERY easy to find information.
8. And then this guy and the other person started a defamation campaign against me on all these platforms, going so far as spamming every user on the server I run, that I put hard work into growing.
9. I also just looked at your “lessons”. I noticed we use completely different methods for detecting ads, and on completely different elements. Add to that, you set the playbackRate to 10, I set it to 16, copied?
10. And now to add to the fire you are continuing to slander me and share my usernames in this lessons thing on GitHub!
Should the prior art extensions who were already doing this exact function also be complaining against you?
I'll even share MY source code just to get this person to shut the fuck up and claiming all this crap:
// content-script.js (function () { function clickSkipButton(player) { const skipButton = player.querySelector( ".ytp-ad-skip-button-modern.ytp-button" ); if (skipButton) { skipButton.click(); } }
function adjustVideoPlayback(player, isAdPlaying) {
const video = player.querySelector("video");
if (video) {
if (isAdPlaying) {
video.playbackRate = 16; // Speed up the video
video.muted = true; // Mute the video
}
}
} function observerCallback(mutations, observer) {
for (const mutation of mutations) {
if (
mutation.type === "attributes" &&
mutation.attributeName === "class"
) {
const player = mutation.target;
const isAdPlaying =
player.classList.contains("ad-showing") ||
player.classList.contains("ad-interrupting");
adjustVideoPlayback(player, isAdPlaying);
}
if (mutation.type === "childList" && mutation.addedNodes.length) {
clickSkipButton(mutation.target);
}
}
}
function setupObserver() {
const player = document.querySelector("#movie_player");
if (player) {
const observer = new MutationObserver(observerCallback);
observer.observe(player, {
attributes: true,
childList: true,
subtree: true,
});
// Initial checks
const isAdPlaying =
player.classList.contains("ad-showing") ||
player.classList.contains("ad-interrupting");
adjustVideoPlayback(player, isAdPlaying);
clickSkipButton(player);
} else {
setTimeout(setupObserver, 50);
}
}
setupObserver();
})();