Closet Item Remover

Helps you remove items from your closet.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==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()
        }
    }
})();