Block all Twitch ads, automatically claim bonus points, and add BTTV emotes
当前为
// ==UserScript==
// @name Enhanced Twitch Ad Blocker with Auto Claim Bonus and BTTV Emotes
// @namespace https://github.com/Brembo19
// @version 1.3
// @description Block all Twitch ads, automatically claim bonus points, and add BTTV emotes
// @author Brembo19
// @match *://*.twitch.tv/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const blockAdsInVideo = () => {
const video = document.querySelector('video');
if (video && video.src.includes('ad_')) {
video.src = '';
}
};
const removeAdBanners = () => {
const adSelectors = [
'[aria-label="Advertisement"]',
'.ad-banner',
'.ad-slot',
'.tw-ad-container',
'[data-ad="true"]'
];
adSelectors.forEach(selector => {
document.querySelectorAll(selector).forEach(ad => ad.remove());
});
};
const observeDynamicContent = () => {
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.type === 'childList') {
removeAdBanners();
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
};
const autoClaimBonus = () => {
let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
let claiming = false;
if (MutationObserver) console.log('Auto claimer is enabled.');
let observer = new MutationObserver(e => {
let bonus = document.querySelector('.claimable-bonus__icon');
if (bonus && !claiming) {
bonus.click();
let date = new Date();
claiming = true;
setTimeout(() => {
console.log('Claimed at ' + date);
claiming = false;
}, Math.random() * 1000 + 2000);
}
});
observer.observe(document.body, { childList: true, subtree: true });
};
const injectBTTVEmotes = () => {
const emoteURL = 'https://betterttv.com/emotes/popular';
const emoteContainer = document.createElement('div');
emoteContainer.id = 'bttv-emotes';
emoteContainer.style.position = 'fixed';
emoteContainer.style.bottom = '0';
emoteContainer.style.right = '0';
emoteContainer.style.backgroundColor = '#000';
emoteContainer.style.color = '#fff';
emoteContainer.style.padding = '10px';
emoteContainer.style.zIndex = '9999';
document.body.appendChild(emoteContainer);
fetch(emoteURL)
.then(response => response.text())
.then(text => {
const parser = new DOMParser();
const doc = parser.parseFromString(text, 'text/html');
const emotes = doc.querySelectorAll('.emote-item img');
emotes.forEach(emote => {
const emoteImg = document.createElement('img');
emoteImg.src = emote.src;
emoteImg.style.width = '32px';
emoteImg.style.height = '32px';
emoteImg.style.margin = '5px';
emoteImg.title = emote.alt;
emoteContainer.appendChild(emoteImg);
});
})
.catch(error => console.error('Error fetching BTTV emotes:', error));
};
blockAdsInVideo();
removeAdBanners();
observeDynamicContent();
autoClaimBonus();
injectBTTVEmotes();
setInterval(blockAdsInVideo, 1000);
setInterval(removeAdBanners, 2000);
})();