Kahoot AntiBot

Remove all bots from the player join screen. Simply start a kahoot game and watch as all bots get killed. Does not work on leaderboards currently.

当前为 2018-11-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Kahoot AntiBot
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Remove all bots from the player join screen. Simply start a kahoot game and watch as all bots get killed. Does not work on leaderboards currently.
  6. // @author theusaf
  7. // @match *://play.kahoot.it/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. window.similarity = function (s1, s2) {
  12. if(!isNaN(s2) && !isNaN(s1)){
  13. return 1;
  14. }
  15. var longer = s1;
  16. var shorter = s2;
  17. if (s1.length < s2.length) {
  18. longer = s2;
  19. shorter = s1;
  20. }
  21. var longerLength = longer.length;
  22. if (longerLength == 0) {
  23. return 1.0;
  24. }
  25. return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);
  26. }
  27.  
  28. window.editDistance = function (s1, s2) {
  29. s1 = s1.toLowerCase();
  30. s2 = s2.toLowerCase();
  31.  
  32. var costs = new Array();
  33. for (var i = 0; i <= s1.length; i++) {
  34. var lastValue = i;
  35. for (var j = 0; j <= s2.length; j++) {
  36. if (i == 0){
  37. costs[j] = j;
  38. }
  39. else {
  40. if (j > 0) {
  41. var newValue = costs[j - 1];
  42. if (s1.charAt(i - 1) != s2.charAt(j - 1)){
  43. newValue = Math.min(Math.min(newValue, lastValue),costs[j]) + 1;
  44. }
  45. costs[j - 1] = lastValue;
  46. lastValue = newValue;
  47. }
  48. }
  49. }
  50. if (i > 0){
  51. costs[s2.length] = lastValue;
  52. }
  53. }
  54. return costs[s2.length];
  55. }
  56.  
  57. window.setup1 = function (){
  58. var launch_button = document.querySelectorAll("[data-functional-selector=\"launch-button\"]")[0];
  59. if(launch_button){
  60. console.warn("launch button found!");
  61. launch_button.addEventListener("click",setup2);
  62. }else{
  63. setTimeout(setup1,1000);
  64. }
  65. }
  66.  
  67. window.setup2 = function (){
  68. var start_button = document.querySelectorAll("[data-functional-selector=\"start-button\"]")[0];
  69. if(start_button){
  70. console.warn("start button found!");
  71. setup3();
  72. }else{
  73. setTimeout(setup2,1000);
  74. }
  75. }
  76.  
  77. window.setup3 = function (){
  78. let playerList = document.getElementsByClassName("player-list")[0];
  79. let conf = {
  80. childList: true,
  81. subtree: true
  82. };
  83. let observer = new MutationObserver(kill_bots);
  84. observer.observe(playerList,conf);
  85. }
  86.  
  87. window.onload = setup1;
  88.  
  89. window.cachedUsernames = [];
  90.  
  91. window.kill_bots = function (e,observer){
  92. console.warn("determining evil now. be warned.");
  93. if(document.getElementsByClassName("player-list").length == 0){
  94. observer.disconnect();
  95. return;
  96. }
  97. let players = document.querySelectorAll("[data-functional-selector=\"player\"]");
  98. for(let i in players){
  99. if(cachedUsernames.length == 0){
  100. cachedUsernames.push({element:players[i],text:players[i].innerText,clicked:false});
  101. continue;
  102. }
  103. for(let k in cachedUsernames){
  104. if(cachedUsernames[k].element == players[i]){
  105. continue;
  106. }
  107. if(similarity(cachedUsernames[k].text,players[i].innerText) >= 0.60){
  108. players[i].click();
  109. if(!cachedUsernames[k].clicked){
  110. cachedUsernames[k].element.click();
  111. cachedUsernames[k].clicked = true;
  112. }
  113. break;
  114. }
  115. }
  116. cachedUsernames.push({element:players[i],text:players[i].innerText,clicked:false});
  117. }
  118. };