☰

leoonjoo script

Chat commands for agma.io: /leo level, coins, gold, fps, ping, buyskins, help. Runs only when you press Enter in the chat, so no lag.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         leoonjoo script
// @namespace    https://agma.io/
// @version      3.1
// @description  Chat commands for agma.io: /leo level, coins, gold, fps, ping, buyskins, help. Runs only when you press Enter in the chat, so no lag.
// @match        https://agma.io/*
// @match        https://www.agma.io/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  var MODE = 'send';

  var YT_NAME = 'Leoo magic';
  var YT_LINK = 'https://www.youtube.com/results?search_query=Leoo+magic';

  var LEVEL_MESSAGE = 'Your level is: {level} 🏴';
  var COINS_MESSAGE = 'Your coins are: {coins} 🏴';
  var GOLD_MESSAGE = 'Your Gold Member days left: {gold} 🏴';
  var NO_GOLD_MESSAGE = 'You are not a Gold Member 🏴';
  var FPS_MESSAGE = 'Your FPS: {fps} 🏴';
  var PING_MESSAGE = 'Your ping: {ping} ms 🏴';
  var SKINS_MESSAGE = 'Your custom skins: {skins} 🏴';
  var HELP_MESSAGE = 'Commands: /leo level, coins, gold, fps, ping, buyskins 🏴';

  var LEVEL_COMMAND = /^\/(?:leo\s+)?(?:level|lvl)\s*$/i;
  var COINS_COMMAND = /^\/(?:leo\s+)?(?:coins|coin|monedhat)\s*$/i;
  var GOLD_COMMAND = /^\/(?:leo\s+)?gold\s*$/i;
  var FPS_COMMAND = /^\/(?:leo\s+)?fps\s*$/i;
  var PING_COMMAND = /^\/(?:leo\s+)?ping\s*$/i;
  var SKINS_COMMAND = /^\/(?:leo\s+)?(?:buyskins|skins)\s*$/i;
  var HELP_COMMAND = /^\/(?:leo\s+)?(?:help|komandat)\s*$/i;
  var DEBUG_COMMAND = /^\/(?:leo\s+)?debug\s*$/i;

  function readNumber(id) {
    var el = document.getElementById(id);
    if (!el) return null;
    var digits = (el.innerText || el.textContent || '').replace(/[^\d]/g, '');
    return digits ? parseInt(digits, 10) : null;
  }

  var GOLD_RE = /(\d+)\s*days?\s*left\s*of\s*gold\s*member/gi;
  var SKIP_IDS = { canvas: 1, minimap: 1, leaderboard: 1 };
  var goldDays = null;
  var welcomeSeen = false;
  var lastUser = null;
  var recentTexts = [];
  var drawCount = 0;
  var chatDrawImage = 0;

  function hookText(ctx) {
    if (!ctx || ctx.__leoText) return;
    ctx.__leoText = true;

    ['fillText', 'strokeText'].forEach(function (name) {
      var original = ctx[name];
      if (typeof original !== 'function') return;

      ctx[name] = function (text) {
        try {
          if (typeof text === 'string') {
            drawCount++;
            recentTexts.push(text);

            if (recentTexts.length > 40) {
              recentTexts.shift();
            }

            if (text.indexOf('elcome') !== -1 || text.indexOf('gma') !== -1) {
              var PHRASE = 'welcomebacktoagma';
              var raw = recentTexts.slice(-10).join('');
              var joined = raw.replace(/\s+/g, '').toLowerCase();
              var curLen = text.replace(/\s+/g, '').length;
              var at = joined.lastIndexOf(PHRASE);

              if (at !== -1 && at + PHRASE.length > joined.length - curLen) {
                welcomeSeen = true;

                var userRe = /welcome\s*back\s*to\s*agma\s*,?\s*([^\s\[\],]+)/gi;
                var um;
                var user = null;

                while ((um = userRe.exec(raw)) !== null) {
                  user = um[1];
                }

                if (user !== null) {
                  if (user !== lastUser) {
                    goldDays = null;
                  }
                  lastUser = user;
                }
              }
            }

            if (text.indexOf('ember') !== -1) {
              var all = recentTexts.join('');
              var m;
              var last = null;

              GOLD_RE.lastIndex = 0;

              while ((m = GOLD_RE.exec(all)) !== null) {
                last = m[1];
              }

              if (last !== null) {
                goldDays = parseInt(last, 10);
              }
            }
          }
        } catch (err) {}

        return original.apply(this, arguments);
      };
    });
  }

  try {
    var originalGetContext = HTMLCanvasElement.prototype.getContext;

    HTMLCanvasElement.prototype.getContext = function (type) {
      var ctx = originalGetContext.apply(this, arguments);

      try {
        if (ctx && type === '2d' && !SKIP_IDS[this.id]) {
          hookText(ctx);
        }
      } catch (err) {}

      return ctx;
    };
  } catch (err) {}

  function hookChatCanvas() {
    var canvas = document.getElementById('chtCanvas');

    if (!canvas) return false;

    var ctx = canvas.getContext('2d');

    if (!ctx) return true;

    if (ctx.__leoChat) return true;

    ctx.__leoChat = true;
    hookText(ctx);

    var original = ctx.drawImage;

    if (typeof original === 'function') {
      ctx.drawImage = function () {
        chatDrawImage++;
        return original.apply(this, arguments);
      };
    }

    return true;
  }

  var toast = null;
  var hideTimer = null;

  function showToast(text, ms) {
    if (!toast) {
      toast = document.createElement('div');

      toast.style.cssText =
        'position:fixed;top:16px;left:50%;transform:translateX(-50%);' +
        'z-index:2147483647;padding:10px 20px;border-radius:10px;' +
        'border:2px solid #e41e20;background:#111;color:#fff;' +
        'font:600 16px/1.4 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;' +
        'pointer-events:none;';

      document.body.appendChild(toast);
    }

    toast.textContent = text;
    toast.style.display = 'block';

    clearTimeout(hideTimer);

    hideTimer = setTimeout(function () {
      toast.style.display = 'none';
    }, ms || 4000);
  }

  function setField(field, text) {
    field.value = text;
  }

  function stopEvent(e) {
    e.preventDefault();
    e.stopPropagation();
    e.stopImmediatePropagation();
  }

  function debugText() {
    return 'Chat canvas: ' +
      (canvasDone ? 'connected' : 'NOT connected') +
      ' | texts captured: ' + drawCount +
      ' | drawImage chat: ' + chatDrawImage +
      ' | gold: ' + goldDays +
      ' | user: ' + lastUser +
      ' | last text: ' +
      (recentTexts.slice(-8).join(' | ') || '(nothing)');
  }

  function onKeyDown(e) {
    if (e.key !== 'Enter') return;

    var box = e.target;
    var typed = (box.value || '').trim();

    if (typed.charAt(0) !== '/') return;

    var text = null;
    var missing = null;
    var failText = null;

    if (LEVEL_COMMAND.test(typed)) {
      var level = readNumber('level');

      if (level === null) {
        missing = 'level';
        failText = 'Level not found, refresh the page 🏴';
      } else {
        text = LEVEL_MESSAGE.replace('{level}', String(level));
      }

    } else if (COINS_COMMAND.test(typed)) {
      var coins = readNumber('coinsDash');

      if (coins === null) {
        missing = 'coins';
        failText = 'Coins not found, refresh the page 🏴';
      } else {
        text = COINS_MESSAGE.replace(
          '{coins}',
          coins.toLocaleString('en-US')
        );
      }

    } else if (GOLD_COMMAND.test(typed)) {
      if (goldDays !== null) {
        text = GOLD_MESSAGE.replace('{gold}', String(goldDays));
      } else if (welcomeSeen) {
        text = NO_GOLD_MESSAGE;
      } else {
        missing = 'Gold Member days';
        failText = 'Gold info not found, join the game and try again 🏴';
      }

    } else if (FPS_COMMAND.test(typed)) {
      var fps = readNumber('fps');

      if (fps === null) {
        missing = 'FPS';
        failText =
          'FPS not found, turn on FPS / Ping / Stats in settings 🏴';
      } else {
        text = FPS_MESSAGE.replace('{fps}', String(fps));
      }

    } else if (PING_COMMAND.test(typed)) {
      var ping = readNumber('ping');

      if (ping === null) {
        missing = 'ping';
        failText =
          'Ping not found, turn on FPS / Ping / Stats in settings 🏴';
      } else {
        text = PING_MESSAGE.replace('{ping}', String(ping));
      }

    } else if (SKINS_COMMAND.test(typed)) {
      var pane = document.getElementById('skinsCustom');

      if (!pane) {
        missing = 'skins';
        failText =
          'Skins not loaded, open the skin shop once and try again 🏴';
      } else {
        var skinCount =
          pane.querySelectorAll('img[id^="skinCustomImg"]').length;

        text = SKINS_MESSAGE.replace(
          '{skins}',
          String(skinCount)
        );
      }

    } else if (HELP_COMMAND.test(typed)) {
      text = HELP_MESSAGE;

    } else if (DEBUG_COMMAND.test(typed)) {
      stopEvent(e);
      setField(box, '');
      showToast(debugText(), 12000);
      return;

    } else {
      return;
    }

    if (missing && MODE === 'send') {
      setField(box, failText);
      return;
    }

    if (missing) {
      stopEvent(e);
      setField(box, '');

      if (GOLD_COMMAND.test(typed)) {
        showToast(
          'Could not find your Gold Member days. ' +
          debugText(),
          12000
        );
      } else {
        var hint =
          (FPS_COMMAND.test(typed) || PING_COMMAND.test(typed))
            ? ' Turn on "FPS / Ping / Stats" in the settings and try again.'
            : ' Refresh the page and try again.';

        showToast(
          'Could not find your ' +
          missing +
          '.' +
          hint
        );
      }

      return;
    }

    if (MODE === 'send') {
      setField(box, text);
      return;
    }

    stopEvent(e);
    setField(box, '');
    showToast(text);
  }

  document.addEventListener(
    'keydown',
    function (e) {
      if (e.key !== 'Enter') return;

      var t = e.target;

      if (!t || t.id !== 'chtbox') return;

      onKeyDown(e);
    },
    true
  );

  var COMMAND_LIST = [
    ['/leo level', 'shows your level'],
    ['/leo coins', 'shows your coins'],
    ['/leo gold', 'shows your Gold Member days'],
    ['/leo fps', 'shows your FPS'],
    ['/leo ping', 'shows your ping'],
    ['/leo buyskins', 'shows your custom skins'],
    ['/leo help', 'shows the command list']
  ];

  var leooPanel = null;

  function getPanel() {
    if (leooPanel) return leooPanel;

    var FONT =
      'Ubuntu,"Open Sans",system-ui,-apple-system,Segoe UI,Roboto,sans-serif';

    var panel = document.createElement('div');

    panel.id = 'leoo-magic-panel';

    panel.style.cssText =
      'position:fixed;display:none;z-index:2147483647;width:300px;' +
      'box-sizing:border-box;padding:12px 16px 14px;background:#1b1b1b;' +
      'border:1px solid #3b3018;border-radius:10px;font:600 14px/1.5 ' +
      FONT +
      ';color:#888;text-align:left;box-shadow:0 6px 18px rgba(0,0,0,.6);';

    var header = document.createElement('div');

    header.textContent = YT_NAME;

    header.style.cssText =
      'text-align:center;color:#f3c37b;font-weight:700;font-size:15px;' +
      'padding-bottom:8px;margin-bottom:8px;border-bottom:1px solid #3b3018;';

    panel.appendChild(header);

    COMMAND_LIST.forEach(function (row) {
      var line = document.createElement('div');

      line.style.cssText =
        'display:flex;align-items:flex-start;gap:8px;margin:5px 0;';

      var box = document.createElement('span');

      box.textContent = '\u2713';

      box.style.cssText =
        'flex:none;width:14px;height:14px;margin-top:4px;border-radius:3px;' +
        'background:#0075ff;color:#fff;font-size:11px;line-height:14px;' +
        'text-align:center;';

      var text = document.createElement('span');

      var cmd = document.createElement('span');

      cmd.textContent = row[0];

      cmd.style.cssText =
        'color:#df901c;font-weight:700;';

      text.appendChild(cmd);

      text.appendChild(
        document.createTextNode(' \u2013 ' + row[1])
      );

      line.appendChild(box);
      line.appendChild(text);

      panel.appendChild(line);
    });

    var note = document.createElement('div');

    note.textContent = '* Type the command in the game chat';

    note.style.cssText =
      'margin-top:8px;font-size:12px;font-style:italic;color:#888;';

    panel.appendChild(note);

    var link = document.createElement('a');

    link.href = YT_LINK;
    link.target = '_blank';
    link.rel = 'noopener noreferrer';
    link.textContent = 'YouTube: ' + YT_NAME;

    link.style.cssText =
      'display:block;margin-top:12px;padding:8px 0;background:#4caf50;' +
      'color:#fff;text-align:center;font-weight:700;border-radius:4px;' +
      'text-decoration:none;';

    panel.appendChild(link);

    document.body.appendChild(panel);

    leooPanel = panel;

    return panel;
  }

  function togglePanel(btn) {
    var p = getPanel();

    if (p.style.display === 'block') {
      p.style.display = 'none';
      return;
    }

    p.style.display = 'block';

    var r = btn.getBoundingClientRect();
    var pw = p.offsetWidth || 300;
    var ph = p.offsetHeight || 260;

    var left = Math.min(
      Math.max(8, r.left + r.width / 2 - pw / 2),
      Math.max(8, window.innerWidth - pw - 8)
    );

    p.style.left = left + 'px';

    if (
      r.bottom + 8 + ph <= window.innerHeight - 8 ||
      r.top - ph - 8 < 8
    ) {
      p.style.top = r.bottom + 8 + 'px';
      p.style.bottom = 'auto';
    } else {
      p.style.bottom =
        window.innerHeight - r.top + 8 + 'px';
      p.style.top = 'auto';
    }
  }

  function findControlsButton() {
    if (!document.body) return null;

    var walker = document.createTreeWalker(
      document.body,
      NodeFilter.SHOW_TEXT,
      null
    );

    var node;
    var first = null;

    while ((node = walker.nextNode())) {
      if ((node.nodeValue || '').trim() !== 'Controls') continue;

      var el = node.parentElement;

      if (!el) continue;

      var btn =
        el.closest(
          'button, a, .btn, [role="button"]'
        ) || el;

      if (
        !btn.parentElement ||
        btn.parentElement.children.length < 2
      ) continue;

      if (
        btn.offsetParent !== null ||
        btn.getClientRects().length
      ) {
        return btn;
      }

      if (!first) first = btn;
    }

    return first;
  }

  function makeLeooButton(model) {
    var btn = model.cloneNode(false);

    [
      'id',
      'onclick',
      'href',
      'title',
      'data-toggle',
      'data-target',
      'data-bs-toggle',
      'data-bs-target'
    ].forEach(function (a) {
      btn.removeAttribute(a);
    });

    btn.id = 'leoo-magic-block';
    btn.textContent = 'L';
    btn.title = YT_NAME;

    if (btn.tagName === 'BUTTON') {
      btn.type = 'button';
    }

    var cs = window.getComputedStyle(model);

    btn.style.background = '#32363d';
    btn.style.backgroundColor = '#32363d';
    btn.style.color = '#999999';
    btn.style.border = '0';
    btn.style.fontWeight = '700';
    btn.style.minWidth = '40px';
    btn.style.textAlign = 'center';
    btn.style.cursor = 'pointer';

    if (cs.borderRadius) {
      btn.style.borderRadius = cs.borderRadius;
    }

    if (cs.height && cs.height !== 'auto') {
      btn.style.height = cs.height;
    }

    btn.style.marginLeft = '6px';

    btn.addEventListener('click', function (ev) {
      ev.preventDefault();
      ev.stopPropagation();
      togglePanel(btn);
    });

    return btn;
  }

  function insertLeooButton() {
    if (document.getElementById('leoo-magic-block')) {
      return true;
    }

    var model = findControlsButton();

    if (!model) return false;

    model.parentElement.appendChild(
      makeLeooButton(model)
    );

    return true;
  }

  document.addEventListener(
    'click',
    function (e) {
      if (
        !leooPanel ||
        leooPanel.style.display !== 'block'
      ) return;

      var t = e.target;

      if (
        leooPanel.contains(t) ||
        (t.closest &&
          t.closest('#leoo-magic-block'))
      ) {
        return;
      }

      leooPanel.style.display = 'none';
    },
    true
  );

  var lastAttempt = 0;
  var attempts = 0;

  document.addEventListener(
    'click',
    function () {
      if (
        document.getElementById(
          'leoo-magic-block'
        )
      ) return;

      var now = Date.now();

      if (
        attempts >= 15 ||
        now - lastAttempt < 2000
      ) return;

      lastAttempt = now;
      attempts++;

      setTimeout(
        insertLeooButton,
        200
      );
    },
    true
  );

  var tries = 0;
  var settingsDone = false;
  var canvasDone = false;
  var observing = false;

  function init() {
    if (!canvasDone) {
      canvasDone = hookChatCanvas();
    }

    if (!observing) {
      var chat =
        document.getElementById('chat');

      if (chat) {
        observing = true;

        new MutationObserver(function () {
          hookChatCanvas();
        }).observe(chat, {
          childList: true,
          subtree: true
        });
      }
    }

    if (!settingsDone) {
      settingsDone = insertLeooButton();
    }

    tries++;

    if (
      !(canvasDone &&
        observing &&
        settingsDone) &&
      tries < 100
    ) {
      setTimeout(init, 200);
    }
  }

  init();
})();