MoreCAPTCHA

Speeds up solving Google reCAPTCHA challenges by shortening transition effects and providing continuous selection ability.

< Feedback on MoreCAPTCHA

Review: Good - script works

§
Posted: 2017-07-14
Edited: 2017-07-14

Low Browser Compatability (fixed after version 1.1)

This script is useful, but it does not support the Pale Moon web browser. Please consider adding support for it.

Here is a modified version that works in Pale Moon that you can use if you would like:

// ==UserScript==
// @name        MoreCAPTCHA
// @description Google reCAPTCHA on steroids.
// @namespace   https://eugenox.appspot.com/
// @include     https://www.google.com/recaptcha/api2/bframe?*
// @version     1.0
// @run-at      document-start
// @grant       unsafeWindow
// ==/UserScript==

// Copyright (C) 2017 Eugene Nouvellieu
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

const SPEED = 5;

var selector = {
  constructor: function() {
    this.selecting = undefined;
  },

  handle: function(event) {
    var tiles = new Set(document.querySelectorAll('#rc-imageselect td')), tile = event.target;

    while (tile && ! tiles.has(tile)) {
      tile = tile.parentNode;
    }

    if (tile) {
      event.stopPropagation();
      event.preventDefault();

      let selected = 'selected' in tile.dataset && tile.dataset.selected == 'true';

      if (this[event.type](selected)) {
        tile.dataset.selected = this.selecting;

        tile.firstElementChild.click();
      }
    }
  },

  mouseover: function(selected) {
    return ! (this.selecting === undefined || this.selecting === selected);
  },

  mousedown: function(selected) {
    this.selecting = ! selected;

    return true;
  },

  mouseup: function(selected) {
    this.selecting = undefined;

    return false;
  }
}; selector.constructor();

window.addEventListener('load', function(event) {
  var sheet = document.body.appendChild(document.createElement('style')).sheet;

  sheet.insertRule(
    '.rc-imageselect-table-42, .rc-imageselect-table-33, .rc-imageselect-table-44' +
    `{ transition-duration: ${1 / SPEED}s !important }`, 0);
  sheet.insertRule(
    '.rc-imageselect-dynamic-selected' + 
    `{ transition-duration: ${2 / SPEED}s !important }`, 1);
  sheet.insertRule(
    '.rc-imageselect-progress' +
    `{ transition-duration: ${1 / SPEED}s !important }`, 2);
  sheet.insertRule(
    '.rc-image-tile-overlay' +
    `{ transition-duration: ${1 / SPEED}s !important }`, 3);

  var handler = selector.handle.bind(selector);

  for (let name of ['mouseover', 'mousedown', 'mouseup']) {
    document.body.addEventListener(name, handler, false);
  }
});

function publish(func) {
  if (typeof exportFunction == 'function') {
    return exportFunction(func, unsafeWindow);
  }

  return func;
}

var __setTimeout = unsafeWindow.setTimeout.bind(unsafeWindow);

unsafeWindow.setTimeout = publish(function(callback, delay) {
  return __setTimeout(callback, Number(delay) / SPEED);
});
§
Posted: 2017-07-14

Thanks for the feedback. I've just refactored all ES6 features in v1.1.

§
Posted: 2017-07-14
Edited: 2017-07-14

I appreciate it, but you are not quite there as you left in the least compatible part of your code. You are using Array.prototype.values(), which according to the Mozilla Developer Network is not supported on Chrome, not supported on Opera, and only supported for Firefox in Nightly builds (and is also not supported by Pale Moon).

This is an easy fix though, since you can just remove the values call. querySelectorAll returns an array which implements the iterable interface, and as a result the constructor for Set can accept it. So simply change "new Set(document.querySelectorAll('#rc-imageselect td').values())" to "new Set(document.querySelectorAll('#rc-imageselect td'))".

It was only that function that no one supported and classes (which are just syntactic sugar so are not at all important for browsers to implement) that was problematic. I will go ahead and update the rating to acknowledge the upcoming fix.

§
Posted: 2017-07-15

Thank you for your work.

I also forgot I'm using the Set class which is an ES6 addition. I think I leave it in if it doesn't cause any trouble.

Post reply

Sign in to post a reply.