facebook - ad block v3

Hides sponsored posts in FB's news-feed

目前為 2021-09-06 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         facebook - ad block v3
// @version      3.02
// @description  Hides sponsored posts in FB's news-feed
// @author       zbluebugz
// @match        https://*.facebook.com/*
// @-icon         https://www.google.com/s2/favicons?domain=facebook.com
// @-icon64URL    https://www.google.com/s2/favicons?domain=facebook.com
// @run-at       document-idle
// @namespace https://greasyfork.org/users/812551
// ==/UserScript==
/*
  Comments:
    original: https://pastebin.com/raw/vmaiA8jJ
    05/09/2021: FB has changed the way sponsored posts are marked - made harder to detect
                - this script detects the new way.
    06/09/2021: Detected a slight variation of the new way - amended code to cope with that.
*/

(function () {
    'use strict';

    var title = 'facebook - ad block';

    // sponsered posts' keyword(s)
    // - if more than one keyword, use this format: ['keyword 1', 'keyword 2']
    var SPONSORED_WORDS = ['Sponsored'];

    // hide various suggested items (often flagged as sponsored posts - not all the time)
    // var suggestions = ['Shop Now', 'Learn More', 'Sign Up', 'Download', 'Get Offer', 'Apply Now', 'Book Now', 'Play Game', 'Get Quote'];
    var suggestions = ['Shop Now', 'Sign Up', 'Download', 'Get Offer', 'Book Now', 'Play Game', 'Get Quote'];

    // hide / highlight the selected posts
    let HIDE_STYLE = (true) ? 'display:none !important' : 'border:3px solid yellow !important';

    // hide certain elements ...
    const TOGGLE_SUGGESTED_CONTENT = false;
    const TOGGLE_SUGGESTED_EVENTS = false;
    const TOGGLE_SUGGESTED_GROUPS = false;
    const TOGGLE_CREATE_ROOM = true;
    const TOGGLE_PEOPLE_YOU_MAY_KNOW = true;
    const TOGGLE_SUGGESTED_PAGES = true ;
    const TOGGLE_PAID_PARTNERSHIP = true;
    const TOGGLE_BLUE_NAVBAR = false;

    if(TOGGLE_SUGGESTED_CONTENT) 	suggestions.push('Suggested for you');
    if(TOGGLE_SUGGESTED_EVENTS) 	suggestions.push('Suggested Events');
    if(TOGGLE_PEOPLE_YOU_MAY_KNOW) 	suggestions.push('People you may know');
    if(TOGGLE_SUGGESTED_PAGES) 	 	suggestions.push('Suggested Pages');
    if(TOGGLE_PAID_PARTNERSHIP) 	suggestions.push('Paid partnership');
    if(TOGGLE_SUGGESTED_GROUPS)	 	suggestions.push('Suggested groups');

    // how often to run this script
    const CHECK_RATE_MS = 100;

    function hide(el) {
        return el.setAttribute('style',HIDE_STYLE);
    };

    function doChanges() {

        if(TOGGLE_BLUE_NAVBAR){
            var navbar = document.querySelector('div[aria-label="Facebook"]');
            if(navbar) navbar.setAttribute('style','background-color:#3b5998 !important');
        };

        if(TOGGLE_CREATE_ROOM){
            var create_room = document.querySelector('div[data-pagelet="VideoChatHomeUnitNoDDD"]');
            if(create_room) hide(create_room);
        };

        function findSponsoredPosts() {
            // get collection of posts, ignore those already read by this script.
            let posts = Array.from(
                document.querySelectorAll('div[data-pagelet*=FeedUnit]:not([adbpr])')
                // next line for use in debugging - ignores the posts that have been already processed.
                //document.querySelectorAll('div[data-pagelet*=FeedUnit]')
            );
            // loop through each post to see if it is a sponsored one or not
            let hidePosts = [];
            posts.forEach(
                post => {
                    // flag this post as not to be read again
                    post.setAttribute('adbpr', true);
                    // within this unread post, find the SPAN element(s) having aria-label = Sponsored
                    // (usually only one is found)
                    let alSpans = Array.from(post.querySelectorAll('span[aria-label="Sponsored"]'));
                    // is the word "Sponsored" visible?
                    // - there are several spans having single letters - all randomised, but will make up "sponsored" when certain span tags are "visible".
                    alSpans.forEach(sp => {
                        let daText = '';
                        /*let nsp = sp.nextSibling.firstChild; */
                        let nsp = sp.nextSibling;
                        if (nsp.tagName === "SPAN") {
                            if (!nsp.style.top) {
                                // visible SPANs do not have a TOP value.
                                daText += nsp.innerText.charAt(0);
                            }
                        }
                        nsp = nsp.firstChild;
                        
                        do {
                            if (nsp.tagName === "SPAN") {
                                if (!nsp.style.top) {
                                    // visible SPANs do not have a TOP value.
                                    daText += nsp.innerText.charAt(0);
                                }
                            }
                            nsp = nsp.nextSibling;
                        } while (nsp);
                        // console.info("--sp:", daText, WORD_SPONSORED.indexOf(daText));
                        if (SPONSORED_WORDS.indexOf(daText) > -1 ) {
                            //console.info("-- sp pushing:", sp);
                            hidePosts.push(sp)
                        }
                    });

                    // suggestions
                    if (suggestions) {
                        // scan the a tags
                        let els = Array.from(post.querySelectorAll('a'));
                        let skip = false;
                        for (let x = 0; x < els.length; x++) {
                            if (suggestions.includes(els[x].textContent)) {
                                hidePosts.push(els[x]);
                                skip = true;
                                break;
                            }
                        };
                        // scan the span tags
                        if (!skip) {
                            els = Array.from(post.querySelectorAll('span'));
                            for (let x = 0; x < els.length; x++) {
                                if (suggestions.includes(els[x].textContent)) {
                                    hidePosts.push(els[x]);
                                    break;
                                }
                            }
                        }
                    }
                }
            );
            return hidePosts
        };

        function kill(element) {
            try {
                if(element) {
                    var limit = 0;
                    while(limit++ < 100) {
                        if(typeof element.getAttribute('data-pagelet') == "string")
                        {
                            if(element.getAttribute('data-pagelet').contains('FeedUnit'))
                            {
                                hide(element);
                                return;
                            };
                        };
                        element = element.parentNode;
                    };
                };
            } catch (e) {
            };
        };

        findSponsoredPosts().forEach( e => kill(e) );

    };

    const callback = function () {
        try {
            doChanges();
        } catch (e) {
            console.warn(title, e);
        }
    };

    setInterval(callback, CHECK_RATE_MS);
})();