Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Mastodon: Auto Privacy
- // @namespace Mastodon
- // @match https://mastodon.art/web/*
- // @run-at document-idle
- // @require https://code.jquery.com/jquery-3.6.0.min.js
- // @grant none
- // @version 1.1
- // @author CBrun
- // @description Set default privacy for posts and replies
- // ==/UserScript==
- /* --- User Settings Start --- */
- //--- Privacy Defaults
- /*
- As of August 2022, there are 4 privacy modes identifiers for posts:
- public - Public (Visible for all)
- unlisted - Unlisted (Visible but opted-out of discovery)
- private - Followers only
- direct - Mentioned people only
- */
- const default_post_privacy = "direct";
- const default_reply_privacy = "unlisted";
- /*
- When enabled, use most restrictive privacy mode by default.
- Eg: You set replies to "unlisted", but are replying a mention-only thread.
- In this case the mention-only privacy mode will be used.
- */
- const smart_privacy = true;
- // --- CSS Identifiers used to trigger privacy change
- // Don't alter in case you're not sure what you're doing
- const reply_quote = "reply-indicator"; // Class of quote showing post being replied to
- const privacy_dropdown = "privacy-dropdown__dropdown"; // Class of post/reply privacy options list
- // The classes below must be preceded by . like regular css notations
- const compose_form = ".compose-panel .compose-form";
- const privacy_change_button = ".compose-panel .compose-form .privacy-dropdown button.privacy-dropdown__value-icon";
- const publish_button = ".compose-panel .compose-form .compose-form__publish"; // Publish toot button
- const reply_cancel_button = ".compose-panel .compose-form .reply-indicator__cancel"; // Publish toot button
- /* --- User Settings End --- */
- // Don't touch this!
- const $ = window.jQuery;
- (function() {
- // Initialize
- let privacy_mode = false;
- let can_reset_post_privacy = false;
- let can_be_smart = false;
- let manual_privacy_bypass = false;
- // ===========================
- // --- CONFIG
- // The node to be monitored
- const target = $('body')[0];
- // Observer configuration
- const config = {
- attributes: true,
- childList: true,
- characterData: false,
- subtree: true
- };
- // ===========================
- // --- FUNCTIONS
- // Set default post privacy
- function setPostPrivacy( mode ) {
- $( privacy_change_button ).trigger("click", false); // Artificial click
- privacy_mode = mode; // Store temporarily for later activation
- }
- // Compare privacy modes, returning strictest
- function comparePrivacy( original_mode, target_mode ) {
- const modes = {
- "direct": 0,
- "private": 1,
- "unlisted": 2,
- "public": 3,
- }
- // Get lowest integer, then key associated to it
- return getKeyByValue( modes, Math.min.apply(Math, [ modes[original_mode], modes[target_mode] ]) );
- }
- // Used in comparePrivacy()
- function getKeyByValue( object, value ) {
- return Object.keys(object).filter(key => object[key] === value);
- }
- // Function to watch for composer changes and change privacy accordingly
- let observer = new MutationObserver( function( mutations ) {
- mutations.forEach(function( mutation ) {
- let newNodes = mutation.addedNodes; // Node addition list
- let delNodes = mutation.removedNodes; // Node removal list
- if( newNodes !== null ) { // If nodes were added
- let $nodes = $( newNodes ); // jQuery set
- // Check each node for a match
- $nodes.each( function() {
- let $node = $( this );
- let dropdown_is_open = $node.hasClass( privacy_dropdown );
- // Call from smart_privacy @ reply_quote
- // if ( can_be_smart && $node.hasClass( privacy_dropdown )) {
- // User clicked on privacy dropdown, do nothing
- if ( manual_privacy_bypass ) {
- manual_privacy_bypass = false;
- return false; // break
- }
- // Call from smart_privacy @ reply_quote
- else if ( can_be_smart && dropdown_is_open ) {
- // Lock it so it won't called from manual clicks on the dropdown button
- can_be_smart = false;
- // Get original privacy mode
- let original_mode = $node.find('[aria-selected="true"]').attr("data-index");
- // Pick strictest one
- let stricter_mode = comparePrivacy( original_mode, privacy_mode );
- // Set privacy mode manually, setPostPrivacy() doesn't work well here
- $node.find('[data-index="' + stricter_mode + '"]').trigger("click");
- }
- // Call from picker when posting or replying
- else if ( privacy_mode !== false && dropdown_is_open ) {
- // Is ready to change privacy mode, do it
- $node.find('[data-index="' + privacy_mode + '"]').trigger("click");
- privacy_mode = false; // Reset to avoid double-activation
- }
- // Change Reply privacy
- else if( $node.hasClass( reply_quote ) && dropdown_is_open === false ) {
- // Intercept and handle separately by triggering mutation
- if (smart_privacy && privacy_mode === false) {
- $( privacy_change_button ).trigger("click", false); // Artificial click
- can_be_smart = true; // Unlock
- privacy_mode = default_reply_privacy; // Unlock
- return;
- }
- setPostPrivacy( default_reply_privacy );
- }
- });
- }
- // =============================================================================
- if (delNodes !== null) { // If nodes were removed
- let $nodes = $( delNodes );
- // Check each node for a match
- $nodes.each( function() {
- let $node = $( this );
- // The html is ready accept a privacy reset after posting/cancelling
- if( can_reset_post_privacy ) {
- // Reset privacy to custom default
- setPostPrivacy( default_post_privacy );
- can_reset_post_privacy = false;
- return false; // Break loop
- }
- });
- }
- });
- });
- // ===========================
- // --- AUTO RUN
- // Monitor node changes in body to handle privacy defaults
- observer.observe( target, config );
- // Reset privacy to custom default after posting
- $("body").on("click", publish_button + ", " + reply_cancel_button , function(e) {
- // Set flag allowing default to reset when ready
- can_reset_post_privacy = true;
- })
- .on("click", privacy_change_button , function(e, organic = true) {
- // Set flag allowing default to reset when ready
- manual_privacy_bypass = organic;
- });
- // On page load, set initial post privacy
- setPostPrivacy( default_post_privacy );
- })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement