Bitcointalk Banned Users Checker

Checks if a user is banned on Bitcointalk.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         Bitcointalk Banned Users Checker
// @namespace    http://tampermonkey.net/
// @version      1.1.1
// @description  Checks if a user is banned on Bitcointalk.
// @author       promise444c5
// @match        https://bitcointalk.org/index.php?action=profile*
// @match        https://bitcointalk.org/index.php?topic=*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @connect      loyce.club
// ==/UserScript==

(function () {
    "use strict";
  
    const BANNED_LIST_URL = "https://loyce.club/bans/usernames.txt";
    const CACHE_KEY_DATA = "bannedUsersData";
    const CACHE_KEY_TIMESTAMP = "bannedUsersTimestamp";
    const CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // cache for 1 day  (24 hours)
  
    let bannedUsers = [];
    let scriptError = false;
  
    function parseBannedUsers(text) {
      const users = [];
      if (!text) return users;
  
      text.split("\n").forEach((line) => {
        const trimmedLine = line.trim();
        if (trimmedLine) {
          const lastColonIndex = trimmedLine.lastIndexOf(":");
          if (lastColonIndex !== -1) {
            const userId = trimmedLine.substring(0, lastColonIndex).trim();
            const username = trimmedLine.substring(lastColonIndex + 1).trim();
            users.push({ username, userId });
          } else {
            console.warn(`Bitcointalk Ban Checker: Skipping malformed line: ${trimmedLine}`);
          }
        }
      });
      return users;
    }
  
    function applyBan() {
      if (scriptError || bannedUsers.length === 0) {
        console.log(
          "Bitcointalk Ban Checker: Skipping application due to error or empty list."
        );
        return;
      }
  
      console.log(
        `Bitcointalk Ban Checker: Applying Ban on ${bannedUsers.length} banned users.`
      );
      const currentUrl = window.location.href;
      const isProfilePage = currentUrl.includes("action=profile");
      const isThreadPage = currentUrl.includes("topic=");
  
      // Add CSS style to the page
      const style = document.createElement("style");
      style.textContent = `
            .banned-user-text {
              text-decoration: line-through;
              color: red;
            }
      
            .banned-label {
              background-color: red;
              color: white;
              font-size: 10px;
              padding: 1px 3px;
              border-radius: 3px;
              margin-left: 5px;
              font-weight: bold;
              display: inline-block;
              vertical-align: middle;
            }
          `;
      document.head.appendChild(style);
  
      if (isProfilePage) {
        console.log("Bitcointalk Ban Checker: Running on profile page.");
        let profileUsernameElement = null;
        // Find the 'Name:' cell and get the next sibling cell which contains the username
        document.querySelectorAll("td.windowbg table td").forEach((td) => {
          const boldElement = td.querySelector("b");
          if (boldElement && boldElement.textContent.trim() === "Name:") {
            profileUsernameElement = td.nextElementSibling;
            console.log(
              "Bitcointalk Ban Checker: Found potential username TD element."
            );
          }
        });
  
        if (profileUsernameElement) {
          let profileUsername = profileUsernameElement.textContent.trim();
          console.log(
            `Bitcointalk Ban Checker: Checking profile username: ${profileUsername}`
          );
  
          // Check if the username exists in the bannedUsers array
          const isBanned = bannedUsers.find(
            (user) => user.username === profileUsername
          );
  
          if (isBanned) {
            let banMessage = `User ${profileUsername} is listed as banned.`;
  
            // Create and insert the ban status message below the username row
            let banStatusElement = document.createElement("div");
            banStatusElement.style.color = "red";
            banStatusElement.style.fontWeight = "bold";
            banStatusElement.style.marginTop = "5px";
            banStatusElement.textContent = banMessage;
  
            let usernameRow = profileUsernameElement.closest("tr");
            if (usernameRow && usernameRow.parentNode) {
              let newRow = document.createElement("tr");
              let newCell = document.createElement("td");
              newCell.colSpan = 2;
              newCell.appendChild(banStatusElement);
              newRow.appendChild(newCell);
              usernameRow.parentNode.insertBefore(
                newRow,
                usernameRow.nextSibling
              );
              console.log(
                "Bitcointalk Ban Checker: Inserted ban status message row."
              );
            } else {
              console.warn(
                "Bitcointalk Ban Checker: Could not find username row to insert message."
              );
            }
  
            // Check if label already exists to prevent duplicates on potential re-runs (though unlikely on profile)
            if (!profileUsernameElement.querySelector(".banned-label")) {
              const bannedLabel = document.createElement("span");
              bannedLabel.textContent = "BANNED";
              bannedLabel.classList.add("banned-label");
              // Append the label to the TD containing the username
              profileUsernameElement.appendChild(bannedLabel);
              console.log(
                "Bitcointalk Ban Checker: Appended BANNED label to username TD."
              );
              // The following lines attempt to wrap the text and re-append the label,
              profileUsernameElement.childNodes[0].nodeValue =
                profileUsernameElement.childNodes[0].nodeValue + " "; // Add space before label - This assumes first child is text node
              profileUsernameElement.innerHTML = `<span class="banned-user-text">${profileUsername}</span>`; // Wrap text - This overwrites existing content including the label just added
              profileUsernameElement.appendChild(bannedLabel);
            }
          } else {
            console.log(
              `Bitcointalk Ban Checker: User ${profileUsername} is not listed as banned.`
            );
          }
        } else {
          console.log(
            "Bitcointalk Ban Checker: Could not find username element on profile page using the 'Name:' label."
          );
        }
      } else if (isThreadPage) {
        console.log("Bitcointalk Ban Checker: Running on thread page.");
        function checkBannedUsersOnThread() {
          const postElements = document.querySelectorAll(".windowbg, .windowbg2");
          let bannedFound = 0;
  
          postElements.forEach((post) => {
            const usernameElement = post.querySelector(".poster_info b a");
            if (!usernameElement) return;
  
            // Check if style already applied to prevent redundant checks/updates
            if (usernameElement.style.textDecoration === "line-through") return;
  
            const username = usernameElement.textContent.trim();
  
            // Check if the username exists in the bannedUsers array
            const isBanned = bannedUsers.find(
              (user) => user.username === username
            );
  
            if (isBanned) {
              // Apply styles directly to the <a> tag
              usernameElement.style.textDecoration = "line-through";
              usernameElement.style.color = "red";
  
              // create a label next to the username link
              if (!usernameElement.parentNode.querySelector(".banned-label")) {
                const bannedLabel = document.createElement("span");
                bannedLabel.textContent = "BANNED";
                bannedLabel.classList.add("banned-label");
                usernameElement.parentNode.insertBefore(
                  bannedLabel,
                  usernameElement.nextSibling
                );
                bannedFound++;
                console.log(
                  `Bitcointalk Ban Checker: Added BANNED label for ${username}.`
                );
              }
            }
          });
          if (bannedFound > 0) {
            console.log(
              `Bitcointalk Ban Checker: Found ${bannedFound} banned occurence`
            );
          }
        }
  
        // Initial check
        checkBannedUsersOnThread();
      }
    }
  
    /*
     ** Fetch and cache list,
     ** Used in the main script execution
     */
    const fetchAndCacheList = () => {
      console.log("Bitcointalk Ban Checker: Fetching fresh banned users list...");
  
      //Modified header
      const reqHeader = {
        "User-Agent": "UserScript/1.0",
        Accept: "text/plain",
        "Accept-Language": "en",
        Referer: "",
      };
  
      GM_xmlhttpRequest({
        method: "GET",
        url: BANNED_LIST_URL,
        headers: reqHeader,
        timeout: 5000, // 5 seconds timeout
        onload: (response) => {
          if (response.status >= 200 && response.status < 300) {
            const fetchedText = response.responseText;
            bannedUsers = parseBannedUsers(fetchedText);
            GM_setValue(CACHE_KEY_DATA, fetchedText); // Store raw text
            GM_setValue(CACHE_KEY_TIMESTAMP, Date.now());
            console.log(
              `Bitcointalk Ban Checker: Successfully fetched and cached ${bannedUsers.length} users.`
            );
            applyBan();
          } else {
            console.error(
              `Bitcointalk Ban Checker: Failed to fetch list. Status: ${response.status}`
            );
            scriptError = true;
            // use stale cache if available?
            applyBan();
          }
        },
        onerror: function (error) {
          console.error(
            "Bitcointalk Ban Checker: Network error fetching list.",
            error
          );
          scriptError = true;
        },
      });
    };
  
    /* --- Main Script Execution ---*/
    const cachedTimestamp = GM_getValue(CACHE_KEY_TIMESTAMP, 0);
    const cachedData = GM_getValue(CACHE_KEY_DATA, null);
    const now = Date.now();
  
    if (cachedData && now - cachedTimestamp < CACHE_DURATION_MS) {
      console.log("Bitcointalk Ban Checker: Using cached banned users list.");
      bannedUsers = parseBannedUsers(cachedData);
      applyBan();
    } else {
      if (cachedData) {
        console.log("Bitcointalk Ban Checker: Cache expired, fetching new list.");
        // Use stale data immediately while fetching in background
        bannedUsers = parseBannedUsers(cachedData);
        applyBan();
        fetchAndCacheList(); // Fetch new list in background
      } else {
        console.log("Bitcointalk Ban Checker: No cache found, fetching list.");
        fetchAndCacheList(); // Fetch list
      }
    }
  })();