Last active
April 30, 2025 12:23
-
-
Save nicolas-goudry/3912ca31f1d8f630a8af160eedbe4df6 to your computer and use it in GitHub Desktop.
Want to be the best at Lucca Faces? Run the game, then execute this code into your console. Let it play until you are the best!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// New version courtesy of JCluzet. Thanks! | |
(() => { | |
const STORAGE_KEY = 'lucca_faces_data_v2'; | |
let people = JSON.parse(localStorage.getItem(STORAGE_KEY)) || {}; | |
let currentImageHash = ''; | |
let retryAttempts = 0; | |
const MAX_RETRY_ATTEMPTS = 5; // Adjust max attempts count | |
function getImageHash(imageSrc) { | |
return new Promise((resolve, reject) => { | |
const img = new Image(); | |
img.crossOrigin = 'Anonymous'; | |
img.onload = () => { | |
const canvas = document.createElement('canvas'); | |
const ctx = canvas.getContext('2d'); | |
canvas.width = img.width; | |
canvas.height = img.height; | |
ctx.drawImage(img, 0, 0, img.width, img.height); | |
canvas.toBlob(blob => { | |
const reader = new FileReader(); | |
reader.onloadend = () => { | |
crypto.subtle.digest('SHA-256', reader.result).then(hashBuffer => { | |
const hashArray = Array.from(new Uint8Array(hashBuffer)); | |
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); | |
resolve(hashHex); | |
}); | |
}; | |
reader.onerror = reject; | |
reader.readAsArrayBuffer(blob); | |
}); | |
}; | |
img.onerror = () => { | |
reject('Image load error'); | |
}; | |
img.src = imageSrc; | |
}); | |
} | |
async function handleNewImage(imageSrc) { | |
try { | |
const hashHex = await getImageHash(imageSrc); | |
if (hashHex !== currentImageHash) { | |
currentImageHash = hashHex; | |
if (people[currentImageHash]) { | |
const choices = document.querySelectorAll('#game .answers .answer'); | |
const correctAnswer = [...choices].find(choice => choice.textContent.trim() === people[currentImageHash].trim()); | |
if (correctAnswer) { | |
correctAnswer.click(); | |
} | |
} else { | |
chooseRandomAnswer(); | |
} | |
} | |
retryAttempts = 0; // Reset attempts counter on success | |
} catch (error) { | |
console.error('Error processing image:', error); | |
retryAttempts++; | |
if (retryAttempts <= MAX_RETRY_ATTEMPTS) { | |
console.log(`Retrying (${retryAttempts}/${MAX_RETRY_ATTEMPTS})...`); | |
retryHandleImage(imageSrc); | |
} else { | |
console.log('Max retry attempts reached. Skipping image.'); | |
retryAttempts = 0; // Reset attempts counter if limit reached | |
clickGoButton(); // Click on "Go" button after reaching end of the game | |
} | |
} | |
} | |
function retryHandleImage(imageSrc) { | |
setTimeout(() => handleNewImage(imageSrc), 100); | |
} | |
function chooseRandomAnswer() { | |
const choices = document.querySelectorAll('#game .answers .answer'); | |
const randomChoice = choices[Math.floor(Math.random() * choices.length)]; | |
randomChoice.click(); | |
setTimeout(() => { | |
const correctAnswer = document.querySelector('#game .answers .is-right'); | |
if (correctAnswer) { | |
const name = correctAnswer.textContent.trim(); | |
people[currentImageHash] = name; | |
localStorage.setItem(STORAGE_KEY, JSON.stringify(people)); | |
console.log(`Discovered ${name} for hash ${currentImageHash}`); | |
} else { | |
console.error('Failed to discover the correct answer!'); | |
} | |
}, 500); // Wait a bit to allow correct answer to be shown | |
} | |
function startGame() { | |
const startButtonContainer = document.querySelector('.main-container.has-loaded .logo .rotation-loader'); | |
if (startButtonContainer) { | |
startButtonContainer.click(); | |
console.log('Clicked the start button'); | |
} else { | |
console.error('Start button not found. Make sure the game is loaded.'); | |
} | |
} | |
function restartGame() { | |
const replayButton = document.querySelector('.main-container .results-card button.button.mod-pill.palette-secondary.mod-XL'); | |
if (replayButton) { | |
replayButton.click(); | |
console.log('Clicked the replay button'); | |
} else { | |
console.log('Please click "Replay" to restart the game.'); | |
} | |
} | |
function clickGoButton() { | |
// Try to click on several elements until "Go" button is found | |
const elementsToClick = [ | |
document.querySelector('.main-container .logo .rotation-loader'), | |
document.querySelector('.main-container .results-card button.button.mod-pill.palette-secondary.mod-XL'), | |
document.querySelector('.main-container .results-card button.button.mod-pill.palette-primary.mod-L'), | |
document.querySelector('.main-container .results-card button.button.mod-pill.palette-primary.mod-XL'), | |
document.querySelector('.main-container .results-card button.button.mod-pill.palette-tertiary.mod-XL') | |
// Add other CSS selectors here if needed | |
]; | |
let clicked = false; | |
elementsToClick.forEach(element => { | |
if (element && !clicked) { | |
element.click(); | |
console.log('Clicked a button to restart the game.'); | |
clicked = true; | |
} | |
}); | |
if (!clicked) { | |
console.log('Go button not found. Please click "Replay" and "Go" manually to restart.'); | |
} | |
} | |
function observeGame() { | |
const gameElement = document.querySelector('#game'); | |
if (!gameElement) { | |
console.error('Game element not found. Make sure the game is loaded.'); | |
return; | |
} | |
const observer = new MutationObserver(() => { | |
const imageElement = document.querySelector('#game app-timer .image'); | |
if (imageElement) { | |
const imageSrc = imageElement.style.backgroundImage.match(/url\("(.*)"\)/)[1]; | |
handleNewImage(imageSrc); | |
} | |
const gameEnded = !!document.querySelector('.main-container .results-card'); | |
if (gameEnded) { | |
restartGame(); | |
startGame(); // Restart game after click on "Rejouer" and "Go" | |
} | |
}); | |
observer.observe(gameElement, { childList: true, subtree: true }); | |
} | |
function main() { | |
startGame(); | |
observeGame(); | |
console.log('Script loaded: It will automatically start the game and handle answers.'); | |
} | |
// Start main function right away | |
main(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tweaked the code a bit so it could run before even pressing "Go."
So, it's very simple: