Auto-solve slide puzzle captcha
// ==UserScript==
// @name RS Slide Captcha Solver
// @namespace RS Slide puzzle captcha
// @version 1.3
// @description Auto-solve slide puzzle captcha
// @author Shnethan
// @match *://*.gamefaucet.fun/*
// @icon https://docs.rs/-/rustdoc.static/favicon-32x32-eab170b8.png
// @license © Shnethan
// @grant none
// ==/UserScript==
/*
* Copyright (c) 2026 Shnethan . All rights reserved.
*/
(() => {
let b = false;
const w = ms => new Promise(r => setTimeout(r, ms));
const v = () => {
const x = document.querySelector('#captchaBox');
if (!x) return false;
return (
x.classList.contains('verified') ||
(
x.querySelector('input[name="rscaptcha_token"]')?.value?.length > 10 &&
x.querySelector('input[name="rscaptcha_response"]')?.value?.length > 10
)
);
};
const r = () => {
const g = document.querySelector('.gc-picture');
const t = document.querySelector('.gc-tile');
const s = document.querySelector('.gc-drag-block');
return g && t && s &&
g.complete && g.naturalWidth &&
g.style.display !== 'none' &&
t.style.display !== 'none';
};
const o = async () => {
if (v()) return;
const x = document.querySelector('#captchaBox');
if (!x) return;
['mousedown', 'mouseup', 'click'].forEach(t =>
x.dispatchEvent(new MouseEvent(t, {
bubbles: true,
cancelable: true,
view: window
}))
);
await w(900);
};
const f = async () => {
const k = document.querySelector('.gc-icon-block svg:last-of-type');
if (!k) return;
k.dispatchEvent(new MouseEvent('click', {
bubbles: true
}));
await w(1400);
};
const i = m => {
const c = document.createElement('canvas');
const x = c.getContext('2d');
c.width = m.naturalWidth;
c.height = m.naturalHeight;
x.drawImage(m, 0, 0);
try {
return x.getImageData(0, 0, c.width, c.height);
} catch {
return null;
}
};
const g = d => {
const w = d.width;
const h = d.height;
const o = new Float32Array(w * h);
for (let i = 0, j = 0; i < d.data.length; i += 4, j++)
o[j] = d.data[i] * 0.299 + d.data[i + 1] * 0.587 + d.data[i + 2] * 0.114;
return {
g: o,
w: w,
h: h
};
};
const s = (m) => {
const w = m.w;
const h = m.h;
const o = new Float32Array(w * h);
const x = [-1, 0, 1, -2, 0, 2, -1, 0, 1];
const y = [-1, -2, -1, 0, 0, 0, 1, 2, 1];
for (let j = 1; j < h - 1; j++) {
for (let i = 1; i < w - 1; i++) {
let p = 0,
q = 0,
k = 0;
for (let b = -1; b <= 1; b++) {
for (let a = -1; a <= 1; a++) {
const v = m.g[(j + b) * w + (i + a)];
p += v * x[k];
q += v * y[k++];
}
}
o[j * w + i] = Math.sqrt(p * p + q * q);
}
}
return {
g: o,
w: w,
h: h
};
};
const n = (g, p, x, y) => {
let a = 0,
b = 0,
n = p.w * p.h;
for (let j = 0; j < p.h; j++) {
for (let i = 0; i < p.w; i++) {
a += g.g[(y + j) * g.w + (x + i)];
b += p.g[j * p.w + i];
}
}
let u = a / n,
v = b / n,
num = 0,
d1 = 0,
d2 = 0;
for (let j = 0; j < p.h; j++) {
for (let i = 0; i < p.w; i++) {
let s = g.g[(y + j) * g.w + (x + i)] - u;
let t = p.g[j * p.w + i] - v;
num += s * t;
d1 += s * s;
d2 += t * t;
}
}
return Math.sqrt(d1 * d2) < 1e-6 ? 0 : num / Math.sqrt(d1 * d2);
};
const h = (gImg, pImg, t) => {
const bgMat = s(g(i(gImg)));
const pcMat = s(g(i(pImg)));
let mx = bgMat.w - pcMat.w;
let bx = 0,
bst = -1;
let y = parseInt(t.style.top) || 0;
y = Math.max(0, Math.min(y, bgMat.h - pcMat.h));
for (let x = 0; x <= mx; x += 4) {
let sVal = n(bgMat, pcMat, x, y);
if (sVal > bst) {
bst = sVal;
bx = x;
}
}
return bst > 0.1 ? {
x: bx,
w: pcMat.w
} : null;
};
const d = async (e, s, t, y) => {
e.dispatchEvent(new MouseEvent('mousedown', {
bubbles: true,
clientX: s,
clientY: y,
buttons: 1
}));
await w(120);
for (let i = 0; i <= 40; i++) {
let k = i / 40;
let x = s + (t - s) * (1 - Math.pow(1 - k, 4));
e.dispatchEvent(new MouseEvent('mousemove', {
bubbles: true,
clientX: x,
clientY: y,
buttons: 1
}));
await w(10);
}
e.dispatchEvent(new MouseEvent('mouseup', {
bubbles: true,
clientX: t,
clientY: y
}));
};
const z = async () => {
if (b || v() || !r()) return;
b = true;
const g = document.querySelector('.gc-picture');
const t = document.querySelector('.gc-tile');
const m = t.querySelector('img');
const s = document.querySelector('.gc-drag-block');
await w(400);
const a = h(g, m, t);
if (!a) {
await f();
b = false;
return;
}
const c = g.getBoundingClientRect();
const l = t.getBoundingClientRect();
const k = s.getBoundingClientRect();
const q = c.width / g.naturalWidth;
const j = c.left + (a.x + a.w / 2) * q;
const e = j - (l.left + l.width / 2);
const x = k.left + k.width / 2;
const y = x + e;
const u = k.top + k.height / 2;
await d(s, x, y, u);
await w(1200);
b = false;
};
setInterval(() => {
if (v()) return;
if (!r()) o();
z();
}, 1500);
})();