facebook set posts to private

Automation tool that sets posts in facebooks activity log to private for the new 2020 design

当前为 2021-02-27 提交的版本,查看 最新版本

// ==UserScript==
// @name        facebook set posts to private
// @description Automation tool that sets posts in facebooks activity log to private for the new 2020 design
// @author      Yorai Levi
// @namespace   https://github.com/YoraiLevi
// @update      https://raw.githubusercontent.com/YoraiLevi/SetFacebookPostsPrivate/master/GreaseMonkeySetFacebookPrivate.user.js
// @supportURL  https://github.com/YoraiLevi/SetFacebookPostsPrivate/issues
// @include     https://www.facebook.com/*
// @version     0.21.1
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM.openInTab
// @grant       window.close
// @run-at      document-idle


// ==/UserScript==

//3 user scripts merged into a single file:
(function () {
    'use strict';

    const SCRIPT_NAME = "facebook set posts to private"
    console.log('Loading', SCRIPT_NAME)
    let GLOBAL_TIMEOUT = Infinity
    function delayPromise(delay) {
        return new Promise(resolve => setTimeout(() => { resolve() }, delay))
    }
    async function get_selector_visible(selector, period, timeout = GLOBAL_TIMEOUT) {
        let s_time = performance.now()
        while (performance.now() - s_time < timeout) {
            let obj = document.querySelector(selector)
            if (obj && !(window.getComputedStyle(obj).display === "none" || window.getComputedStyle(obj).visibility === "hidden"))
                // checks if exists in dom? and supposedly? visible
                return obj
            await delayPromise(period)
        }
        throw "Waiting timed out: " + selector;
    }
    async function get_selector_not_visible(selector, period, timeout = GLOBAL_TIMEOUT) {
        let s_time = performance.now()
        while (performance.now() - s_time < timeout) {
            let obj = document.querySelector(selector)
            if (!obj || (window.getComputedStyle(obj).display === "none" || window.getComputedStyle(obj).visibility === "hidden"))
                // checks if exists in dom? and supposedly? visible
                return obj
            await delayPromise(period)
        }
        throw "Waiting timed out: " + selector;
    }
    //set privacy action
    if (document.URL.match("https://www.facebook.com/.+/posts/.+|https://www.facebook.com/photo.+")) {
        (function () {
            'use strict';

            console.log("Initializing")
            let three_dot_menu_selector = "div > div.nqmvxvec.j83agx80.jnigpg78.cxgpxx05.dflh9lhu.sj5x9vvc.scb9dxdr.odw8uiq3 > div > div"
            let menu_buttons_selector = "div.cwj9ozl2.ue3kfks5.pw54ja7n.uo3d90p7.l82x9zwi.nwpbqux9.rq0escxv.jgsskzai.ni8dbmo4.stjgntxs > div > div.j83agx80.cbu4d94t.buofh1pr > div.tojvnm2t.a6sixzi8.k5wvi7nf.q3lfd5jv.pk4s997a.bipmatt0.cebpdrjk.qowsmv63.owwhemhu.dp1hu0rb.dhp61c6y.l9j0dhe7.iyyx5f41.a8s20v7p > div"
            let only_me_choice_selector = "div.kr520xx4.pedkr2u6.ms05siws.pnx7fd3z.b7h9ocf4.pmk7jnqg.j9ispegn.k4urcfbm > div.cbu4d94t.j83agx80 > div > div > div > div > div > div > div:nth-child(5) > div"
            window.addEventListener('load', async () => {
                await delayPromise(1000)
                setPrivate()
            })
            async function setPrivate() {
                console.log("Setting post to private")

                //checking privacy state:
                const only_me_lock_icon = "https://static.xx.fbcdn.net/rsrc.php/v3/yD/r/JSmL99pVrUz.png"
                let audience = document.querySelector("div > span > span > div > div > div> img")
                if (audience && audience.src === only_me_lock_icon)
                    close()
                //The actual action to set a post to private
                let three_dot_menu = await get_selector_visible(three_dot_menu_selector)
                three_dot_menu.click()


                let edit_audience_menu_button = null
                await get_selector_visible(menu_buttons_selector)
                let buttons = document.querySelectorAll(menu_buttons_selector)
                //audience icrons:
                //public : https://static.xx.fbcdn.net/rsrc.php/v3/yS/r/k1K2sJ70emI.png
                //friends with/out : https://static.xx.fbcdn.net/rsrc.php/v3/yH/r/hHt2U1bRtLs.png
                //specific friends : https://static.xx.fbcdn.net/rsrc.php/v3/yv/r/cD5R2-Z_DDa.png
                //lock - private : https://static.xx.fbcdn.net/rsrc.php/v3/yU/r/cfUGV2EoMCu.png
                let imgs = ["https://static.xx.fbcdn.net/rsrc.php/v3/yS/r/k1K2sJ70emI.png",
                    "https://static.xx.fbcdn.net/rsrc.php/v3/yH/r/hHt2U1bRtLs.png",
                    "https://static.xx.fbcdn.net/rsrc.php/v3/yv/r/cD5R2-Z_DDa.png",
                    "https://static.xx.fbcdn.net/rsrc.php/v3/yU/r/cfUGV2EoMCu.png"
                ]
                for (const b of buttons) {
                    //make cross language with icon detection instead?
                    let img = b.querySelector("*> img")
                    if (img && imgs.indexOf(img.src) !== -1)
                        edit_audience_menu_button = b
                }
                if (edit_audience_menu_button) {
                    edit_audience_menu_button.click()
                }
                else {
                    close()
                }
                let only_me_choice = await get_selector_visible(only_me_choice_selector)

                await delayPromise(1000)
                //dummy(presses the x to close window)
                // let closeX = await get_selector_visible("#mount_0_0 > div > div:nth-child(1) > div.rq0escxv.l9j0dhe7.du4w35lb > div:nth-child(5) > div > div > div.rq0escxv.l9j0dhe7.du4w35lb > div > div.iqfcb0g7.tojvnm2t.a6sixzi8.k5wvi7nf.q3lfd5jv.pk4s997a.bipmatt0.cebpdrjk.qowsmv63.owwhemhu.dp1hu0rb.dhp61c6y.l9j0dhe7.iyyx5f41.a8s20v7p > div > div > div > div > div.kr520xx4.pedkr2u6.ms05siws.pnx7fd3z.b7h9ocf4.pmk7jnqg.j9ispegn.k4urcfbm > div.cypi58rs.pmk7jnqg.fcg2cn6m.tkr6xdv7 > div")
                // closeX.click()
                only_me_choice.click()
                await get_selector_not_visible(only_me_choice_selector)
                //wait for privacy to change in page
                while (audience && audience.src !== "https://static.xx.fbcdn.net/rsrc.php/v3/yD/r/JSmL99pVrUz.png") {
                    console.log("Waiting for audience to update")
                    await delayPromise(100)
                }
                close()
            }
        })();
    }
    //inject activity manager
    else if (document.URL.match("https://www.facebook.com/.+/allactivity.+")) {
        (function () {
            'use strict'
            console.log("Initializing")
            function get_items() {
                let activity_selector = "div > div:nth-child(1) > div.rq0escxv.l9j0dhe7.du4w35lb > div.rq0escxv.l9j0dhe7.du4w35lb > div > div > div.j83agx80.cbu4d94t.d6urw2fd.dp1hu0rb.l9j0dhe7.du4w35lb > div.rq0escxv.l9j0dhe7.du4w35lb.j83agx80.pfnyh3mw.jifvfom9.gs1a9yip.owycx6da.btwxx1t3.buofh1pr.dp1hu0rb.ka73uehy > div.rq0escxv.l9j0dhe7.tkr6xdv7.j83agx80.cbu4d94t.pfnyh3mw.d2edcug0.hpfvmrgz.dp1hu0rb.rek2kq2y.o36gj0jk > div > div.q5bimw55.rpm2j7zs.k7i0oixp.gvuykj2m.j83agx80.cbu4d94t.ni8dbmo4.eg9m0zos.l9j0dhe7.du4w35lb.ofs802cu.pohlnb88.dkue75c7.mb9wzai9.d8ncny3e.buofh1pr.g5gj957u.tgvbjcpo.l56l04vs.r57mb794.kh7kg01d.c3g1iek1.k4xni2cv > div.j83agx80.cbu4d94t.buofh1pr > div.aov4n071 > div *> div> a"
                return document.querySelectorAll(activity_selector)
            }
            window.addEventListener('load', async () => {
                console.log("Injecting GUI")
                let parent = document.body
                function insertAfter(referenceNode, newNode) {
                    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
                }
                let divInputs = document.createElement('div')
                let spanMin = document.createElement('div'); spanMin.innerText = "From:(Blank=First)", divInputs.appendChild(spanMin)
                let min = addInput(divInputs)
                min.value = GM_getValue("from", null) + 1 //one based
                let spanMax = document.createElement('div'); spanMax.innerText = "To:(Blank=No Limit)", divInputs.appendChild(spanMax)
                let max = addInput(divInputs)

                function openRangeButtonActionClosure(min_input_element, max_input_element) {
                    return function openRangeButtonAction() {
                        //The gui is 1 indexed and the functions are 0 indexed
                        let from = min_input_element.value ? min_input_element.value - 1 : 0
                        let to = max_input_element.value ? max_input_element.value - 1 : Infinity
                        console.log("Processing range [from:", from, "to:", to, ")")
                        openRange(from, to)
                    }
                }
                async function openButtonAction() {
                    openRange(0, Infinity)
                }
                let divButtons = document.createElement('div')
                addButton('Open Range', openRangeButtonActionClosure(min, max), divButtons)
                addButton('Open All', openButtonAction, divButtons)

                let div = document.createElement('div')
                let cssObj = { position: 'fixed', display: "block", 'z-index': 3, background: "#ffffff", border: "3px solid red" }
                Object.keys(cssObj).forEach(key => div.style[key] = cssObj[key])
                div.appendChild(divButtons)
                div.appendChild(divInputs)

                parent.insertBefore(div, parent.childNodes[0])

            })
            function addInput(parentElement = document.body, cssObj) {
                cssObj = cssObj || { position: 'relative', 'z-index': 3 }
                let input = document.createElement('input'), btnStyle = input.style
                parentElement.appendChild(input)
                input.type = "number"
                Object.keys(cssObj).forEach(key => btnStyle[key] = cssObj[key])
                return input
            }
            function addButton(text, onclick, parentElement = document.body, cssObj) {
                cssObj = cssObj || { position: 'relative', 'z-index': 3 }
                let button = document.createElement('button'), btnStyle = button.style
                parentElement.appendChild(button)
                button.innerHTML = text
                button.onclick = onclick
                Object.keys(cssObj).forEach(key => btnStyle[key] = cssObj[key])
                return button
            }
            async function openRange(from, to) {
                //zero indexed [0from,to)
                async function handleRange(from, to) {
                    let items = Array.from(get_items())
                    let rangeItems = items.slice(from, to)
                    //reseting from value to valid value per iteration
                    GM_setValue("from", from)
                    const only_me_lock_icon = "https://static.xx.fbcdn.net/rsrc.php/v3/yD/r/JSmL99pVrUz.png"
                    for (const item of rangeItems) {
                        console.log("Processing element:", item)
                        let audience = item.querySelector("*>img")
                        if (audience && audience.src !== only_me_lock_icon) {
                            await new Promise(async (resolve, reject) => {
                                let tab = await GM.openInTab(item.href, false)
                                tab.onclose = () => {
                                    resolve()
                                }
                            })
                        }
                        GM_setValue("from", GM_getValue("from", 0) + 1)
                    }
                    return items.length
                }
                async function scrollRange(from, max_failures = 30) {
                    //zero indexed [0from,to)
                    let failed = 0;
                    let prevscrollTop = null;
                    while (from > get_items().length - 1) {
                        //from is both an index and is inclusive!
                        let scrolling_container_selector = "div > div:nth-child(1) > div.rq0escxv.l9j0dhe7.du4w35lb > div.rq0escxv.l9j0dhe7.du4w35lb > div > div > div.j83agx80.cbu4d94t.d6urw2fd.dp1hu0rb.l9j0dhe7.du4w35lb > div.rq0escxv.l9j0dhe7.du4w35lb.j83agx80.pfnyh3mw.jifvfom9.gs1a9yip.owycx6da.btwxx1t3.buofh1pr.dp1hu0rb.ka73uehy > div.rq0escxv.l9j0dhe7.tkr6xdv7.j83agx80.cbu4d94t.pfnyh3mw.d2edcug0.hpfvmrgz.dp1hu0rb.rek2kq2y.o36gj0jk > div > div.q5bimw55.rpm2j7zs.k7i0oixp.gvuykj2m.j83agx80.cbu4d94t.ni8dbmo4.eg9m0zos.l9j0dhe7.du4w35lb.ofs802cu.pohlnb88.dkue75c7.mb9wzai9.d8ncny3e.buofh1pr.g5gj957u.tgvbjcpo.l56l04vs.r57mb794.kh7kg01d.c3g1iek1.k4xni2cv"
                        let scrolling_container = document.querySelector(scrolling_container_selector)
                        //are we at the bottom?
                        if (prevscrollTop === scrolling_container.scrollTop) {
                            failed++;
                            //yes we are and for too long, something is either wrong or we're done.
                            if (failed > max_failures)
                                throw "Failure Scrolling Down, is that everything?"
                        }
                        prevscrollTop = scrolling_container.scrollTop
                        scrolling_container.scrollTop = scrolling_container.scrollHeight
                        await delayPromise(1000)
                    }
                }
                while (from < to) {
                    await scrollRange(from)
                    from = await handleRange(from, to)
                }
            }
        }())
    }
    //ignore
    else if (document.URL.match("https://www.facebook.com/permalink.php.*|https://www.facebook.com/groups/.*")) {
        close()
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址