Greasy Fork

来自缓存

显示Steam游戏在线人数

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

目前为 2023-10-16 提交的版本。查看 最新版本

// ==UserScript==
// @name         显示Steam游戏在线人数
// @description  在Steam商店页右侧信息面板增加在线人数, 便于观察游戏的实际热度
// @icon         https://store.steampowered.com/favicon.ico
// @version      1.4
// @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 fillText(msg, type) {
    if (type == 'peak') {
        if (onedayPeakTextNode) onedayPeakTextNode.textContent = msg
        else onedayInitText = msg
        return;
    }
    if (onlineTextNode) onlineTextNode.textContent = msg
    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)
            } 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(`解析返回值失败:${response.responseText}`, '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">浏览所有评测</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: #7cc53f;">${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: #7cc53f;">${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 });