Closet Item Remover

Helps you remove items from your closet.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Closet Item Remover
// @namespace    Nyu@Clraik
// @version      1.0.0
// @description  Helps you remove items from your closet.
// @author       Nyu
// @match        *://*.neopets.com/closet.phtml*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=neopets.com
// @license      MIT
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM.getValue
// @grant        GM.setValue
// ==/UserScript==

(async function() {
    'use strict';

    if (typeof GM_getValue == "undefined") GM_getValue = GM.getValue
    if (typeof GM_setValue == "undefined") GM_setValue = GM.setValue

    const sleep = ms => new Promise(r => setTimeout(r, ms))
    const randWait = () => sleep(3000 + Math.random() * 2000)

    const PREFIX = 'cir.'
    const get = key => GM_getValue(PREFIX + key)
    const set = (key, val) => GM_setValue(PREFIX + key, val)

    const container = document.createElement('div')
    container.style.display = 'flex'
    container.style.alignItems = 'center'
    container.style.justifyContent = 'center'
    container.style.gap = '16px'
    container.style.padding = '12px 20px'
    container.style.margin = '10px auto'
    container.style.background = '#efefc3'
    container.style.border = '2px solid #c5c587'
    container.style.borderRadius = '8px'
    container.style.maxWidth = '500px'
    container.style.flexWrap = 'wrap'

    const makeCheckbox = (label, id, checked) => {
        const wrapper = document.createElement('label')
        wrapper.style.display = 'flex'
        wrapper.style.alignItems = 'center'
        wrapper.style.gap = '4px'
        wrapper.style.cursor = 'pointer'
        wrapper.style.fontWeight = 'bold'
        wrapper.style.fontSize = '14px'
        const cb = document.createElement('input')
        cb.type = 'checkbox'
        cb.id = id
        cb.checked = checked
        cb.style.cursor = 'pointer'
        wrapper.append(cb, label)
        return wrapper
    }

    const savedNp = await get('np')
    const savedNc = await get('nc')
    const npCheck = makeCheckbox('NP Items', 'cir-np', savedNp ?? true)
    const ncCheck = makeCheckbox('NC Items', 'cir-nc', savedNc ?? false)
    npCheck.querySelector('input').addEventListener('change', e => set('np', e.target.checked))
    ncCheck.querySelector('input').addEventListener('change', e => set('nc', e.target.checked))
    container.append(npCheck, ncCheck)

    const pinExists = document.getElementById('pin_field')
    if (pinExists) {
        const pinWrapper = document.createElement('label')
        pinWrapper.style.display = 'flex'
        pinWrapper.style.alignItems = 'center'
        pinWrapper.style.gap = '4px'
        pinWrapper.style.fontWeight = 'bold'
        pinWrapper.style.fontSize = '14px'
        const pinInput = document.createElement('input')
        pinInput.type = 'text'
        pinInput.id = 'cir-pin'
        pinInput.maxLength = 4
        pinInput.placeholder = '0000'
        pinInput.value = await get('pin') ?? ''
        pinInput.style.width = '50px'
        pinInput.style.padding = '4px 6px'
        pinInput.style.borderRadius = '4px'
        pinInput.style.border = '1px solid #c5c587'
        pinInput.style.textAlign = 'center'
        pinInput.style.fontSize = '14px'
        pinInput.addEventListener('input', e => set('pin', e.target.value))
        pinWrapper.append('PIN ', pinInput)
        container.append(pinWrapper)
    }

    const running = await get('running') ?? false
    const button = document.createElement('button')
    button.className = 'button-default__2020'
    button.style.cursor = 'pointer'

    const setRunning = (state) => {
        set('running', state)
        button.textContent = state ? 'Stop' : 'Remove Items'
        button.classList.toggle('button-yellow__2020', !state)
        button.classList.toggle('button-red__2020', state)
    }
    setRunning(running)

    button.onclick = async () => {
        if (await get('running')) { setRunning(false); return }
        setRunning(true)
        set('nextPage', currentPage)
        fillAndSubmit()
    }

    container.append(button)

    const quickStockForm = document.querySelector('form[action="process_closet.phtml"]')
    if (quickStockForm) {
        quickStockForm.parentNode.insertBefore(container, quickStockForm)
    }

    const pageSelect = document.querySelector('select[name="page"]')
    const currentPage = pageSelect ? parseInt(pageSelect.value) : 1
    const lastPage = pageSelect ? parseInt(pageSelect.options[pageSelect.options.length - 1].value) : 1

    const goToPage = (page) => {
        const url = new URL(window.location.href)
        url.searchParams.set('page', page)
        window.location.href = url.toString()
    }

    const fillAndSubmit = () => {
        const doNp = document.getElementById('cir-np').checked
        const doNc = document.getElementById('cir-nc').checked
        const rows = quickStockForm.querySelectorAll('tr[bgcolor]')
        let filled = false
        for (const row of rows) {
            const isNc = row.textContent.includes('(Artifact -')
            if ((isNc && !doNc) || (!isNc && !doNp)) continue
            const tds = row.querySelectorAll('td')
            const qty = tds[4]?.querySelector('b')?.textContent?.trim()
            const input = tds[5]?.querySelector('input[type="text"]')
            if (qty && input) { input.value = qty; filled = true }
        }
        if (!filled) {
            if (currentPage >= lastPage) setRunning(false)
            else { set('nextPage', currentPage + 1); goToPage(currentPage + 1) }
            return
        }
        const pinField = document.getElementById('pin_field')
        if (pinField) {
            const savedPin = document.getElementById('cir-pin')?.value
            if (!savedPin) { setRunning(false); alert('PIN is required but not set.'); return }
            pinField.value = savedPin
        }
        if (currentPage >= lastPage) set('running', false)
        else set('nextPage', currentPage + 1)
        quickStockForm.querySelector('input[type="submit"]').click()
    }

    if (running && quickStockForm) {
        await randWait()
        const targetPage = await get('nextPage') ?? 1
        if (currentPage !== targetPage) {
            goToPage(targetPage)
        } else {
            fillAndSubmit()
        }
    }
})();