// ==UserScript==
// @name Facebook Enhancer with Smart Menu
// @namespace https://github.com/TamperMonkeyDevelopment/TamperMonkeyScripts
// @version 2.8
// @description Enhance Facebook: block ads, stop autoplay, mute videos, unwrap links, auto-expand comments, hide suggestions, hide reels, apply themes, keyword filter, draggable UI, reset options, and debug logging. Fully customizable with smart settings menu and CSS injection support.
// @author Eliminater74
// @match *://www.facebook.com/*
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const settings = {
blockSponsored: true,
blockSuggested: true,
disableAutoplay: true,
muteVideos: true,
removeBubbles: true,
unwrapLinks: true,
moveMessengerDock: false,
forceDarkMode: false,
forceMostRecentFeed: true,
hidePeopleYouMayKnow: true,
autoExpandComments: true,
autoClosePopups: true,
classicBlueTheme: false,
hideReels: true,
themePreset: 'default',
keywordFilter: 'kardashian,tiktok,reaction',
debugMode: false,
customCSS: ''
};
const labelMap = {
blockSponsored: 'Block Sponsored Posts',
blockSuggested: 'Block "Suggested for You"',
disableAutoplay: 'Stop Video Autoplay',
muteVideos: 'Mute Videos on Load',
removeBubbles: 'Remove Notification Bubbles',
unwrapLinks: 'Unwrap Redirect Links',
moveMessengerDock: 'Move Messenger Dock to Bottom',
forceDarkMode: 'Force Dark Mode',
forceMostRecentFeed: 'Use "Most Recent" Feed',
hidePeopleYouMayKnow: 'Hide "People You May Know"',
autoExpandComments: 'Auto-Expand Comments',
autoClosePopups: 'Auto-Close Popups',
classicBlueTheme: 'Enable Classic Blue Theme',
hideReels: 'Hide Facebook Reels',
themePreset: 'Theme Preset (default, dark, minimal)',
keywordFilter: 'Filter Posts with Keywords',
debugMode: 'Enable Debug Logs',
customCSS: 'Custom CSS (Advanced)'
};
const storageKey = 'fb-enhancer-settings';
let menuVisible = false;
function loadSettings() {
const saved = localStorage.getItem(storageKey);
if (saved) Object.assign(settings, JSON.parse(saved));
}
function saveSettings() {
localStorage.setItem(storageKey, JSON.stringify(settings));
}
function resetSettings() {
localStorage.removeItem(storageKey);
alert('Settings reset. Reloading...');
location.reload();
}
function downloadSettings() {
const blob = new Blob([JSON.stringify(settings, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'fb-enhancer-settings.json';
a.click();
URL.revokeObjectURL(url);
}
function uploadSettings() {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'application/json';
input.addEventListener('change', e => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = event => {
try {
const imported = JSON.parse(event.target.result);
Object.assign(settings, imported);
saveSettings();
alert('Settings loaded. Reloading...');
location.reload();
} catch (err) {
alert('Failed to load settings file.');
}
};
reader.readAsText(file);
});
input.click();
}
function applyCustomCSS() {
if (settings.customCSS) {
const style = document.createElement('style');
style.id = 'fb-enhancer-custom-css';
style.textContent = settings.customCSS;
document.head.appendChild(style);
}
}
function applyThemePreset(preset) {
switch (preset) {
case 'dark':
settings.customCSS = 'body { background-color: #121212 !important; color: #ccc !important; }';
break;
case 'minimal':
settings.customCSS = '[role="complementary"], [role="banner"], [aria-label="Stories"] { display: none !important; }';
break;
default:
settings.customCSS = '';
break;
}
saveSettings();
document.getElementById('custom-css').value = settings.customCSS;
document.getElementById('fb-enhancer-custom-css')?.remove();
applyCustomCSS();
}
function makeDraggable(el) {
let posX = 0, posY = 0, mouseX = 0, mouseY = 0;
el.style.position = 'fixed';
el.style.cursor = 'move';
el.onmousedown = function (e) {
e.preventDefault();
mouseX = e.clientX;
mouseY = e.clientY;
document.onmouseup = () => { document.onmousemove = null; };
document.onmousemove = (e) => {
posX = mouseX - e.clientX;
posY = mouseY - e.clientY;
mouseX = e.clientX;
mouseY = e.clientY;
el.style.top = (el.offsetTop - posY) + "px";
el.style.left = (el.offsetLeft - posX) + "px";
};
};
}
function createToggleButton() {
const toggle = document.createElement('div');
toggle.id = 'fb-enhancer-toggle';
toggle.textContent = '⚙ FB Enhancer';
toggle.style.cssText = 'top:60px;right:10px;background:#4267B2;color:#fff;font-weight:bold;padding:6px 10px;border-radius:6px;z-index:99999;font-size:14px;box-shadow:0 0 5px #000;';
toggle.addEventListener('click', () => {
const panel = document.getElementById('fb-enhancer-menu');
menuVisible = !menuVisible;
panel.style.display = menuVisible ? 'block' : 'none';
});
document.body.appendChild(toggle);
makeDraggable(toggle);
}
function createSettingsMenu() {
const menu = document.createElement('div');
menu.id = 'fb-enhancer-menu';
menu.style.cssText = 'top:100px;right:10px;background:#fff;color:#000;font-size:14px;padding:10px;border:1px solid #ccc;z-index:99998;width:280px;max-height:80vh;overflow-y:auto;border-radius:6px;box-shadow:0 0 5px rgba(0,0,0,0.5);font-family:sans-serif;display:none;position:fixed;';
menu.innerHTML = `<h4>Facebook Enhancer Settings</h4>
${Object.keys(settings).filter(k => k !== 'customCSS').map(key => `
<label style="display:block;margin-bottom:6px;">
${key === 'keywordFilter' || key === 'themePreset' ? `<input type="text" id="toggle-${key}" value="${settings[key]}" style="width:100%;">` :
`<input type="checkbox" id="toggle-${key}" ${settings[key] ? 'checked' : ''}>`} ${labelMap[key] || key}
</label>`).join('')}
<label>${labelMap.customCSS}<textarea id="custom-css">${settings.customCSS}</textarea></label>
<button id="btn-save-settings">Save</button>
<button id="btn-load-settings">Load</button>
<button id="btn-reset-settings">Reset</button>
<div style="margin-top:10px; font-size:12px; text-align:right; opacity:0.6;">v2.8</div>`;
document.body.appendChild(menu);
Object.keys(settings).forEach(key => {
const el = document.getElementById(`toggle-${key}`);
if (!el) return;
if (el.type === 'checkbox') {
el.addEventListener('change', () => {
settings[key] = el.checked;
saveSettings();
location.reload();
});
} else if (el.type === 'text') {
el.addEventListener('change', () => {
settings[key] = el.value.trim();
if (key === 'themePreset') applyThemePreset(settings[key]);
saveSettings();
});
}
});
document.getElementById('custom-css').addEventListener('input', e => {
settings.customCSS = e.target.value;
saveSettings();
document.getElementById('fb-enhancer-custom-css')?.remove();
applyCustomCSS();
});
document.getElementById('btn-save-settings').addEventListener('click', downloadSettings);
document.getElementById('btn-load-settings').addEventListener('click', uploadSettings);
document.getElementById('btn-reset-settings').addEventListener('click', resetSettings);
makeDraggable(menu);
}
function stopVisibleVideoAutoplay() {
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
const video = entry.target;
if (video.dataset.fbEnhanced || video.closest('[class*="reel"]')) continue;
if (entry.isIntersecting && video.readyState >= 2 && !video.paused) {
video.pause();
video.removeAttribute('autoplay');
if (settings.muteVideos) video.muted = true;
video.dataset.fbEnhanced = 'true';
if (settings.debugMode) console.log('[FB Enhancer] Video paused and muted.');
}
}
}, { threshold: 0.5 });
document.querySelectorAll('video:not([data-fb-enhanced])').forEach(video => {
if (video.closest('[class*="reel"]')) return;
if (video.readyState >= 2) {
video.pause();
video.removeAttribute('autoplay');
if (settings.muteVideos) video.muted = true;
video.dataset.fbEnhanced = 'true';
}
observer.observe(video);
});
}
function hideReels() {
document.querySelectorAll('a[href*="/reels/"], [aria-label*="Reels"], [class*="reel"]').forEach(el => el.remove());
}
function filterKeywordPosts() {
const keywords = settings.keywordFilter.split(',').map(k => k.trim().toLowerCase());
document.querySelectorAll('[role="article"]').forEach(post => {
const text = post.innerText.toLowerCase();
if (keywords.some(keyword => text.includes(keyword))) post.remove();
});
}
function runEnhancements() {
document.querySelectorAll('[role="feed"] [role="article"]').forEach(post => {
if (settings.blockSponsored && /Sponsored/i.test(post.innerText)) post.remove();
if (settings.blockSuggested && /Suggested for you/i.test(post.innerText)) post.remove();
if (settings.autoExpandComments) {
post.querySelectorAll('[role="button"]').forEach(btn => {
if (btn.innerText.includes('View more comments') || btn.innerText.includes('replies')) btn.click();
});
}
});
if (settings.hidePeopleYouMayKnow) {
document.querySelectorAll('[role="complementary"], section, aside').forEach(el => {
const text = el.innerText?.trim();
if (text?.match(/^People you may know$/i) || el.querySelector('button')?.textContent.toLowerCase().includes('add friend')) {
el.remove();
}
});
}
if (settings.removeBubbles) {
document.querySelectorAll('span').forEach(el => {
if (/^\\d+$/.test(el.textContent) && el.closest('[aria-label]')) el.textContent = '';
});
}
if (settings.unwrapLinks) {
document.querySelectorAll('a[href*="l.facebook.com/l.php"]').forEach(link => {
const url = new URL(link.href);
const real = decodeURIComponent(url.searchParams.get('u') || '');
if (real.startsWith('http')) link.href = real;
});
}
if (settings.disableAutoplay) stopVisibleVideoAutoplay();
if (settings.hideReels) hideReels();
if (settings.keywordFilter) filterKeywordPosts();
if (settings.autoClosePopups) {
document.querySelectorAll('[role="dialog"]').forEach(d => {
const text = d.innerText.toLowerCase();
if (text.includes('log in') || text.includes('feedback') || text.includes('report')) d.remove();
});
}
if (settings.forceMostRecentFeed) {
const feedSwitch = document.querySelector('a[href*="sk=h_chr"]');
if (feedSwitch) feedSwitch.click();
}
if (settings.classicBlueTheme) document.body.style.backgroundColor = '#e9ebee';
if (settings.moveMessengerDock) {
const dock = document.querySelector('[aria-label="Chat tab bar"]');
if (dock) {
dock.style.bottom = '0';
dock.style.top = 'auto';
}
}
document.documentElement.classList.toggle('fb-dark-mode', settings.forceDarkMode);
}
function init() {
loadSettings();
applyCustomCSS();
createToggleButton();
createSettingsMenu();
setInterval(runEnhancements, 2500);
window.addEventListener('load', runEnhancements);
}
init();
})();