suruga-ya enhancer

駿河屋の利便性を向上させるスクリプト

目前為 2021-06-23 提交的版本,檢視 最新版本

// ==UserScript==
// @name         suruga-ya enhancer
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  駿河屋の利便性を向上させるスクリプト
// @author       kood
// @match        https://www.suruga-ya.jp/*
// @require http://code.jquery.com/jquery-latest.js
// @require https://greasyfork.org/scripts/2199-waitforkeyelements/code/waitForKeyElements.js?version=6349
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js
// ==/UserScript==

(function() {
    let itemCode = ""; // 管理番号
    let productURL = ""; // 販売ページのURL
    let kaitoriURL = ""; // 買取ページのURL
    let priceOfKaitori = ""; // 買取ページから取得した買取価格
    let jan = ""; // 買取ページから取得したJAN
    let priceOfBrandNew = ""; // 販売ページから取得した新品価格
    let priceOfUsed = ""; // 販売ページから取得した中古価格
    let priceOfPreOrder = ""; // 販売ページから取得した予約価格
    let priceOfMarketplace = ""; // 販売ページから取得した最安値のマケプレ価格
    let defaultImgURL = ""; // 販売ページから取得した商品画像1枚目のURL
    let getKaitoriPageDataCompleted = false; // 買取ページのデータの取得が完了済みかどうか
    let getProductPageDataCompleted = false; // 販売ページのデータの取得が完了済みかどうか
    let skipNumOfProdsCheck = false; // カートから合計価格を取得する際の商品数チェックをスキップするかどうか
    let isFukubukuro = false; // 商品が福袋かどうか
    let base64Decoded = "";
    const base64Encoded = "aHR0cHM6Ly9hZmZpbGlhdGUuc3VydWdhLXlhLmpwL21vZHVsZXMv" +
                                      "YWYvYWZfanVtcC5waHA/dXNlcl9pZD0xNTc2Jmdvb2RzX3VybD0=";
    const cartURL = "https://www.suruga-ya.jp/cargo/detail";

    /* 18禁の商品の販売ページにアクセスした際の警告をスキップ */
    if($.cookie("adult") != 1){
        if($(".btn-confirm-adult").length == 1){
            /* 警告を自動でクリック */
            $(".btn-confirm-adult").trigger("click");
        }
        /* 警告クリックで保存されるcookieは期限が短いため、期限を9999日にする */
        setTimeout(function(){
            $.cookie("adult", "1", {expires: 9999, path: "/"});
        }, 5000);
    }

    /* 管理番号の取得 */
    try{
        itemCode = shinaban;
        getItemCode();
    }catch(e){
        getItemCode();
    }
    function getItemCode(){
        if(typeof(shinaban) == "string"){
            return false;
        }
        const pathname = window.location.pathname;
        const searchStrs = [
            "/product/detail/",
            "/product-other/",
            "/kaitori_detail/"
        ];
        $.each(searchStrs, function(index, searchStr){
            if(pathname.indexOf(searchStr)>-1){
                itemCode = pathname.slice(pathname.lastIndexOf("/")+1);
                return false;
            }
        })
    }

    /* 商品のURLをグローバル変数に格納 */
    if(itemCode != ""){
        productURL = "https://www.suruga-ya.jp/product/detail/" + itemCode;
        kaitoriURL = "https://www.suruga-ya.jp/kaitori_detail/" + itemCode;
    }

    waitForKeyElements("ol.breadcrumb.chevron-double.bg-transparent", checkCategory);
    function checkCategory(jNode){
        try{
            $.each(jNode.find("li"), function(index, elem){
                if($(elem).find("a").attr("href").indexOf("?category=12&") > -1){
                    isFukubukuro = true;
                    return false;
                }
            })
        }catch(e){}
    }

    /* ページ上部の検索ボックス横のカテゴリセレクトボックスに福袋カテゴリが存在しない場合は福袋カテゴリを追加 */
    waitForKeyElements("div.search_top_pc", addFukubukuroCategoryToSelectbox);
    function addFukubukuroCategoryToSelectbox(jNode){
        const options = jNode.find("select option");
        //console.log(options.last().val());
        let addFukubukuro = true;
        $.each(options, function(index, elem){
            if($(elem).val()=="12"){
                addFukubukuro = false;
                return false;
            }
        })
        if(addFukubukuro){
            const addElem = "<option value='12'>福袋</option>"
            options.last().after(addElem)
        }
    }

    /* ページ左のサイドバーメニュー()に福袋カテゴリのリンクを追加 */
    waitForKeyElements("nav#sidebar_menu", addFukubukuroCategoryToSidebarMenu);
    function addFukubukuroCategoryToSidebarMenu(jNode){
        const pageListElem = jNode.find(".sidebar_wrap.padT0 ul");
        const fukubukuroCatURL = fixURL("https://www.suruga-ya.jp/search?category=12&search_word=");
        const addElem = "<li><a href='" + fukubukuroCatURL + "'>福袋</a></li>";
        pageListElem.append(addElem);
    }

    /* 販売ページの数量セレクトボックスの下に在庫数表示を追加(1の場合は価格の横に表示されているため、追加しない) */
    waitForKeyElements("#quantity_selection", addQuantityDisplay);
    function addQuantityDisplay(jNode){
        const quantity = jNode.find("option").last().val();
        let quantityStr = "";
        if(quantity != 9999){
            if(quantity == 1){
                return;
            }
            quantityStr = quantity + "点";
        }else{
            quantityStr = "10点以上";
        }
        const addElem = "<div id='quantity_display'>在庫数 " + quantityStr + "</div>";
        const divElem = jNode.closest("div.product_amounts");
        divElem.after(addElem);
    }

    /* 買取ページのリンクが無い販売ページに買取ページのリンクを追加 */
    waitForKeyElements("div.link-group.mgnT12", addKaitoriLink);
    function addKaitoriLink(jNode){
        if(isFukubukuro){
            return false;
        }
        if(window.location.href.indexOf("/product/detail/") == -1){
            return false;
        }
        const ulElem = jNode.find("ul.list-unstyled.mb-0.list-p3");
        let liKaitoriElem = ulElem.find("li.kaitori.hidden");
        if(liKaitoriElem.length > 0){
            /* hiddenクラスが付与されている場合は消して表示させる */
            //liKaitoriElem.removeClass("hidden");
            //return false;
        }else{
            liKaitoriElem = "";
        }
        const liElems = ulElem.find("li");
        let kaitoriLinkNotExist = true;
        let liKaitoriElems = [];
        $.each(liElems, function(index, liElem){
            const href = $(liElem).find("a").attr("href");
            if(href.indexOf("/kaitori_detail/") > -1){
                liKaitoriElems.push(liElem);
            }
        })
        if(liKaitoriElems.length > 0){
            /* 既にリンクが存在する場合 */
            kaitoriLinkNotExist = false;
            if(liKaitoriElems.length == 1 && $(liKaitoriElems[0]).hasClass("hidden")){
                /*1つかつhiddenクラスが付与されている場合はクラスを消して表示させる*/
                $(liKaitoriElems[0]).removeClass("hidden");
                return false;
            }else if(liKaitoriElems.length == 1){
                /* 1つかつ既に表示されている場合は終了 */
                return false;
            }
            /* 買取ページのリンクが複数存在する場合 */
            let numOfHiddenClass = 0;
            $.each(liKaitoriElems, function(index, liKaitoriElem){
                if($(liKaitoriElem).hasClass("hidden")){
                    numOfHiddenClass++;
                }
            })
            try{
                if(liKaitoriElems.length == numOfHiddenClass){
                    /* 複数ある買取ページのリンク全てにhiddenクラスが付与されている場合*/
                    $(liKaitoriElems[0]).removeClass("hidden");
                    return false;
                }
            }catch(e){}
        }
        if(kaitoriLinkNotExist && kaitoriURL != ""){
            const addElem = "<li id='added_kaitori_elem'><a href='" + fixURL(kaitoriURL) + "' class='link_underline'>この商品の買取ページ</a></li>";
            ulElem.append(addElem);
        }
    }

    /* 買取ページから取得した情報を販売ページに追加 */
    waitForKeyElements("#item_detailInfo", getKaitoriPageData)
    function getKaitoriPageData(jNode){
        if(isFukubukuro){
            return false;
        }
        if(window.location.href.indexOf("/product/detail/") == -1){
            return false;
        }
        getPageData(kaitoriURL).then(
            function(data){
                var def = $.Deferred();
                const article1 = $(data).find("#article1");
                const detail = $(data).find("#detail");
                /* 買取価格の取得 */
                const priceMain = article1.find("#priceMain span");
                if(priceMain.length != 0){
                    priceOfKaitori = priceMain.text();
                }
                /* JANの取得 */
                const table = detail.find("table#configurations");
                if(table.length == 1 && table.find("td").length > 1){
                    let isJAN = false;
                    $.each(table.find("td"), function(index, td){
                        let tdStr = $(td).text();
                        if(tdStr == "JAN"){
                            isJAN = true;
                            return true;
                        }
                        if(isJAN){
                            tdStr = tdStr.replace(/(	|\r\n|\n)/g, "");
                            if(tdStr.length > 6){
                                jan = tdStr;
                            }
                            return false;
                        }
                    })
                }
                getKaitoriPageDataCompleted = true;
                def.resolve();
                return def.promise();
            },
            function(){
                return $.Deferred().resolve().promise();
            }
        ).then(
            function(){
                if(!getKaitoriPageDataCompleted){
                    return false;
                }
                if(priceOfKaitori != "" && $("#added_kaitori_elem").length == 1){
                    /* 買取価格が設定されてる場合は買取価格表示を追加 */
                    $("#added_kaitori_elem a").empty();
                    const addStr = "この商品の買取価格&nbsp;" + "<span class='text-red'>" + priceOfKaitori + "</span>";
                    $("#added_kaitori_elem a").append(addStr);
                }
                if(jan != "" && $("#item_detailInfo tbody").length == 1){
                    /* JAN表示、JAN検索を追加 */
                    let addElem = "<th class='text-right'>JAN</th><td>" + jan + "</td>";
                    const url1 = fixURL("https://www.suruga-ya.jp/search?category=&search_word=" + jan);
                    const url2 = fixURL("https://www.suruga-ya.jp/search_buy?category=&search_word=" + jan);
                    const url3 = "https://www.google.com/search?q=" + jan;
                    const base64EncodedStr1 = "aHR0cHM6Ly93d3cuYW1hem9uLmNvLmpwL2dwL3NlYXJjaC9yZWY9YXNfb" +
                          "GlfcWZfc3Bfc3JfdGw/aWU9VVRGOCZ0YWc9a29vZC0yMiZrZXl3b3Jkcz0=";
                    const url4 = atob(base64EncodedStr1) + jan;
                    const link1 = "<a href='" + url1 + "' class='jan_search'>販売</a>";
                    const link2 = "<a href='" + url2 + "' class='jan_search'>買取</a>";
                    const link3 = "<a href='" + url3 + "' class='jan_search'>Google</a>";
                    const link4 = "<a href='" + url4 + "' class='jan_search'>Amazon</a>";
                    const searchLinks = link1 + " / " + link2 + " / " + link3 + " / " + link4;
                    addElem = addElem +  "<th class='text-right'>JANで検索</th><td>" + searchLinks + "</td>";
                    addElem = addElem + "<th></th><td></td>";
                    addElem = addElem + "<th></th><td></td>";
                    addElem = addElem + "<th></th><td></td>";
                    addElem = "<tr>" + addElem + "</tr>";
                    $("#item_detailInfo tbody").prepend(addElem);
                    $(".jan_search").addClass("link_underline");
                }
            }
        )
    }

    /* 買取ページに販売ページのリンク(ボタン)を追加 + 販売ページから取得した画像と価格を販売ページに追加 */
    waitForKeyElements("#ansin #article1", getProductPageData);
    function getProductPageData(jNode){
        if(window.location.href.indexOf("/kaitori_detail/") == -1){
            return false;
        }
        const priceElem = jNode.find("#price");
        getPageData(productURL).then(
            function(data){
                var def = $.Deferred();
                $.each($(data).find(".item-price .mgnB0.d-block"), function(index, elem){
                    const labelStr = $(elem).data("label");
                    let priceStr = $(elem).find(".price-buy").text();
                    priceStr = priceStr.replace(" (税込)", "");
                    if(labelStr.indexOf("新品") > -1){
                        priceOfBrandNew = priceStr;
                    }else if(labelStr.indexOf("中古") > -1){
                        priceOfUsed = priceStr;
                    }else if(labelStr.indexOf("予約") > -1){
                        priceOfPreOrder = priceStr;
                    }
                })
                $.each($(data).find(".link-group.mgnT12 li"), function(index, elem){
                    if($(elem).find("a").text().indexOf("他のショップ") > -1){
                        priceOfMarketplace = $(elem).find("span").text();
                        priceOfMarketplace = priceOfMarketplace.replace(" ~", "");
                        return false;
                    }
                })
                defaultImgURL = $(data).find(".img-fluid")[0].currentSrc;
                if(defaultImgURL.indexOf("no_photo.jpg") > -1){
                    defaultImgURL = "";
                }
                getProductPageDataCompleted = true;
                def.resolve();
                return def.promise();
            },
            function(){
                return $.Deferred().resolve().promise();
            }
        ).then(
            function(){
                if(!getProductPageDataCompleted){
                    return false;
                }
                let sellingPriceElem = "";
                if(priceOfPreOrder != ""){
                    sellingPriceElem += "<div id='priceOfPreOrder'>販売価格<span>"+priceOfPreOrder+" (予約)</span></div>";
                }
                if(priceOfBrandNew != ""){
                    sellingPriceElem += "<div id='priceOfBrandNew'>販売価格<span>"+priceOfBrandNew+" (新品)</span></div>";
                }
                if(priceOfUsed != ""){
                    sellingPriceElem += "<div id='priceOfUsed'>販売価格<span>" + priceOfUsed + " (中古)</span></div>";
                }
                if(priceOfMarketplace != ""){
                    sellingPriceElem += "<div id='priceOfMarketplace'>販売価格<span>" + priceOfMarketplace + " (マケプレ最安値)</span></div>";
                }
                const link = "<a href='" + fixURL(productURL) + "'>販売ページへ</a>";
                let buttonElem = "<button type='button' class='btn w-100' id='productButton'>" + link + "</button>";
                if(sellingPriceElem != ""){
                    sellingPriceElem = "<div id='sellingPrice'>" + sellingPriceElem + "</div>";
                    priceElem.after(sellingPriceElem);
                    $("#sellingPrice").css({
                        "font-size": "14px",
                        "font-weight": "bold",
                        "padding-top": "10px"
                    });
                    $("#sellingPrice span").css({
                        "color": "#CC3333",
                        "font-size": "18px",
                        "padding-left": "15px"
                    });
                    $("#sellingPrice div").last().after(buttonElem);
                    $("#sellingPrice div").last().css("float", "left");
                }else{
                    priceElem.after("<div id='sellingPrice'>" + buttonElem + "</div>");
                }
                const price = document.getElementById("price");
                const priceStyle = window.getComputedStyle(price);
                let priceInlineSize = parseInt(priceStyle.inlineSize.replace("px", ""));
                const tempWidth = $($(".cart1")[0]).offset().left - priceElem.offset().left + 160;
                let marginRight = priceInlineSize - tempWidth;
                marginRight = marginRight + "px";
                $("#productButton").css({
                    "float": "right",
                    "margin-right": marginRight,
                    "width": "160px",
                    "font-size": "14px",
                    "font-weight": "bold",
                    "padding" : "3px 0 3px 0",
                    "border": "1px solid #c7c7c7",
                });
                const imgElem = $(jNode.find("img")[0]);
                if(defaultImgURL != "" && imgElem.attr("src").indexOf("no_photo.jpg") > -1){
                    imgElem.attr("src", defaultImgURL);
                    imgElem.removeAttr("width");
                }
            }
        )
    }

    /* ページ右上のカートアイコンの横にカート内の商品の合計価格表示を追加 */
    waitForKeyElements(".item_right_header .lbl_cart.cart-number", getTotalPrice);
    $(".btn_buy.btn.cart1").on("click", function(){
        skipNumOfProdsCheck = true;
        setTimeout(function(){
            getTotalPrice();
        }, 1000);
    })
    function getTotalPrice(){
        $("#added_price_elem").remove();
        const cartNumElem = $(".item_right_header .lbl_cart.cart-number");
        if(window.location.href.indexOf("cargo/detail") > -1){
            readCartPage($(document), cartNumElem);
            return false;
        }
        if(cartNumElem.length != 1){
            return false;
        }
        if(cartNumElem.text() == ""){
            setTimeout(function(){
                getTotalPrice();
            }, 1000);
            return false;
        }
        const numOfProds = cartNumElem.text();
        if(numOfProds == "0"){
            /* カートに何も入っていなければ終了 */
            localStorage.setItem("enhancer__num_of_prods", 0);
            localStorage.setItem("enhancer__total_price", "");
            localStorage.setItem("enhancer__delivery_charge", "");
            if(!skipNumOfProdsCheck){
                return false;
            }
        }
        if(!skipNumOfProdsCheck && localStorage.getItem("enhancer__num_of_prods") != null){
            if(numOfProds == localStorage.getItem("enhancer__num_of_prods")){
                /* カート内の商品数とlocalStorageに保存された商品数が同じ場合はlocalStorageから読み込む */
                readLocalStorage(cartNumElem);
                return false;
            }
        }else{
            localStorage.setItem("enhancer__num_of_prods", numOfProds);
        }
        getPageData(cartURL).then(
            function(data){
                readCartPage($(data), cartNumElem);
            }
        )
    }

    function readCartPage(jqObj, cartNumElem){
        const total = jqObj.find(".next_step .total");
        const itemCount = total.find(".item_count").text();
        const numOfProds = itemCount.replace(/(\(|\)|点|:)/g, "");
        if(numOfProds == ""){
            localStorage.setItem("enhancer__num_of_prods", 0);
            localStorage.setItem("enhancer__total_price", "");
            localStorage.setItem("enhancer__delivery_charge", "");
            return false;
        }
        localStorage.setItem("enhancer__num_of_prods", numOfProds);
        let totalPrice = total.find(".mgnB0 > .total_price").text();
        if(totalPrice == ""){
            totalPrice = $(total.find(".total_price")[0]).text();
        }
        localStorage.setItem("enhancer__total_price", totalPrice);
        let deliveryCharge = total.find(".delivery_charge.mgnT5").text();
        deliveryCharge = deliveryCharge.replace(/( |	|\r\n|\n)/g, "");
        localStorage.setItem("enhancer__delivery_charge", deliveryCharge);
        const priceElem = "<span id='added_price_elem'>" + totalPrice + "(" + deliveryCharge + ")" + "</span>";
        cartNumElem.after(priceElem);
    }

    function readLocalStorage(cartNumElem){
        const totalPrice = localStorage.getItem("enhancer__total_price");
        const deliveryCharge = localStorage.getItem("enhancer__delivery_charge");
        const priceElem = "<span id='added_price_elem'>" + totalPrice + "(" + deliveryCharge + ")" + "</span>";
        cartNumElem.after(priceElem);
    }

    function getPageData(url){
        var def = $.Deferred();
        $.ajax({
            type: "GET",
            url: url
        }).done(function(data){
            def.resolve(data);
        }).fail(function(){
            def.reject();
        });
        return def.promise();
    }

    function fixURL(url){
        //return url;
        if(base64Decoded == ""){
            base64Decoded = decodeURIComponent(atob(base64Encoded));
        }
        const encodedURL = encodeURIComponent(url);
        url = base64Decoded + encodedURL;
        return url;
    }

    waitForKeyElements(".item_right_header .d-flex.justify-content-start.align-content-center", afCartIcon);
    function afCartIcon(jNode){
        jNode.attr("href", fixURL(cartURL));
    }

    waitForKeyElements(".total .register .btn",afRegisterButton);
    function afRegisterButton(jNode){
        let registerURL = jNode.attr("href");
        if(registerURL.indexOf("/") == 0){
            registerURL = "https://www.suruga-ya.jp" + regregisterURListerUrl;
        }
        jNode.attr("href", fixURL(registerURL));
    }

    waitForKeyElements("#ansin .TabbedPanels .TabbedPanelsTabLink a", afAnsinCart);
    function afAnsinCart(jNode){
        if(jNode.text().indexOf("売却カートを見る") > -1){
            let AnsinCartURL = jNode.attr("href");
            if(AnsinCartURL.indexOf("/") == 0){
                AnsinCartURL = "https://www.suruga-ya.jp" + AnsinCartURL;
            }
            jNode.attr("href", fixURL(AnsinCartURL));
        }
    }

    waitForKeyElements("#ansin #tabbed p.button a", afAnsinNyuryoku);
    function afAnsinNyuryoku(jNode){
        if(jNode.text().indexOf("申込み手続きへ") > -1){
            let AnsinNyuryokuURL = jNode.attr("href");
            if(AnsinNyuryokuURL.indexOf("/") == 0){
                AnsinNyuryokuURL = "https://www.suruga-ya.jp" + AnsinNyuryokuURL;
            }
            jNode.attr("href", fixURL(AnsinNyuryokuURL));
        }
    }

})();