[KissAnime] Captcha Solver

Saves initial responses to KissAnime captcha and auto-selects images if it knows the answer.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         [KissAnime] Captcha Solver
// @namespace    https://greasyfork.org/en/users/193865-westleym
// @author       WestleyM
// @version      2018.07.07.2
// @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      http://kissanime.ru/Special/AreYouHuman2*
// @require      http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// ==/UserScript==


//Global variables
var currentVersion = "2018.07.07";
var installText = "Thank you for installing [KissAnime] Captcha Solver!";
var updateText = "The Import/Export section disapearing has been fixed.\n\nIf you would like to help out your fellow users, I would be grateful if you could send me your solutions using the 'export' option.  I will verify it and compile a master list to publish.\n\nYou can reach me through GreasyFork @WestleyM or Reddit @WarriorSolution\nPlease report any bugs or issues!";
var $ = window.jQuery;
var words = [];
var undefinedWords = [];
var unknownwords = [];
var knownwords = [];
var matchfound = 0;
var dataurl = "";
var imageSrc = [];
var clickImage = [];
var count = 0;
var formVerify = document.getElementById("formVerify");
var impExpFlag = 0;
var wordImagePairs = {};
var wordsObj = {};

if (formVerify === null) {
    var link = document.getElementsByTagName("a");
    link = link[0];
    if (localStorage.getItem("lastDescriptions") != null) {
        wordsObj = JSON.parse(localStorage.getItem("lastDescriptions"));
        localStorage.removeItem(wordsObj.firstWord);
        localStorage.removeItem(wordsObj.secondWord);
        localStorage.removeItem("lastDescriptions");
        console.log("Deleted the last two entries");
    }
    console.log("Redirecting page. . . .");
    link.click();
}


if (formVerify != null) { //User is on the regular captcha page
    //Alert for initial install of the script
    if (localStorage.getItem("version") === null) {
        console.log(installText);
        localStorage.setItem("version", currentVersion);
    }

    //Alerts based on new updates
    if (localStorage.getItem("version") != currentVersion && localStorage.getItem("version") != null) {
        alert("(You will only see this message once per update)\n\n" + updateText);
        localStorage.setItem("version", currentVersion);
    }


    var imageElements = $("#formVerify").find("img").toArray(); //All images under the "formVerify" form
    var imageNumber = imageElements.length; //How many images are in the captcha
    words = Words();

    //Image onclick events
    imageElements.forEach(function(currentImage, imageIndex) {
        currentImage.onclick = function() {
            if (!localStorage.getItem("helpword")) { //Saves the solution to local storage
                localStorage.setItem(localStorage.getItem("helpWord"), ProcessImages()[imageIndex]);
                localStorage.removeItem("helpword");
            }

            if (count === 1) { //Changes text in the alert box
                alertBoxText.innerText = "Selections complete.  Loading next page. . . .";
            }

            if (unknownwords[1] !== undefined && count < 1) { //If there is a word that is not known it will ask for help.  This specific if statement will only activate after you've made your first selection and if the second is unknown.
                askForHelp(unknownwords[1]);
                count++;
            }
        }
    });

    //Message box creation
    var firstDiv = $("#formVerify").find("div").toArray()[0];
    firstDiv.style.cssText = "width:100%;"; //The box holding the information at the top was not wide enough originally

    var 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;";
    }

    var 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.

    var 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;";

    var 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
    var 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";

    var 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";

    var inputJSON = document.createElement("input");
    inputJSON.type = "text";
    inputJSON.name = "JSON input";
    inputJSON.id = "inputJSON";
    inputJSON.placeholder = "Paste solution here (will not overwrite existing solutions)";
    inputJSON.style.cssText = "display:none; width:50%; margin-left:auto; margin-right:auto; margin-bottom:5px;";

    var 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";

    var 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";

    var 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";

    var 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";

    var 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);

    //Import/Export onclick events
    impExpButton.onclick = function() {
        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;
        }
    }

    inputSubmit.onclick = function() {
        var inputData = inputJSON.value;

        try {
            var newCaptchaData = JSON.parse(inputData);
            Object.keys(newCaptchaData).forEach(function(current) {
                if (localStorage.getItem(current) === null) {
                    localStorage.setItem(current, newCaptchaData[current]);
                }
            });
            inputSubmit.innerText = "Submitted successfully!";
            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);
        }
    }

    exportButton.onclick = function() {
        //Grab data from local storage and convert to JSON string
        for (var i = 0; i < localStorage.length; i++) {
            if (localStorage.key(i) != "helpWord" && localStorage.key(i) != "lastDescriptions" && localStorage.key(i) != "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";
    }

    //Avoid conflicts
    this.$ = this.jQuery = jQuery.noConflict(true);
    $(document).ready(function() {
        unknownwords = UnknownWords();
        knownwords = KnownWords();
        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]);
        }
        knownwords.forEach(function(word) {
            matchfound = 0;
            console.log("processing known word:" + word);
            ProcessImages().forEach(function(image,counter) { //Grabs known value from local storage and clicks the corresponding image
                console.log("counter: " + counter);
                if (localStorage.getItem(word) == image) {
                    console.log("found match for word " + word);
                    matchfound = 1;
                    $("[indexValue='" + counter + "']").click();
                } else if (counter === imageNumber-1 && matchfound === 0) {
                    location.reload();
                }
            });
        });
    });

    //Functions
    function askForHelp(word) { //Asks you to select an answer when the script doesn't know.
        alertBoxText.innerText = "Please select image: " + word;
        localStorage.setItem("helpWord", word);
    }

    function UnknownWords() { //Finds the words that the script doesn't know the answer to
        words.forEach(function(word) {
            if(!localStorage.getItem(word)) { //If the solution isn't found in the local storage, it will be added to the "unknownwords" array
                unknownwords.push(word);
            }
        });
        return unknownwords;
    }

    function KnownWords() { //Finds the words that the script knows the answer to
        words.forEach(function(word) {
            if(localStorage.getItem(word)) { //If solution is found in the local storage, it will be added to the "Knownwords" array
                knownwords.push(word);
            }
        });
        return knownwords;
    }

    function SaveWord(word, dataurl) {
        if(!localStorage.getItem(word)) {
            localStorage.removeItem(word);
            localStorage.setItem(word, dataurl);
        } else {
            localStorage.setItem(word, dataurl);
        }
    }

    function Words() { //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 = $("#formVerify").find("p").toArray();
        var finalPElement = pElements[pElements.length-1];
        var words = $(finalPElement).find("span").toArray();
        var firstDesc = words[0].innerText;
        var secondDesc = words[1].innerText;

        //Saves the descriptions to local Storage
        var lastDescriptions = { "firstWord":firstDesc, "secondWord":secondDesc };
        var DescJSON = JSON.stringify(lastDescriptions);
        localStorage.setItem("lastDescriptions", DescJSON);
        return [firstDesc, secondDesc];
    }

    function Images() {
        return $("[indexValue]").toArray();
    }

    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 ProcessImages() {
        var imagedata = [];
        Images().forEach(function(image, counter) {
            dataurl = ConvertToDataUrl(image);
            imagedata.push(MinimiseDataUrl(MinimiseDataUrl(MinimiseDataUrl(dataurl, 5), 4), 3));
        });
        return imagedata;
    }
}