remote_instance_actions/remote_instance_actions.use...

95 lines
3.4 KiB
JavaScript

// ==UserScript==
// @name Remote Instance Actions
// @namespace https://hollymcfarland.com
// @version 1.0
// @description Easily limit a remote instance from your Mastodon instance via the timeline
// @author monorail
<?php
foreach ($_GET["instances"] as $instance) {
echo "// @match https://*.{$instance}/web/*" . PHP_EOL;
}
?>
// @grant GM_openInTab
// @run-at context-menu
// ==/UserScript==
(function() {
'use strict';
// Check whether the domain is already limited on the instance, and open the relevant form if not
// This is imperfect, it just does a search of limited domains in the admin backend
// This means it handles substrings weirdly, and interacts weirdly with suspending subdomains
// But there's an override so it's not so bad
function checkStatus(domain, callback) {
function resultsFound(response) {
// reconstruct the results page in memory
const parser = new DOMParser();
const resultsPage = parser.parseFromString(response, "text/html");
// .directory__tag is the class for the div with results, if it exists
// so its presense indicates that a result was found, and the current domain is likely limited
return resultsPage.getElementsByClassName("directory__tag").length;
}
// perform a search for limited instances that match the highlighted text
let url = `https://${window.location.host}/admin/instances?utf8=%E2%9C%93&limited=1&by_domain=${domain}`;
let request = new XMLHttpRequest();
request.open('GET', url);
request.addEventListener('load', function() {
if (request.status === 403) {
alert("You are not logged in to an administrator account.");
return;
}
if (request.status !== 200 && !confirm("Recieved unexpected HTML status code. Continue anyway?")) {
return;
}
if (!resultsFound(request.response) || confirm(`${domain} may already be limited. Continue anyway?`)) {
callback(domain);
}
});
request.send();
}
// Open a new tab to the form for applying moderation actions to the selected domain
function newBlock(domain) {
GM_openInTab(`https://${window.location.host}/admin/domain_blocks/new?_domain=${domain}`, false);
}
// Clean up the selected domain
function sanitize(domain) {
// clear out accidental whitespace
domain = domain.trim();
// in case a full link was provided
domain = domain.replace(/https?:\/\//, "");
// in case the domain is being copied from a user@domain string
domain = domain.split("@").slice(-1)[0];
// in case the domain has a path included
domain = domain.split("/")[0];
return domain;
}
// Make sure a domain was actually selected
// This is imperfect, but can be overridden in case of a false negative
function validate(domain) {
// For now just check for a domain + tld and no whitespace
return domain.includes(".") && !domain.match(/\s/);
}
let domain = sanitize(document.getSelection().toString());
if (!domain.trim()) {
alert("Nothing selected.");
return;
}
if (validate(domain) || confirm(`Are you sure you meant to select "${domain}"?`)) {
checkStatus(domain, newBlock);
}
})();