Created
May 21, 2022 19:45
-
-
Save gsuberland/af8373a6add07ab7e9a2792379803369 to your computer and use it in GitHub Desktop.
Tampermonkey / Greasemonkey script to automatically set the privacy of replies to unlisted by default on Mastodon.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Mastodon Unlisted Replies | |
// @namespace http://tampermonkey.net/ | |
// @version 0.1 | |
// @description Sets the privacy of replies to unlisted by default on Mastodon. | |
// @author Graham Sutherland (@[email protected]) | |
// @match https://chaos.social/* https://mastodon.social/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=chaos.social | |
// @grant none | |
// @run-at document-idle | |
// ==/UserScript== | |
// https://stackoverflow.com/a/39165137/978756 | |
function FindReact(dom, traverseUp = 0) { | |
const key = Object.keys(dom).find(key=>{ | |
return key.startsWith("__reactFiber$") // react 17+ | |
|| key.startsWith("__reactInternalInstance$"); // react <17 | |
}); | |
const domFiber = dom[key]; | |
if (domFiber == null) return null; | |
// react <16 | |
if (domFiber._currentElement) { | |
let compFiber = domFiber._currentElement._owner; | |
for (let i = 0; i < traverseUp; i++) { | |
compFiber = compFiber._currentElement._owner; | |
} | |
return compFiber._instance; | |
} | |
// react 16+ | |
const GetCompFiber = fiber=>{ | |
//return fiber._debugOwner; // this also works, but is __DEV__ only | |
let parentFiber = fiber.return; | |
while (typeof parentFiber.type == "string") { | |
parentFiber = parentFiber.return; | |
} | |
return parentFiber; | |
}; | |
let compFiber = GetCompFiber(domFiber); | |
for (let i = 0; i < traverseUp; i++) { | |
compFiber = GetCompFiber(compFiber); | |
} | |
return compFiber.stateNode; | |
} | |
(function() { | |
'use strict'; | |
document.mastodon_unlistreply = {}; | |
document.mastodon_unlistreply.elements = {}; | |
document.mastodon_unlistreply.react = {}; | |
document.mastodon_unlistreply.timers = {}; | |
// use setInterval to wait for the forms to be set up and working | |
document.mastodon_unlistreply.timers.elementFinder = window.setInterval(function() { | |
var pagers = document.getElementsByClassName('drawer__pager'); | |
if (pagers.length == 0) | |
return; | |
var composers = pagers[0].getElementsByClassName('compose-form'); | |
if (composers.length == 0) | |
return; | |
var privacy_dropdowns = composers[0].getElementsByClassName('privacy-dropdown'); | |
if (privacy_dropdowns.length == 0) | |
return; | |
document.mastodon_unlistreply.elements.pager = pagers[0]; | |
document.mastodon_unlistreply.elements.composer = composers[0]; | |
document.mastodon_unlistreply.elements.privacy = privacy_dropdowns[0]; | |
document.mastodon_unlistreply.react.composer = FindReact(document.mastodon_unlistreply.elements.composer); | |
document.mastodon_unlistreply.react.privacy = FindReact(document.mastodon_unlistreply.elements.privacy); | |
// ok, setup complete. kill the elementFinder timer. | |
clearInterval(document.mastodon_unlistreply.timers.elementFinder); | |
document.mastodon_unlistreply.timers.elementFinder = null; | |
// every 500ms we check for changes. | |
document.mastodon_unlistreply.timers.update = window.setInterval(function() { | |
let composer = document.mastodon_unlistreply.react.composer; | |
let privacy = document.mastodon_unlistreply.react.privacy; | |
// only care about replies | |
if (composer.props.isInReply) | |
{ | |
// get the reply indicator element and component so we can see if it changed since we last touched things | |
document.mastodon_unlistreply.elements.reply = document.mastodon_unlistreply.elements.composer.getElementsByClassName('reply-indicator')[0]; | |
document.mastodon_unlistreply.react.reply = FindReact(document.mastodon_unlistreply.elements.reply); | |
// have we touched this composer since it was last updated? (react removes extra properties on update) | |
if (!composer.props.hasOwnProperty('__unlistreply_touched')) | |
{ | |
// there has been an update! mark as touched. | |
composer.props.__unlistreply_touched = new Date(); | |
// have we touched the reply since it was last updated? (react removes extra properties on update) | |
let reply = document.mastodon_unlistreply.react.reply; | |
if (!reply.props.hasOwnProperty('__unlistreply_touched')) | |
{ | |
// there has been an update! mark as touched. | |
reply.props.__unlistreply_touched = new Date(); | |
// if the reply is marked as public and the control is enabled, mark the reply as unlisted. | |
if (privacy.props.value == 'public' && !privacy.props.disabled) | |
{ | |
privacy.handleChange('unlisted'); | |
} | |
} | |
} | |
} | |
}, 500); | |
}, 500); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment