Skip to content

Instantly share code, notes, and snippets.

@BrendanEich
Last active August 2, 2026 05:21
Show Gist options
  • Select an option

  • Save BrendanEich/facbf7349bea195f252188e79c77e97e to your computer and use it in GitHub Desktop.

Select an option

Save BrendanEich/facbf7349bea195f252188e79c77e97e to your computer and use it in GitHub Desktop.
Brave user scriptlet for showing true popcornmeter ratio
(function() {
'use strict';
const waitForElement = (selector) => {
return new Promise(resolve => {
if (document.querySelector(selector)) return resolve(document.querySelector(selector));
const observer = new MutationObserver(() => {
const el = document.querySelector(selector);
if (el) {
observer.disconnect();
resolve(el);
}
});
if (document.body) observer.observe(document.body, { childList: true, subtree: true });
});
};
const run = async () => {
try {
// 1. Wait for JSON Data
const scriptEl = await waitForElement('script#media-scorecard-json');
const blob = JSON.parse(scriptEl.textContent);
if (!blob.overlay || !blob.overlay.audienceAll) {
setTimeout(run, 1000);
return;
}
// 2. Calculate "True" Ratio (All - Verified)
const trueLikes = blob.overlay.audienceAll.likedCount - blob.overlay.audienceVerified.likedCount;
const trueDislikes = blob.overlay.audienceAll.notLikedCount - blob.overlay.audienceVerified.notLikedCount;
if ((trueLikes + trueDislikes) === 0) return;
const trueRatio = Math.round(100 * trueLikes / (trueLikes + trueDislikes));
const trueRatioString = trueRatio + '%';
const colorValue = trueRatio >= 60 ? '#43B02A' : '#FA320A'; // Green if >=60, else Red
console.log('Calculated True Ratio:', trueRatio);
// 3. Target the Slotted Element (Light DOM)
const targetSelector = 'rt-text[slot="audience-score"]';
const targetElement = await waitForElement(targetSelector);
if (!targetElement) {
setTimeout(run, 500);
return;
}
// 4. Apply Update Function
const applyUpdate = () => {
targetElement.innerText = trueRatioString;
targetElement.textContent = trueRatioString;
targetElement.style.setProperty('--textColor', colorValue);
targetElement.style.setProperty('color', colorValue, 'important');
targetElement.style.fontWeight = 'bold';
// FIX: Remove explicit font-size and line-height to inherit natural sizing
// OR match the Tomatometer exactly if you know its font-size
targetElement.style.fontSize = ''; // Reset to inherit
targetElement.style.lineHeight = ''; // Reset to inherit (likely 1.25)
targetElement.style.display = 'inline-block';
targetElement.style.verticalAlign = 'baseline';
targetElement.style.marginTop = '0';
targetElement.style.marginBottom = '0';
targetElement.classList.remove('hide', 'critics-score-empty', 'audience-score-empty');
};
// Apply immediately
applyUpdate();
// 5. Persistent Observer (Prevent Revert)
const observer = new MutationObserver(() => {
const currentText = targetElement.innerText;
if (currentText !== trueRatioString) {
applyUpdate();
}
});
observer.observe(targetElement, { childList: true, characterData: true, subtree: true });
console.log('--- SUCCESS: Layout-Corrected Update Active ---');
} catch (err) {
console.error('Script Error:', err);
}
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', run);
} else {
run();
}
})();
@BrendanEich

Copy link
Copy Markdown
Author

RT seems to be manipulating user scores, see https://www.reddit.com/r/KotakuInAction/s/MWZojN6et4.

Fixable thanks to Brave's custom scriptlets support: https://brave.com/privacy-updates/32-custom-scriptlets/.

Installation Guide Step-by-step instructions:

  1. Go to brave://settings/shields/filters (past this in the address bar).
  2. Enable Developer Mode.
  3. Click Add new scriptlet.
  4. Name it user-rt-true-score.js. Note you enter only the rt-true-score part of the name.
  5. Copy the gist's code and paste it into the scriptlet input.
  6. Add this filter rule to the "Create custom filters" textarea: rottentomatoes.com##+js(user-rt-true-score.js).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment