[Off-Topic] Coding advice: building a Firefox extension

Hello all,

With the crumbling of Twitter and similar platforms, I’ve been thinking about the problems of moderation, scale, and discoverability. I’ve seen a lot of people talking about webrings lately, but webrings still have a central maintainer responsible for vetting websites that apply to participate. I want a decentralized webring—a system by which you can designate websites you trust, and if those websites are part of the webring, the sites that they have designated as trustworthy are inherited, perhaps at a lower trust level. Similarly, if there are sites that should NOT be part of the webring, you could designate them as blocked sites, and this information could be inherited from other users as well. This would work like a whisper network.

I have a lot of other things I should be working on instead, but I just couldn’t get this idea out of my head, so I started writing an extension for Firefox to see if I could get it to work. This is far outside of my comfort zone, though; it feels like I’m trying to build a car with masking tape and baling wire.

This extension is all about creating “Whisper Network Code Blocks” that can be added to websites and read by other users’ installed extension. Here’s a sample of what such a code block might look like:

<!-- Whisper Network Code Block STARTS -->
  <img src="WNbanner.png" alt="Whisper Network banner" onclick="openTrustLv1Website()">

  <!-- JavaScript code to handle the image click event -->
  <script>
    function openTrustLv1Website() {
      var trustLv1Websites = [
        "https://www.example1.com",
        "https://www.example2.com",
        "https://www.example3.com"
      ];
      var blockLv1Websites = [
        "https://www.evilexample1.com",
        "https://www.evilexample2.com",
        "https://www.evilexample3.com"
      ];
      var trustLv2Websites = [
        "https://www.lv2example1.com",
        "https://www.lv2example2.com",
        "https://www.lv2example3.com"
      ];
      var blockLv2Websites = [
        "https://www.lv2evilexample1.com",
        "https://www.lv2evilexample2.com",
        "https://www.lv2evilexample3.com"
      ];
      var trustLv3Websites = [
        "https://www.lv3example1.com",
        "https://www.lv3example2.com",
        "https://www.lv3example3.com"
      ];
      var blockLv3Websites = [
        "https://www.lv3evilexample1.com",
        "https://www.lv3evilexample2.com",
        "https://www.lv3evilexample3.com"
      ];
      var trustLv4Websites = [
        "https://www.lv4example1.com",
        "https://www.lv4example2.com",
        "https://www.lv4example3.com"
      ];
      var blockLv4Websites = [
        "https://www.lv4evilexample1.com",
        "https://www.lv4evilexample2.com",
        "https://www.lv4evilexample3.com"
      ];
      var trustLv5Websites = [
        "https://www.lv5example1.com",
        "https://www.lv5example2.com",
        "https://www.lv5example3.com"
      ];
      var blockLv5Websites = [
        "https://www.lv5evilexample1.com",
        "https://www.lv5evilexample2.com",
        "https://www.lv5evilexample3.com"
      ];

      var randomIndex = Math.floor(Math.random() * trustLv1Websites.length);
      var randomWebsite = trustLv1Websites[randomIndex];

      // Open the random trusted website in a new tab or window
      window.open(randomWebsite, "_blank");
    }
  </script>
<!-- Whisper Network Code Block ENDS -->

The extension should have a control panel with a series of buttons: TRUST and BLOCK to add sites to your list of trusted and blocked websites; WIDGET would display your code block so that you can copy it into your website editor of choice; LIST displays all the websites currently in your code block so that you can make specific changes, while RANDOM open a random trusted site (from all five trust levels, rather than only showing level 1 trusted sites like in the code block).

