Greasy Fork is available in English.

Brick Hill Outfit Randomizer And Purge

Adds 2 buttons to randomize and purge your avatar

Versione datata 07/03/2021. Vedi la nuova versione l'ultima versione.

// ==UserScript==
// @name         Brick Hill Outfit Randomizer And Purge
// @version      1.0
// @description  Adds 2 buttons to randomize and purge your avatar
// @author       Noah Cool Boy
// @match        https://www.brick-hill.com/customize/
// @namespace https://greasyfork.org/users/725966
// ==/UserScript==

let token = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let outfitCard = document.querySelector(".outfit-card .content")
let buttons = document.createElement("div")
buttons.style.display = "flex"
buttons.style.marginTop = "5px"
buttons.innerHTML = `<button class="blue" style="width: 100%; margin-right: 5px" onclick="rand()">Randomize</button><button class="red" style="width: 100%; margin-left: 5px" onclick="purge()">Purge</button>`
// No judging please ^
outfitCard.appendChild(buttons)

document.purge = async function() {
    // THIS IS SLOW AND BAD AAAAAAAAAAAAAAAAAA (thanks for the rate limiting, jefemy)
    let status = document.createElement("span")
    outfitCard.appendChild(status)
    status.innerText = "Starting..."
    let defaultColors = {Head:"F3B700", "Left Arm": "F3B700", "Right Arm": "F3B700", "Torso":"3292D3", "Left Leg": "85AD00", "Right Leg":"85AD00"}
    let keys = Object.keys(defaultColors)
    for(let x = 0; x < keys.length; x++) {
        let key = keys[x]
        let req = new XMLHttpRequest()
        req.open("POST", "/api/avatar/process", false)
        req.withCredentials = true
        req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
        status.innerText = "Resetting "+key
        req.send(`_token=${token}&type=color&part=${key}&color=${defaultColors[key]}`) // Why is this api so slow??
        await wait(5)
    }
    setTimeout(()=>{
        status.innerText = "Resetting clothing"
        let http = new XMLHttpRequest()
        http.open("GET", "/api/avatar/wearing", false) // Only gangstas don't use async :sunglasses:
        http.withCredentials = true
        http.send()
        let wearing = JSON.parse(http.responseText)
        wearing.forEach((clothing, i) => {
            setTimeout(()=>{
                avatarUpdate("remove", clothing.id)
            }, i*1500)
        })
        setTimeout(()=>{document.location.reload()}, wearing.length*1500+1500)
    }, 1000)

}

let types = {}
document.querySelectorAll(".item-types a").forEach(v=>{
    if(v.innerText == "Outfits") return
    types[v.getAttribute("data-url")] = v.innerText
})

document.rand = function() {
    let modal = document.createElement("div")
    modal.className = "modal"
    modal.innerHTML = `<div class="modal-content"><span class="close">x</span>Random Outfit Generator<hr>What would you like to randomize?<br>${Object.values(types).map(v=>`<div class="option"><input type="checkbox" checked>${v}<br></div>`).join("")}<div class="colors"><input type="checkbox">Body Colors<br></div><div class="modal-buttons"><button class="green">Randomize!</button></div></div>`
    modal.querySelector(".close").addEventListener("click",()=>{
        modal.remove()
    })
    modal.querySelector("button").addEventListener("click", ()=>{
        randomize(modal)
    })
    outfitCard.appendChild(modal)
}

function wait(ms) {
    return new Promise(a => {
        setTimeout(a, ms)
    })
}

function randomize(modal) {
    modal.querySelector(".close").remove()
    modal.querySelector("button").remove()
    let status = document.createElement("span")
    modal.querySelector(".modal-content").appendChild(status)
    let ad = document.createElement("img")
    ad.src = "https://noah.ovh/bh/randomizer/"
    ad.alt = "This used to be an ad"
    ad.style.marginTop = "10px"
    ad.width = 400
    modal.querySelector(".modal-content").appendChild(ad)
    let opts = [...modal.querySelectorAll(".option")].map(v => v.innerText.trim())
    setTimeout(async ()=>{
        let inventory = {}
        if(window.localStorage.randomizer_cache && window.localStorage.randomizer_cache_date && Date.now() - window.localStorage.randomizer_cache_date < 1000 * 60 * 60 * 24) {
            inventory = JSON.parse(window.localStorage.randomizer_cache)
        } else {
            for(let x = 0; x < opts.length; x++) {
                let type = opts[x]
                inventory[type] = []
                let apiType = Object.keys(types).find(key => types[key] == type)
                let page = 1
                while(true) {
                    let req = new XMLHttpRequest()
                    req.open("GET","/api/avatar/crate/"+apiType+"/"+page,false)
                    req.withCredentials = true
                    req.send()
                    let data = JSON.parse(req.responseText)
                    inventory[type] = inventory[type].concat(data.data.map(v=>v.item_id))
                    if(data.pages.current >= data.pages.pageCount) {
                        break
                    }
                    page++
                    //console.log(`Getting ${type} ${data.pages.current}/${data.pages.pageCount}`)
                    await wait(5)
                    status.innerText = `Getting ${type} ${data.pages.current}/${data.pages.pageCount}`
                }
            }
            //console.log(inventory)
            //console.log(JSON.stringify(inventory))

            window.localStorage.randomizer_cache = JSON.stringify(inventory)
            window.localStorage.randomizer_cache_date = Date.now()
        }
        opts = [...modal.querySelectorAll(".option")].map(v => [v.innerText.trim(), v.querySelector("input").checked])
        opts = opts.filter(v=>v[1]).map(v=>v[0])
        Object.keys(inventory).filter(v => !opts.includes(v)).forEach(v=>delete inventory[v])
        if(inventory.Hats) {
            inventory.Hats2 = inventory.Hats
            inventory.Hats3 = inventory.Hats
        }
        let messages = ["Shuffling the stuff", "Doing things", "Randomizing the avatar", "Making your new outfit", "Tiny computer is thinking", "Generating a combo", "The machine is hard at work"]
        status.innerText = messages[Math.floor(Math.random()*messages.length)]
        let outfit = Object.values(inventory).filter(v=>v.length).map(v=>v[Math.floor(Math.random()*v.length)])
        for(let x = 0; x < outfit.length; x++) {
            avatarUpdate("wear", outfit[x])
            await wait(1000)
        }
        let bodyColors = modal.querySelector(".colors > input")
        if(bodyColors.checked) {
            console.log("Checked!")
            let bodyParts = ["Torso", "Left Arm", "Right Arm", "Left Leg", "Right Leg", "Head"]
            for(let x = 0; x < bodyParts.length; x++) {
                let req = new XMLHttpRequest()
                req.open("POST", "/api/avatar/process", false)
                req.withCredentials = true
                req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
                let randColor = Array(6).fill(0).map(v=>"0123456789ABCDEF"[Math.floor(Math.random()*16)]).join("")
                req.send(`_token=${token}&type=color&part=${bodyParts[x]}&color=${randColor}`)
                let parts = [...document.querySelectorAll(".part-btn")] // es-lint is NOT happy so I had to make it 2 lines
                parts.find(v=>v.onclick.toString().includes(bodyParts[x])).style.backgroundColor = "#"+randColor
                await wait(5)
            }
            window.location.reload() // I didn't find any way to force reload the avatar preview
        } else {
            modal.remove()
        }
    }, 1)
}