// ==UserScript== // @name Fμck Facebook // @namespace https://github.com/FlandreDaisuki // @version 1.3.1 // @description Remove all Facebook shit // @author FlandreDaisuki // @match https://*.facebook.com/* // @require https://unpkg.com/sentinel-js@0.0.5/dist/sentinel.js // @grant GM_setValue // @grant GM_getValue // @grant GM_info // @noframes // @downloadURL none // ==/UserScript== /* cSpell:ignoreRegExp \.[\w\d]{8}\b */ /* cSpell:ignore algo visualcompletion rsrc */ /* global sentinel */ /* 推薦與以下樣式一起使用,效果更佳 https://github.com/FlandreDaisuki/My-Browser-Extensions/tree/master/usercss#facebullshit */ const LOCALE_DICT = ((lang) => { switch (lang.toLowerCase()) { case 'zh-hant': return { settingsTitle: 'Fμck Facebook', fuckSponsors: '幹掉全部贊助貼文', fuckFriendsRecommendation: '不要推薦別人當我朋友', fuckPostsRecommendation: '不要推薦貼文', }; default: return { settingsTitle: 'Fμck Facebook', fuckSponsors: 'Fμck off sponsors', fuckFriendsRecommendation: 'Fμck off friends recommendation', fuckPostsRecommendation: 'Fμck off posts recommendation', }; } })(document.documentElement.lang); const $t = (keyPath) => { return keyPath.split('.').reduce((dict, kp) => dict?.[kp], LOCALE_DICT) ?? keyPath; }; const noop = () => {}; const $el = (tag, attrs = {}, callback = noop) => { const el = document.createElement(tag); for (const [k, v] of Object.entries(attrs)) { el.setAttribute(k, v); } callback(el); return el; }; const DEFAULT_CONF = { NO_SPONSORS: 1, NO_FRIENDS_RECOMMENDATION: 1, NO_POSTS_RECOMMENDATION: 1, }; const saveConf = (conf) => GM_setValue(GM_info.script.version, conf); const loadConf = () => { const config = GM_getValue(GM_info.script.version); if (!config) { saveConf(DEFAULT_CONF); return loadConf(); } return config; }; const config = loadConf(); /* fix: Facebook 壞壞 */ sentinel.on('html._8ykn', (htmlEl) => { // FaceBook add following rule to disable sentinel // ._8ykn :not(.always-enable-animations){ // animation-duration:0 !important; // animation-name:none !important; // transition-duration:0 !important; // transition-property:none !important // } htmlEl.classList.remove('_8ykn'); }); /* Feature 1: 刪掉贊助 */ // ref: https://openuserjs.org/scripts/burn/Facebook_Hide_Ads_(a.k.a._sponsored_posts)/source /* cSpell:disable */ /* eslint-disable */ const sponsorWords = { 'af': ['Geborg'], 'am': ['የተከፈለበት ማስታወቂያ'], 'ar': ['إعلان مُموَّل'], 'as': ['পৃষ্ঠপোষকতা কৰা'], 'ay': ['Yatiyanaka'], 'az': ['Sponsor dəstəkli'], 'be': ['Рэклама'], 'bg': ['Спонсорирано'], 'br': ['Paeroniet'], 'bs': ['Sponzorirano'], 'bn': ['সৌজন্যে'], 'ca': ['Patrocinat'], 'cb': ['پاڵپشتیکراو'], 'co': ['Spunsurizatu'], 'cs': ['Sponzorováno'], 'cx': ['Giisponsoran'], 'cy': ['Noddwyd'], 'da': ['Sponsoreret'], 'de': ['Gesponsert'], 'el': ['Χορηγούμενη'], 'en': ['Sponsored', 'Chartered'], 'eo': ['Reklamo'], 'es': ['Publicidad', 'Patrocinado'], 'et': ['Sponsitud'], 'eu': ['Babestua'], 'fa': ['دارای پشتیبانی مالی'], 'fi': ['Sponsoroitu'], 'fo': ['Stuðlað'], 'fr': ['Commandité', 'Sponsorisé'], 'fy': ['Sponsore'], 'ga': ['Urraithe'], 'gl': ['Patrocinado'], 'gn': ['Oñepatrosinapyre'], 'gx': ['Χορηγούμενον'], 'hi': ['प्रायोजित'], 'hu': ['Hirdetés'], 'id': ['Bersponsor'], 'it': ['Sponsorizzata'], 'ja': ['広告'], 'jv': ['Disponsori'], 'kk': ['Демеушілік көрсеткен'], 'km': ['បានឧបត្ថម្ភ'], 'lo': ['ໄດ້ຮັບການສະໜັບສະໜູນ'], 'mk': ['Спонзорирано'], 'ml': ['സ്പോൺസർ ചെയ്തത്'], 'mn': ['Ивээн тэтгэсэн'], 'mr': ['प्रायोजित'], 'ms': ['Ditaja'], 'ne': ['प्रायोजित'], 'nl': ['Gesponsord'], 'or': ['ପ୍ରଯୋଜିତ'], 'pa': ['ਸਰਪ੍ਰਸਤੀ ਪ੍ਰਾਪਤ'], 'pl': ['Sponsorowane'], 'ps': ['تمويل شوي'], 'pt': ['Patrocinado'], 'ru': ['Реклама'], 'sa': ['प्रायोजितः |'], 'si': ['අනුග්‍රහය දක්වන ලද'], 'so': ['La maalgeliyey'], 'sv': ['Sponsrad'], 'te': ['స్పాన్సర్ చేసినవి'], 'th': ['ได้รับการสนับสนุน'], 'tl': ['May Sponsor'], 'tr': ['Sponsorlu'], 'tz': ['ⵉⴷⵍ'], 'uk': ['Реклама'], 'ur': ['تعاون کردہ'], 'vi': ['Được tài trợ'], 'zh-Hans': ['赞助内容'], 'zh-Hant': ['贊助'] }[document.documentElement.lang]; /* eslint-enable */ /* cSpell:enable */ sentinel.on('span[id^="jsc"] a[tabindex]', (sponsorEl) => { if (!config.NO_SPONSORS) { return; } const sponsorElText = sponsorEl.textContent; const hasSponsorWord = sponsorWords.some((word) => [...word].every((ch) => sponsorElText.includes(ch))); if (!hasSponsorWord) { return; } const feedRootEl = sponsorEl.closest('[role="feed"] > div'); if (!feedRootEl) { return; } /* eslint-disable-next-line no-console */ console.count('🖕📘 NO_SPONSORS'); feedRootEl.hidden = true; }); /* Feature 2: 刪掉你可能認識誰誰誰 */ const recommendFriendsRules = [ 'div:empty + div.j83agx80.l9j0dhe7.k4urcfbm', ]; sentinel.on(recommendFriendsRules.join(','), (recommendFriendsEl) => { const feedRootEl = recommendFriendsEl.closest('[data-pagelet^="FeedUnit_"]'); if (feedRootEl && config.NO_FRIENDS_RECOMMENDATION) { /* eslint-disable-next-line no-console */ console.count('🖕📘 NO_FRIENDS_RECOMMENDATION'); feedRootEl.hidden = true; } }); /* Feature 3: 刪掉「為你推薦」 */ const recommendPostsRules = [ '.j1vyfwqu', ]; sentinel.on(recommendPostsRules.join(','), (recommendPostsEl) => { if (!config.NO_POSTS_RECOMMENDATION) { return; } const hasFriendsInteraction = recommendPostsEl.querySelectorAll('a').length > 0; if (hasFriendsInteraction) { return; } const feedRootEl = recommendPostsEl.closest('[data-pagelet^="FeedUnit_"]'); /* eslint-disable-next-line no-console */ console.count('🖕📘 NO_POSTS_RECOMMENDATION'); feedRootEl.hidden = true; }); /* Feature 4: 以上皆可個別設定 */ const findProfileConfigEl = () => { return [...document.querySelectorAll('#ssrb_top_nav_start ~ div [style*="translateZ"]')].filter((el) => { return el.offsetParent; })[0]; }; const resetProfileDrawer = () => { const profileConfigEl = findProfileConfigEl(); if (profileConfigEl) { profileConfigEl.style.transform = 'translateX(0%) translateZ(1px)'; } document.querySelector('#🖕📘⚙️🗄️')?.classList.remove('slide-left-to-show'); }; const slideProfileDrawer = () => { const profileConfigEl = findProfileConfigEl(); if (profileConfigEl) { profileConfigEl.style.transform = 'translateX(-100%) translateZ(1px)'; } document.querySelector('#🖕📘⚙️🗄️')?.classList.add('slide-left-to-show'); }; const createConfListItem = (id, text) => $el('div', { 'data-visualcompletion': 'ignore-dynamic', 'role': 'listitem', 'class': 'px-8', }, (el) => { el.innerHTML = ` `; }); const confDrawerEl = $el('div', { 'id': '🖕📘⚙️🗄️', 'class': 'border-box z-0 opacity-0 transition-duration-fast transition-timing-soft absolute left-0 w-full', 'aria-hidden': 'true', 'style': 'transition-property: opacity, transform; transform: translateX(100%) translateZ(1px);', }, (confDrawerEl) => { confDrawerEl.innerHTML = `

