Clan depo quick sets

Арендовать кастомный набор со склада в 1 клик. Кнопка снять все арты, вернуть все арты на складе. Инструкция на скрине снизу.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Clan depo quick sets
// @namespace    http://tampermonkey.net/
// @version      0.4.11
// @description  Арендовать кастомный набор со склада в 1 клик. Кнопка снять все арты, вернуть все арты на складе. Инструкция на скрине снизу.
// @author       Something begins
// @license     none
// @match       https://www.heroeswm.ru/sklad_info*
// @match       https://my.lordswm.com/sklad_info*
// @match       https://www.lordswm.com/sklad_info*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=lordswm.com
// @grant        none
// ==/UserScript==
const setAmount = 5;
const redirectTo = "/inventory.php";
const defaultSets = '{"1":"Меч холода, Кольцо холода, Кольцо холода, Доспех солнца, Сапоги солнца, Шлем солнца, Клевер фортуны, Плащ солнца, Щит холода","2":"Мифриловый перстень времён [N12E12A12W12F12], Великое кольцо аномалий [N12E12A12W12F12], Кулон сингулярности [N12E12A12W12F12]","3":"Мифриловый перстень времён [E11A11W11F11] || Мифриловый перстень времён [N10E10A10W10F10] || Мифриловый перстень времён [N12E12A12W12F12], Великий доспех ловчего [D12E12A12W12F12]","4":"","5":""}';
const defaultNames = '{"1":"Акционка","2":"КБО книга","3":"КБО раш","4":"","5":""}';
const stylesHTML = `
<style>
    .set_container {
        display: flex;
        flex-direction: row;
        align-items: flex-start;
    }

    .set_list {
        width: 100%;
        box-sizing: border-box;
        margin-bottom: 10px;
    }
    .set_name {
        width: 20%;
        box-sizing: border-box;
        margin-bottom: 10px;
        margin-right: 10px;
        align-self: center;
    }

    button, span, select.available_battles_count {
        width: auto;
        align-self: center;
        padding: 5px;
        margin-left: 5px;
    }
    .undress_button{
cursor: pointer;
align-self: center;
    }
</style>
`;

const setParentHTML = `
<div id = "set_parent" style="display: flex;flex-direction: column;"></div>
`;
const saveButtonHTML = `
<button id = "save_button"> Сохранить </button>
`;

const origin = location.origin + location.pathname + "?id=" + location.href.match(/id=(\d+)/)[1];
console.log(origin);

async function fetchMultipleUrls(urls) {
    const fetchPromises = urls.map(url => {
        return fetch(url, {
            method: 'GET',
            headers: new Headers({
                'Content-Type': 'text/html; charset=windows-1251',
            }),
        })
            .then(response => {
            if (!response.ok) {
                throw new Error(`Network response was not ok: ${response.status}`);
            }
            return response.arrayBuffer();
        })
            .then(buffer => {
            const decoder = new TextDecoder('windows-1251');
            return { url: url, text: decoder.decode(new Uint8Array(buffer)) };
        });
    });

    try {
        const results = await Promise.all(fetchPromises);
        return results;
    } catch (error) {
        console.error('Error fetching URLs:', error);
        throw error;
    }
}

function returnAll() {
    const allAs = document.querySelectorAll("a");
    const returnAs = Array.from(allAs).filter(a => { return a.href.includes("art_return") });
    const allLinks = returnAs.map(a => a.href);
    console.log(allLinks);
    consequetiveFetches(allLinks, () => { location.reload() });
}

function undress() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/inventory.php?all_off=100', true);
    xhr.overrideMimeType('text/plain; charset=windows-1251');
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200)
            // send_storage_async_get(document.location);
            location.reload();
    };
    xhr.send(null);
}

function draw_undress_button(content) {
    content.insertAdjacentHTML("afterEnd", "<b>");
    var a = document.createElement('a');
    a.href = '';
    a.textContent = ' (вернуть все) ';

    content.appendChild(a);
    const undressButtonHTML = `<td><img class = 'undress_button' src = 'https://dcdn.heroeswm.ru/i/inv_im/btn_art_rem.png'></img></td>`;

    content.appendChild(a);
    document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(1) > tbody > tr:nth-child(4) > td > table > tbody:nth-child(1) > tr").insertAdjacentHTML("beforeEnd", undressButtonHTML);
    const undressButton = document.querySelector(".undress_button");
    a.addEventListener('click', function(e) {
        e.preventDefault();
        returnAll();
    });
    undressButton.addEventListener('click', function(e) {
        e.preventDefault();
        undress();
    });
    document.addEventListener("keydown", event => {
        if (event.altKey) {
            if (["q", "Q", "й", "Й"].includes(event.key)) {
                returnAll();
            }
            if (["w", "W", "Ц", "ц"].includes(event.key)) {
                undress();
            }
        }
    });
}

function getAllCatsURLs() {
    const weaponA = document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(2) > tbody > tr > td:nth-child(2) > a");
    const armorA = document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(2) > tbody > tr > td:nth-child(3) > a");
    const jewelA = document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(2) > tbody > tr > td:nth-child(4) > a")
    const backpackA = document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(2) > tbody > tr > td:nth-child(5) > a");
    if ([weaponA, armorA, jewelA, backpackA].includes(null)) return false;
    return [weaponA.href, armorA.href, jewelA.href, backpackA.href];
}


function countOccurrences(arr, target) {
    return arr.reduce((count, element) => (element === target ? count + 1 : count), 0);
}

function consequetiveFetches(urlArr, callback = () => {}, i = 0) {
    if (i >= urlArr.length) {
        callback();
        return;
    } else {
        fetch(urlArr[i]).then((response) => {
            if (!response.ok) {
                console.error(`HTTP error! Status: ${response.status}, Text: ${response.statusText}`);
                consequetiveFetches(urlArr, callback, i);
            } else {
                consequetiveFetches(urlArr, callback, i + 1);
            }
        })
    }
}

function getReqDepoArts(requiredArts, battlesAmount, fetchedData) {
    let allArts = [];
    const neededArts = [];
    const missingArts = [];
    for (const data of fetchedData) {
        const arts = getArtList(data.text);
        console.log("arts", arts);
        allArts = allArts.concat(arts);
    }
    for (let i = 0; i < allArts.length; i++) {
        allArts[i].index = i;
    }
    console.log("allArts", allArts);
    for (const reqArtName of requiredArts) {
        console.log("reqArtName", reqArtName);
        const alternatives = reqArtName.split("||");
        let matchedArts;
        if (alternatives.length > 1) {
            for (const alternative of alternatives) {
                matchedArts = allArts.filter(art => { return alternative.trim().toLowerCase() === art.name.toLowerCase() && !art.taken && art.availableBattlesCount >= battlesAmount });
                if (matchedArts.length === 0) {
                    matchedArts = allArts.filter(art => { return alternative.trim().toLowerCase() === art.name.toLowerCase() && !art.taken });
                }
                if (matchedArts.length > 0) break;
            }
        } else {
            matchedArts = allArts.filter(art => { return reqArtName.trim().toLowerCase() === art.name.toLowerCase() && !art.taken && art.availableBattlesCount >= battlesAmount });
            if (matchedArts.length === 0) matchedArts = allArts.filter(art => { return reqArtName.trim().toLowerCase() === art.name.toLowerCase() && !art.taken });
        }
        console.log("matchedArts", matchedArts);
        if (matchedArts.length === 0) {
            missingArts.push(reqArtName);
            continue;
        };
        const chosenArt = matchedArts[0];
        neededArts.push(chosenArt);
        allArts[chosenArt.index].taken = true;
    }
    console.log("neededArts", neededArts);
    return { neededArts: neededArts, missingArts: missingArts };
}
async function fetchDataAndProcess(requiredArts, battlesAmount) {
    const neededLinks = [];
    let warningMessage = "";
    const fetchedData = await fetchMultipleUrls(getAllCatsURLs());
    const artData = getReqDepoArts(requiredArts, battlesAmount, fetchedData);
    for (const chosenArt of artData.neededArts) {
        neededLinks.push(getRentLink(origin, chosenArt.artId, chosenArt.sign, chosenArt.category, battlesAmount));
        if (battlesAmount > chosenArt.availableBattlesCount) {
            warningMessage += "Взято " + chosenArt.name + " на " + chosenArt.availableBattlesCount + " боев;\n";
        }
    }
    for (const missingArtName of artData.missingArts) {
        warningMessage += missingArtName + " недоступен;\n";
    }
    consequetiveFetches(neededLinks, () => { location.href = location.origin + redirectTo });
    warningMessage !== "" && alert(warningMessage);
}

const parser = new DOMParser();


