Menangani AntiCaptcha (chillfaucet.in/offerzono.com) dan uCaptcha (litoshipay.com/claimlitoshi.top)
// ==UserScript==
// @name AntiCaptcha & uCaptcha Solver
// @namespace http://tampermonkey.net/ http://violentmonkey.net
// @version 1.0
// @description Menangani AntiCaptcha (chillfaucet.in/offerzono.com) dan uCaptcha (litoshipay.com/claimlitoshi.top)
// @author OjoNgono
// @match https://chillfaucet.in/*
// @match https://offerzono.com/*
// @match https://litoshipay.com/*
// @match https://claimlitoshi.top/*
// @grant none
// @run-at document-end
// @icon https://i.ibb.co/XJSPdz0/large.png
// @license Copyright of OjoNgono
// ==/UserScript==
(function() {
'use strict';
// ========== DETEKSI JENIS SITUS ==========
const currentUrl = window.location.hostname;
const isAntiCaptchaSite = currentUrl.includes('chillfaucet.in') || currentUrl.includes('offerzono.com');
const isUCaptchaSite = currentUrl.includes('litoshipay.com') || currentUrl.includes('claimlitoshi.top');
console.log(`Combined Captcha Solver: Running on ${currentUrl} (${isAntiCaptchaSite ? 'AntiCaptcha' : isUCaptchaSite ? 'uCaptcha' : 'Unknown'})`);
// ========== ANTI-CAPTCHA SECTION ==========
if (isAntiCaptchaSite) {
// ========== ANTI-CAPTCHA SETTING ==========
const WEIGHTS = {
ssim: 44,
contour: 3,
color: 12,
edge: 13,
template: 8,
histogram: 20
};
const ANTI_CONFIG = {
weights: WEIGHTS,
autoStart: true,
maxRetries: 5,
maxSessionRetries: 3,
retryDelay: 2000,
checkboxDelay: 1500,
errorCheckDelay: 1000,
refreshDelay: 3000,
debugMode: false,
boxTimeout: 25000 // 25 detik timeout untuk anticap-box
};
let isProcessing = false;
let retryCount = 0;
let sessionRetryCount = 0;
let captchaSolved = false;
let errorObserver = null;
let boxTimeoutId = null;
// ========== ANTI-CAPTCHA UTILITY ==========
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// ========== ANTI-CAPTCHA FUNGSI SCROLL ==========
function scrollToAnticapBox() {
const anticapBox = document.querySelector('[data-id="anticap-box"]');
if (anticapBox) {
anticapBox.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
return true;
}
return false;
}
// ========== ANTI-CAPTCHA FUNGSI REFRESH ==========
function refreshAnticapBox() {
console.log('AntiCaptcha: Timeout 25 detik, merefresh anticap-box...');
// Cari tombol refresh atau reload captcha
const refreshButton = document.querySelector('[data-id="anticap-refresh"], .anticap-refresh, button[onclick*="refresh"]');
if (refreshButton) {
refreshButton.click();
return true;
}
// Alternatif: reload halaman jika tidak ada tombol refresh
location.reload();
return false;
}
// ========== ANTI-CAPTCHA FUNGSI CEK STATUS ==========
function checkAntiCaptchaStatus() {
const feedback = document.querySelector('[data-id="anticap-feedback"]');
if (feedback) {
const text = feedback.textContent || '';
if (text.includes('Success') || text.includes('success')) {
return 'success';
}
if (text.includes('Error') || text.includes('error') || text.includes('Wrong')) {
return 'error';
}
}
// Cek juga dari info label
const infoLabel = document.querySelector('[data-id="anticap-info-label"]');
if (infoLabel) {
const text = infoLabel.textContent || '';
if (text.includes('Success')) return 'success';
if (text.includes('Error')) return 'error';
}
return 'unknown';
}
// ========== ANTI-CAPTCHA FUNGSI MONITOR TIMEOUT ==========
function startAntiCaptchaTimeoutMonitor() {
// Hapus timeout sebelumnya jika ada
if (boxTimeoutId) {
clearTimeout(boxTimeoutId);
}
// Set timeout baru
boxTimeoutId = setTimeout(async () => {
const status = checkAntiCaptchaStatus();
// Jika masih unknown (tidak ada respon success/error) setelah 25 detik
if (status === 'unknown' && !captchaSolved) {
console.log('AntiCaptcha: Box tidak merespon selama 25 detik');
// Reset processing state
isProcessing = false;
// Refresh box
refreshAnticapBox();
// Tunggu sebentar lalu coba lagi
await wait(3000);
if (!captchaSolved && !isProcessing) {
solveAntiCaptcha();
}
}
boxTimeoutId = null;
}, ANTI_CONFIG.boxTimeout);
}
// ========== ANTI-CAPTCHA ERROR DETECTION ==========
function checkAntiCaptchaError() {
const feedback = document.querySelector('[data-id="anticap-feedback"]');
if (feedback && feedback.classList.contains('error')) {
const errorText = feedback.textContent || '';
if (errorText.includes('Wrong selection') || errorText.includes('Try again')) {
return true;
}
}
const captchaRoot = document.querySelector('[data-id="anticap-root"]');
if (captchaRoot && captchaSolved) {
return true;
}
return false;
}
async function waitForAntiCaptchaError() {
const startTime = Date.now();
const timeout = 5000;
while (Date.now() - startTime < timeout) {
if (checkAntiCaptchaError()) {
return true;
}
await wait(500);
}
return false;
}
// ========== ANTI-CAPTCHA REFRESH PAGE ==========
function refreshAntiCaptchaPage() {
sessionRetryCount++;
captchaSolved = false;
isProcessing = false;
if (errorObserver) {
errorObserver.disconnect();
}
if (boxTimeoutId) {
clearTimeout(boxTimeoutId);
}
location.reload();
}
// ========== ANTI-CAPTCHA CHECKBOX CLICK ==========
async function findAndClickAntiCaptchaCheckbox() {
// Scroll ke box terlebih dahulu
scrollToAnticapBox();
await wait(500); // Tunggu scroll selesai
const checkbox = document.querySelector('input[data-id="anticap-checkbox"]');
if (checkbox && !checkbox.disabled) {
checkbox.click();
checkbox.dispatchEvent(new Event('change', { bubbles: true }));
checkbox.dispatchEvent(new Event('input', { bubbles: true }));
['mousedown', 'mouseup', 'click'].forEach(eventType => {
checkbox.dispatchEvent(new MouseEvent(eventType, {
view: window,
bubbles: true,
cancelable: true
}));
});
return true;
}
const toggleLabel = document.querySelector('.anticap-toggle');
if (toggleLabel) {
toggleLabel.click();
return true;
}
const elements = document.querySelectorAll('span, div, label');
for (let el of elements) {
if (el.textContent && el.textContent.includes('I\'m not a robot')) {
el.click();
return true;
}
}
return false;
}
// ========== ANTI-CAPTCHA GRID DETECTION ==========
async function waitForAntiCaptchaGrid(timeout = 8000) {
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
const grid = document.querySelector('[data-id="anticap-grid"]');
if (grid && grid.children.length > 0) {
return grid;
}
await wait(300);
}
return null;
}
// ========== ANTI-CAPTCHA IMAGE PROCESSING ==========
async function loadImage(src, size = 128) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, size, size);
resolve(ctx.getImageData(0, 0, size, size));
};
img.onerror = reject;
img.src = src;
});
}
// SSIM
function calculateSSIM(img1, img2) {
let mssim = 0;
let windows = 0;
for (let y = 0; y < 128 - 8; y += 4) {
for (let x = 0; x < 128 - 8; x += 4) {
let mu1 = 0, mu2 = 0, sigma1 = 0, sigma2 = 0, sigma12 = 0;
for (let wy = 0; wy < 8; wy++) {
for (let wx = 0; wx < 8; wx++) {
const idx = ((y + wy) * 128 + (x + wx)) * 4;
const val1 = (img1.data[idx] + img1.data[idx+1] + img1.data[idx+2]) / 3;
const val2 = (img2.data[idx] + img2.data[idx+1] + img2.data[idx+2]) / 3;
mu1 += val1;
mu2 += val2;
}
}
mu1 /= 64;
mu2 /= 64;
for (let wy = 0; wy < 8; wy++) {
for (let wx = 0; wx < 8; wx++) {
const idx = ((y + wy) * 128 + (x + wx)) * 4;
const val1 = (img1.data[idx] + img1.data[idx+1] + img1.data[idx+2]) / 3;
const val2 = (img2.data[idx] + img2.data[idx+1] + img2.data[idx+2]) / 3;
sigma1 += Math.pow(val1 - mu1, 2);
sigma2 += Math.pow(val2 - mu2, 2);
sigma12 += (val1 - mu1) * (val2 - mu2);
}
}
sigma1 = Math.sqrt(sigma1 / 63);
sigma2 = Math.sqrt(sigma2 / 63);
sigma12 /= 63;
const c1 = 0.01 * 255;
const c2 = 0.03 * 255;
const ssim = ((2 * mu1 * mu2 + c1) * (2 * sigma12 + c2)) /
((mu1 * mu1 + mu2 * mu2 + c1) * (sigma1 * sigma1 + sigma2 * sigma2 + c2));
if (!isNaN(ssim)) {
mssim += ssim;
windows++;
}
}
}
return windows > 0 ? mssim / windows : 0;
}
// Contour detection
function detectContours(img) {
const width = 128;
const height = 128;
const binary = new Array(width * height);
for (let i = 0; i < img.data.length; i += 4) {
const gray = (img.data[i] + img.data[i+1] + img.data[i+2]) / 3;
binary[i/4] = gray < 128 ? 1 : 0;
}
let contourCount = 0;
const visited = new Array(width * height).fill(false);
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < width - 1; x++) {
const idx = y * width + x;
if (binary[idx] === 1 && !visited[idx]) {
contourCount++;
const stack = [{x, y}];
while (stack.length) {
const p = stack.pop();
const pIdx = p.y * width + p.x;
if (p.x < 0 || p.x >= width || p.y < 0 || p.y >= height) continue;
if (visited[pIdx] || binary[pIdx] !== 1) continue;
visited[pIdx] = true;
stack.push({x: p.x+1, y: p.y});
stack.push({x: p.x-1, y: p.y});
stack.push({x: p.x, y: p.y+1});
stack.push({x: p.x, y: p.y-1});
}
}
}
}
return contourCount;
}
// Color similarity
function calculateColorSimilarity(img1, img2) {
let diff = 0;
const samples = 800;
const step = Math.floor(img1.data.length / 4 / samples) * 4;
for (let i = 0; i < img1.data.length; i += step) {
const rDiff = Math.abs(img1.data[i] - img2.data[i]);
const gDiff = Math.abs(img1.data[i+1] - img2.data[i+1]);
const bDiff = Math.abs(img1.data[i+2] - img2.data[i+2]);
diff += (rDiff + gDiff + bDiff) / 3;
}
return 1 - (diff / (255 * samples));
}
// Edge detection
function detectEdges(img) {
let edgeCount = 0;
for (let y = 1; y < 127; y++) {
for (let x = 1; x < 127; x++) {
const idx = (y * 128 + x) * 4;
const left = (img.data[((y) * 128 + (x-1)) * 4] +
img.data[((y) * 128 + (x-1)) * 4 + 1] +
img.data[((y) * 128 + (x-1)) * 4 + 2]) / 3;
const right = (img.data[((y) * 128 + (x+1)) * 4] +
img.data[((y) * 128 + (x+1)) * 4 + 1] +
img.data[((y) * 128 + (x+1)) * 4 + 2]) / 3;
if (Math.abs(left - right) > 30) edgeCount++;
}
}
return edgeCount;
}
// Template matching
function templateMatching(img1, img2) {
let bestScore = 0;
for (let y = 0; y <= 64; y += 8) {
for (let x = 0; x <= 64; x += 8) {
let score = 0;
for (let ty = 0; ty < 64; ty += 2) {
for (let tx = 0; tx < 64; tx += 2) {
const pIdx = (ty * 128 + tx) * 4;
const gIdx = ((y + ty) * 128 + (x + tx)) * 4;
const rDiff = Math.abs(img1.data[pIdx] - img2.data[gIdx]);
const gDiff = Math.abs(img1.data[pIdx+1] - img2.data[gIdx+1]);
const bDiff = Math.abs(img1.data[pIdx+2] - img2.data[gIdx+2]);
score += (255*3 - (rDiff + gDiff + bDiff)) / (255*3);
}
}
bestScore = Math.max(bestScore, score / (32*32));
}
}
return bestScore;
}
// Histogram
function calculateHistogram(img) {
const hist = new Array(48).fill(0);
for (let i = 0; i < img.data.length; i += 4) {
const r = Math.floor(img.data[i] / 32);
const g = Math.floor(img.data[i+1] / 32);
const b = Math.floor(img.data[i+2] / 32);
hist[r]++;
hist[16 + g]++;
hist[32 + b]++;
}
return hist;
}
function compareHistogram(h1, h2) {
let sim = 0;
for (let i = 0; i < 48; i++) {
const max = Math.max(h1[i], h2[i], 1);
sim += 1 - Math.abs(h1[i] - h2[i]) / max;
}
return sim / 48;
}
// ========== ANTI-CAPTCHA MAIN SOLVER ==========
async function solveAntiCaptcha() {
if (isProcessing || captchaSolved) return;
if (sessionRetryCount >= ANTI_CONFIG.maxSessionRetries) {
return;
}
isProcessing = true;
// Mulai monitor timeout untuk box
startAntiCaptchaTimeoutMonitor();
try {
await findAndClickAntiCaptchaCheckbox();
await wait(ANTI_CONFIG.checkboxDelay);
const grid = await waitForAntiCaptchaGrid();
if (!grid) {
throw new Error('Grid tidak muncul');
}
const previewImg = document.querySelector('.anticap-preview');
if (!previewImg) {
throw new Error('Preview tidak ditemukan');
}
const previewData = await loadImage(previewImg.src, 128);
const previewContours = detectContours(previewData);
const previewEdges = detectEdges(previewData);
const previewHist = calculateHistogram(previewData);
const items = Array.from(grid.querySelectorAll('.anticap-item img'));
const matches = [];
for (let i = 0; i < items.length; i++) {
try {
const gridData = await loadImage(items[i].src, 128);
const ssim = calculateSSIM(previewData, gridData);
const contour = 1 - (Math.abs(previewContours - detectContours(gridData)) / Math.max(previewContours, 1));
const color = calculateColorSimilarity(previewData, gridData);
const edge = 1 - (Math.abs(previewEdges - detectEdges(gridData)) / Math.max(previewEdges, 1));
const template = templateMatching(previewData, gridData);
const histogram = compareHistogram(previewHist, calculateHistogram(gridData));
const totalWeight = (WEIGHTS.ssim + WEIGHTS.contour + WEIGHTS.color +
WEIGHTS.edge + WEIGHTS.template + WEIGHTS.histogram) / 100;
const score = (
(ssim * WEIGHTS.ssim) +
(contour * WEIGHTS.contour) +
(color * WEIGHTS.color) +
(edge * WEIGHTS.edge) +
(template * WEIGHTS.template) +
(histogram * WEIGHTS.histogram)
) / (totalWeight * 100);
matches.push({
index: i,
element: items[i].closest('.anticap-item'),
score: score
});
} catch (e) {}
}
matches.sort((a, b) => b.score - a.score);
const best = matches[0];
if (!best) {
throw new Error('Tidak ada gambar');
}
await wait(300);
best.element.scrollIntoView({ behavior: 'smooth', block: 'center' });
await wait(200);
best.element.click();
best.element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
best.element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
best.element.dispatchEvent(new MouseEvent('click', { bubbles: true }));
await wait(ANTI_CONFIG.errorCheckDelay);
// Cek status box setelah klik
const status = checkAntiCaptchaStatus();
if (checkAntiCaptchaError() || status === 'error') {
if (retryCount < ANTI_CONFIG.maxRetries) {
retryCount++;
isProcessing = false;
await wait(ANTI_CONFIG.retryDelay);
await solveAntiCaptcha();
} else {
refreshAntiCaptchaPage();
}
} else if (status === 'success') {
captchaSolved = true;
retryCount = 0;
sessionRetryCount = 0;
// Hentikan monitor timeout karena sudah success
if (boxTimeoutId) {
clearTimeout(boxTimeoutId);
}
}
} catch (error) {
if (retryCount < ANTI_CONFIG.maxRetries) {
retryCount++;
await wait(ANTI_CONFIG.retryDelay);
isProcessing = false;
await solveAntiCaptcha();
} else {
refreshAntiCaptchaPage();
}
} finally {
isProcessing = false;
}
}
// ========== ANTI-CAPTCHA ERROR OBSERVER ==========
function startAntiCaptchaErrorObserver() {
if (errorObserver) {
errorObserver.disconnect();
}
errorObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === 'childList' || mutation.type === 'attributes') {
const feedback = document.querySelector('[data-id="anticap-feedback"].error');
if (feedback && !isProcessing && !captchaSolved) {
if (retryCount < ANTI_CONFIG.maxRetries) {
retryCount++;
setTimeout(() => {
isProcessing = false;
solveAntiCaptcha();
}, ANTI_CONFIG.retryDelay);
} else {
refreshAntiCaptchaPage();
}
}
}
}
});
errorObserver.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class']
});
}
// ========== ANTI-CAPTCHA INITIALIZATION ==========
function initAntiCaptcha() {
startAntiCaptchaErrorObserver();
const captchaObserver = new MutationObserver((mutations) => {
if (captchaSolved) return;
for (const mutation of mutations) {
if (mutation.addedNodes.length) {
if (document.querySelector('[data-id="anticap-root"]')) {
if (ANTI_CONFIG.autoStart && !isProcessing && !captchaSolved) {
setTimeout(solveAntiCaptcha, 1000);
}
}
}
}
});
captchaObserver.observe(document.body, {
childList: true,
subtree: true
});
if (document.querySelector('[data-id="anticap-root"]')) {
setTimeout(solveAntiCaptcha, 2000);
}
}
// Jalankan AntiCaptcha
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initAntiCaptcha);
} else {
initAntiCaptcha();
}
}
// ========== uCaptcha SECTION ==========
if (isUCaptchaSite) {
// ========== uCaptcha KONFIGURASI ==========
const WIDGET_SELECTOR = 'div.upside-captcha-widget[data-pc-theme="light"][data-ucaptcha="widget"]';
const CHECKBOX_SELECTOR = 'input[data-uc-checkbox]';
const CONTAINER_SELECTOR = 'div.ucaptcha-container[data-uc-container]';
const SHOW_SELECTOR = 'div.ucaptcha-show[data-uc-show]';
const IMG_SELECTOR = 'img[data-uc-img]';
const DOT_SELECTOR = '[data-uc-dot]';
let ukuranGambar = 40;
let widgetElement = null;
let refreshTimer = null;
let klikTerjadi = false;
let prosesSedangBerjalan = false;
// ========== uCaptcha FUNGSI CEK APAKAH SUDAH ADA KLIK ==========
function isUCaptchaClicked() {
// Cek apakah sudah ada elemen dot (indikator sudah diklik)
return document.querySelector(DOT_SELECTOR) !== null;
}
// ========== uCaptcha FUNGSI RESET TIMER ==========
function resetUCaptchaRefreshTimer() {
if (refreshTimer) {
clearTimeout(refreshTimer);
}
refreshTimer = setTimeout(() => {
if (!klikTerjadi && !isUCaptchaClicked() && widgetElement) {
console.log('⏰ 25 detik tanpa klik - Merefresh widget uCaptcha...');
refreshUCaptchaWidget();
}
}, 25000); // 25 detik
}
// ========== uCaptcha FUNGSI REFRESH WIDGET ==========
function refreshUCaptchaWidget() {
if (!widgetElement || prosesSedangBerjalan) return;
// Cari checkbox dan klik ulang untuk memicu refresh
const checkbox = widgetElement.querySelector(CHECKBOX_SELECTOR);
if (checkbox) {
prosesSedangBerjalan = true;
klikTerjadi = false;
// Uncheck dulu jika sudah checked
if (checkbox.checked) {
checkbox.click();
}
// Trigger events
['mousedown', 'mouseup', 'change'].forEach(t => {
try {
checkbox.dispatchEvent(new Event(t, { bubbles: true }));
} catch (e) {}
});
// Tunggu sebentar lalu check lagi
setTimeout(() => {
if (!checkbox.checked) {
checkbox.click();
['mousedown', 'mouseup', 'change'].forEach(t => {
try {
checkbox.dispatchEvent(new Event(t, { bubbles: true }));
} catch (e) {}
});
}
// Reset timer dan proses
setTimeout(() => {
prosesSedangBerjalan = false;
resetUCaptchaRefreshTimer();
// Mulai proses klik lagi
setTimeout(() => {
klikUCaptchaGambarFlipped();
}, 2000);
}, 3000);
}, 1000);
}
}
// ========== uCaptcha FUNGSI CEK APAKAH INI WIDGET YANG DITUJU ==========
function isTargetUCaptchaWidget() {
widgetElement = document.querySelector(WIDGET_SELECTOR);
return widgetElement !== null;
}
// ========== uCaptcha FUNGSI TUNGGU WIDGET READY ==========
function tungguUCaptchaPageLoad() {
return new Promise(resolve => {
if (document.readyState === 'complete') {
resolve();
} else {
window.addEventListener('load', resolve);
}
});
}
// ========== uCaptcha FUNGSI SCROLL KE WIDGET ==========
function scrollKeUCaptchaWidget() {
return new Promise(resolve => {
if (!widgetElement) {
resolve();
return;
}
// Scroll ke widget
widgetElement.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
// Tunggu scroll selesai
setTimeout(resolve, 1500);
});
}
// ========== uCaptcha FUNGSI CENTANG CHECKBOX ==========
async function centangUCaptchaCheckbox() {
if (!widgetElement) return false;
// Cari checkbox hanya dalam widget
const checkbox = widgetElement.querySelector(CHECKBOX_SELECTOR);
if (checkbox && !checkbox.checked) {
checkbox.click();
// Trigger events
['mousedown', 'mouseup', 'change'].forEach(t => {
try {
checkbox.dispatchEvent(new Event(t, { bubbles: true }));
} catch (e) {}
});
// Tunggu captcha muncul
await new Promise(r => setTimeout(r, 3000));
return true;
}
return checkbox !== null;
}
// ========== uCaptcha FUNGSI CEK APAKAH ELEMEN VISIBLE ==========
function isUCaptchaElementVisible(el) {
if (!el) return false;
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
// ========== uCaptcha FUNGSI KLIK GAMBAR FLIPPED ==========
async function klikUCaptchaGambarFlipped() {
if (!widgetElement) return false;
// Reset status klik
klikTerjadi = false;
// Reset timer
resetUCaptchaRefreshTimer();
// Tunggu data captcha (max 20 detik)
for (let i = 0; i < 20; i++) {
// Cek apakah sudah ada klik dari luar
if (isUCaptchaClicked()) {
console.log('✅ uCaptcha sudah diklik secara manual');
klikTerjadi = true;
if (refreshTimer) clearTimeout(refreshTimer);
return true;
}
if (window.UCaptchaPos && window.UCaptchaPos.length > 0) {
// Ambil ukuran gambar
if (window.UCaptchaPos[0] && window.UCaptchaPos[0].icon_size) {
ukuranGambar = window.UCaptchaPos[0].icon_size;
}
// Filter gambar flipped
const flippedItems = window.UCaptchaPos.filter(item => item.flipped === true);
if (flippedItems.length === 0) {
return false;
}
// Cari elemen show dalam widget
const showElement = widgetElement.querySelector(SHOW_SELECTOR);
if (!showElement) return false;
// Scroll ke show element
showElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
await new Promise(r => setTimeout(r, 1500));
// Pastikan visible
if (!isUCaptchaElementVisible(showElement)) {
showElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
await new Promise(r => setTimeout(r, 1500));
}
const rect = showElement.getBoundingClientRect();
// Klik semua gambar flipped
for (const item of flippedItems) {
// Hitung titik tengah
const x = rect.left + item.x + ukuranGambar/2;
const y = rect.top + item.y + ukuranGambar/2;
// Pastikan koordinat dalam viewport
if (x >= 0 && x <= window.innerWidth && y >= 0 && y <= window.innerHeight) {
const el = document.elementFromPoint(x, y);
if (el) {
// Direct click
el.click();
// Simulasi events
['mousedown', 'mouseup', 'click'].forEach(t => {
try {
const event = new MouseEvent(t, {
clientX: x,
clientY: y,
bubbles: true,
cancelable: true,
view: window
});
el.dispatchEvent(event);
} catch (e) {}
});
// Tandai bahwa klik sudah terjadi
klikTerjadi = true;
}
}
// Jeda antar klik
await new Promise(r => setTimeout(r, 400));
}
// Reset timer setelah klik
if (klikTerjadi) {
if (refreshTimer) clearTimeout(refreshTimer);
}
return true;
}
await new Promise(r => setTimeout(r, 1000));
}
return false;
}
// ========== uCaptcha FUNGSI UTAMA ==========
async function mainUCaptcha() {
// Cek apakah ini widget yang dituju
if (!isTargetUCaptchaWidget()) {
return;
}
// Tunggu page load
await tungguUCaptchaPageLoad();
// Scroll ke widget
await scrollKeUCaptchaWidget();
// Centang checkbox
await centangUCaptchaCheckbox();
// Klik gambar flipped
await klikUCaptchaGambarFlipped();
}
// ========== uCaptcha EKSEKUSI ==========
// Jalankan setelah DOM siap
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
setTimeout(mainUCaptcha, 1000);
});
} else {
setTimeout(mainUCaptcha, 1000);
}
// Observer untuk mendeteksi jika widget muncul kemudian
const uCaptchaObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.addedNodes.length) {
for (const node of mutation.addedNodes) {
if (node.nodeType === 1) {
if (node.matches && node.matches(WIDGET_SELECTOR)) {
setTimeout(mainUCaptcha, 1000);
break;
}
if (node.querySelector && node.querySelector(WIDGET_SELECTOR)) {
setTimeout(mainUCaptcha, 1000);
break;
}
}
}
}
}
});
uCaptchaObserver.observe(document.body, {
childList: true,
subtree: true
});
// Observer untuk mendeteksi klik manual
const uCaptchaClickObserver = new MutationObserver(() => {
if (isUCaptchaClicked() && refreshTimer) {
clearTimeout(refreshTimer);
}
});
// Tunggu sebentar sebelum observe dot
setTimeout(() => {
uCaptchaClickObserver.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['data-uc-dot']
});
}, 5000);
}
// ========== LOG STATUS ==========
console.log(`Combined Captcha Solver: Active on ${currentUrl}`);
if (isAntiCaptchaSite) {
console.log('Mode: AntiCaptcha (chillfaucet/offerzono)');
} else if (isUCaptchaSite) {
console.log('Mode: uCaptcha (litoshipay/claimlitoshi)');
}
})();