${ $t('settingsTitle') }

`; confDrawerEl.querySelector('#🖕📘⚙️🗄️🤏').onclick = resetProfileDrawer; // no sponsors { const noSponsorListItemEl = createConfListItem('🖕📘⚙️-no-sponsors', $t('fuckSponsors')); confDrawerEl.querySelector('[role="list"]')?.appendChild(noSponsorListItemEl); const checkboxEl = noSponsorListItemEl.querySelector('input[type="checkbox"]'); checkboxEl.checked = Boolean(config.NO_SPONSORS); checkboxEl.onchange = () => { config.NO_SPONSORS = checkboxEl.checked ? 1 : 0; saveConf(config); }; } // no friends recommendation { const noFriendsRecommendationListItemEl = createConfListItem('🖕📘⚙️-no-friends-recommendation', $t('fuckFriendsRecommendation')); confDrawerEl.querySelector('[role="list"]')?.appendChild(noFriendsRecommendationListItemEl); const checkboxEl = noFriendsRecommendationListItemEl.querySelector('input[type="checkbox"]'); checkboxEl.checked = Boolean(config.NO_FRIENDS_RECOMMENDATION); checkboxEl.onchange = () => { config.NO_FRIENDS_RECOMMENDATION = checkboxEl.checked ? 1 : 0; saveConf(config); }; } // no posts recommendation { const noPostsRecommendationListItemEl = createConfListItem('🖕📘⚙️-no-posts-recommendation', $t('fuckPostsRecommendation')); confDrawerEl.querySelector('[role="list"]')?.appendChild(noPostsRecommendationListItemEl); const checkboxEl = noPostsRecommendationListItemEl.querySelector('input[type="checkbox"]'); checkboxEl.checked = Boolean(config.NO_POSTS_RECOMMENDATION); checkboxEl.onchange = () => { config.NO_POSTS_RECOMMENDATION = checkboxEl.checked ? 1 : 0; saveConf(config); }; } }); sentinel.on('#ssrb_top_nav_start ~ div [style*="translateZ"]:first-child', (profileConfigEl) => { if (profileConfigEl.querySelector('[href="/messages/t/"]')) { return; } profileConfigEl.insertAdjacentElement('afterend', confDrawerEl); }); const confButtonEl = $el('div', { 'id': '🖕📘⚙️', 'data-visualcompletion': 'ignore-dynamic', 'class': 'px-8', }, (confButtonEl) => { confButtonEl.onclick = slideProfileDrawer; confButtonEl.innerHTML = `
${ $t('settingsTitle') }
`; }); sentinel.on('[data-visualcompletion="ignore-dynamic"] + hr + div [role="list"]>[data-visualcompletion="ignore-dynamic"][role="listitem"]:first-child', (accountDrawerFirstListItemEl) => { accountDrawerFirstListItemEl.insertAdjacentElement('beforebegin', confButtonEl); resetProfileDrawer(); }); $el('style', { id: '🖕📘-style' }, (el) => { document.head.appendChild(el); el.textContent = ` #🖕📘⚙️-icon { background-image: url(https://static.xx.fbcdn.net/images/emoji.php/v9/tfe/1/32/1f4a9.png); background-position: initial; background-size: contain; background-repeat: no-repeat; display: inline-block; height: 20px; width: 20px; } input[id^="🖕📘⚙️"]:not(:checked) + [for^="🖕📘⚙️"] .check-circle-rounded, input[id^="🖕📘⚙️"]:checked + [for^="🖕📘⚙️"] .cancel-rounded { display: none; } `; }); $el('style', { id: '🖕📘-style-util' }, (el) => { document.head.appendChild(el); el.textContent = ` .__fb-dark-mode:root, .__fb-dark-mode { --fuck-facebook-hover-overlay: #4e4e4f; } :root, .__fb-light-mode { --fuck-facebook-hover-overlay: #d8dadf; } /** atomic utilities **/ .relative { position: relative; } .absolute { position: absolute; } .flex { display: flex; } .block { display: block; } .inline-flex { display: inline-flex; } .inline-block { display: inline-block; } .flex-1 { flex: 1; } .flex-row { flex-direction: row;} .flex-column { flex-direction: column;} .flex-basis-0 { flex-basis: 0px; } .items-center { align-items: center; } .items-stretch { align-items: stretch; } .align-self-start { align-self: flex-start; } .justify-center { justify-content: center; } .justify-space-between { justify-content: space-between; } .p-0 { padding: 0; } .p-8 { padding: 8px; } .p-16 { padding: 16px; } .px-0 { padding-left: 0; padding-right: 0; } .px-8 { padding-left: 8px; padding-right: 8px; } .px-32 { padding-left: 32px; padding-right: 32px; } .px-60 { padding-left: 60px; padding-right: 60px; } .py-0 { padding-top: 0; padding-bottom: 0; } .py-12 { padding-top: 12px; padding-bottom: 12px; } .py-16 { padding-top: 16px; padding-bottom: 16px; } .pb-24 { padding-bottom: 24px; } .pl-10 { padding-left: 10px; } .m-0 { margin: 0; } .-my-5 { margin-top: -5px; margin-bottom: -5px; } .my-5 { margin-top: 5px; margin-bottom: 5px; } .my-8 { margin-top: 8px; margin-bottom: 8px; } .my-12 { margin-top: 12px; margin-bottom: 12px; } .ml-12 { margin-left: 12px; } .mr-12 { margin-right: 12px; } .-mb-16 { margin-bottom: -16px; } .-mt-4 { margin-top: -4px; } .inset-0 { top: 0px; right: 0px; bottom: 0px; left: 0px; } .left-0 { left: 0; } .rounded-8 { border-radius: 8px; } .rounded-50p { border-radius: 50%; } .border-0 { border-width: 0; } .border-solid { border-style: solid; } .bg-transparent { background-color: transparent; } .border-box { box-sizing: border-box; } .w-36 { width: 36px; } .h-36 { height: 36px; } .w-full { width: 100%; } .min-h-0 { min-height: 0; } .min-h-44 { min-height: 44px; } .min-h-100vh { min-height: 100vh; } .min-w-0 { min-width: 0; } .max-w-full { max-width: 100%; } .break-word { word-break: break-word; word-wrap: break-word; } .font-medium { font-weight: 500; } .font-bold { font-weight: 700; } .line-height-seven-sixth { line-height: 1.1667; } .text-2xl { font-size: 1.5rem; /* 24px */ } .text-base { font-size: 1rem; /* 16px */ } .text-left { text-align: left; } .text-green-500 { color: rgb(34 197 94); } .text-red-500 { color: rgb(239 68 68); } .z-0 { z-index: 0; } .overflow-hidden { overflow: hidden; } .cursor-pointer { cursor: pointer; } .touch-manipulation { touch-action: manipulation; } .no-underline, .no-underline:hover { text-decoration: none; } .outline-none { outline: none; } .pointer-events-none { pointer-events: none; } .list-none { list-style-type: none; } .select-none { user-select: none; -moz-user-select: none; } .opacity-0 { opacity: 0; } .vertical-align-bottom { vertical-align: bottom; } .rounded-inherit { border-radius: inherit; } .text-align-inherit { text-align: inherit; } .color-inherit { color: inherit; } .font-size-inherit { font-size: inherit; } .font-weight-inherit { font-weight: inherit; } /** with variables **/ .border-ado { border-color: var(--always-dark-overlay); } .bgc-ho2:hover { background-color: var(--fuck-facebook-hover-overlay) } .transition-ho { transition-duration: var(--fds-duration-extra-extra-short-out); transition-property: opacity; transition-timing-function: var(--fds-animation-fade-out); background-color: var(--hover-overlay); } .bg-card { background-color: var(--card-background); } .bg-btn-2 { background-color: var(--secondary-button-background); } .default-font { font-family: var(--font-family-default); } .primary-text { color: var(--primary-text); } .secondary-text { color: var(--secondary-text); } .filter-primary-icon { filter: var(--filter-primary-icon); } .filter-secondary-icon { filter: var(--filter-secondary-icon); } .transition-duration-fast { transition-duration: var(--fds-fast); } .transition-timing-soft { transition-timing-function: var(--fds-soft); } /** self defined **/ .icon-compat { background-image: url("https://static.xx.fbcdn.net/rsrc.php/v3/yJ/r/pX1dNHbjZEM.png"); background-size: auto; background-repeat: no-repeat; display: inline-block; } .icon-compat.left-arrow-20 { background-position: -25px -46px; width: 20px; height: 20px; } .icon-compat.chevron-right-24 { background-position: -108px -13px; width: 24px; height: 24px; } [id^="🖕📘"] [data-visualcompletion="ignore"] { opacity: 0; } [id^="🖕📘"] [data-visualcompletion="ignore"]:hover { opacity: 1; } .slide-left-to-show { transform: translateX(0%) translateZ(1px) !important; opacity: 1 !important; } `; });