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-10 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Kahoot AntiBot
// @namespace    http://tampermonkey.net/
// @version      1.3
// @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.
// @author       theusaf
// @match        *://play.kahoot.it/*
// @grant        none
// ==/UserScript==

window.similarity = function (s1, s2) {
  if(!isNaN(s2) && !isNaN(s1)){
    return 1;
  }
  var longer = s1;
  var shorter = s2;
  if (s1.length < s2.length) {
    longer = s2;
    shorter = s1;
  }
  var longerLength = longer.length;
  if (longerLength == 0) {
    return 1.0;
  }
  return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);
}

window.editDistance = function (s1, s2) {
  s1 = s1.toLowerCase();
  s2 = s2.toLowerCase();

  var costs = new Array();
  for (var i = 0; i <= s1.length; i++) {
    var lastValue = i;
    for (var j = 0; j <= s2.length; j++) {
      if (i == 0){
        costs[j] = j;
      }
      else {
        if (j > 0) {
          var newValue = costs[j - 1];
          if (s1.charAt(i - 1) != s2.charAt(j - 1)){
            newValue = Math.min(Math.min(newValue, lastValue),costs[j]) + 1;
          }
          costs[j - 1] = lastValue;
          lastValue = newValue;
        }
      }
    }
    if (i > 0){
      costs[s2.length] = lastValue;
    }
  }
  return costs[s2.length];
}

window.test_leaderboard = function (mu,observer){
  if(document.getElementsByTagName("iframe")[1].contentDocument.querySelectorAll("[data-functional-selector=\"highscores\"]").length > 0){
    if(document.getElementsByTagName("iframe")[1].contentDocument.querySelectorAll("[data-functional-selector=\"highscores\"]")[0].querySelectorAll("[data-functional-selector=\"player-name\"]").length == 0){
        cachedLeaderboard = [];
        return;
    }
  }else{
    cachedLeaderboard = [];
    return;
  }
  let players = document.getElementsByTagName("iframe")[1].contentDocument.querySelectorAll("[data-functional-selector=\"highscores\"]")[0].querySelectorAll("[data-functional-selector=\"player-name\"]");
  for(let i in players){
    if(cachedLeaderboard.length == 0){
      cachedLeaderboard.push({element:players[i],text:players[i].innerText,clicked:false});
      continue;
    }
    for(let k in cachedLeaderboard){
      if(cachedLeaderboard[k].text == players[i].innerText){
        continue;
      }
      if(similarity(cachedLeaderboard[k].text,players[i].innerText) >= 0.60){
        players[i].click();
        if(!cachedLeaderboard[k].clicked){
          cachedLeaderboard[k].element.click();
          cachedLeaderboard[k].clicked = true;
        }
        break;
      }
    }
    if(cachedLeaderboard.filter(function(item){return item.text == players[i].innerText}).length === 0){
        cachedLeaderboard.push({element:players[i],text:players[i].innerText,clicked:false});
    }
  }
}

window.setup1 = function (){
  setInterval(test_leaderboard,1000);
  var launch_button = document.querySelectorAll("[data-functional-selector=\"launch-button\"]")[0];
  if(launch_button){
    console.warn("launch button found!");
    launch_button.addEventListener("click",setup2);
  }else{
    setTimeout(setup1,1000);
  }
}

window.setup2 = function (){
  var start_button = document.querySelectorAll("[data-functional-selector=\"start-button\"]")[0];
  if(start_button){
    console.warn("start button found!");
    setup3();
  }else{
    setTimeout(setup2,1000);
  }
}

window.setup3 = function (){
  let playerList = document.getElementsByClassName("player-list")[0];
  let conf = {
    childList: true,
    subtree: true
  };
  let observer = new MutationObserver(kill_bots);
  observer.observe(playerList,conf);
}

window.onload = setup1;

window.cachedUsernames = [];
window.cachedLeaderboard = [];

window.kill_bots = function (e,observer){
  console.warn("determining evil now. be warned.");
  if(document.getElementsByClassName("player-list").length == 0){
    observer.disconnect();
    return;
  }
  let players = document.querySelectorAll("[data-functional-selector=\"player\"]");
  for(let i in players){
    if(cachedUsernames.length == 0){
      cachedUsernames.push({element:players[i],text:players[i].innerText,clicked:false});
      continue;
    }
    for(let k in cachedUsernames){
      if(cachedUsernames[k].element == players[i]){
        continue;
      }
      if(similarity(cachedUsernames[k].text,players[i].innerText) >= 0.60){
        players[i].click();
        if(!cachedUsernames[k].clicked){
          cachedUsernames[k].element.click();
          cachedUsernames[k].clicked = true;
        }
        break;
      }
    }
    if(cachedUsernames.filter(function(item){return item.text == players[i].innerText}).length === 0){
        cachedUsernames.push({element:players[i],text:players[i].innerText,clicked:false});
    }
  }
};