Clan depo quick sets

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 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));

    }
});