Saves initial responses to KissAnime captcha and auto-selects images if it knows the answer.
// ==UserScript== // @name [KissAnime] Captcha Solver // @namespace https://greasyfork.org/en/users/193865-westleym // @author WestleyM // @version 2019.4.3 // @icon http://kissanime.ru/Content/images/favicon.ico // @description Saves initial responses to KissAnime captcha and auto-selects images if it knows the answer. // @grant none // @include *://kissanime.ru/Special/AreYouHuman2* // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js // ==/UserScript== function main() { //Variable declarations var currentVersion = "2018.10.15"; var installText = "Thank you for installing [KissAnime] Captcha Solver!"; var updateText = "Updated to version 2019.4.3. I no longer actively update this script. I can't guarantee support if KA changes things again.\nThe best way to reach me is on Reddit @WarriorSolution"; var $ = window.jQuery; var formVerify = document.getElementById("formVerify1"); var words = [], undefinedWords = [], unknownWords = [], knownWords = [], imageSrc = [], clickImage = [], imageData = [], imageElements = [], multiImageFlag = []; var matchFound = 0, count = 0, impExpFlag = 0, askedForHelp = 0, PHObjFlag = 0; var wordImagePairs = {}, wordsObj = {}, imageObj = {}, clickedImgs = {}, placeholderObjOne = {}, placeholderObjTwo = {}; var dataURL = ""; var impExpButton, inputSubmit, exportButton, firstDiv, PElements, thirdPElement, alertBoxDiv, alertBoxText, importExport, inputJSON, lineSeparator, exportDirections, exportBox; //Variables used for created HTML elements if (formVerify === null) { var link = document.getElementsByTagName("a"); link = link[0]; if (localStorage.getItem("KCS-lastDescriptions") != null) { wordsObj = JSON.parse(localStorage.getItem("KCS-lastDescriptions")); localStorage.removeItem(wordsObj.firstWord); localStorage.removeItem(wordsObj.secondWord); localStorage.removeItem("KCS-lastDescriptions"); console.log("Deleted the last two entries."); } console.log("Redirecting page. . . ."); link.click(); } if (formVerify != null) { //User is on the regular captcha page //Alerts for initial install or update of the script if (localStorage.getItem("KCS-version") === null && localStorage.getItem("version") === null) { messagePusher("install"); } if (localStorage.getItem("KCS-version") != currentVersion && localStorage.getItem("KCS-version") != null) { messagePusher("update"); } if (localStorage.getItem("KCS-version") === null && localStorage.getItem("version") != null) { messagePusher("update"); } //Image onclick events imageElements = $("#formVerify1").find("img").toArray(); imageElements.forEach(function(currentImage, imageIndex) { currentImage.onclick = function() { onClickEvents("image", currentImage, imageIndex); } }); //Create custom HTML customHTML(); //Import/Export onclick function calls impExpButton.onclick = function() { onClickEvents("impExpButton") }; inputSubmit.onclick = function() { onClickEvents("inputSubmit") }; exportButton.onclick = function() { onClickEvents("exportButton") }; //Avoid conflicts, start main processes this.$ = this.jQuery = jQuery.noConflict(true); $(document).ready(function() { wordGrabber(); unknownWordGrabber(); knownWordGrabber(); imageGrabber(); clickImages(); console.log("Unknown words: " + unknownWords); console.log("Known words: " + knownWords); if (unknownWords[0] != undefined) { //Ask for help with the first unknown word askForHelp(unknownWords[0]); } }); } //Functions function askForHelp(word) { //Asks you to select an answer when the script doesn't know. alertBoxText.innerText = "Please select image: " + word; localStorage.setItem("KCS-helpWord", word); } function unknownWordGrabber() { //Finds the words that the script doesn't know the answer to words.forEach(function(word) { if(!localStorage.getItem("KCS-" + word)) { //If the solution isn't found in the local storage, it will be added to the "unknownWords" array unknownWords.push(word); } }); } function knownWordGrabber() { //Finds the words that the script knows the answer to words.forEach(function(word) { if(localStorage.getItem("KCS-" + word)) { //If solution is found in the local storage, it will be added to the "knownWords" array knownWords.push(word); } }); } function wordGrabber() { //Grabs span elements that are children of the "formVerify" form. This will include the two sections saying what to select. Ex: "cat, glasses, 0" var pElements = $("#formVerify1").find("p").toArray(); var finalPElement, wordElements; pElements.forEach(function(pElement) { //Grabs the p element that contains 2 span elements in it. if ($(pElement).find("span").toArray().length === 2) { wordElements = $(pElement).find("span").toArray(); } }); words = [wordElements[0].innerText, wordElements[1].innerText]; //Saves the descriptions to local Storage var lastDescriptions = { "firstWord":wordElements[0].innerText, "secondWord":wordElements[1].innerText }; var DescJSON = JSON.stringify(lastDescriptions); localStorage.setItem("KCS-lastDescriptions", DescJSON); } function imageGrabber() { imageElements.forEach(function(image, index) { var objKey = "image" + index.toString(); var imageData = convertToDataUrl(image); imageData = minimiseDataUrl(minimiseDataUrl(minimiseDataUrl(imageData, 5), 4), 3); imageObj[objKey] = imageData; }); } function convertToDataUrl(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0); var dataURL = canvas.toDataURL("image/png"); return dataURL.replace(/^data:image\/(png|jpg);base64,/, ""); } function minimiseDataUrl(dataUrl,jump) { var a = ""; for(var i = 0; i < dataUrl.length; i=i+jump) { a += dataUrl.charAt(i); } return a; } function clickImages() { knownWords.forEach(function(word) { var i = 0; for (var key in imageObj) { if (localStorage.getItem("KCS-" + word) == imageObj[key]) { $("[indexValue='" + i + "']").click(); break; } else if (i === Object.keys(imageObj).length-1) { var multiImageDesc = localStorage.getItem("KCS-" + word); var foundFlag = 0; try { JSON.parse(multiImageDesc); for (var j = 0; j < Object.keys(multiImageDesc).length; j++) { if (multiImageDesc[j] === imageObj[key]) { console.log("Description with multiple images found and clicked: " + word); $("[indexValue='" + i + "']").click(); foundFlag = 1; } } } catch(err) {} if (foundFlag === 0) { console.log("Description with multiple images found. Solution unknown: " + word); multiImageFlag.push(word); unknownWords.push(word); knownWords.splice(knownWords.indexOf(word), 1); } } i++; } }); } function convertSolutions() { var tempVarKey = ""; var tempVarDesc = ""; for (var i = 0; i < localStorage.length; i++) { if (localStorage.key(i) != "KCS-helpWord" && localStorage.key(i) != "KCS-lastDescriptions" && localStorage.key(i) != "KCS-version") { tempVarKey = localStorage.key(i); tempVarKey = tempVarKey.replace(/KCS-/g, ""); tempVarDesc = localStorage.getItem(localStorage.key(i)); localStorage.removeItem(localStorage.key(i)); localStorage.setItem("KCS-" + tempVarKey, tempVarDesc); } } } function removeBrokenSolutions() { for (var i = 0; i < localStorage.length; i++) { if (localStorage.getItem(localStorage.key(i))[0] === "[" || localStorage.getItem(localStorage.key(i)) === undefined || localStorage.getItem(localStorage.key(i)) === "undefined") { localStorage.removeItem(localStorage.key(i)); } } } function messagePusher(type) { switch(type) { case "install": console.log(installText); localStorage.removeItem("version"); localStorage.removeItem("lastDescriptions"); localStorage.removeItem("helpWord"); localStorage.setItem("KCS-version", currentVersion); break; case "update": //alert("(You will only see this message once per update)\n\n" + updateText); localStorage.removeItem("version"); localStorage.removeItem("lastDescriptions"); localStorage.removeItem("helpWord"); localStorage.setItem("KCS-version", currentVersion); convertSolutions(); removeBrokenSolutions(); break; } } function customHTML() { //Message box firstDiv = $("#formVerify1").find("div").toArray()[0]; firstDiv.style.cssText = "width:100%;"; //The box holding the information at the top was not wide enough originally PElements = $(firstDiv).find("p").toArray(); if (PElements.length === 2) { PElements[0].style.cssText = "opacity:0; height:0px; width:100%; line-height:0px; font-size:0px;"; } if (PElements.length === 3) { PElements[0].style.cssText = "display: none;"; PElements[1].style.cssText = "opacity:0; height:0px; width:100%; line-height:0px; font-size:0px;"; } thirdPElement = PElements[PElements.length-1]; thirdPElement.style.cssText = "opacity:0; height:0px; width:100%; line-height:0px; font-size:0px;"; //Hides where it lists both selection choices. This is to insure users select the images in the correct order. alertBoxDiv = document.createElement("div"); //Creation of div element which will contain the below text element alertBoxDiv.style.cssText = "background:#518203; color:white; height:30px; width:100%; line-height:30px; text-align:center;"; alertBoxText = document.createElement("h3"); //Creation of text element which will say the descriptions of images the script doesn't know the answer to alertBoxText.innerText = "Checking data. . . ."; alertBoxText.style.cssText = "background:#518203; color:white; height:100%; width:100%; text-align:center; font-size: 20px; margin-top:0px;"; alertBoxDiv.insertAdjacentElement("afterbegin", alertBoxText); //Inserting "alertBoxText" into "alertBoxDiv" at the top thirdPElement.insertAdjacentElement("afterend", alertBoxDiv); //Placing "alertBoxDiv" at the end of "mainBlock" //Import/Export area importExport = document.createElement("div"); importExport.style.cssText = "display:block; background: #111111; color:white; width:970px; padding:2px; text-align:center; margin-left:auto; margin-right:auto; border:1px solid #2f2f2f;"; importExport.id = "importExport"; impExpButton = document.createElement("p"); impExpButton.style.cssText = "background:#518203; color:white; height:15px; width:960px; margin-top:5px; margin-bottom:5px; text-align:center; font-size: 15px; padding:5px; cursor:pointer;"; impExpButton.innerText = "[+] Solution List Importing/Exporting"; impExpButton.id = "impExpButton"; inputJSON = document.createElement("input"); inputJSON.type = "text"; inputJSON.name = "JSON input"; inputJSON.id = "inputJSON"; inputJSON.placeholder = "Paste solution here"; inputJSON.style.cssText = "display:none; width:50%; margin-left:auto; margin-right:auto; margin-bottom:5px;"; inputSubmit = document.createElement("div"); inputSubmit.style.cssText = "display:none; background:#518203; color:white; height:20px; width:50%; margin-left:auto; margin-right:auto; margin-bottom:5px; border:1px solid #5a5a5a; cursor:pointer;"; inputSubmit.innerText = "Submit"; inputSubmit.id = "inputSubmit"; lineSeparator = document.createElement("div"); lineSeparator.style.cssText = "display:none; background:#5f5f5f; height:3px; width:100%; margin-left:auto; margin-right:auto; margin-bottom:5px;"; lineSeparator.id = "lineSeparator"; exportButton = document.createElement("div"); exportButton.style.cssText = "display:none; background:#518203; color:white; height:20px; width:50%; margin-left:auto; margin-right:auto; margin-bottom:5px; border:1px solid #5a5a5a; cursor:pointer;"; exportButton.innerText = "Export list"; exportButton.id = "exportButton"; exportDirections = document.createElement("div"); exportDirections.style.cssText = "display:none; background:#518203; color:white; height:20px; width:50%; margin-left:auto; margin-right:auto; margin-bottom:5px; border:1px solid #5a5a5a;"; exportDirections.innerText = "Copy the below data: (triple click to select all)"; exportDirections.id = "exportDirections"; exportBox = document.createElement("p"); exportBox.style.cssText = "display:none; #111111; color:white; width:75%; margin-left:auto; margin-right:auto; margin-top:0px; margin-bottom:5px; text-align:center; font-size:10px; border:1px solid #2f2f2f; word-wrap: break-word; overflow:auto; max-height:500px;"; exportBox.innerText = ""; exportBox.id = "exportBox"; importExport.insertAdjacentElement("afterbegin", impExpButton); importExport.insertAdjacentElement("beforeend", inputSubmit); inputSubmit.insertAdjacentElement("afterend", lineSeparator); lineSeparator.insertAdjacentElement("afterend", exportButton); exportButton.insertAdjacentElement("afterend", exportDirections); exportDirections.insertAdjacentElement("afterend", exportBox); impExpButton.insertAdjacentElement("afterend", inputJSON); document.getElementById("containerRoot").insertAdjacentElement("afterend", importExport); } function onClickEvents(clickedItem, clickedImage, imageIndexValue) { switch(clickedItem) { case "impExpButton": if (impExpFlag === 0) { impExpButton.innerText = "[-] Solution List Importing/Exporting"; inputJSON.style.display = "block"; inputSubmit.style.display = "block"; lineSeparator.style.display = "block"; exportButton.style.display = "block"; impExpFlag = 1; } else { impExpButton.innerText = "[+] Solution List Importing/Exporting"; inputJSON.style.display = "none"; inputSubmit.style.display = "none"; lineSeparator.style.display = "none"; exportButton.style.display = "none"; exportDirections.style.display = "none"; exportBox.style.display = "none"; impExpFlag = 0; } break; case "exportButton": //Grab data from local storage and convert to JSON string for (var i = 0; i < localStorage.length; i++) { if (localStorage.key(i) != "KCS-helpWord" && localStorage.key(i) != "KCS-lastDescriptions" && localStorage.key(i) != "KCS-version") { wordImagePairs[localStorage.key(i)] = localStorage.getItem(localStorage.key(i)); } } var wordImagePairsJSON = JSON.stringify(wordImagePairs); exportBox.innerText = wordImagePairsJSON; exportDirections.style.display = "block"; exportBox.style.display = "block"; break; case "inputSubmit": var inputData = inputJSON.value; var currentTemp = ""; var oldListLength = localStorage.length.toString(); try { var newCaptchaData = JSON.parse(inputData); Object.keys(newCaptchaData).forEach(function(current) { currentTemp = current.replace(/KCS-/g, ""); //Allows for compatibility between old export lists and new ones. localStorage.setItem("KCS-" + currentTemp, newCaptchaData[current]); }); inputSubmit.innerText = "Submitted successfully! Old/new/changed solutions: " + oldListLength + "/" + localStorage.length.toString() + "/" + Object.keys(newCaptchaData).length; console.log("Solution list has been updated."); } catch(err) { inputSubmit.innerText = "There was an issue. Check the console."; console.log("Issue with list upload: " + err); } removeBrokenSolutions(); convertSolutions(); break; case "image": if ($(clickedImage).attr("class") === "imgCapSelect") { clickedImgs[localStorage.getItem("KCS-helpWord")] = imageIndexValue; } else { words.forEach(function(word) { if (imageIndexValue === clickedImgs[word]) { delete clickedImgs[word]; } }); } if (Object.keys(clickedImgs).length === words.length) { for (var key in clickedImgs) { if (key !== multiImageFlag[0] && key !== multiImageFlag[1]) { localStorage.setItem("KCS-" + key, imageObj["image" + clickedImgs[key].toString()]); } else { var currentSolution = localStorage.getItem(key); try { JSON.parse(currentSolution); currentSolution[Object.keys(currentSolution).length] = imageObj["image" + clickedImgs[key].toString()]; } catch(err) { if (PHObjFlag === 0) { placeholderObjOne[0] = currentSolution; placeholderObjOne[1] = imageObj["image" + clickedImgs[key].toString()]; currentSolution = placeholderObjOne; PHObjFlag = 1; } else if (PHObjFlag === 1) { placeholderObjTwo[0] = currentSolution; placeholderObjTwo[1] = imageObj["image" + clickedImgs[key].toString()]; currentSolution = placeholderObjTwo; PHObjFlag = 2; } } JSON.stringify(currentSolution); localStorage.setItem("KCS-" + key, currentSolution); } } alertBoxText.innerText = "Selections complete. Loading next page. . . ."; } if (Object.keys(clickedImgs).length < words.length) { words.forEach(function(word, index) { if (clickedImgs[word] === undefined && askedForHelp === 0) { askForHelp(word); askedForHelp = 1; } }); askedForHelp = 0; } } } } main();