The way it’s supposed to work is that, when TRUST or BLOCK are clicked, Trust.js or Block.js runs. In either case, the script is supposed to check a variable in Local Storage (whisperNetworkCode) to determine whether a code block has already been generated. If not, a blank code block is created, the current web address is added to the trustLv1Websites or blockLv1Websites array before saving the code block back to Local Storage. If a code block already exists, it’s retrieved for evaluation: if the site isn’t already at level 1 trusted or blocked status, it’s added to the array. Furthermore, if you’re blocking a site, it’s removed from all of the trust arrays, and if you’re trusting a site, it’s removed from all of the block arrays. Finally, if a trusted website contains a Whisper Network Code Block of its own (a “Neighbor Block” in the code), all of its trusted and blocked websites that are not contradicted by your own level 1 trust/block settings are inherited at one level remove: sites listed in trustLv1Websites in a Neighbor Block are added to your own code block in the trustLv2Websites array, as long as they don’t show up in your blockLv1Websites array. (And so on.) (Level 5 trust and block settings are only of use to the user’s own extension, but I didn’t want to differentiate between code blocks as they’re shown on the website and as they’re used by the browser extension.)

I haven’t tried to implement the LIST or RANDOM buttons yet. The WIDGET button is supposed to generate your Whisper Network Code Block in preformatted text, which you can then copy into your webpage or blog editor or whatever.

Somewhere along the way, though, my files aren’t working the way I expected them to. I’m providing what I’ve got so far below (which I haven’t put on github because I haven’t figured out how to do so, yet).

manifest.json
{
  "manifest_version": 3,
  "name": "Whisper Network",
  "version": "1.0",
  "description": "Adds a browser action icon to the toolbar. Click the button to choose various options related to creating and managing a network of trusted and blocked sites.",
  "homepage_url": "https://github.com/jsnlxndrlv/Whisper-Network/tree/main",
  "icons": {
    "48": "icons/wn-48.png"
  },
  "permissions": [
    "storage",
    "activeTab"
  ],
  "action": {
    "default_icon": "icons/wn-48.png",
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content_script.js"]
    }
  ]
}

popup.html
<html>
<head>
  <title>Whisper Network Popup</title>
</head>
<body>
  <h1>Whisper Network</h1>
  <button id="trustButton">TRUST</button>
  <button id="blockButton">BLOCK</button>
  <button id="randomButton">RANDOM</button>
  <button id="listButton">LIST</button>
  <button id="widgetButton">WIDGET</button>
  <button id="aboutButton">ABOUT</button>

  <script src="popup.js"></script>
</body>
</html>

popup.js
// popup.js

function trustFunction() {
  // Execute Trust.js in the active tab when the TRUST button is clicked
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    var tabId = tabs[0].id;
    chrome.scripting.executeScript({
      target: { tabId: tabId },
      files: ["Trust.js"],
    });
  });
};
function blockFunction() {
  // Execute Block.js in the active tab when the BLOCK button is clicked
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    var tabId = tabs[0].id;
    chrome.scripting.executeScript({
      target: { tabId: tabId },
      files: ["Block.js"],
    });
  });
};
function randomFunction() {
  // Execute Random.js in the active tab when the RANDOM button is clicked
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    var tabId = tabs[0].id;
    chrome.scripting.executeScript({
      target: { tabId: tabId },
      files: ["Random.js"],
    });
  });
};
function listFunction() {
  // Execute List.js in the active tab when the LIST button is clicked
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    var tabId = tabs[0].id;
    chrome.scripting.executeScript({
      target: { tabId: tabId },
      files: ["List.js"],
    });
  });
};
function widgetFunction() {
  // Execute Widget.js in the active tab when the WIDGET button is clicked
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    var tabId = tabs[0].id;
    chrome.scripting.executeScript({
      target: { tabId: tabId },
      files: ["Widget.js"],
    });
  });
};

function aboutFunction() {
  // Open a new tab to a specific web address when the ABOUT button is clicked
  var newTabUrl = "https://github.com/jsnlxndrlv/Whisper-Network/tree/main";
  chrome.tabs.create({ url: newTabUrl });
};

document.addEventListener("DOMContentLoaded", function () {
  document.getElementById("trustButton").addEventListener("click", function () {
    // Execute Trust.js functionality directly
    trustFunction();
  });

  document.getElementById("blockButton").addEventListener("click", function () {
    // Execute Block.js functionality directly
    blockFunction();
  });

  document.getElementById("randomButton").addEventListener("click", function () {
    // Execute Random.js functionality directly
    randomFunction();
  });

  document.getElementById("listButton").addEventListener("click", function () {
    // Execute List.js functionality directly
    listFunction();
  });

  document.getElementById("widgetButton").addEventListener("click", function () {
    // Execute Widget.js functionality directly
    widgetFunction();
  });

  document.getElementById("aboutButton").addEventListener("click", function () {
    // Execute About.js functionality directly
    aboutFunction();
  });
});

content_script.js
// Listen for messages from the background script
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
  if (message.action === "showPopup") {
    // Inject the popup HTML into the current web page
    var popupContainer = document.createElement("div");
    popupContainer.id = "whisperNetworkPopup";
    popupContainer.innerHTML = message.popupHTML;

    // Append the popup container to the body of the web page
    document.body.appendChild(popupContainer);

    // Add event listener to close the popup when clicking outside the popup area
    document.addEventListener("click", function (event) {
      if (!popupContainer.contains(event.target)) {
        popupContainer.style.display = "none";
      }
    });

    // Show the popup
    popupContainer.style.display = "block";
  }
});

// Function to open the popup when the extension button is clicked
function openPopup() {
  // Send a message to the background script to request the popup HTML
  chrome.runtime.sendMessage({ action: "getPopupHTML" });
}

// Function to handle keyboard shortcuts
function handleShortcuts(event) {
  if (event.ctrlKey && event.shiftKey) {
    if (event.key === "T") {
      // Ctrl+Shift+T is pressed, open the TRUST popup
      openPopup();
    } else if (event.key === "B") {
      // Ctrl+Shift+B is pressed, open the BLOCK popup
      openPopup();
    } else if (event.key === "?") {
      // Ctrl+Shift+? is pressed, open the RANDOM popup
      openPopup();
    }
  }
}

// Add event listener to handle keyboard shortcuts
document.addEventListener("keydown", handleShortcuts);

Trust.js

This one scares me. I’m sure there are problems with it.

// Helper function to perform the "inheriting trust" process
function inheritTrust(whisperNetworkCode, neighborTrustArrays, currentBlockArrays) {
  var trustArrays = ["trustLv2Websites", "trustLv3Websites", "trustLv4Websites", "trustLv5Websites"];
  var blockArrays = ["blockLv2Websites", "blockLv3Websites", "blockLv4Websites", "blockLv5Websites"];

  for (var i = 0; i < 4; i++) {
    var trustArray = neighborTrustArrays[i];
    var blockArray = currentBlockArrays[i];

    trustArray.forEach(function (url) {
      if (!blockArray.includes(url)) {
        var targetArray = whisperNetworkCode[trustArrays[i]];
        targetArray.push(url);
      }
    });
  }
}

// Get the current tab's URL
browser.tabs.query({ active: true, currentWindow: true })
  .then(function(tabs) {
    var currentURL = tabs[0].url;

    // Retrieve the Whisper Network Code Block from Local Storage
    var whisperNetworkCode = localStorage.getItem("whisperNetworkCode");

    if (!whisperNetworkCode) {
      // Create an empty version of the Whisper Network Code Block
      whisperNetworkCode = `
        <!-- Whisper Network Code Block STARTS -->
        <img src="WNbanner.png" alt="Whisper Network banner" onclick="openTrustLv1Website()">
      
        <!-- JavaScript code to handle the image click event -->
        <script>
          var trustLv1Websites = [];
          var blockLv1Websites = [];
          var trustLv2Websites = [];
          var blockLv2Websites = [];
          var trustLv3Websites = [];
          var blockLv3Websites = [];
          var trustLv4Websites = [];
          var blockLv4Websites = [];
          var trustLv5Websites = [];
          var blockLv5Websites = [];
          
          function openTrustLv1Website() {
            var randomIndex = Math.floor(Math.random() * trustLv1Websites.length);
            var randomWebsite = trustLv1Websites[randomIndex];
          
            // Open the random trusted website in a new tab or window
            window.open(randomWebsite, "_blank");
          }
        </script>
        <!-- Whisper Network Code Block ENDS -->
      `;
    }

    // Check if the HTML source of the current tab contains a Neighbor Block
    browser.tabs.executeScript({ code: "document.documentElement.innerHTML" })
      .then(function(results) {
        var htmlSource = results[0];
        var hasNeighborBlock = htmlSource.includes("Whisper Network Code Block STARTS");

        if (hasNeighborBlock) {
          // Extract the Neighbor Block's trustLv arrays from the HTML source
          var neighborTrustLvArrays = [];
          for (var i = 1; i <= 5; i++) {
            var regex = new RegExp(`trustLv${i}Websites = \\[([^\\]]+)\\]`);
            var match = regex.exec(htmlSource);
            if (match && match[1]) {
              var urls = match[1].split(",").map(function(url) {
                return url.trim().replace(/['"]/g, ''); // Remove surrounding quotes
              });
              neighborTrustLvArrays.push(urls);
            } else {
              neighborTrustLvArrays.push([]);
            }
          }

          // Perform the "inheriting trust" process
          inheritTrust(whisperNetworkCode, neighborTrustLvArrays, ["blockLv1Websites", "blockLv2Websites", "blockLv3Websites", "blockLv4Websites"]);

          // Perform the second half of "inheriting trust" by adding entries from Neighbor Block's blockLv arrays to our blockLv arrays
          for (var i = 0; i < 4; i++) {
            var blockArray = neighborTrustLvArrays[i];
            var targetArray = whisperNetworkCode["blockLv" + (i + 2) + "Websites"];
            blockArray.forEach(function (url) {
              if (!targetArray.includes(url)) {
                targetArray.push(url);
              }
            });
          }
        } else {
          // Check if the current URL is already in the trustLv1Websites array
          var trustLv1Websites = extractTrustLvWebsites(whisperNetworkCode, 1);
          var isURLTrusted = trustLv1Websites.includes(currentURL);

          if (!isURLTrusted) {
            // Add the current URL to trustLv1Websites array
            trustLv1Websites.push(currentURL);

            // Retrieve the blockLv1Websites, blockLv2Websites, blockLv3Websites, blockLv4Websites, and blockLv5Websites arrays
            var blockLv1Websites = extractBlockLvWebsites(whisperNetworkCode, 1);
            var blockLv2Websites = extractBlockLvWebsites(whisperNetworkCode, 2);
            var blockLv3Websites = extractBlockLvWebsites(whisperNetworkCode, 3);
            var blockLv4Websites = extractBlockLvWebsites(whisperNetworkCode, 4);
            var blockLv5Websites = extractBlockLvWebsites(whisperNetworkCode, 5);

            // Remove the current URL from blockLv1Websites, blockLv2Websites, blockLv3Websites, blockLv4Websites, and blockLv5Websites arrays
            removeURLFromBlockArrays(currentURL, blockLv1Websites);
            removeURLFromBlockArrays(currentURL, blockLv2Websites);
            removeURLFromBlockArrays(currentURL, blockLv3Websites);
            removeURLFromBlockArrays(currentURL, blockLv4Websites);
            removeURLFromBlockArrays(currentURL, blockLv5Websites);

            // Update the trustLv1Websites, blockLv1Websites, blockLv2Websites, blockLv3Websites, blockLv4Websites, and blockLv5Websites arrays in the Whisper Network Code Block
            var updatedWhisperNetworkCode = updateWhisperNetworkCode(whisperNetworkCode, trustLv1Websites, blockLv1Websites, blockLv2Websites, blockLv3Websites, blockLv4Websites, blockLv5Websites);

            // Store the updated Whisper Network Code Block in Local Storage
            localStorage.setItem("whisperNetworkCode", updatedWhisperNetworkCode);
          }
        }
      });
  });

// Helper function to extract trustLvWebsites arrays from the Whisper Network Code Block
function extractTrustLvWebsites(whisperNetworkCode, level) {
  var regex = new RegExp(`trustLv${level}Websites = \\[([^\\]]+)\\]`);
  var match = regex.exec(whisperNetworkCode);
  if (match && match[1]) {
    return match[1].split(",").map(function(url) {
      return url.trim().replace(/['"]/g, ''); // Remove surrounding quotes
    });
  }
  return [];
}

// Helper function to extract blockLvWebsites arrays from the Whisper Network Code Block
function extractBlockLvWebsites(whisperNetworkCode, level) {
  var regex = new RegExp(`blockLv${level}Websites = \\[([^\\]]+)\\]`);
  var match = regex.exec(whisperNetworkCode);
  if (match && match[1]) {
    return match[1].split(",").map(function(url) {
      return url.trim().replace(/['"]/g, ''); // Remove surrounding quotes
    });
  }
  return [];
}

// Helper function to update the Whisper Network Code Block with new trust and block arrays
function updateWhisperNetworkCode(whisperNetworkCode, trustLv1Websites, blockLv1Websites, blockLv2Websites, blockLv3Websites, blockLv4Websites, blockLv5Websites) {
  function updateArrayInCode(arrayName, arrayData) {
    var regex = new RegExp(`${arrayName} = \\[([^\\]]*)\\]`);
    var replacement = `${arrayName} = [${arrayData.map(url => `"${url}"`).join(", ")}]`;
    return whisperNetworkCode.replace(regex, replacement);
  }

  whisperNetworkCode = updateArrayInCode("trustLv1Websites", trustLv1Websites);
  whisperNetworkCode = updateArrayInCode("blockLv1Websites", blockLv1Websites);
  whisperNetworkCode = updateArrayInCode("blockLv2Websites", blockLv2Websites);
  whisperNetworkCode = updateArrayInCode("blockLv3Websites", blockLv3Websites);
  whisperNetworkCode = updateArrayInCode("blockLv4Websites", blockLv4Websites);
  whisperNetworkCode = updateArrayInCode("blockLv5Websites", blockLv5Websites);

  return whisperNetworkCode;
}

// Helper function to remove a URL from an array
function removeURLFromBlockArrays(url, blockArray) {
  var index = blockArray.indexOf(url);
  if (index !== -1) {
    blockArray.splice(index, 1);
  }
}

Block.js
// Get the current tab's URL
browser.tabs.query({ active: true, currentWindow: true })
  .then(function(tabs) {
    var currentURL = tabs[0].url;

    // Retrieve the Whisper Network Code Block from Local Storage
    var whisperNetworkCode = localStorage.getItem("whisperNetworkCode");

    if (!whisperNetworkCode) {
      // Create an empty version of the Whisper Network Code Block
      document.body.style.backgroundColor = "red";
      whisperNetworkCode = `
        <!-- Whisper Network Code Block STARTS -->
        <img src="WNbanner.png" alt="Whisper Network banner" onclick="openTrustLv1Website()">
      
        <!-- JavaScript code to handle the image click event -->
        <script>
          var trustLv1Websites = [];
          var blockLv1Websites = [];
          var trustLv2Websites = [];
          var blockLv2Websites = [];
          var trustLv3Websites = [];
          var blockLv3Websites = [];
          var trustLv4Websites = [];
          var blockLv4Websites = [];
          var trustLv5Websites = [];
          var blockLv5Websites = [];
          
          function openTrustLv1Website() {
            var randomIndex = Math.floor(Math.random() * trustLv1Websites.length);
            var randomWebsite = trustLv1Websites[randomIndex];
          
            // Open the random trusted website in a new tab or window
            window.open(randomWebsite, "_blank");
          }
        </script>
        <!-- Whisper Network Code Block ENDS -->
      `;
    }

    // Check if the current URL is already in the blockLv1Websites array
    var blockLv1Websites = extractBlockLv1Websites(whisperNetworkCode);
    var isURLBlocked = blockLv1Websites.includes(currentURL);

    if (!isURLBlocked) {
      // Add the current URL to blockLv1Websites array
      blockLv1Websites.push(currentURL);

      // Retrieve the trustLv1Websites, trustLv2Websites, trustLv3Websites, trustLv4Websites, and trustLv5Websites arrays
      var trustLv1Websites = extractTrustLvWebsites(whisperNetworkCode, 1);
      var trustLv2Websites = extractTrustLvWebsites(whisperNetworkCode, 2);
      var trustLv3Websites = extractTrustLvWebsites(whisperNetworkCode, 3);
      var trustLv4Websites = extractTrustLvWebsites(whisperNetworkCode, 4);
      var trustLv5Websites = extractTrustLvWebsites(whisperNetworkCode, 5);

      // Remove the current URL from trustLv1Websites, trustLv2Websites, trustLv3Websites, trustLv4Websites, and trustLv5Websites arrays
      removeURLFromTrustArrays(currentURL, trustLv1Websites);
      removeURLFromTrustArrays(currentURL, trustLv2Websites);
      removeURLFromTrustArrays(currentURL, trustLv3Websites);
      removeURLFromTrustArrays(currentURL, trustLv4Websites);
      removeURLFromTrustArrays(currentURL, trustLv5Websites);

      // Update the blockLv1Websites, trustLv1Websites, trustLv2Websites, trustLv3Websites, trustLv4Websites, and trustLv5Websites arrays in the Whisper Network Code Block
      var updatedWhisperNetworkCode = updateWhisperNetworkCode(whisperNetworkCode, blockLv1Websites, trustLv1Websites, trustLv2Websites, trustLv3Websites, trustLv4Websites, trustLv5Websites);

      // Store the updated Whisper Network Code Block in Local Storage
      localStorage.setItem("whisperNetworkCode", updatedWhisperNetworkCode);
    }
  });

// ... (rest of the helper functions from the previous provided source remain unchanged)


// Helper function to extract blockLv1Websites array from the Whisper Network Code Block
function extractBlockLv1Websites(whisperNetworkCode) {
  var startIndex = whisperNetworkCode.indexOf("var blockLv1Websites = [");
  var endIndex = whisperNetworkCode.indexOf("];", startIndex);
  var blockLv1WebsitesString = whisperNetworkCode.slice(startIndex, endIndex + 1);
  return eval(blockLv1WebsitesString);
}

// Helper function to extract trustLvWebsites arrays from the Whisper Network Code Block
function extractTrustLvWebsites(whisperNetworkCode, level) {
  var startIndex = whisperNetworkCode.indexOf("var trustLv" + level + "Websites = [");
  var endIndex = whisperNetworkCode.indexOf("];", startIndex);
  var trustLvWebsitesString = whisperNetworkCode.slice(startIndex, endIndex + 1);
  return eval(trustLvWebsitesString);
}

// Helper function to remove a URL from a trustLvWebsites array
function removeURLFromTrustArrays(url, trustLvWebsitesArray) {
  var index = trustLvWebsitesArray.indexOf(url);
  if (index !== -1) {
    trustLvWebsitesArray.splice(index, 1);
  }
}

// Helper function to update the Whisper Network Code Block with the modified arrays
function updateWhisperNetworkCode(whisperNetworkCode, blockLv1Websites, trustLv1Websites, trustLv2Websites, trustLv3Websites, trustLv4Websites, trustLv5Websites) {
  whisperNetworkCode = whisperNetworkCode.replace(/var blockLv1Websites = \[.*?\];/, "var blockLv1Websites = " + JSON.stringify(blockLv1Websites) + ";");
  whisperNetworkCode = whisperNetworkCode.replace(/var trustLv1Websites = \[.*?\];/, "var trustLv1Websites = " + JSON.stringify(trustLv1Websites) + ";");
  whisperNetworkCode = whisperNetworkCode.replace(/var trustLv2Websites = \[.*?\];/, "var trustLv2Websites = " + JSON.stringify(trustLv2Websites) + ";");
  whisperNetworkCode = whisperNetworkCode.replace(/var trustLv3Websites = \[.*?\];/, "var trustLv3Websites = " + JSON.stringify(trustLv3Websites) + ";");
  whisperNetworkCode = whisperNetworkCode.replace(/var trustLv4Websites = \[.*?\];/, "var trustLv4Websites = " + JSON.stringify(trustLv4Websites) + ";");
  whisperNetworkCode = whisperNetworkCode.replace(/var trustLv5Websites = \[.*?\];/, "var trustLv5Websites = " + JSON.stringify(trustLv5Websites) + ";");
  return whisperNetworkCode;
}

Widget.js
// Get the Whisper Network Code Block from Local Storage
var whisperNetworkCode = localStorage.getItem("whisperNetworkCode");

// Format the code as preformatted text
var preformattedCode = "<pre>" + escapeHTML(whisperNetworkCode) + "</pre>";

// Inject the preformatted code into the popup
document.getElementById("codeContainer").innerHTML = preformattedCode;

// Function to escape special characters in the code
function escapeHTML(html) {
  return html.replace(/&/g, "&amp;")
             .replace(/</g, "&lt;")
             .replace(/>/g, "&gt;")
             .replace(/"/g, "&quot;")
             .replace(/'/g, "&#039;");
}

I’m far enough along now that I don’t want to abandon this, but I’m in way over my head. I’d like to get back to my IF projects, so before I rake myself over the coals of Stack Exchange, I thought I’d check in with folks here.

If anybody knows this stuff enough to see what I’m doing wrong, I’d really appreciate the guidance. I feel like I’ve gotta be messing up the permissions or the content_script.js code to begin with. At this point I can only guess what kind of problems lie in wait in the Trust.js and Block.js scripts, as I don’t think they’re being run successfully.

If you’ve scrolled this far, thanks for reviewing my post. I know this is a little out of left field compared to our usual IF discussion, but at this point I need all the help I can get.

Thanks again!

1 Like

I’ve been thinking along these lines too. It’s quite a treat to hear I’m not alone!

I hadn’t yet got as far as you, ie: considering what an implementation might look like. My initial gut instinct is to incorporate JSONFeed somehow. I’ve been playing with that recently.

So our tech stack might be at odds. Nevertheless, I would be glad to help. I recognize this sort of thing needs some experimentation. You never know quite where it might lead.

I’m comfortable with Git repos, software packaging, licencing, etc. Maybe that could be a first step, to get your code to a place where it can be shared by others.

By all means DM me, but it might be fun to let the discussion roll on this thread for a while.

2 Likes

The theoretical idea is great! Just today I thought that search engines (not only google) are a privacy nightmare. I’m not sure if I understood you correctly but it seems to me that you make finding other sites more private (or aim it).

If I understand correctly this is a problem in the fediverse, too. Fediverse = high privacy but very little chance to find nodes beyond hashtags.

Unfortunately I don’t comprehend the tech aspects.

Webrings linked sites based on topics. That seems orthogonal to issues of trust.

Any shared forum on the Internet has to think about trust issues, or else drown in spam.

The first thing I did when I saw this post was to google “fediverse webring” and “decentralized webring”. I found some webrings of fediverse people. As Jason said, they used the model of a central maintainer who could approve or deny add-me requests. (As far as I could tell. I didn’t look very far in.)

This isn’t necessarily a mistake. “Decentralized”, in the current era, tends to mean “A lot of resources, each with its own ‘central’ administrator.” A bunch of interoperating web-rings-or-whatever would fit that.

(Maybe the “ring” metaphor is just not right any more? The whole point of an OG-1990s webring was that it was a linear trail. One arrow goes forward, one arrow goes back, no choices. In a federated model, you should be able to follow my trail but then change tracks to someone else’s if you like it better.)

I’m afraid I can’t tell if your TRUST/BLOCK idea is workable or not. I just don’t have any experience with this stuff.

(I’ve been using Mastodon heavily for six months but I still don’t really understand how server defederation works! Sigh.)

2 Likes

I’ve reread your proposal again several times. And I think I understand the technological aspects now (partially).

If Javascript/browser extension fails, you could implement it perhaps as HTML? Or is HTML too static?

Or in C/Python/…!

I still don’t understand the levels.

Edit: IMHO you should drop the blocks completely. It’s enough to connect to trusted and interesting sites. No need to tell others what to NOT visit.