fc2 show all products

show full list of products in 1 page and sort by id / show full title

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         fc2 show all products
// @namespace    https://github.com/x94fujo6rpg/SomeTampermonkeyScripts
// @version      0.3
// @description  show full list of products in 1 page and sort by id / show full title
// @author       x94fujo6
// @match        https://adult.contents.fc2.com/*
// @grant        none
// ==/UserScript==
/* jshint esversion: 9 */

(function () {
    'use strict';
    let msgid = "fc2_script_message";
    let listener = false;

    window.document.body.onload = () => {
        startScript();
    };

    function dPrint(...any) {
        console.log(`[${msgid}]: `, ...any);
    }

    function startScript() {
        if (document.visibilityState == "visible") {
            if (listener) {
                document.removeEventListener("visibilitychange", startScript);
                //dPrint("remove event listener");
            } else {
                //dPrint("normal start");
            }
            setReload();
            checkLink();
        } else {
            document.addEventListener("visibilitychange", startScript);
            //dPrint("document not visible, set event listener");
            listener = true;
        }
    }

    function setReload() {
        let menu = document.querySelector("[data-menulist]");
        if (!menu) return;
        let links = menu.querySelectorAll("a");
        links.forEach(a => {
            if (a.getAttribute("reload")) return;
            a.onclick = (event) => {
                event.preventDefault();
                document.location.href = a.href;
            };
            a.setAttribute("reload", true);
        });
    }

    function checkLink() {
        let link = document.location.href;
        //dPrint(`link: ${link}`);
        if (link.match(/users\/[^\/]+\/articles\?sort=date&order=desc/)) {
            let regtest = link.match(/page=(\d+)/);
            let page = regtest ? regtest[1] : false;
            if (regtest) page = (page == 1) ? true : false;
            if (!regtest || page) {
                dPrint("listview");
                dPrint(`script start, link: ${link}`);
                sortList();
            }
        } else if (link.match(/article_search.php\?id=\d+/) || link.match(/\/article\/\d+\//)) {
            dPrint("productpage");
            productpage();
        }
    }

    function updateMessage(text = "") {
        document.getElementById(msgid).textContent = text;
        dPrint(text);
    }

    function sortList() {
        let pos = document.querySelector("section.seller_user_articlesList");
        let products;
        let list;
        
        if (!pos) return;

        dPrint("sortList");
        products = [...pos.children];
        list = products.map(div => processDiv(div));

        document.querySelector(".c-pager-101").remove();
        list.sort((a, b) => b.id - a.id);

        products.forEach(e => e.remove());
        list.forEach(data => { pos.appendChild(data.ele); });

        let message = Object.assign(document.createElement("span"), {
            id: msgid,
            textContent: "script start",
            style: `
                    display: inline-block;
                    margin: 0.5rem;
                    color: gold;
                `,
        });
        document.querySelector("div.seller_user_articles_pageHeader").appendChild(message);
        getAllProduct();

        async function getAllProduct() {
            let total = document.querySelector(".seller_user_articles_pageHeaderCount");
            if (!total) return;
            total = total.textContent.match(/\((\d*)\)/)[1];
            total = parseInt(total, 10);

            let max_page = Math.ceil(total / 30);
            if (max_page == 1) {
                updateMessage(`only 1 page, abort`);
            } else {
                let user = document.location.href.match(/users\/([^\/]*)\/articles/)[1];
                let url = `https://adult.contents.fc2.com/users/${user}/articles?sort=date&order=desc&deal=&page=`;
                updateMessage(`max page = ${max_page}, start to retrieve data`);

                for (let page = 2; page <= max_page; page++) {
                    updateMessage(`processing... please wait [page: ${page}, total: ${max_page}]`);
                    await getPage(url, page)
                        .then(async (resolve) => {
                            await resort(resolve, page);
                        })
                        .catch((reject) => {
                            updateMessage(`somthing went wrong...script stopped`);
                            dPrint(reject);
                            return;
                        });
                }
            }
            updateMessage(`done`);

            function getPage(rq_url, page) {
                return new Promise((resolve, reject) => {
                    let rq = new XMLHttpRequest();
                    rq.open("GET", `${rq_url}${page}`);
                    rq.onreadystatechange = function () {
                        if (rq.readyState == 4) {
                            return (rq.status == 200) ? setTimeout(resolve, 500, rq.responseText) : reject(rq.responseText);
                        }
                    };
                    rq.send(null);
                });
            }

            function resort(data) {
                return new Promise((resolve, reject) => {
                    let current = getCurrentProduct();
                    if (!current) return reject(false);

                    data = extractProducts(data);
                    current.push(...data);
                    current.sort((a, b) => b.id - a.id);

                    let pos = document.querySelector("section.seller_user_articlesList");
                    [...pos.children].forEach(e => e.remove());

                    current.forEach(p => pos.appendChild(p.ele));

                    data = null;
                    current = null;
                    return resolve(true);
                });

                function getCurrentProduct() {
                    let pos = document.querySelector("section.seller_user_articlesList");
                    if (pos) {
                        return [...pos.children].map(ele => {
                            return {
                                id: ele.querySelector("a").href.match(/id=(\d*)/)[1],
                                ele: ele.cloneNode(true),
                            };
                        });
                    } else {
                        return false;
                    }
                }

                function extractProducts(domtext) {
                    let parser = new DOMParser();
                    let new_document = parser.parseFromString(domtext, "text/html");
                    let pos = new_document.querySelector("section.seller_user_articlesList");
                    let products = [...pos.children];
                    let list = products.map(div => processDiv(div));
                    parser = null; // release memory
                    new_document = null;
                    return list;
                }
            }
        }
    }

    function processDiv(div) {
        let id = div.querySelector("a").href.match(/id=(\d*)/)[1];
        let box = div.querySelector(".c-cntCard-110-f_indetail");
        let title_ele = div.querySelector(".c-cntCard-110-f_itemName");
        let title_span = convertToSpan(title_ele);
        let id_span = Object.assign(document.createElement("span"), {
            textContent: id,
            style: `font-size: 1.5rem;`,
        });
        let all_link;
        let remove_ele = [
            ".items_article_SmapleVideo",
            "span.c-cntCard-110-f_thumb_type",
            "button",
            "section.c-tooltip-107",
            ".detail-layout",
            ".c-cntCard-110-f_seller",
        ];
        box.insertAdjacentElement("afterbegin", title_span);
        box.insertAdjacentElement("afterbegin", id_span);
        title_ele.remove();

        div.querySelector("img").setAttribute("loading", "lazy");
        remove_ele.forEach(css_selector => {
            removeFromEle(div, css_selector);
        });

        all_link = div.querySelectorAll("a");
        if (all_link) all_link.forEach(a => { a.target = "_blank"; });
        return { id: id, ele: div.cloneNode(true) };

        function removeFromEle(ele, css_selector) {
            let target = ele.querySelector(css_selector);
            if (target) target.remove();
        }

        function convertToSpan(ele) {
            return Object.assign(document.createElement("span"), {
                textContent: ele.textContent,
                className: ele.className,
                style: `
                    overflow: visible;
                    display: inline-block;
                    width: auto;
                `,
            });
        }
    }

    function productpage() {
        let data = document.querySelector("[type='application/ld+json']").textContent;
        data = JSON.parse(data);
        let id = data.productID;
        let title = data.name;
        let pos = document.querySelector(".items_article_headerInfo h3");
        let e = newButton(`Copy [${id} ${title}]`, `${id} ${title}`);
        pos.insertAdjacentElement("afterend", e);
    }

    function newButton(text, copy) {
        let e = document.createElement("a");
        e.style = "color: deeppink; font-size: 1.5rem;";
        e.textContent = text;
        e.onclick = function () {
            navigator.clipboard.writeText(repalceForbiddenChar(copy));
        };
        return e;
    }

    function repalceForbiddenChar(string = "") {
        let forbidden = `<>:"/|?*\\`;
        let replacer = `<>:”/|?*\`;
        for (let index of forbidden) {
            string = string.replaceAll(forbidden[index], replacer[index]);
        }
        return string.trim();
    }
})();