VNDB Steam Enhancer

Enhance Steam app pages with data from VNDB.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         VNDB Steam Enhancer
// @namespace    https://vndb.org/
// @version      0.1
// @description  Enhance Steam app pages with data from VNDB.
// @author       Midori Kochiya
// @match        https://store.steampowered.com/app/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=steampowered.com
// @grant        GM_xmlhttpRequest
// @connect      api.vndb.org
// @run-at       document-end
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const LENGTH_MAP = {
        1: "Very short",
        2: "Short",
        3: "Medium",
        4: "Long",
        5: "Very long"
    };

    function formatMinutes(minutes) {
        if (minutes < 60) {
            return "" + minutes + "m";
        }
        return "" + Math.floor(minutes / 60) + "h" + (minutes % 60) + "m";
    }

    // From SteamDB
    var CurrentAppID;
    function GetAppIDFromUrl( url )
    {
        const appid = url.match( /\/(?:app|sub|bundle|friendsthatplay|gamecards|recommended|widget)\/(?<id>[0-9]+)/ );

        return appid ? parseInt( appid.groups.id, 10 ) : -1;
    }
    function GetCurrentAppID()
    {
        if( !CurrentAppID )
        {
            CurrentAppID = GetAppIDFromUrl( location.pathname );
        }

        return CurrentAppID;
    }

    function makeRow(rowClass, subtitle, linkText, linkUrl) {
        const row = document.createElement("div");
        row.className = "dev_row " + rowClass;

        const subtitleEl = document.createElement("div");
        subtitleEl.className = 'subtitle column';
        subtitleEl.textContent = subtitle;

        let linkEl;
        if (linkUrl) {
            linkEl = document.createElement("a");
            linkEl.className = "date";
            linkEl.textContent = linkText;
            linkEl.href = linkUrl;
        } else {
            linkEl = document.createElement("div");
            linkEl.className = "date";
            linkEl.textContent = linkText;
        }

        row.appendChild(subtitleEl);
        row.appendChild(linkEl);

        return row;
    }

    let appId = GetCurrentAppID();
    if (appId == -1) {
        return;
    }

    GM_xmlhttpRequest({
        method: "POST",
        url: "https://api.vndb.org/kana/vn",
        data: JSON.stringify({
            "filters": ["release", "=", ["extlink", "=", ["steam", appId]]],
            "fields": "length,length_votes,length_minutes,rating,votecount"
        }),
        headers: {
            "Content-Type": "application/json"
        },
        onload: function(response) {
            let result = JSON.parse(response.responseText);
            if (!result.results || result.results.length == 0) {
                return;
            }

            let item = result.results[0];

            const vndbIdRow = makeRow(
                "vndb_id",
                "VNDB",
                item.id,
                "https://vndb.org/" + item.id
            );

            const rows = [
                vndbIdRow,
            ];

            if (item.rating) {
                rows.push(makeRow(
                    "vndb_rating",
                    "VNDB Rating",
                    "" + item.rating + " (" + item.votecount + ")"
                ));
            }

            if (item.length) {
                let lengthText = LENGTH_MAP[item.length];

                if (item.length_minutes && item.length_votes) {
                    lengthText += " (" + formatMinutes(item.length_minutes) + " from " + item.length_votes + " votes)";
                }

                rows.push(makeRow(
                    "vndb_length",
                    "VNDB Length",
                    lengthText
                ));
            }

            // Reverse due to how they are inserted
            rows.reverse();
            const releaseDate = document.querySelector('.release_date');

            if( releaseDate ){
                for (const el of rows) {
                    releaseDate.parentNode.insertBefore(el, releaseDate.nextSibling);
                }
            } else {
                const firstDevRow = document.querySelector( '.glance_ctn_responsive_left .dev_row' );
                if(firstDevRow) {
                    for (const el of rows) {
                        firstDevRow.parentNode.insertBefore(el, firstDevRow);
                    }
                }
            }
        }
    });
})();