Greasy Fork

Greasy Fork is available in English.

Show account names (all locales)

Replaces all character names with account names on any esologs locale (e.g., ru.esologs.com)

// ==UserScript==
// @name        Show account names (all locales)
// @namespace   io.inp
// @match       https://*.esologs.com/reports/*
// @grant       none
// @version     1.3
// @author      Xandaros (tweaked)
// @license     BSD2
// @run-at      document-end
// @description Replaces all character names with account names on any esologs locale (e.g., ru.esologs.com)
// ==/UserScript==

(function() {
  "use strict";

  // Replace character names with account display names inside a jQuery-like wrapper or Node
  function replaceNames(nodeOr$) {
    const $root = window.jQuery ? window.jQuery(nodeOr$) : null;
    const nodeList = $root ? $root.contents().toArray() : (nodeOr$?.childNodes ? Array.from(nodeOr$.childNodes) : []);

    for (const inner of nodeList) {
      if (!inner) continue;

      // Only process text nodes; skip anything inside script/style/textarea/input
      if (inner.nodeType === Node.TEXT_NODE && inner.parentElement) {
        const tag = inner.parentElement.tagName;
        if (tag === "SCRIPT" || tag === "STYLE" || tag === "TEXTAREA" || tag === "INPUT") {
          continue;
        }

        const txt = inner.textContent;
        if (!txt || !Array.isArray(window.players)) continue;

        let out = txt;
        for (const player of window.players) {
          if (!player) continue;
          if (player.type === "NPC" || player.anonymous) continue;
          if (!player.name || !player.displayName) continue;

          // Avoid re-replacing if we've already swapped in the display name
          if (out.includes(player.displayName)) continue;

          // Plain string replaceAll. Names on logs are not localized, so this works across locales.
          out = out.replaceAll(player.name, player.displayName);
        }

        if (out !== txt) inner.textContent = out;
      }

      // Recurse
      if (inner.childNodes && inner.childNodes.length) replaceNames(inner);
    }
  }

  // Run once players are available, then observe DOM changes
  function initWhenReady() {
    if (Array.isArray(window.players) && window.players.length > 0) {
      // Initial sweep
      replaceNames(document.documentElement);

      // Observe changes so dynamic UI updates also get rewritten
      const obs = new MutationObserver((mutations) => {
        for (const m of mutations) {
          if (m.type === "childList") {
            m.addedNodes.forEach((n) => replaceNames(n));
          } else if (m.type === "characterData" && m.target?.parentElement) {
            replaceNames(m.target.parentElement);
          }
        }
      });

      obs.observe(document.documentElement, {
        childList: true,
        characterData: true,
        subtree: true
      });
      return true;
    }
    return false;
  }

  // Try immediately, then retry a few times in case players loads late
  if (!initWhenReady()) {
    const maxTries = 30;
    let tries = 0;
    const timer = setInterval(() => {
      tries++;
      if (initWhenReady() || tries >= maxTries) clearInterval(timer);
    }, 500);
  }
})();