/* Make sure you have Node.JS and Outguess.app installed. Copy this file as 'outguess.js' into an empty folder. In that folder, run: npm init npm i guess-file-type tmp png-js Change OUTGUESS_APP, WORK_DIR, SOURCE and VERBOSE below as you need them. Add your keys to the keys array below. Then run: node outguess Note: guess-file-type might yield false positives */ const { spawn } = require('child_process'); const fileGuesser = require('guess-file-type'); const tmp = require('tmp'); const fs = require('fs'); const OUTGUESS_APP = '/Applications/Outguess.app/Contents/outguess'; const WORK_DIR = '/Users/claus/Downloads/'; const SOURCE = WORK_DIR + 'Syphon-Signal-Registered-VIVIVICIVICIIVIII.jpg'; const VERBOSE = true; const keys = [ 'Gorham, New Hampshire', 'Zurich, Switzerland', ]; const allKeys = keys .map(key => permutations(key)) .flat() .filter((item, i, arr) => arr.indexOf(item) == i); console.log(`Testing ${allKeys.length} keys...`); outguessAll(); async function outguessAll() { for (let i = 0; i < allKeys.length; i++) { await outguess(allKeys[i]); } } function outguess(key) { const promise = new Promise((resolve, reject) => { const out = tmp.fileSync(); const child = spawn(OUTGUESS_APP, ['-k', key, '-r', SOURCE, out.name]); child.on('close', async code => { const mime = await fileGuesser.guessByFileSignature(out.name); if (mime != null && mime !== 'unknown') { const ext = fileGuesser.getExtensionFromMime(mime); const file = `${WORK_DIR}${key}.${ext}`; fs.renameSync(out.name, file); resolve({ key, mime, file }); return; } reject({ key, code }); }); }); return promise .then(result => { console.log(`🎉🎉 ${result.key}: ${result.file} (${result.mime})`); return result; }) .catch(e => { VERBOSE && console.log(`👎 ${e.key}`); return e; }); } function permutations(input) { const rawKeys = input .split(',') .map(rawKey => rawKey.replace(/\s+/g, '').toLowerCase()); const keys = permutator(rawKeys).map(key => key.join('')); return keys; } function permutator(inputArr) { const result = []; const permute = (arr, m = []) => { if (arr.length === 0) { result.push(m); } else { for (let i = 0; i < arr.length; i++) { let curr = arr.slice(); let next = curr.splice(i, 1); permute(curr.slice(), m.concat(next)); } } }; combinations(inputArr).forEach(arr => permute(arr)); return result; } function combinations(arr) { var fn = function (active, rest, a) { if (active.length === 0 && rest.length === 0) { return; } if (rest.length === 0) { a.push(active); } else { fn([...active, rest[0]], rest.slice(1), a); fn(active, rest.slice(1), a); } return a; }; return fn([], arr, []); }