diff --git a/Auto-Image.js b/Auto-Image.js
index 27f5396..320a564 100644
--- a/Auto-Image.js
+++ b/Auto-Image.js
@@ -1,5 +1,4 @@
(async () => {
- // Configurações
const CONFIG = {
COOLDOWN_DEFAULT: 31000,
TRANSPARENCY_THRESHOLD: 100,
@@ -16,7 +15,6 @@
}
};
- // Estado do aplicativo
const state = {
running: false,
imageLoaded: false,
@@ -33,10 +31,10 @@
selectingPosition: false,
region: null,
minimized: false,
- lastPosition: { x: 0, y: 0 } // Armazena a última posição pintada
+ lastPosition: { x: 0, y: 0 },
+ language: 'en'
};
- // Funções utilitárias
const Utils = {
sleep: ms => new Promise(r => setTimeout(r, ms)),
@@ -114,7 +112,6 @@
}
};
- // Serviço de comunicação com a API
const WPlaceService = {
async paintPixelInRegion(regionX, regionY, pixelX, pixelY, color) {
try {
@@ -127,7 +124,6 @@
const data = await res.json();
return data?.painted === 1;
} catch (error) {
- console.error('Erro ao pintar pixel:', error);
return false;
}
},
@@ -143,13 +139,11 @@
cooldown: data.charges?.cooldownMs || CONFIG.COOLDOWN_DEFAULT
};
} catch (error) {
- console.error('Erro ao obter cargas:', error);
return { charges: 0, cooldown: CONFIG.COOLDOWN_DEFAULT };
}
}
};
- // Processador de imagem
class ImageProcessor {
constructor(imageSrc) {
this.imageSrc = imageSrc;
@@ -179,7 +173,6 @@
}
}
- // Encontra a cor mais próxima
function findClosestColor(rgb, palette) {
let closestColor = palette[0];
let minDistance = Utils.colorDistance(rgb, palette[0].rgb);
@@ -195,15 +188,81 @@
return closestColor.id;
}
- // Cria a interface do usuário
+ async function detectUserLanguage() {
+ try {
+ const response = await fetch('https://ipapi.co/json/');
+ const data = await response.json();
+ if (data.country === 'BR') {
+ state.language = 'pt';
+ } else if (data.country === 'US') {
+ state.language = 'en';
+ } else {
+ state.language = 'en';
+ }
+ } catch {
+ state.language = 'en';
+ }
+ }
+
function createUI() {
- // Adiciona Font Awesome
+ const translations = {
+ pt: {
+ title: "WPlace Auto-Image",
+ initBot: "Iniciar Auto-BOT",
+ uploadImage: "Upload da Imagem",
+ selectPos: "Selecionar Posição",
+ startPaint: "Iniciar Pintura",
+ stopPaint: "Parar Pintura",
+ noPosition: "Nenhuma posição selecionada",
+ waiting: "Aguardando inicialização...",
+ checkingColors: "Verificando cores disponíveis...",
+ noColors: "Nenhuma cor disponível encontrada",
+ colorsFound: "cores disponíveis encontradas",
+ loadingImage: "Carregando imagem...",
+ imageLoaded: "Imagem carregada com sucesso!",
+ selectPosition: "Aguardando você pintar o pixel de referência...",
+ positionSet: "Posição definida com sucesso!",
+ startPainting: "Iniciando pintura na região",
+ paintingStopped: "Pintura interrompida pelo usuário",
+ paintingComplete: "Pintura concluída!",
+ progress: "Progresso",
+ pixels: "Pixels",
+ charges: "Cargas",
+ remaining: "Restantes"
+ },
+ en: {
+ title: "WPlace Auto-Image",
+ initBot: "Start Auto-BOT",
+ uploadImage: "Upload Image",
+ selectPos: "Select Position",
+ startPaint: "Start Painting",
+ stopPaint: "Stop Painting",
+ noPosition: "No position selected",
+ waiting: "Waiting for initialization...",
+ checkingColors: "Checking available colors...",
+ noColors: "No available colors found",
+ colorsFound: "available colors found",
+ loadingImage: "Loading image...",
+ imageLoaded: "Image loaded successfully!",
+ selectPosition: "Waiting for you to paint the reference pixel...",
+ positionSet: "Position set successfully!",
+ startPainting: "Starting painting in region",
+ paintingStopped: "Painting stopped by user",
+ paintingComplete: "Painting completed!",
+ progress: "Progress",
+ pixels: "Pixels",
+ charges: "Charges",
+ remaining: "Remaining"
+ }
+ };
+
+ const t = translations[state.language] || translations.en;
+
const fontAwesome = document.createElement('link');
fontAwesome.rel = 'stylesheet';
fontAwesome.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css';
document.head.appendChild(fontAwesome);
- // Adiciona estilos
const style = document.createElement('style');
style.textContent = `
@keyframes pulse {
@@ -388,7 +447,6 @@
`;
document.head.appendChild(style);
- // Cria o container principal
const container = document.createElement('div');
container.id = 'wplace-image-bot-container';
container.innerHTML = `
@@ -396,10 +454,10 @@
`;
document.body.appendChild(container);
- // Tornar arrastável
const header = container.querySelector('.wplace-header');
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
@@ -485,7 +542,6 @@
document.onmousemove = null;
}
- // Elementos da UI
const initBotBtn = container.querySelector('#initBotBtn');
const uploadBtn = container.querySelector('#uploadBtn');
const selectPosBtn = container.querySelector('#selectPosBtn');
@@ -498,7 +554,6 @@
const positionInfo = container.querySelector('#positionInfo');
const content = container.querySelector('.wplace-content');
- // Minimizar/Maximizar
minimizeBtn.addEventListener('click', () => {
state.minimized = !state.minimized;
if (state.minimized) {
@@ -510,7 +565,6 @@
}
});
- // Atualiza a UI
window.updateUI = (message, type = 'default') => {
statusText.textContent = message;
statusText.className = `wplace-status status-${type}`;
@@ -519,12 +573,11 @@
statusText.style.animation = 'slideIn 0.3s ease-out';
};
- // Atualiza as estatísticas
window.updateStats = async () => {
if (!state.colorsChecked) return;
const { charges, cooldown } = await WPlaceService.getCharges();
- state.currentCharges = Math.floor(charges); // Arredonda para baixo
+ state.currentCharges = Math.floor(charges);
state.cooldown = cooldown;
const progress = state.totalPixels > 0 ?
@@ -535,68 +588,64 @@
statsArea.innerHTML = `
-
Progresso
+
${t.progress}
${progress}%
-
Pixels
+
${t.pixels}
${state.paintedPixels}/${state.totalPixels}
-
Cargas
-
${Math.floor(state.currentCharges)}
+
${t.charges}
+
${Math.floor(state.currentCharges)}
-
Restantes
-
${remainingPixels} pixels
+
${t.remaining}
+
${remainingPixels} ${t.pixels.toLowerCase()}
`;
};
- // Atualiza a informação da posição
function updatePositionInfo() {
if (state.startPosition && state.region) {
positionInfo.style.display = 'block';
positionInfo.innerHTML = `
- Posição: (${state.startPosition.x}, ${state.startPosition.y}) | Região: ${state.region.x}/${state.region.y}
+ ${state.language === 'pt' ? 'Posição' : 'Position'}: (${state.startPosition.x}, ${state.startPosition.y}) | ${state.language === 'pt' ? 'Região' : 'Region'}: ${state.region.x}/${state.region.y}
`;
} else {
positionInfo.style.display = 'none';
}
}
- // Evento do botão Iniciar Auto-BOT
initBotBtn.addEventListener('click', async () => {
try {
- updateUI('🔍 Verificando cores disponíveis...', 'default');
+ updateUI(`🔍 ${t.checkingColors}`, 'default');
state.availableColors = Utils.extractAvailableColors();
if (state.availableColors.length === 0) {
- Utils.showAlert('Abra a paleta de cores no site e tente novamente!', 'error');
- updateUI('❌ Nenhuma cor disponível encontrada', 'error');
+ Utils.showAlert(state.language === 'pt' ? 'Abra a paleta de cores no site e tente novamente!' : 'Open the color palette on the site and try again!', 'error');
+ updateUI(`❌ ${t.noColors}`, 'error');
return;
}
state.colorsChecked = true;
uploadBtn.disabled = false;
selectPosBtn.disabled = false;
- initBotBtn.style.display = 'none'; // Esconde o botão após iniciar
+ initBotBtn.style.display = 'none';
- updateUI(`✅ ${state.availableColors.length} cores disponíveis encontradas`, 'success');
+ updateUI(`✅ ${state.availableColors.length} ${t.colorsFound}`, 'success');
updateStats();
} catch (error) {
- console.error('Erro ao verificar cores:', error);
- updateUI('❌ Erro ao verificar cores', 'error');
+ updateUI('❌ ' + (state.language === 'pt' ? 'Erro ao verificar cores' : 'Error checking colors'), 'error');
}
});
- // Evento do botão Upload da Imagem
uploadBtn.addEventListener('click', async () => {
try {
- updateUI('🖼️ Carregando imagem...', 'default');
+ updateUI(`🖼️ ${t.loadingImage}`, 'default');
const imageSrc = await Utils.createImageUploader();
const processor = new ImageProcessor(imageSrc);
@@ -615,21 +664,19 @@
state.totalPixels = state.imageData.totalPixels;
state.paintedPixels = 0;
state.imageLoaded = true;
- state.lastPosition = { x: 0, y: 0 }; // Reseta a última posição
+ state.lastPosition = { x: 0, y: 0 };
if (state.startPosition) {
startBtn.disabled = false;
}
updateStats();
- updateUI('✅ Imagem carregada com sucesso!', 'success');
+ updateUI(`✅ ${t.imageLoaded}`, 'success');
} catch (error) {
- console.error('Erro ao carregar imagem:', error);
- updateUI('❌ Erro ao carregar imagem', 'error');
+ updateUI('❌ ' + (state.language === 'pt' ? 'Erro ao carregar imagem' : 'Error loading image'), 'error');
}
});
- // Evento do botão Selecionar Posição
selectPosBtn.addEventListener('click', async () => {
if (state.selectingPosition) return;
@@ -639,8 +686,8 @@
startBtn.disabled = true;
updatePositionInfo();
- Utils.showAlert('Pinte o primeiro pixel na localização onde deseja que a arte comece!', 'info');
- updateUI('👆 Aguardando você pintar o pixel de referência...', 'default');
+ Utils.showAlert(state.language === 'pt' ? 'Pinte o primeiro pixel na localização onde deseja que a arte comece!' : 'Paint the first pixel at the location where you want the art to start!', 'info');
+ updateUI(`👆 ${t.selectPosition}`, 'default');
const originalFetch = window.fetch;
@@ -669,11 +716,13 @@
x: payload.coords[0],
y: payload.coords[1]
};
- state.lastPosition = { x: 0, y: 0 }; // Reseta a última posição
+ state.lastPosition = { x: 0, y: 0 };
updatePositionInfo();
- updateUI('✅ Posição definida com sucesso!', 'success');
- Utils.showAlert(`Posição capturada na região ${state.region.x}/${state.region.y}!`, 'success');
+ updateUI(`✅ ${t.positionSet}`, 'success');
+ Utils.showAlert(state.language === 'pt' ?
+ `Posição capturada na região ${state.region.x}/${state.region.y}!` :
+ `Position captured in region ${state.region.x}/${state.region.y}!`, 'success');
if (state.imageLoaded) {
startBtn.disabled = false;
@@ -686,7 +735,6 @@
return response;
} catch (error) {
- console.error('Erro ao interceptar requisição:', error);
return originalFetch(url, options);
}
}
@@ -697,16 +745,15 @@
if (state.selectingPosition) {
window.fetch = originalFetch;
state.selectingPosition = false;
- updateUI('❌ Tempo esgotado para selecionar posição', 'error');
- Utils.showAlert('Tempo esgotado! Clique em "Selecionar Posição" novamente.', 'error');
+ updateUI('❌ ' + (state.language === 'pt' ? 'Tempo esgotado para selecionar posição' : 'Time expired to select position'), 'error');
+ Utils.showAlert(state.language === 'pt' ? 'Tempo esgotado! Clique em "Selecionar Posição" novamente.' : 'Time expired! Click "Select Position" again.', 'error');
}
}, 120000);
});
- // Evento do botão Iniciar Pintura
startBtn.addEventListener('click', async () => {
if (!state.imageLoaded || !state.startPosition || !state.region) {
- updateUI('❌ Carregue uma imagem e selecione uma posição primeiro', 'error');
+ updateUI('❌ ' + (state.language === 'pt' ? 'Carregue uma imagem e selecione uma posição primeiro' : 'Load an image and select a position first'), 'error');
return;
}
@@ -717,13 +764,12 @@
uploadBtn.disabled = true;
selectPosBtn.disabled = true;
- updateUI(`🎨 Iniciando pintura na região ${state.region.x}/${state.region.y}...`, 'success');
+ updateUI(`🎨 ${t.startPainting} ${state.region.x}/${state.region.y}...`, 'success');
try {
await processImage();
} catch (error) {
- console.error('Erro durante a pintura:', error);
- updateUI('❌ Erro durante a pintura', 'error');
+ updateUI('❌ ' + (state.language === 'pt' ? 'Erro durante a pintura' : 'Error during painting'), 'error');
} finally {
state.running = false;
stopBtn.disabled = true;
@@ -738,22 +784,19 @@
}
});
- // Evento do botão Parar Pintura
stopBtn.addEventListener('click', () => {
state.stopFlag = true;
state.running = false;
stopBtn.disabled = true;
- updateUI('⏹️ Pintura interrompida pelo usuário', 'warning');
+ updateUI(`⏹️ ${t.paintingStopped}`, 'warning');
});
}
- // Processa a imagem
async function processImage() {
const { width, height, pixels } = state.imageData;
const { x: startX, y: startY } = state.startPosition;
const { x: regionX, y: regionY } = state.region;
- // Começa da última posição ou do início
let startRow = state.lastPosition.y || 0;
let startCol = state.lastPosition.x || 0;
@@ -761,7 +804,6 @@
for (let y = startRow; y < height; y++) {
for (let x = (y === startRow ? startCol : 0); x < width; x++) {
if (state.stopFlag) {
- // Salva a última posição pintada
state.lastPosition = { x, y };
break outerLoop;
}
@@ -775,7 +817,7 @@
const colorId = findClosestColor(rgb, state.availableColors);
if (state.currentCharges < 1) {
- updateUI(`⌛ Sem cargas. Aguardando ${Utils.formatTime(state.cooldown)}...`, 'warning');
+ updateUI(`⌛ ${state.language === 'pt' ? 'Sem cargas. Aguardando' : 'No charges. Waiting'} ${Utils.formatTime(state.cooldown)}...`, 'warning');
await Utils.sleep(state.cooldown);
const chargeUpdate = await WPlaceService.getCharges();
@@ -800,23 +842,22 @@
if (state.paintedPixels % CONFIG.LOG_INTERVAL === 0) {
updateStats();
- updateUI(`🧱 Progresso: ${state.paintedPixels}/${state.totalPixels} pixels...`, 'default');
+ updateUI(`🧱 ${state.language === 'pt' ? 'Progresso' : 'Progress'}: ${state.paintedPixels}/${state.totalPixels} ${state.language === 'pt' ? 'pixels...' : 'pixels...'}`, 'default');
}
}
}
}
if (state.stopFlag) {
- updateUI('⏹️ Pintura interrompida pelo usuário', 'warning');
+ updateUI(`⏹️ ${t.paintingStopped}`, 'warning');
} else {
- updateUI(`✅ Pintura concluída! ${state.paintedPixels} pixels pintados.`, 'success');
- state.lastPosition = { x: 0, y: 0 }; // Reseta para próxima execução
+ updateUI(`✅ ${t.paintingComplete} ${state.paintedPixels} ${state.language === 'pt' ? 'pixels pintados.' : 'pixels painted.'}`, 'success');
+ state.lastPosition = { x: 0, y: 0 };
}
updateStats();
}
- // Inicialização
+ await detectUserLanguage();
createUI();
- console.log('WPlace Image Bot - Interface carregada com sucesso!');
})();