server changer

gives you magical ping!

  1. // ==UserScript==
  2. // @name server changer
  3. // @version 0.1
  4. // @description gives you magical ping!
  5. // @author wealthydev
  6. // @match *://*.tankionline.com/*
  7. // @grant none
  8. // @run-at document-start
  9. // @namespace https://greasyfork.org/users/1347888
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. const ws = WebSocket;
  14. window.WebSocket = class extends ws {
  15. constructor(url) {
  16. let data = window.target_server?.split(":"),
  17. target = data ? `wss://${data[0]}.tankionline.com:${data[1]}/` : null;
  18.  
  19. super(target || url);
  20.  
  21. console.log("server", this.url);
  22. }
  23. };
  24.  
  25. const server_changer = (JSON.parse(localStorage.getItem("server_changer")) || {});
  26. window.target_server = server_changer.target;
  27.  
  28. server_changer.target = null;
  29. if(window.target_server) {
  30. localStorage.setItem("server_changer", JSON.stringify(server_changer));
  31.  
  32. return alert(`targeting server [${window.target_server}]`)
  33. }
  34.  
  35. let shadow = { host: document.createElement("div") }
  36. document.body.appendChild(shadow.host);
  37. shadow.root = shadow.host.attachShadow({ mode: 'open' });
  38.  
  39. shadow.root.innerHTML = `<style>.mini-box{z-index:999999;position:absolute;top:100px;left:100px;width:140px;background-color:#f9f9f9;border:1px solid #ccc;border-radius:6px;padding:10px;box-shadow:0 2px 10px rgba(0,0,0,.1);cursor:move;user-select:none}.mini-box label,.mini-box select{font-size:12px}.mini-box select{width:100%;padding:4px;margin-top:5px}</style><script></script><div class=mini-box id=box><div style=display:flex;justify-content:space-between;align-items:center;margin-bottom:6px><label style=font-size:large>servers</label> <button id=connect_server style="font-size:10px;padding:4px 8px">connect</button></div></div>`;
  40.  
  41. const box = shadow.root.querySelector("#box")
  42.  
  43. let hue = 0;
  44.  
  45. function animate() {
  46. hue = (hue + 1) % 360;
  47. box.style["background-color"] = `hsl(${hue}, 100%, 60%)`;
  48. }
  49.  
  50. setInterval(animate, 50);
  51.  
  52. function update_list(servers) {
  53. const select = document.createElement("select");
  54. select.name = "servers";
  55. select.id = "server";
  56. select.style.marginTop = "8px";
  57.  
  58. let option = document.createElement("option");
  59. option.value = option.text = `default`;
  60. select.appendChild(option);
  61.  
  62. const sorted = Object.entries(servers).sort((a, b) => a[1] - b[1]);
  63. sorted.forEach(([name, ping]) => {
  64. option = document.createElement("option");
  65. option.value = name;
  66. option.text = `${name.split(":")[0]} / ${ping} ms`;
  67. select.appendChild(option);
  68. });
  69.  
  70. box.appendChild(select);
  71.  
  72. select.value = `default`;
  73.  
  74. const button = shadow.root.querySelector("#connect_server");
  75. button.addEventListener("click", () => {
  76. if(select.value === "default") return box.remove();
  77.  
  78. server_changer.target = select.value;
  79. localStorage.setItem("server_changer", JSON.stringify(server_changer));
  80.  
  81. return window.location.reload();
  82. });
  83. }
  84.  
  85. const scan = (url, callback) => {
  86. const ws = new WebSocket(url);
  87.  
  88. let start, pause;
  89.  
  90. ws.onopen = () => {
  91. start = Date.now();
  92. ws.close();
  93. }
  94.  
  95. ws.onclose = () => {
  96. const responseTime = Date.now() - start;
  97. callback(Math.round(responseTime / 2));
  98. clearTimeout(pause);
  99. }
  100.  
  101. ws.onerror = () => {
  102. callback();
  103. ws.close();
  104. clearTimeout(pause);
  105. }
  106.  
  107. pause = setTimeout(() => {
  108. callback();
  109. ws.close();
  110. }, 500);
  111. }
  112.  
  113. let servers;
  114.  
  115. function update() {
  116. fetch("https://tankionline.com/s/status.js").then(async res => {
  117. const data = await res.json();
  118. servers = {};
  119.  
  120. for (const [, value] of Object.entries(data.nodes)) {
  121. let server = value.endpoint,
  122. key = server.host.split(".tanki")[0];
  123.  
  124. if(server.status !== "NORMAL") continue;
  125.  
  126. scan(`wss://${server.host}:${server.wsPorts[0]}`, function(ping) {
  127. if(!ping) return null;
  128.  
  129. servers[`${key}:${server.wsPorts[0]}`] = ping;
  130. });
  131. }
  132.  
  133. setTimeout(() => update_list(servers), 1e3)
  134. });
  135. }
  136.  
  137. update();
  138. })();