upvote
HEH... I'm sorry man but I truly don't understand what point you're trying to make, other than change the subject and get nasty.

You take care now.

reply
The trick to not be confused is to read more than the title of the article.
reply
It's a shame that there's no way to block obnoxious people on HN.

I think I'll ask codex to write me a Chrome extension to censor you. :)

EDIT: Done!

(() => { "use strict";

  const BLOCKED_USER = "bopbopbop7";

  // -------- helpers --------

  /** True if the node (or its descendants) contain a user link matching blocked user */
  function containsBlockedUserLink(root) {
    if (!root || !(root instanceof Element)) return false;
    const sel = `a[href^="user?id="], a[href*="user?id="]`;
    const links = root.querySelectorAll(sel);
    for (const a of links) {
      const href = a.getAttribute("href") || "";
      // HN uses relative href like "user?id=pg"
      // Algolia uses full/relative links; check query portion.
      if (href.includes(`user?id=${BLOCKED_USER}`)) return true;
      if ((a.textContent || "").trim() === BLOCKED_USER && href.includes("user?id=")) return true;
    }
    return false;
  }

  /** Remove the closest HN listing block (table row pairs) for a story */
  function removeHNStoryFromListing(anchorUserLink) {
    // On HN listings, a story is typically 2 consecutive <tr>:
    // 1) title row (class="athing"), 2) subtext row.
    const userTr = anchorUserLink.closest("tr");
    if (!userTr) return;

    // If we are in the subtext row, the associated title row is usually previousElementSibling
    // The title row has class "athing".
    const maybeTitleTr = userTr.previousElementSibling;
    const titleTr = maybeTitleTr && maybeTitleTr.classList && maybeTitleTr.classList.contains("athing")
      ? maybeTitleTr
      : userTr.classList && userTr.classList.contains("athing")
        ? userTr
        : null;

    if (titleTr) {
      const subtextTr = titleTr.nextElementSibling;
      titleTr.remove();
      if (subtextTr && subtextTr.tagName === "TR") subtextTr.remove();

      // Sometimes there is a spacing row after; remove if it's just spacing
      const spacer = (subtextTr && subtextTr.nextElementSibling) || null;
      if (spacer && spacer.tagName === "TR" && spacer.textContent.trim() === "") {
        spacer.remove();
      }
    } else {
      // Fallback: remove just the row containing the user link
      userTr.remove();
    }
  }

  /** Collapse/remove comments by the blocked user on item pages */
  function collapseHNComment(anchorUserLink) {
    // HN comments are in <tr class="athing comtr"> (or similar)
    const comtr = anchorUserLink.closest("tr.athing.comtr, tr.comtr");
    if (!comtr) return;

    // Remove the comment row plus the following "spacer" row if present
    const next = comtr.nextElementSibling;
    comtr.remove();
    if (next && next.tagName === "TR" && next.textContent.trim() === "") {
      next.remove();
    }
  }

  /** Algolia results: remove the result item container */
  function removeAlgoliaResult(anchorUserLink) {
    // Algolia HN search commonly uses .item-title-and-infos or .Story or .Comment containers.
    // We'll just walk up to a reasonable container.
    const container =
      anchorUserLink.closest("li, .item, .Story, .Comment, .SearchResults__item, .search-result, article, .result") ||
      anchorUserLink.parentElement;

    if (container) container.remove();
  }

  function handleUserLink(a) {
    const href = a.getAttribute("href") || "";
    const isBlocked =
      href.includes(`user?id=${BLOCKED_USER}`) || (a.textContent || "").trim() === BLOCKED_USER;

    if (!isBlocked) return;

    const host = location.hostname;

    if (host === "news.ycombinator.com") {
      // Distinguish listing pages vs item pages by presence of "item?id="
      const isItemPage = location.pathname === "/item";
      if (isItemPage) {
        collapseHNComment(a);
        // Also on item page: if OP is blocked, remove the top submission block.
        // We can try removing the whole "athing" story block if the subtext shows blocked user.
        const topStoryTr = document.querySelector("tr.athing");
        if (topStoryTr && containsBlockedUserLink(topStoryTr.nextElementSibling)) {
          topStoryTr.remove();
          const sub = topStoryTr.nextElementSibling;
          if (sub && sub.tagName === "TR") sub.remove();
        }
      } else {
        removeHNStoryFromListing(a);
      }
    } else if (host === "hn.algolia.com") {
      removeAlgoliaResult(a);
    }
  }

  function scanAndRemove(root = document) {
    const links = root.querySelectorAll(`a[href*="user?id=${BLOCKED_USER}"]`);
    for (const a of links) handleUserLink(a);

    // Extra safety: sometimes the link text is present but href format differs.
    // Catch those too.
    const maybeTextLinks = root.querySelectorAll(`a`);
    for (const a of maybeTextLinks) {
      if ((a.textContent || "").trim() === BLOCKED_USER && (a.getAttribute("href") || "").includes("user?id=")) {
        handleUserLink(a);
      }
    }
  }

  // Initial sweep
  scanAndRemove(document);

  // Keep it working with infinite scroll / dynamic loads
  const obs = new MutationObserver((mutations) => {
    for (const m of mutations) {
      for (const node of m.addedNodes) {
        if (node instanceof Element) scanAndRemove(node);
      }
    }
  });

  obs.observe(document.documentElement, { childList: true, subtree: true });
})();
reply
Speaking of obnoxious
reply