+++ /dev/null
-<html>
- <head>
- <title>MastoWoT?</title>
- <style>
- body {
- background-color: black;
- padding: 0px;
- margin: 0px;
- color: #CAA;
- font-family: "Audiowide", "Sans";
- }
-
- h1 {
- width: 100%;
- text-style: italic;
- text-align: center;
- }
-
- h2 {
- display: inline-block;
- margin: .3em .5em .5em .5em;
- vertical-align: middle;
- }
-
- .panelbutton {
- display: inline-block;
- }
-
- #settingsPanel #sourceHost {
- display: inline-block;
- width: 100%;
- }
-
- #hostsPanel {
- display: inline-block;
- width: calc( 70% - 10px );
- min-width: 30em;
- height: calc(100% - 3em);
- /*background-color: #600;
- border: 3px solid #A00;*/
- margin: 0px;
- vertical-align: top;
- }
-
-/* #hostsTrusted, #hostsUntrusted, #hostsKnown, #manPanel {*/
- .subpanel, #manPanel {
- padding: 0em 1em;
- border: 3px solid #C00;
- border-radius: 1em;
- background-color: #600;
- margin-bottom: 1em;
- }
-
- #settingsPanel {
- display: inline-block;
- width: calc( 30% - 10px - 2em);
- min-width: 10em;
- height: calc(100% - 2em);
- background-color: #400;
- border: 3px solid #C00;
- margin: 0px;
- border-radius: 1em;
- padding: 1em;
- vertical-align: top;
- }
-
- #settingsPanel a {
- display: block;
- width: 100%;
- text-align: center;
- margin-bottom: 1em;
- font-weight: bold;
- color: #C00;
- }
-
- #settingsPanel button {
- display: block;
- width: 100%;
- }
-
- #settingsPanel div {
- border: 1px solid black;
- border-radius: 1em;
- padding: 0em 0em 1em 0em;
- margin-top: 1em;
- }
-
- #settingsPanel h2 {
- width: 100%;
- }
-
- #settingsPanel label {
- margin-left: 10%;
- display: inline-block;
- width: 40%;
- }
-
- #settingsPanel input {
- display: inline-block;
- width: 40%;
- }
-
- #shade {
- position: fixed;
- width: 100%;
- height: 100%;
- background-color: black;
- opacity: 0.8;
- z-index: 100;
- left: 0px;
- top: 0px;
- }
-
- #shade-text {
- position: fixed;
- width: 40%;
- height: 40%;
- left: 30%;
- top: 30%;
- z-index: 150;
- }
-
- #shade-text-button {
- position: fixed;
- width: 40%;
- height: 5%;
- left: 30%;
- top: 70%;
- z-index: 150;
- font-size: 3vh;
- }
-
- .subpanel .list {
- display: none;
- }
-
- .subpanel .list .instanceElem:nth-child(2n+3) {
- background-color: #C11;
- }
-
- .subpanel .list div {
- display: block;
- position: relative;
- border-bottom: 1px solid black;
- }
-
- .subpanel .list div h3 {
- display: inline-block;
- width: calc( 50% - 20em );
- margin: 0em;
- padding: 0em;
- overflow: scroll;
- }
-
- .subpanel .list div div {
- display: inline-block;
- position: relative;
- width: 20em;
- vertical-align: middle;
- }
-
- .subpanel .list div .comments {
- display: inline-block;
- margin: none;
- width: 48%;
- border: none;
- }
-
- .subpanel .list div div input[type=text] {
- display: inline-block;
- width: 3em;
- vertical-align: middle;
- }
-
- .subpanel .list div div input[type=range] {
- display: inline-block;
- width: 17em;
- vertical-align: middle;
- }
-
- .subpanel .list div div h3 {
- width: 100%;
- }
-
- .subpanel .list div:first-child h3 {
- font-weight: bold;
- text-decoration: underline;
- }
- </style>
- <script>
- // Initialize the site by loading in a list of known hosts
- var instances = [];
- var subLists = [];
-
- function init() {
- var buttons = document.getElementsByClassName("panelButton");
- for(var i = 0; i < buttons.length; i++) {
- buttons[i].onclick = openPanel;
- }
- }
-
- function synchronize() {
- var sourceInstance = "https://" + document.getElementById("sourceHost").value; //mastodon.slightlycyberpunk.com";
- fetch(sourceInstance + "/api/v1/instance/peers")
- .then(response => response.json())
- .then(peers => {
- console.log(peers);
-// var instances = [];
- for(var i = 0; i < peers.length; i++) {
-// var instance = directory[i].acct.replace( directory[i].username + "@", "" );
- var instance = peers[i];
-
- if( instances[instance] == null ) {
- instances[instance] = new Object();
- instances[instance].domain = instance;
- instances[instance].reasons = [];
- }
- }
-// console.log(instances);
- resetHosts();
- });
-
- fetch(sourceInstance + "/api/v1/instance/domain_blocks")
- .then(response => response.json())
- .then(blocklist => {
- console.log(blocklist);
-
- for(var i = 0; i < blocklist.length; i++) {
- instance = blocklist[i].domain;
- if(instance.indexOf("*") != -1) {
- continue;
- }
- if(instances[instance] == null) {
- instances[instance] = new Object();
- instances[instance].domain = instance;
- instances[instance].reasons = [];
- }
-
- if( blocklist[i].comment == null ) {
- blocklist[i].comment = "[ No comments provided ]"
- }
- if( blocklist[i].severity == "silence" ) {
- instances[instance].trust = -1 * document.getElementById("threshold-suspend").value;
- instances[inst].reasons[instance] = "SILENCED: "+blocklist[i].comment;
- } else {
- instances[instance].trust = -1 * document.getElementById("threshold-limit");
- instances[inst].reasons[instance] = "LIMITED: "+blocklist[i].comment;
- }
-// instances
- }
- });
-
-// document.getElementById("processButton").onclick = process;
- }
-
- async function process() {
- document.getElementById("processButton").disabled = true;
- var total = 0;
- for(instance in instances) {
- if(instances[instance].trust > 0) {
- try {
- await fetch("https://"+instance+"/api/v1/instance/domain_blocks")
- .then(response => response.json())
- .then(blocklist => {
- for(var i = 0; i < blocklist.length; i++) {
- inst = blocklist[i].domain;
- if(inst.indexOf("*") != -1) {
- continue;
- }
- if(instances[inst] == null) {
- instances[inst] = new Object();
- instances[inst].domain = inst;
- instances[inst].reasons = [];
- }
-
- if(typeof instances[inst].subtrust == "undefined") {
- instances[inst].subtrust = 0;
- }
- if( blocklist[i].comment == null ) {
- blocklist[i].comment = "[ No comments provided ]"
- }
- if( blocklist[i].severity == "silence" ) {
- instances[inst].subtrust -= instances[instance].trust *
- parseFloat(document.getElementById("multiplier-suspend").value);
- instances[inst].reasons[instance] = "SILENCED: "+blocklist[i].comment;
- } else {
- instances[inst].subtrust -= instances[instance].trust *
- parseFloat(document.getElementById("multiplier-limit").value);
- instances[inst].reasons[instance] = "LIMITED: "+blocklist[i].comment;
- }
- }
- total++;
- });
- } catch(e) {
- console.log(e);
- }
- }
- }
- // Normalize trust values
- for(instance in instances) {
- if(typeof instances[instance].subtrust != "undefined") {
- instances[instance].trust = instances[instance].subtrust / total;
- if(instances[instance].trust > 100) { instances[instance].trust = 100; }
- if(instances[instance].trust < -100) { instances[instance].trust = -100; }
- }
- }
- resetHosts();
- document.getElementById("processButton").disabled = false;
- }
-
- async function assocWithEnemies() {
- document.getElementById("assocWithEnemies").disabled = true;
- var total = 0;
- subLists.aoe = [];
- for(instance in instances) {
- if(instances[instance].trust < 0) {
- try {
- var c = 0;
- while(c < 10) {
- await fetch("https://"+instance+"/api/v1/directory?limit=80&offset=0", { signal: AbortSignal.timeout(5000) })
- .then(response => response.json())
- .then(directory => {
- if(directory.length < 80) {
- c = 10;
- }
- for(var i = 0; i < directory.length; i++) {
- inst = directory[i].acct.split("@")[1];
- if(inst == null || inst.indexOf("*") != -1) {
- continue;
- }
- if(subLists.aoe[inst] == null) {
- subLists.aoe[inst] = new Object();
- subLists.aoe[inst].domain = inst;
- subLists.aoe[inst].reasons = [];
- subLists.aoe[inst].trust = 0;
- subLists.aoe[inst].aoesubtrust = 0;
- }
-
- subLists.aoe[inst].aoesubtrust += parseFloat(instances[instance].trust);
- if(subLists.aoe[inst].aoesubtrust < total) {
- total = subLists.aoe[inst].aoesubtrust;
- }
- }
- });
- c++;
- }
- } catch(e) {
- console.log(e);
- }
- }
- }
- // Normalize trust values
- for(instance in subLists.aoe) {
- if(typeof subLists.aoe[instance].aoesubtrust != "undefined") {
- subLists.aoe[instance].trust = (subLists.aoe[instance].aoesubtrust * 100) / total;
- if(subLists.aoe[instance].trust > 100) { subLists.aoe[instance].trust = 100; }
- if(subLists.aoe[instance].trust < -100) { subLists.aoe[instance].trust = -100; }
- }
- }
- addTable("aoe", "Associates of Enemies", subLists.aoe);
- document.getElementById("assocWithEnemies").disabled = false;
- }
-
- async function friendsOfFriends() {
- document.getElementById("friendsOfFriends").disabled = true;
- var total = 0;
- subLists.fof = [];
- for(instance in instances) {
- if(instances[instance].trust > 0) {
- try {
- var c = 0;
- while(c < 10) {
- await fetch("https://"+instance+"/api/v1/directory?limit=80&offset="+(80*c), { signal: AbortSignal.timeout(5000) })
- .then(response => response.json())
- .then(directory => {
- if(directory.length < 80) {
- c = 10;
- }
- for(var i = 0; i < directory.length; i++) {
- inst = directory[i].acct.split("@")[1];
- if(inst == null || inst.indexOf("*") != -1) {
- continue;
- }
- if(subLists.fof[inst] == null) {
- subLists.fof[inst] = new Object();
- subLists.fof[inst].domain = inst;
- subLists.fof[inst].reasons = [];
- subLists.fof[inst].trust = 0;
- subLists.fof[inst].fofsubtrust = 0;
- }
-
- subLists.fof[inst].fofsubtrust += parseFloat(instances[instance].trust);
- if(subLists.fof[inst].fofsubtrust > total) {
- total = subLists.fof[inst].fofsubtrust;
- }
- }
- });
- c++;
- }
- } catch(e) {
- console.log(e);
- }
- }
- }
- // Normalize trust values
- for(instance in subLists.fof) {
- if(typeof subLists.fof[instance].fofsubtrust != "undefined") {
- subLists.fof[instance].trust = (int)(subLists.fof[instance].fofsubtrust * 100) / total;
- if(subLists.fof[instance].trust > 100) { subLists.fof[instance].trust = 100; }
- if(subLists.fof[instance].trust < -100) { subLists.fof[instance].trust = -100; }
- }
- }
- addTable("fof", "Friends of Friends", subLists.fof);
- document.getElementById("friendsOfFriends").disabled = false;
- }
-
-
- async function enemiesOfEnemies() {
- document.getElementById("enemiesOfEnemies").disabled = true;
- var total = 0;
- subLists.eoe = [];
- for(instance in instances) {
- if(instances[instance].trust < 0) {
- try {
- await fetch("https://"+instance+"/api/v1/instance/domain_blocks", { signal: AbortSignal.timeout(5000) })
- .then(response => response.json())
- .then(blocklist => {
- for(var i = 0; i < blocklist.length; i++) {
- inst = blocklist[i].domain;
- if(inst.indexOf("*") != -1) {
- continue;
- }
- if(subLists.eoe[inst] == null) {
- subLists.eoe[inst] = new Object();
- subLists.eoe[inst].domain = inst;
- subLists.eoe[inst].reasons = [];
- subLists.eoe[inst].eoesubtrust = 0;
- }
-
- if( blocklist[i].comment == null ) {
- blocklist[i].comment = "[ No comments provided ]"
- }
- if( blocklist[i].severity == "silence" ) {
- subLists.eoe[inst].eoesubtrust -= instances[instance].trust *
- parseFloat(document.getElementById("multiplier-suspend").value);
- subLists.eoe[inst].reasons[instance] = "SILENCED: "+blocklist[i].comment;
- } else {
- subLists.eoe[inst].eoesubtrust -= instances[instance].trust *
- parseFloat(document.getElementById("multiplier-limit").value);
- subLists.eoe[inst].reasons[instance] = "LIMITED: "+blocklist[i].comment;
- }
- }
- total++;
- });
- } catch(e) {
- console.log(e);
- }
- }
- }
- // Normalize trust values
- for(instance in subLists.eoe) {
- if(typeof subLists.eoe[instance].eoesubtrust != "undefined") {
- subLists.eoe[instance].trust = subLists.eoe[instance].eoesubtrust / total;
- if(subLists.eoe[instance].trust > 100) { subLists.eoe[instance].trust = 100; }
- if(subLists.eoe[instance].trust < -100) { subLists.eoe[instance].trust = -100; }
- }
- }
- addTable("eoe", "Enemies of Enemies", subLists.eoe);
- document.getElementById("enemiesOfEnemies").disabled = false;
- }
-
- function addTable(id, title, data) {
- var mainDiv = document.getElementById("hosts"+id);
- if(mainDiv != null) {
- mainDiv.parentElement.removeChild(mainDiv);
- }
- mainDiv = document.createElement("div");
- mainDiv.setAttribute("id", "hosts"+id);
- mainDiv.setAttribute("class", "subpanel");
-
- var button = document.createElement("button");
- button.setAttribute("id", "hosts"+id+"Open");
- button.setAttribute("class", "panelButton");
- button.innerHTML = "+";
- button.onclick = openPanel;
- mainDiv.appendChild(button);
-
- var header = document.createElement("h2");
- header.innerHTML = title;
- mainDiv.appendChild(header);
-
- var listElem = document.createElement("div");
- listElem.setAttribute("id", "hosts"+id+"List");
- listElem.setAttribute("class", "list");
- listElem.setAttribute("listId", id);
- for(element in data) {
- var instance = element;
-
- var instElem = document.createElement("div");
- instElem.innerHTML = "<h3>" + instance + "</h3>";
- instElem.setAttribute("id", "instance-"+instance);
- instElem.setAttribute("class", "instanceElem");
-
- var commentsElem = document.createElement("div");
- commentsElem.setAttribute("class", "comments");
- commentsElem.innerHTML = "";
- for(inst in data[element].reasons) {
- commentsElem.innerHTML += inst + " - " + data[element].reasons[inst] + "<br>";
- }
- instElem.appendChild(commentsElem);
-
- var divElem = document.createElement("div");
- var rangeElem = document.createElement("input");
- rangeElem.setAttribute("type", "range");
- rangeElem.setAttribute("min", "-100");
- rangeElem.setAttribute("max", "100");
- rangeElem.setAttribute("value",data[element].trust);
- rangeElem.oninput = syncRange;
- rangeElem.onchange = updateRange;
- divElem.appendChild(rangeElem);
-
- var valElem = document.createElement("input");
- valElem.setAttribute("type", "text");
- valElem.value = data[element].trust;
- valElem.onchange = updateVal;
- divElem.appendChild(valElem);
- instElem.appendChild(divElem);
-
- addButton = document.createElement("button");
- addButton.onclick = subListAdd;
- addButton.innerHTML = "Add";
- instElem.appendChild(addButton);
-
- listElem.appendChild(instElem);
- }
- mainDiv.appendChild(listElem);
-
- document.getElementById("hostsPanel").appendChild(mainDiv);
- }
-
- function subListAdd(event) {
- var instance = event.target.parentElement.children[0].innerText;
- var id = event.target.parentElement.parentElement.getAttribute("listId");
-
- // TODO: Check for confirmation if it already exists
- instances[instance] = subLists[id][instance];
- event.target.parentElement.parentElement.removeChild(event.target.parentElement);
- resetHosts();
- }
-
- function resetHosts() {
- document.getElementById("hostsTrustedList").innerHTML = "<div><h3>Instance</h3><div class='comments'></div><div><h3>Trust Value</h3></div></div>";
- document.getElementById("hostsUntrustedList").innerHTML = "<div><h3>Instance</h3><div class='comments'></div><div><h3>Trust Value</h3></div></div>";
- document.getElementById("hostsKnownList").innerHTML = "<div><h3>Instance</h3><div class='comments'></div><div><h3>Trust Value</h3></div></div>";
- var instanceKeys = Object.keys(instances).sort();
- for(var i = 0; i < instanceKeys.length; i++) {
- var instance = instanceKeys[i]; //.domain; //.acct.replace( directory[i].username + "@", "" );
- if(instances[instance].trust == undefined) {
- instances[instance].trust = 0;
- }
-
- var instElem = document.createElement("div");
- instElem.innerHTML = "<h3>" + instance + "</h3>";
- instElem.setAttribute("id", "instance-"+instance);
- instElem.setAttribute("class", "instanceElem");
-
- var commentsElem = document.createElement("div");
- commentsElem.setAttribute("class", "comments");
- commentsElem.innerHTML = "";
- for(inst in instances[instance].reasons) {
- commentsElem.innerHTML += inst + " - " + instances[instance].reasons[inst] + "<br/>";
- }
- instElem.appendChild(commentsElem);
-
- var divElem = document.createElement("div");
- var rangeElem = document.createElement("input");
- rangeElem.setAttribute("type", "range");
- rangeElem.setAttribute("min", "-100");
- rangeElem.setAttribute("max", "100");
- rangeElem.setAttribute("value",instances[instance].trust);
- rangeElem.oninput = syncRange;
- rangeElem.onchange = updateRange;
- divElem.appendChild(rangeElem);
-
- var valElem = document.createElement("input");
- valElem.setAttribute("type", "text");
- valElem.value = instances[instance].trust;
-// valElem.disabled = true;
- valElem.onchange = updateVal;
- divElem.appendChild(valElem);
- instElem.appendChild(divElem);
-
-/* var headerDiv = document.createElement("div");
- headerDiv.innerHTML = "<h3>Instance</h3><div><h3>Trust Value</h3></div>";
- document.getElementById("hostsTrustedList").innerHTML = "";
- document.getElementById("hostsUntrustedList").innerHTML = "";*/
- if(instances[instance].trust == 0) {
- document.getElementById("hostsKnownList").appendChild(instElem);
- } else if(instances[instance].trust > 0) {
- document.getElementById("hostsTrustedList").appendChild(instElem);
- } else {
- document.getElementById("hostsUntrustedList").appendChild(instElem);
- }
- }
-// document.getElementById("hostsKnownOpen").onclick();
- }
-
- function openPanel(event) {
- var listElem = this.parentElement.getElementsByClassName("list")[0];
- if( listElem.style.display == "block" ) {
- this.parentElement.getElementsByClassName("list")[0].style.display = "none";
- this.innerHTML = "+";
- } else {
- this.parentElement.getElementsByClassName("list")[0].style.display = "block";
- this.innerHTML = "-";
- }
- }
-
- function updateRange(event) {
- var id = this.parentElement.parentElement.parentElement.getAttribute("listId");
- var instance = this.parentElement.parentElement.firstChild.innerText;
- if( id == null) {
- instances[instance].trust = this.value;
- } else {
- subLists[id][instance].trust = this.value;
- }
- this.parentElement.children[1].value = this.value;
-
- if(id == null) {
- var parentPanel = this.parentElement.parentElement.parentElement;
- var instElem = this.parentElement.parentElement;
- if( this.value < 0 && parentPanel != document.getElementById("hostsUntrustedList") ) {
- parentPanel.removeChild(instElem);
- document.getElementById("hostsUntrustedList").appendChild(instElem);
- } else if( this.value > 0 && parentPanel != document.getElementById("hostsTrustedList") ) {
- parentPanel.removeChild(instElem);
- document.getElementById("hostsTrustedList").appendChild(instElem);
- } else if( this.value == 0 && parentPanel != document.getElementById("hostsKnownList") ) {
- parentPanel.removeChild(instElem);
- document.getElementById("hostsKnownList").appendChild(instElem);
- }
- }
- }
-
- function syncRange(event) {
- this.parentElement.children[1].value = this.value;
- }
-
- function updateVal(event) {
- var id = event.target.parentElement.parentElement.getAttribute("listId");
- var instance = this.parentElement.parentElement.firstChild.innerText;
- if(this.value < -100) { this.value = -100; }
- if(this.value > 100) { this.value = 100; }
- this.parentElement.children[0].value = this.value;
- instances[instance].trust = this.value;
-
- if(id == null) {
- var parentPanel = this.parentElement.parentElement.parentElement;
- var instElem = this.parentElement.parentElement;
- if( this.value < 0 && parentPanel != document.getElementById("hostsUntrustedList") ) {
- parentPanel.removeChild(instElem);
- document.getElementById("hostsUntrustedList").appendChild(instElem);
- } else if( this.value > 0 && parentPanel != document.getElementById("hostsTrustedList") ) {
- parentPanel.removeChild(instElem);
- document.getElementById("hostsTrustedList").appendChild(instElem);
- } else if( this.value == 0 && parentPanel != document.getElementById("hostsKnownList") ) {
- parentPanel.removeChild(instElem);
- document.getElementById("hostsKnownList").appendChild(instElem);
- }
- }
- }
-
- function importStr(str = "") {
- var shade = document.createElement("div");
- shade.setAttribute("id", "shade");
- shade.onclick = function() {
- document.body.removeChild(document.getElementById("shade"));
- document.body.removeChild(document.getElementById("shade-text"));
- document.body.removeChild(document.getElementById("shade-text-button"));
- }
-
- var text = document.createElement("textarea");
- text.innerHTML = str;
- text.setAttribute("id", "shade-text");
-
- var btn = document.createElement("button");
- btn.innerHTML = "Import";
- btn.setAttribute("id", "shade-text-button");
- btn.onclick = function() {
- loadStr(document.getElementById("shade-text").value);
- document.getElementById("shade").onclick();
- resetHosts();
- };
-
- document.body.appendChild(shade);
- document.body.appendChild(text);
- document.body.appendChild(btn);
- }
-
- function saveStr() {
- var instancesArr = [];
- for(instance in instances) {
- instancesArr.push(instances[instance]);
- if(typeof instances[instance].reasons == "object") {
- reasonsExport = [];
- for(inst in instances[instance].reasons) {
- var rsn = {};
- rsn.domain = inst;
- rsn.text = instances[instance].reasons[inst];
- reasonsExport.push(rsn);
- }
- instancesArr[instancesArr.length-1].reasons = reasonsExport;
- }
- }
-
- var configArr = {};
- configArr.instances = instancesArr;
- configArr.srchost = document.getElementById("sourceHost").value;
- configArr.mulLim = document.getElementById("multiplier-limit").value;
- configArr.mulSus = document.getElementById("multiplier-suspend").value;
- configArr.thrLim = document.getElementById("threshold-limit").value;
- configArr.thrSus = document.getElementById("threshold-suspend").value;
- return JSON.stringify(configArr);
- }
- function loadStr(configJSON) {
- instances = [];
- configArr = JSON.parse(configJSON);
- document.getElementById("sourceHost").value = configArr.srchost;
- document.getElementById("multiplier-limit").value = configArr.mulLim;
- document.getElementById("multiplier-suspend").value= configArr.mulSus;
- document.getElementById("threshold-limit").value = configArr.thrLim;
- document.getElementById("threshold-suspend").value = configArr.thrSus;
- for(var i = 0; i < configArr.instances.length; i++) {
- instances[configArr.instances[i].domain] = configArr.instances[i];
- if(typeof configArr.instances[i].reasons == "object") {
- reasonsArr = [];
- for(j = 0; j < configArr.instances[i].reasons.length; j++) {
- reasonsArr[configArr.instances[i].reasons[j].domain] =
- configArr.instances[i].reasons[j].text;
- }
- configArr.instances[i].reasons = reasonsArr;
- }
- }
- }
-
- function exportStr() {
- importStr(saveStr());
- }
-
- function loadCache() {
- loadStr(localStorage.getItem("config"));
- resetHosts();
- }
-
- function saveCache() {
- localStorage.setItem("config", saveStr());
- }
-
- function checkImpotence(hostList, instance, response = null) {
- if(typeof instances[instance].impotent != "undefined" && hostList.length > 0) {
- instance = hostList.pop();
- checkImpotence(hostList, instance, response);
- }
- if(response != null) {
- if(response.status == "404") {
- instances[instance].impotent = 1;
- if(instances[instance].impotent == 1) {
- document.getElementById("instance-"+instance).style.display = "none";
- } else {
- document.getElementById("instance-"+instance).style.display = "block";
- }
- } else if(response.status == "200") {
- instances[instance].impotent = 0;
- if(instances[instance].impotent == 1) {
- document.getElementById("instance-"+instance).style.display = "none";
- } else {
- document.getElementById("instance-"+instance).style.display = "block";
- }
- } else {
- instances[instance].impotent = 1;
- if(instances[instance].impotent == 1) {
- document.getElementById("instance-"+instance).style.display = "none";
- } else {
- document.getElementById("instance-"+instance).style.display = "block";
- }
- }
- }
-
- if(hostList.length == 0) {
- return;
- }
- var instance = hostList.pop();
- fetch("https://"+instance+"/api/v1/instance/domain_blocks", { signal: AbortSignal.timeout(5000) })
- .then(response => checkImpotence(hostList, instance, response))
- .catch(response => checkImpotence(hostList, instance, response));
- }
-
- function hideImpotent() {
- var keys = Object.keys(instances);
- for(i = 0; i < keys.length; i+=(keys.length/10)) {
- var sublist = keys.slice(i, i+(keys.length/10));
- var instance = sublist.pop();
- checkImpotence( sublist, instance )
- }
- }
-
- async function hideSubdomains() {
- alert("STUB");
- }
-
- function exportCSV() {
- var data = "";
- for(instance in instances) {
- var action = "";
- if(instances[instance].trust <= document.getElementById('threshold-limit').value) {
- action = "limit";
- } else if(instances[instance].trust <= document.getElementById('threshold-suspend').value) {
- action = "suspend";
- }
-
- if(action != "") {
- data += instance + ",";
- data += action + ",";
- data += '"';
- for(inst in instances[instance].reasons) {
- data += inst + " - " + instances[instance].reasons[inst] + "\n";
- }
- data = data.trim();
- data += '"\n';
- }
- }
- var elem = document.createElement("a");
- elem.setAttribute("href", "data:text/plain;charset=utf-8,"
- + encodeURIComponent(data.trim()));
- elem.setAttribute('download', 'mastowot.csv');
- document.body.appendChild(elem);
- elem.click();
- document.body.removeChild(elem);
- }
- </script>
- </head>
- <body>
- <h1>MastoWoT: A Web-of-Trust inspired defederation station</h1>
- <!-- Constant iteration of blacklist generation for spam immoliation,
- without subjugation, now with extra alliteration! -->
- <!-- Although likely just mental masturbation becaues really is
- anyone going to use this thing? I doubt it... -->
- <div id="manPanel">
- <button id="manPanelOpen" class="panelButton">-</button>
- <h2>Instructions</h2>
- <div class="list" style="display: block">
- <p><strong>This tool is intended for Mastodon instance administrators</strong></p>
- <p>You can still play around with it even if you aren't a server admin, but
- don't complain to me that you can't figure out how to work it :)</p>
- <p>This tool is designed to <em>suggest</em> a blocklist that you may
- want to configure on your Mastodon instance. The goal is to create a
- system simpler than scrolling #FediBlock, more proactive than relying
- entirely on user reports, and more federated than distributing blocklists
- from a central authority.</p>
- <p>To start, enter your instance's domain (no 'https://', no page, just the domain)
- into the box above the synchronize button
- on the right side menu, and click "Synchronize". This will make two calls
- to your server's API to fetch the known peers and the block list. This
- WILL require that your instance is configured to share this information.
- This can be configured in your instance settings, under Site Settings,
- enable 'publish list of discovered servers' and 'enable profile directory'.
- Also set "show domain blocks" and "show rationale" as "to everyone".</p>
- <p>Once you synchronie, any domains you have already blocked will appear
- under Untrusted Hosts. All other known peers will appear under Known Hosts.
- Now, you need to find some hosts you trust in the Known Hosts list and move
- their slider to the right. The slider moves between -100 and 100, and once
- you select a value it will update in the text box (you can also enter a
- value into the box directly). This should
- represent how much you "trust" this server, with -100 meaning you think this
- server is "evil" and 100 meaning it is to be trusted entirely (at least for
- the purposes of generating a blocklist). As you set values, these hosts will
- move to Trusted Hosts or Untrusted Hosts accordingly. I do NOT recommend
- trying to set a value for every single instance in the list. Search the page
- for instances that you are already familiar with instead.</p>
- <p>Once you have added a few trusted instances, click "Process" from the right
- side menu. This will fetch the block list from each instance on your trusted
- list. A host that appears on any of these blocklists will receive a negative
- trust value equal to the trust value of the hosts that have blocked it,
- multiplied by the appropriate multiplier values (configured in the side
- menu), averaged by dividing it by the total number of hosts in the list.</p>
- <p>Finally, you can use the "Export for Mastodon" button from the side menu
- to export a blocklist as a CSV file, which you can then import into your
- instance using the script provided below. This export will be
- generated based on the Thresholds values set on the right side menu. Any
- hosts with a trust value equal to or below the suspend threshold will be
- suspended; any remaining hosts with a trust value equal to or below the
- limit thershold will be limited.</p>
- <p>Also please be aware that some instances may choose to obfuscate certain
- URLs from their block list. Please don't do that. <strong>This tool cannot
- work with obfuscated URLs.</strong></p>
- <p>The remaining options are mentioned below:</p>
- <ul>
- <li>Hide Impotents: Tries to fetch a blocklist from all hosts in the list.
- If no blocklist can be downloaded, the host will be hidden (They will NOT
- be removed from the list, only hidden from display.) There is no point
- adding one of these hosts to your trusted list if they do not provide a
- their block list.</li>
- <li>Find Enemies of Enemies: Creates a new list of hosts that are blocked
- by the hosts on your untrusted list. The hosts on this list will NOT be
- considered trusted or untrusted until you click the 'add' button to move
- them into the main list with the given trust value.</li>
- <li>Find Friends of Friends: Creates a new list of hosts that are in the
- directory of the hosts in your trusted list. Trust values will be based
- on both the trust value of the trusted host and the number of accounts
- in its directory that are hosted at the this instance.</li>
- <li>FInd Associates of Enemies: Creates a new list of hosts that are in the
- directory of the hosts in your untrusted list. Trust values will be based
- on both the trust value of the untrusted host and the number of accounts
- in its directory that are hosted at the this instance.</li>
- <li>Load from cache: Load instances list from the browser cache</li>
- <li>Save to cache: Save instances list to your browser cache</li>
- <li>Export to you: Show the instances list as a JSON string</li>
- <li>Import from you: Import a JSON string exported previously</li>
- </ul>
-
-<hr/>
-<pre>
-# IMPORT SCRIPT
-# I realize Mastodon already has an import function, but as far as I can tell, that
-# does not allow you to include the comments. This script will.
-
-# This script assumes the export file is available in the current directory
-# and named 'mastowot.csv'
-
-# This should be your mastodon API token with admin access
-# (Generate from your admin user's development menu. Requires admin;write permissions)
-ADMIN_ACCESS_TOKEN=""
-# And your instance hostname of course
-MASTODON_HOST="https://"
-
-ts="`date +%Y%m%d-%H:%M:%S`"
-awk -v RS='"\n' \
- -v FS="," \
- -v authtoken="$ADMIN_ACCESS_TOKEN" \
- -v tgthost="$MASTODON_HOST" \
- -v timestamp="$ts" \
-'{
- system("curl -X POST -H \"Authorization: Bearer "authtoken"\" \
- -F \"domain="$1"\" -F \"private_comment=Updated by MastoWoT "timestamp"\" \
- -F \"public_comment="$2"\" \
- "tgthost"/api/v1/admin/domain_blocks");
-}' mastowot.csv
-
-</pre>
-<hr/>
- <pre>
-TODO:
- Styling:
- Color chooser, high contrast mode
- Sort lists by name or trust level
- Determine if blocked hosts have/had direct associations? and when?
-
-</pre>
- <p>Ultimately I do think this would make more sense as a shell script run
- via cron job...but I think this is a better way to display the concept,
- so that version is part two :)</p>
- </div>
- </div>
- <div id="hostsPanel">
- <div id="hostsTrusted" class="subpanel">
- <button id="hostsTrustedOpen" class="panelButton">+</button>
- <h2>Trusted Hosts</h2>
- <div id="hostsTrustedList" class="list">
- <div>
- <h3>Instance</h3>
- <div>
- <h3>Trust Value</h3>
- </div>
- </div>
- </div>
- </div>
-
- <div id="hostsUntrusted" class="subpanel">
- <button id="hostsUntrustedOpen" class="panelButton">+</button>
- <h2>Untrusted Hosts</h2>
- <div id="hostsUntrustedList" class="list">
- <div>
- <h3>Instance</h3>
- <div>
- <h3>Trust Value</h3>
- </div>
- </div>
- </div>
- </div>
-
- <div id="hostsKnown" class="subpanel">
- <button id="hostsKnownOpen" class="panelButton">+</button>
- <h2>Known Hosts</h2>
- <div id="hostsKnownList" class="list">
- <div>
- <h3>Instance</h3>
- <div>
- <h3>Trust Value</h3>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <div id="settingsPanel">
- <input type="text" id="sourceHost" />
- <button id="syncButton" onclick="synchronize()">Synchronize</button>
- <br/>
- <button id="processButton" onclick="process()">Process</button>
- <br/>
- <button onclick="hideImpotent()" >Hide impotents</button>
- <button id="enemiesOfEnemies" onclick="enemiesOfEnemies()">Find Enemies of Enemies</button>
- <button id="friendsOfFriends" onclick="friendsOfFriends()">Find Friends of Friends</button>
- <button id="assocWithEnemies" onclick="assocWithEnemies()">Find Associates of Enemies</button>
- <br/>
- <button onclick="loadCache()" >Load from cache</button>
- <button onclick="saveCache()" >Save to cache</button>
- <br/>
- <button onclick="exportStr()" >Export to you</button>
- <button onclick="importStr()" >Import from you</button>
- <br/>
- <button onclick="exportCSV()" >Export for Mastodon</button>
- <br/>
-<!-- <button onclick="hideSubdomains()" >Hide Subdomains</button> -->
-<!-- <button>Share</button> -->
- <div>
- <h2>Multipliers</h2>
- <label>Limit</label>
- <input type="text" value="1" id="multiplier-limit" />
- <label>Suspend</label>
- <input type="text" value="2" id="multiplier-suspend" />
- </div>
- <div>
- <h2>Thresholds</h2>
- <label>Limit</label>
- <input type="text" value="-50" id="threshold-limit" />
- <label>Suspend</label>
- <input type="text" value="-100" id="threshold-suspend" />
- </div>
- </div>
- <script>init();</script>
- </body>
-</html>