Removes ads for the janitor ai app and janitor ai plus
// ==UserScript==
// @name Janitor AI Ad Remover
// @namespace https://janitorai.com/
// @version 1.1
// @description Removes ads for the janitor ai app and janitor ai plus
// @author pooiod7
// @match https://janitorai.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function () {
'use strict';
const PATTERNS = {
brand: /\b(janitor\s*\+|janitor\s*plus|najitor\s*(ai)?\s*(\+|plus)|jai\s*\+|jai\s*plus|janitorai\s*(\+|plus))\b/i,
pricing: /([$€£¥]\s*\d+(\.\d{1,2})?\s*(usd|eur|gbp)?\s*(\/|a|per)?\s*(month|mo|year|yr)?|\b\d+(\.\d{1,2})?\s*(usd|eur|gbp)\s*(a|\/|per)?\s*(month|mo|year|yr)?\b)/i,
cta: /\b(subscribe(\s+now)?|upgrade(\s+now|\s+to\s+plus)?|speed\s+up\s+responses|give\s+my\s+characters\s+more\s+memory|get\s+janitor\+|try\s+janitor\+|join\s+(the\s+)?plus|become\s+a\s+(subscriber|supporter|patron)|unlock\s+(all\s+)?models|claim\s+credit|start\s+(your\s+)?(free\s+)?trial|buy\s+credits?)\b/i,
perks: /(faster\s+replies|better\s+memory|longer\s+memory|router\s+access|\$\d+\s+credit|the\s+bots\s+will\s+understand|lose\s+context\s+as\s+your\s+chat\s+grows|reply\s+is\s+taking\s+a\s+while|skip\s+the\s+queue|priority\s+(queue|generation|access)|unlimited\s+context|more\s+context\s+size|advanced\s+models|cancel\s+anytime|billed\s+(monthly|annually|yearly))/i,
appInstall: /\b(download(\s+the)?\s+(mobile\s+)?app|get(\s+the)?\s+(mobile\s+)?app|install(\s+the)?\s+(mobile\s+)?app|open\s+in(\s+the)?\s+app|available\s+on\s+(google\s+play|app\s+store)|add\s+to\s+home\s*screen|install\s+pwa|get\s+the\s+apk|download\s+apk|testflight)\b/i,
adLinks: /(\/plus|\/subscription|\/pricing|\/upgrade|\/premium|play\.google\.com|apps\.apple\.com|testflight\.apple\.com|\/download-app|\/app-install)/i,
assetHints: /(premium-nebula-bg|stars\.webp|plus-banner|app-badge|google-play-badge|app-store-badge|download-app)/i
};
function isAdTrigger(el) {
if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
const ariaLabel = el.getAttribute('aria-label') || '';
const title = el.getAttribute('title') || '';
const href = el.getAttribute('href') || (el.tagName === 'A' ? el.href : '');
const src = el.getAttribute('src') || '';
if (PATTERNS.brand.test(ariaLabel) || PATTERNS.brand.test(title)) return true;
if (PATTERNS.adLinks.test(href)) return true;
if (PATTERNS.assetHints.test(src)) return true;
const text = el.innerText || el.textContent || '';
if (text.length > 0 && text.length < 800) {
const hasBrand = PATTERNS.brand.test(text);
const hasPricing = PATTERNS.pricing.test(text);
const hasCta = PATTERNS.cta.test(text);
const hasPerks = PATTERNS.perks.test(text);
const hasApp = PATTERNS.appInstall.test(text);
if (hasApp) return true;
if (hasBrand && (hasCta || hasPricing || hasPerks)) return true;
if (hasPricing && (hasCta || hasPerks)) return true;
if (hasCta && hasPerks) return true;
}
return false;
}
function resolveAdContainer(el) {
if (el.matches('[role="menuitem"], li, a[href*="/plus"]')) {
return el.closest('[role="menuitem"], li') || el;
}
let curr = el;
let candidate = el;
while (curr && curr !== document.body && curr !== document.documentElement) {
const tag = curr.tagName.toLowerCase();
if (['main', 'nav', 'header'].includes(tag)) break;
if (curr.id === 'root' || curr.id === '__next') break;
if (curr.querySelector('textarea, input:not([type="button"]):not([type="submit"]), [contenteditable="true"]')) {
break;
}
if (
['aside', 'section', 'dialog'].includes(tag) ||
curr.getAttribute('role') === 'dialog' ||
curr.getAttribute('role') === 'alert' ||
/(banner|card|nudge|modal|promo|upgrade|popup)/i.test(curr.className || '')
) {
candidate = curr;
break;
}
candidate = curr;
curr = curr.parentElement;
}
return candidate;
}
function tryDismiss(container) {
const dismissBtn = container.querySelector(
'button[aria-label*="dismiss" i], button[aria-label*="close" i], button[title*="close" i], button[title*="dismiss" i], button._dismiss'
);
if (dismissBtn) {
console.log('[JAI Ad Remover] Clicked close/dismiss button:\n', dismissBtn.outerHTML);
try {
dismissBtn.click();
} catch (err) {}
}
}
function cleanElement(el) {
if (el.dataset.jaiAdScanned) return;
el.dataset.jaiAdScanned = 'true';
if (isAdTrigger(el)) {
const container = resolveAdContainer(el);
if (container.dataset.jaiAdBlocked) return;
tryDismiss(container);
console.log('[JAI Ad Remover] Removed ad container:\n', container.outerHTML);
container.style.setProperty('display', 'none', 'important');
container.style.setProperty('visibility', 'hidden', 'important');
container.setAttribute('aria-hidden', 'true');
container.dataset.jaiAdBlocked = 'true';
}
}
function sweep() {
const selectors = [
'aside',
'section',
'dialog',
'a[href*="/plus"]',
'a[href*="/subscription"]',
'a[href*="/pricing"]',
'a[href*="/upgrade"]',
'a[href*="google.com"]',
'a[href*="apple.com"]',
'[aria-label*="janitor+" i]',
'[aria-label*="plus" i]',
'[aria-label*="subscribe" i]',
'[aria-label*="upgrade" i]',
'[class*="nudge"]',
'[class*="banner"]',
'[class*="card"]',
'[class*="promo"]',
'[class*="modal"]',
'button'
];
const elements = document.querySelectorAll(selectors.join(','));
for (let i = 0; i < elements.length; i++) {
cleanElement(elements[i]);
}
}
const style = document.createElement('style');
style.textContent = `
[data-jai-ad-blocked="true"],
aside[class*="nudge"],
[class*="hp-plus-banner"],
a[href="/plus"][role="menuitem"],
svg[aria-label="janitor+"]:not(nav svg) {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
}
`;
(document.head || document.documentElement).appendChild(style);
let scheduled = false;
const observer = new MutationObserver(() => {
if (scheduled) return;
scheduled = true;
(window.requestIdleCallback || window.requestAnimationFrame)(() => {
sweep();
scheduled = false;
});
});
if (document.body) {
sweep();
observer.observe(document.body, { childList: true, subtree: true });
} else {
document.addEventListener('DOMContentLoaded', () => {
sweep();
observer.observe(document.body, { childList: true, subtree: true });
});
}
})();