function getArtList(HTMLText) {

    const arts = [];
    const doc = parser.parseFromString(HTMLText, 'text/html');
    const tbody = doc.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(3) > tbody > tr > td > table > tbody");
    for (const tr of tbody.children) {
        const nameEle = tr.querySelector("font");
        if (!nameEle) continue;
        let name = nameEle.textContent.match(/\'(.*?)\'/);
        // const _dura = nameEle.textContent.match(/(\d+)\//)[1];
        if (!name) {
            console.log(tr);
            console.error("Название арта не найдено");
            continue;
        }
        name = name[1];
        // name = name.split("[")[0].trim();
        name = name.trim();

        const button = tr.querySelector("input[value='Взять в аренду']");
        if (!button) continue;
        const artId = button.id.match(/\d+/)[0];
        const sign = tr.querySelector("input[name='sign']").value;
        const category = tr.querySelector("input[name='cat']").value;
        const availableBattlesCount = tr.querySelector("select").children.length;
        arts.push({ name: name, artId: artId, sign: sign, category: category, availableBattlesCount: availableBattlesCount, taken: false });
    }
    return arts;
}

function getRentLink(origin, artId, sign, category, battlesAmount) {
    const link = origin + "&sign=" + sign + "&cat" + category + "&action=rent&inv_id=" + artId + "&set_id=0&bcnt" + artId + "=" + battlesAmount;
    return link;
}
document.addEventListener("input", event => {
    if (!["set_list", "set_name"].includes(event.target.className)) return;
    event.target.style.height = "auto";
    event.target.style.height = `${event.target.scrollHeight+2}px`;
});
const attachTo = document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(1) > tbody > tr:nth-child(1) > td:nth-child(1)");
attachTo.insertAdjacentHTML("afterbegin", stylesHTML + setParentHTML);
const parent = document.querySelector("#set_parent");
let sets = localStorage.getItem("depoScript1_sets");
let names = localStorage.getItem("depoScript1_set_names");

if (!sets) sets = JSON.parse(defaultSets);
else sets = JSON.parse(sets);
if (!names) names = JSON.parse(defaultNames);
else names = JSON.parse(names);

console.log("sets", sets);
for (let i = 0; i < setAmount; i++) {
    const test = sets[i + 1];
    const set = test ? test.toString() : "";
    const test2 = names[i + 1];
    const name = test2 ? test2.toString() : "";

    const setHTML = `
<div class="set_container">
    <span>${i+1}. </span>
    <textarea class = "set_name" placeholder = "Навание комплекта" rows="2" cols="3">${name}</textarea>
    <textarea class="set_list" placeholder="Список артефактов через запятую, альтернативы через ||. Пример: Меч холода, Амулет холода || Клевер фортуны, Кольцо холода" cols="5" rows="3">${set}</textarea>
    <span> на </span>
    <select id = "set_select${i}" class="available_battles_count"></select>
    <span> боев </span>
    <button class="set_button"> Аренда </button>
</div>
`;
    parent.insertAdjacentHTML("beforeend", setHTML);
    console.log("check", document.querySelector(`#set_select${i}`));
    const select = document.querySelector(`#set_select${i}`);
    for (let i = 1; i <= 20; i++) {
        select.insertAdjacentHTML("beforeend", `<option value=${i}>${i}</option>`);
    }
}
[".set_list", ".set_name"].forEach(selector => {
    for (const textarea of document.querySelectorAll(selector)) {
        textarea.style.height = "auto";
        textarea.style.height = `${textarea.scrollHeight+2}px`;
    }
})
parent.insertAdjacentHTML("beforeend", saveButtonHTML);
document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(1) > tbody").textContent.includes("Ваша аренда") && draw_undress_button(document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table:nth-child(1) > tbody > tr:nth-child(3) > td"));
document.addEventListener("click", event => {
    const ele = event.target;
    if (ele.className === "set_button") {
        const areaText = ele.parentElement.querySelector(".set_list").value;
        const battlesAmount = ele.parentElement.querySelector(".available_battles_count").selectedIndex + 1;
        let requiredArts = areaText.split(",");
        for (let i = 0; i < requiredArts.length; i++) {
            requiredArts[i] = requiredArts[i].trim();
        }
        requiredArts = requiredArts.filter(artName => { return artName !== "" && artName !== " " });
        ele.textContent = " Загрузка... ";
        fetchDataAndProcess(requiredArts, battlesAmount);
    }
    if (ele.id === "save_button") {
        const dict = {};
        const names = {};
        for (const setTextArea of document.querySelectorAll(".set_list")) {
            const areaNo = setTextArea.parentElement.querySelector("span").textContent.match(/\d+/)[0];
            dict[areaNo] = setTextArea.value;
        }
        for (const nameTextArea of document.querySelectorAll(".set_name")) {
            const areaNo = nameTextArea.parentElement.querySelector("span").textContent.match(/\d+/)[0];
            names[areaNo] = nameTextArea.value;
        }
        // set_name
        console.log(dict);
        localStorage.setItem("depoScript1_sets", JSON.stringify(dict));
        localStorage.setItem("depoScript1_set_names", JSON.stringify(names));

    }
});