Greasy Fork

来自缓存

Greasy Fork is available in English.

显示Steam游戏在线人数

在Steam商店页右侧信息面板增加在线人数, 便于观察游戏的实际热度

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         显示Steam游戏在线人数
// @description  在Steam商店页右侧信息面板增加在线人数, 便于观察游戏的实际热度
// @icon         https://store.steampowered.com/favicon.ico
// @version      1.7
// @author       cweijan
// @namespace    cweijan/steam_online_players
// @license      MIT
// @run-at       document-start
// @grant        GM_xmlhttpRequest
// @include      *store.steampowered.com/app/*
// ==/UserScript==

function makeElement(htmlString) {
    var div = document.createElement('div');
    div.innerHTML = htmlString.trim();
    return div.firstChild;
}


let onlineTextNode, onedayPeakTextNode;
let initText = GM_xmlhttpRequest ? '数据加载中' : '无网络权限!', onedayInitText = initText
const appId = location.href.match(/app\/(\d+)/)?.[1];

function colorization(msg, node) {
    let color = '#848683';
    if (Number.isNaN(parseInt(msg))) return color;
    if (msg > 100000) {
        color = '#e72424'
    } else if (msg > 50000) {
        color = '#ce3a3a'
    } else if (msg > 10000) {
        color = '#7cc53f'
    } else if (msg > 3000) {
        color = '#579227'
    }
    if (node) {
        node.setAttribute('style', `color: ${color}`)
    }
    return color;
}

function fillText(msg, type) {
    if (type == 'peak') {
        if (onedayPeakTextNode) {
            onedayPeakTextNode.textContent = msg
            colorization(msg, onedayPeakTextNode)
        }
        else onedayInitText = msg
        return;
    }
    if (onlineTextNode) {
        onlineTextNode.textContent = msg
        colorization(msg, onlineTextNode)
    }
    else initText = msg
}

if (GM_xmlhttpRequest) {
    // 接口参考: https://partner.steamgames.com/doc/webapi/ISteamUserStats#GetNumberOfCurrentPlayers
    GM_xmlhttpRequest({
        method: "GET",
        url: `https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/?appid=${appId}`,
        onload(response) {
            try {
                const playerCount = JSON.parse(response.responseText).response.player_count;
                fillText(playerCount || 0)
            } catch (error) {
                fillText(`解析API返回值失败:${response.responseText}`)
            }
        },
        onerror(response) {
            console.log(response)
            fillText("请求失败")
        }
    })
    GM_xmlhttpRequest({
        method: "GET",
        url: `https://steamcharts.com/app/${appId}`,
        onload(response) {
            try {
                const playerCount = response.responseText.match(/(?<="num">)(\d+)/g)[1];
                fillText(playerCount, 'peak')
            } catch (error) {
                fillText(`解析返回值失败`, 'peak')
            }
        },
        onerror(response) {
            console.log(response)
            fillText("请求失败", 'peak')
        }
    })
}

let addedHistory = false;
const observer = new MutationObserver(mutationList => {
    for (var mutation of mutationList) {
        for (var node of mutation.addedNodes) {
            if (!node.querySelectorAll) continue;
            if (node.getAttribute("class") == 'btn_addtocart' && !addedHistory) {
                addedHistory = true;
                // 增加历史价格记录
                const historyBtnHtml = `<div class="btn_addtocart"><a class="btn_blue_steamui btn_medium" href="https://steamdb.info/app/${appId}/#pricehistory" target="_blank"> <span>查看历史价格</span> </a></div>`
                node.parentNode.insertBefore(makeElement(historyBtnHtml), node)
            } else if (node.getAttribute("id") == 'userReviews') {
                // 增加查看所有评价的链接
                node.appendChild(makeElement(`<a style="padding-left: 104px;" target="_blank" href="https://steamcommunity.com/app/${appId}/reviews?browsefilter=toprated">浏览所有评测</a>`))
                // 当前正在玩
                const html = `<div class="user_reviews">
                                <div class="user_reviews_summary_row">
                                    <div class="subtitle column">在玩人数:</div>
                                    <div class="summary column">
                                        <span id="onlinePlayers" style="color: ${colorization(initText)};">${initText}</span>
                                    </div>
                                </div>
                                <div class="user_reviews_summary_row">
                                    <div class="subtitle column">24小时峰值:</div>
                                        <div class="summary column">
                                        <span id="onedayPeakPlayers" style="color: ${colorization(onedayInitText)};">${onedayInitText}</span>
                                    </div>
                                </div>
                            </div>`
                // node.insertBefore(makeElement(html), node.firstChild)
                node.parentNode.insertBefore(makeElement(html), node)
                onlineTextNode = document.getElementById('onlinePlayers')
                onedayPeakTextNode = document.getElementById('onedayPeakPlayers')
            }
        }
    }
});

observer.observe(document, { childList: true, subtree: true });