Skip to content

Instantly share code, notes, and snippets.

@saschanaz
Last active March 31, 2023 19:12
Show Gist options
  • Save saschanaz/701908eb329af5991061f8813b5bf4bc to your computer and use it in GitHub Desktop.
Save saschanaz/701908eb329af5991061f8813b5bf4bc to your computer and use it in GitHub Desktop.
Mastodon redirector (Click the "Raw" button)
// ==UserScript==
// @name Mastodon Redirector
// @namespace http://saschanaz.github.io/
// @version 0.1.11
// @description Redirects to your home server when applicable
// @author Kagami Rosylight
// @match https://*/*
// @icon https://mastodon.social/favicon.ico
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-end
// @updateURL https://gist.github.com/saschanaz/701908eb329af5991061f8813b5bf4bc/raw/mastodon-redirector.user.js
// @downloadURL https://gist.github.com/saschanaz/701908eb329af5991061f8813b5bf4bc/raw/mastodon-redirector.user.js
// @supportURL https://gist.github.com/saschanaz/701908eb329af5991061f8813b5bf4bc
// ==/UserScript==
(() => {
'use strict';
const homeServers = GM_getValue("homeServers", ["https://mozilla.social"]);
GM_registerMenuCommand("Set home servers", () => {
const dialog = createDialog(`
<form style="padding: 15px;">
Type home servers below, line by line.
<p>
<textarea
id="saschanaz-redirector-textarea"
placeholder="Example:\nhttps://fosstodon.org/\nhttps://mastodon.social/"
style="width: 100%; font-size: 0.8em; font-family: sans-serif;"
rows="3"
></textarea>
</p>
<button id="saschanaz-redirector-button" type="button">Save</button>
</form>
`);
const button = dialog.querySelector("#saschanaz-redirector-button");
const textarea = dialog.querySelector("#saschanaz-redirector-textarea");
textarea.value = homeServers.join("\n");
button.addEventListener("click", ev => {
const servers = textarea.value.split("\n");
GM_setValue("homeServers", servers);
dialog.close();
});
button.focus({ focusVisible: false });
});
if (homeServers.includes(new URL(location.href).origin)) {
return;
}
const link = document.querySelector("link[rel=alternate][type='application/activity+json']");
if (!link) {
return;
}
popover();
function resolve(server) {
const url = new URL("api/v2/search", server);
url.searchParams.set("q", link.href);
url.searchParams.set("resolve", "true");
GM_xmlhttpRequest({
method: "GET",
url: url.toString(),
headers: {
"Content-Type": "application/json"
},
onload: function(response) {
const body = JSON.parse(response.response);
if (body.accounts[0]) {
location.href = new URL(`@${body.accounts[0].acct}`, server);
} else if (body.statuses[0]) {
location.href = new URL(`@${body.statuses[0].account.acct}/${body.statuses[0].id}`, server);
}
},
});
}
function popover() {
// TODO: try popover when implemented
const dialog = createDialog(`
<form id="saschanaz-redirector-form" style="padding: 15px;">
Redirect to:
<p id="saschanaz-redirector-list" style="margin: 1em 0; display: flex; flex-direction: column;"></p>
<button id="saschanaz-redirector-button" type="button">Redirect</button>
</form>
`);
const servers = homeServers.map(server => {
return document.createRange().createContextualFragment(`
<label><input type="radio" name="server" value="${server}"> ${new URL(server).hostname}</label>
`).children[0];
});
dialog.querySelector("#saschanaz-redirector-list").append(...servers);
const button = dialog.querySelector("#saschanaz-redirector-button");
const form = dialog.querySelector("#saschanaz-redirector-form");
if (form.elements.server) {
(form.elements.server[0] ?? form.elements.server).checked = true;
}
button.addEventListener("click", ev => {
const homeServer = form.elements.server.value;
if (!homeServer) {
return;
}
button.disabled = true;
resolve(homeServer);
});
button.focus({ focusVisible: false });
}
function createDialog(content) {
const dialog = document.createElement("dialog");
dialog.style = "background: #fff8; color: #444; backdrop-filter: blur(15px); padding: 0; border: 0; border-radius: 15px; top: 100px; bottom: initial; font-size: 20px; font-family: sans-serif; text-shadow: white 0 0 10px; line-height: 1.2em;";
dialog.innerHTML = content;
dialog.addEventListener("click", ev => {
if (ev.target === dialog) {
dialog.close();
}
});
dialog.addEventListener("close", ev => {
dialog.remove();
});
document.body.append(dialog);
dialog.showModal();
return dialog;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment