Ukrainian Steam Improvements

Adds (1) the state flag for games that have Ukrainian language, (2) alert emojis for ua and ru -made games, (3) prices at the top, (4) more noticeable score over the game banner.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           Ukrainian Steam Improvements
// @description    Adds (1) the state flag for games that have Ukrainian language, (2) alert emojis for ua and ru -made games, (3) prices at the top, (4) more noticeable score over the game banner.
// @include        https://store.steampowered.com/*
// @grant          GM_addStyle
// @icon           https://community.akamai.steamstatic.com/public/images/countryflags/ua.gif
// @license        https://creativecommons.org/licenses/by-sa/4.0/
// @author         Prudten
// @version        1.1.2
// @namespace https://greasyfork.org/users/1235514
// ==/UserScript==
'use strict';

GM_addStyle(`
    .btn_red_steamui {
    border-radius: 2px;
    border: none;
    padding: 1px;
    display: inline-block;
    cursor: pointer;
    text-decoration: none !important;
    color: #D28BA9; !important;

    background: transparent;    text-shadow: 1px 1px 0px rgba( 0, 0, 0, 0.3 );}

    .btn_red_steamui > span {
        border-radius: 2px;
        display: block;


                    background: #D34320;
            background: -webkit-linear-gradient( top, #D34320 5%, #BC261B 95%);
    background: linear-gradient( to bottom, #D34320 5%, #BC261B 95%);
        background: linear-gradient( to right, #D94C22 5%, #BC261B 95%);    }

.btn_red_steamui:not(.btn_disabled):not(:disabled):not(.btn_active):not(.active):hover {
    text-decoration: none !important;
    color: #fff; !important;

    background: transparent;    }

    .btn_red_steamui:not(.btn_disabled):not(:disabled):not(.btn_active):not(.active):hover > span {
                    background: #8E0E29;
            background: -webkit-linear-gradient( top, #8E0E29 5%, #CE4221 95%);
    background: linear-gradient( to bottom, #8E0E29 5%, #CE4221 95%);
        background: linear-gradient( to right, #8E0E29 5%, #CE4221 95%);    }

    .btn_red_steamui.btn_active, btn_red_steamui.active {
    text-decoration: none !important;
    color: #fff; !important;

        background: transparent;            }

    .btn_red_steamui.btn_active > span, btn_red_steamui.active > span {
                    background: #8E0E29;
            background: -webkit-linear-gradient( top, #8E0E29 5%, #CE4221 95%);
    background: linear-gradient( to bottom, #8E0E29 5%, #CE4221 95%);
        background: linear-gradient( to right, #8E0E29 5%, #CE4221 95%);    }

.discount_block .discount_pct_red, .discount_pct_red {
            font-family: "Motiva Sans", Sans-serif;
        font-weight: normal; /* normal */

            font-weight: 500;
    color: #FF2611;
    background: #B00722;
    display: inline-block;
}

.game_purchase_discount .discount_pct_red,
.game_purchase_discount .bundle_base_discount {
    display: inline-block;
    height: 32px;
    line-height: 32px;
    font-size: 25px;
    text-align: center;
    overflow: hidden;
    padding: 0 6px;
}

.image-container {
    position: relative;
    display: inline-block;
}

.overlay-text {
    position: absolute;
    bottom: 0;
    right: 0;
    background-color: #A00000;
    font-size: 20px;
}

.box {
    position: absolute;
    bottom: 0;
    right: 0;
    background-color: #FF0000;
    float: left;
    height: 40px;
    width: 40px;
    margin-bottom: 1%;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #272727;
    font-size: 25px;
    font-weight: bold;
    font-family: HelveticaNeue;
}

.score95 {
    background-color: #00D25F;
}
.score85 {
    background-color: #66CC33;
}
.score75 {
    background-color: #98DD75;
}
.score70 {
    background-color: #FFCC33;
}
.score55 {
    background-color: #FE9640;
}

`);


function insertAfter(newNode, existingNode) {
    existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
}

function isNumeric(str) {
    if (typeof str != "string") return false
    return !isNaN(str) && !isNaN(parseFloat(str))
}


if(window.location.toString().includes("app")) {
    // check translations
    var cells = document.getElementsByClassName("ellipsis");
    var title = document.getElementsByClassName("apphub_AppName")[0];
    var oldTitle = title.innerHTML;
    var uagif = "<img src=\"https://community.akamai.steamstatic.com/public/images/countryflags/ua.gif\">";

    var notSupported = ["\n                  Не підтримується                ",
                        "\n\t\t\t\t\tНе підтримується\t\t\t\t"];
    var russian      = ["\n                Russian           ",
                        "\n\t\t\t\tRussian\t\t\t",
                        "\n                російська           ",
                        "\n\t\t\t\tросійська\t\t\t"];
    var ukrainian    = ["\n                Ukrainian           ",
                        "\n\t\t\t\tUkrainian\t\t\t",
                        "\n                українська           ",
                        "\n\t\t\t\tукраїнська\t\t\t"];

    var sunflower = "🌻"
    Array.prototype.forEach.call(cells, function(cell) {
        if (russian.includes(cell.textContent) &&
        !notSupported.includes(cell.nextSibling.nextSibling.textContent)) {
            sunflower = "";
        };
    });

    Array.prototype.forEach.call(cells, function(cell) {
        if (ukrainian.includes(cell.textContent) &&
        !notSupported.includes(cell.nextSibling.nextSibling.textContent)) {
            var original_ua = cell.textContent.split(/(\p{L}.*)/u);
            cell.innerHTML = original_ua[0] + uagif + " " + original_ua[1];
            title.innerHTML = `${oldTitle} ${sunflower}${uagif}`;
        };
    });

    // check if it's Ukrainian
    oldTitle = title.innerHTML;
    var imgs = document.getElementsByTagName("img");
    var ridne = "93f3a9d4a6868bbaadc90dbbeeecfa13770a59a1";
    Array.prototype.forEach.call(imgs, function(img) {
        var imgName = img.src.split("/").pop()
        if ((imgName == `${ridne}.jpg`) ||
        (imgName == `${ridne}_medium.jpg`) ||
        (imgName == `${ridne}_full.jpg`)) {
            title.innerHTML = `💙💛 ${oldTitle}`;
        };
    });

    // check if it's made by 🐷🐶
    oldTitle = title.innerHTML;
    var prices = document.querySelectorAll('.game_purchase_price, .discount_final_price');
    var btns = document.querySelectorAll('.btn_green_steamui, .btn_blue_steamui');
    var dscs = document.querySelectorAll('.discount_pct');
    var roosnya = false;
    var niroosni = ["329f37319a1d6a0c79c67a388414278e3b2996c0.jpg",
                    "329f37319a1d6a0c79c67a388414278e3b2996c0_medium.jpg",
                    "329f37319a1d6a0c79c67a388414278e3b2996c0_full.jpg",
                    "992f3008daabfe9a3a795896a407525ce11b1cc5.jpg",
                    "992f3008daabfe9a3a795896a407525ce11b1cc5_medium.jpg",
                    "992f3008daabfe9a3a795896a407525ce11b1cc5_full.jpg",
                    "5d05c9a196c34e3860fcb34a389c8d0cd6801de8.jpg",
                    "5d05c9a196c34e3860fcb34a389c8d0cd6801de8_medium.jpg",
                    "5d05c9a196c34e3860fcb34a389c8d0cd6801de8_full.jpg"];

    Array.prototype.forEach.call(imgs, function(img) {
        var imgName = img.src.split("/").pop();
        if (!roosnya && niroosni.includes(imgName)) {
            roosnya = true;
            title.innerHTML = `🐷🐶 <font color="red">${oldTitle}</font>`;
            Array.prototype.forEach.call(prices, function(price) {
                var oldPrice = price.innerHTML;
                price.innerHTML = `<font color="red">${oldPrice}</font> 🐷🐶`;
            });
            Array.prototype.forEach.call(btns, function(btn) {
                btn.classList.remove('btn_green_steamui','btn_blue_steamui');
                btn.classList.add('btn_red_steamui');
            });
            Array.prototype.forEach.call(dscs, function(dsc) {
                dsc.classList.remove('discount_pct');
                dsc.classList.add('discount_pct_red');
            });
        };
    });

    // add elements to the top right corner
    var hub = document.getElementsByClassName("btnv6_blue_hoverfade")[0];
    hub.innerHTML = "\n                    <span>✚</span>\n                ";

    var price = document.createElement("div");
    price.classList.add('btnv6_blue_hoverfade','btn_medium');
    insertAfter(price, hub);

    // check if it's not a demo
    if ((document.getElementsByClassName("game_purchase_action").length > 1) &&
    (document.getElementById("demoGameBtn"))) {
        var priceNode = document.getElementsByClassName("game_purchase_action")[1];
    } else {
        var priceNode = document.getElementsByClassName("game_purchase_action")[0];
    };

    // check if it's not released yet
    if (document.getElementsByClassName("game_area_comingsoon")[0]) {
        var priceText = "В розробці";
        if (roosnya) {
            priceText = `<font color="red">${priceText}</font> 🐷🐶`;
        };
    // check the price if it's been released
    } else if (priceNode.getElementsByClassName("game_purchase_price").length > 0) {
        var priceText = priceNode.getElementsByClassName("game_purchase_price")[0].innerHTML;
        // check if it's a free game
        if (document.getElementById("freeGameBtn")) {
            priceText = `<font color="#beee11">${priceText}</font>`;
        };
    // check if it's on sale
    } else if (priceNode.getElementsByClassName("discount_final_price").length > 0) {
        var priceText = priceNode.getElementsByClassName("discount_final_price")[0].innerHTML;

        var discount = document.createElement("div");
        discount.classList.add('btnv6_blue_hoverfade','btn_medium');
        insertAfter(discount, hub);

        if (roosnya) {
            var discountText = priceNode.getElementsByClassName("discount_pct_red")[0].innerHTML;
            discount.innerHTML = `<span><font color="red">${discountText}</font></span>`;
        } else {
            var discountText = priceNode.getElementsByClassName("discount_pct")[0].innerHTML;
            //discount.innerHTML = `<span><font color="#66cc33">${discountText}</font></span>`;
            discount.innerHTML = `<span><font color="#a3cf06">${discountText}</font></span>`;
            //discount.innerHTML = `<span><font color="#beee11">${discountText}</font></span>`;
        };
        discount.insertAdjacentText('beforebegin', `\n                `);
    } else if ((priceNode.getElementsByClassName("game_purchase_price").length === 0) && 
    (priceNode.getElementsByClassName("btn_addtocart").length > 0)) {
        var priceText = `<font color="#beee11">Безкоштовно</font>`;
    };

    price.innerHTML = `<span>${priceText}</span>`;
    price.insertAdjacentText('beforebegin', `\n                `);

    // add score
    var banner = document.getElementsByClassName("game_header_image_full")[0];
    var banner_parent = banner.parentNode;
    var banner_wrapper = document.createElement('div');
    banner_wrapper.classList.add("image-container");
    banner_parent.replaceChild(banner_wrapper, banner);
    banner_wrapper.appendChild(banner);

    var score_txt = document.getElementsByClassName("user_reviews_summary_row")[1];
    if (!score_txt.hasAttribute("data-tooltip-html")) {
        score_txt = document.getElementsByClassName("user_reviews_summary_row")[0];
    };

    score_txt = score_txt.getAttribute("data-tooltip-html").split('%', 1);

    if (isNumeric(score_txt[0])) {
        var score_int = parseInt(score_txt);

        var score = document.createElement("div");
        score.classList.add('box');
        score.textContent = score_txt;

        if (score_int > 95) {
            score.classList.add('score95');
        } else if (score_int >= 85) {
            score.classList.add('score85');
        } else if (score_int >= 75) {
            score.classList.add('score75');
        } else if (score_int >= 70) {
            score.classList.add('score70');
        } else if (score_int >= 55) {
            score.classList.add('score55');
        };

        banner_wrapper.appendChild(score);
    };
};

// insert html inside a text
// and replace specific part of that text
// i.e. insert a tag inside a text node
// from https://stackoverflow.com/a/29301739
// huy znaye yak vono robe ale krasyvo
var matchText = function(node, regex, callback, excludeElements) { 

    excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']);
    var child = node.firstChild;

    while (child) {
        switch (child.nodeType) {
        case 1:
            if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1)
                break;
            matchText(child, regex, callback, excludeElements);
            break;
        case 3:
            var bk = 0;
            child.data.replace(regex, function(all) {
                var args = [].slice.call(arguments),
                    offset = args[args.length - 2],
                    newTextNode = child.splitText(offset+bk), tag;
                bk -= child.data.length + all.length;

                newTextNode.data = newTextNode.data.substr(all.length);
                tag = callback.apply(window, [child].concat(args));
                child.parentNode.insertBefore(tag, newTextNode);
                child = newTextNode;
            });
            regex.lastIndex = 0;
            break;
        }

        child = child.nextSibling;
    }

    return node;
};

// add spaces before ₴ sign
matchText(document.body, new RegExp("₴", "g"), function(node, match, offset) {
    var hryvnia = document.createElement("span");
    hryvnia.style.cssText += "font-family: 'Calibri Light'; font-weight: bold; font-size: 110%;";
    hryvnia.innerHTML = " ₴";
    return hryvnia;
});