Skip to content

Instantly share code, notes, and snippets.

@iahuang
Last active March 22, 2021 16:36
Show Gist options
  • Save iahuang/d76936f6bc76134f63423aef8c7256ab to your computer and use it in GitHub Desktop.
Save iahuang/d76936f6bc76134f63423aef8c7256ab to your computer and use it in GitHub Desktop.
Find a unique League of Legends username by adding various combinations of diacritics to an existing name

Dependencies and Setup

> npm install random-useragent @types/random-useragent jsdom @types/jsdom node-fetch @types/node-fetch
> tsc --init
> tsc
> node main.js
console.log("Loading modules...");
import randomUseragent from "random-useragent";
import jsdom from "jsdom";
import fetch from "node-fetch";
const charSubstitutions: { [k: string]: string } = {
i: "iìíîïı1",
u: "µμùúûü",
b: "ßþ8",
c: "çć",
a: "àáâãäåą4ª",
s: "śš",
o: "0ðòóôõöøº",
l: "1ł",
n: "ńñ",
f: "ƒ",
e: "èéêëę",
z: "źźž"
};
const userAgentString = randomUseragent.getRandom()!;
async function fetchAsHTML(url: string) {
let resp = await fetch(url, {
headers: {
"User-Agent": userAgentString,
},
});
let content = await resp.text();
let dom = new jsdom.JSDOM(content).window.document;
return dom;
}
async function checkUsernameAvailability(uname: string) {
let url = `https://lols.gg/en/name/checker/na/${encodeURIComponent(uname)}/`;
let doc = await fetchAsHTML(url);
let text = doc.getElementsByClassName("text-center")[0].textContent!;
if (text.includes("is available in")) {
return false;
}
return true;
}
function permuteUsername(uname: string) {
uname = uname.toLowerCase();
let movableCharIndices: number[] = [];
let i = 0;
for (let char of uname) {
if (charSubstitutions[char]) {
movableCharIndices.push(i);
}
i++;
}
let all: string[] = [];
_permuteChars(uname, movableCharIndices, 0, "", all);
let perms: string[] = [];
for (let perm of all) {
let s = Array.from(uname);
i = 0;
for (let c of perm) {
s[movableCharIndices[i]] = c;
i++;
}
perms.push(s.join(""));
}
return perms;
}
function _permuteChars(uname: string, movableCharIndices: number[], i: number, s: string, all: string[]): void {
if (i === movableCharIndices.length) {
all.push(s);
return;
}
let charIndex = movableCharIndices[i];
let possibleChars = uname[charIndex] + charSubstitutions[uname[charIndex]];
for (let c of possibleChars) {
_permuteChars(uname, movableCharIndices, i + 1, s + c, all);
}
}
function shuffle<T>(array: T[]) {
var currentIndex = array.length,
temporaryValue,
randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
const settings = {
randomize: true,
stop_once_found: false
}
async function findAlternatives(uname: string) {
if (await checkUsernameAvailability(uname)) {
console.log(`"${uname}" is available`);
return;
}
let perms = permuteUsername(uname);
if (settings.randomize) perms = shuffle(perms);
console.log(perms.length, "possible usernames");
for (let p of perms) {
console.log(`trying "${p}"...`);
if (await checkUsernameAvailability(p)) {
console.log(`"${p}" is available`);
if (settings.stop_once_found) return;
}
}
}
findAlternatives("yasuo");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment