Greasy Fork is available in English.

Did they even play?

Show play stats on Steam Gifts winners pages. Adapted from kelnage's Do You Even Play, Bro? script.

Ajankohdalta 1.8.2017. Katso uusin versio.

// ==UserScript==
// @name         Did they even play?
// @namespace    https://www.steamgifts.com/user/lext
// @version      0.15
// @description  Show play stats on Steam Gifts winners pages. Adapted from kelnage's Do You Even Play, Bro? script.
// @author       Lex
// @match        *://www.steamgifts.com/giveaway/*/winners*
// @require      http://code.jquery.com/jquery-3.2.1.min.js
// @connect      api.steampowered.com
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// ==/UserScript==

(function() {
    'use strict';

    const PLAYTIME_URL = "https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/"; // takes a steamid and API key
    const ACHIEVEMENTS_URL = "https://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/"; // takes a steamid, appid and API key
    const SG_USER_URL = "https://www.steamgifts.com/user/";
    const GAME_ACHIEVEMENTS_URL = "http://steamcommunity.com/profiles/$1/stats/$2/achievements/";

    const INVALIDATION_TIME = 30*60*1000; // 30 minute cache time
    const PLAYTIME_CACHE_KEY = "PLAYTIME_CACHE_KEY_";
    function getCachedPlaytime(steamID64, gameID) { return getCachedJSONValue(PLAYTIME_CACHE_KEY + encodeURIComponent(steamID64) + "_g" + encodeURIComponent(gameID)); }
    function setCachedPlaytime(steamID64, gameID, value) { cacheJSONValue(PLAYTIME_CACHE_KEY + encodeURIComponent(steamID64) + "_g" + encodeURIComponent(gameID), value); }
    const ACHIEVEMENTS_CACHE_KEY = "ACHIEVEMENTS_CACHE_KEY_";
    function getCachedAchievements(steamID64, gameID) { return getCachedJSONValue(ACHIEVEMENTS_CACHE_KEY + encodeURIComponent(steamID64) + "_g" + encodeURIComponent(gameID)); }
    function setCachedAchievements(steamID64, gameID, value) { cacheJSONValue(ACHIEVEMENTS_CACHE_KEY + encodeURIComponent(steamID64) + "_g" + encodeURIComponent(gameID), value); }
    const STEAMID_CACHE_KEY = "STEAMID_CACHE_";
    function getCachedSteamID(username) { return GM_getValue(STEAMID_CACHE_KEY + encodeURIComponent(username)); }
    function setCachedSteamID(username, steamID64) { GM_setValue(STEAMID_CACHE_KEY + encodeURIComponent(username), steamID64); }
    const API_KEY_REGEXP = /[0-9A-Z]{32}/;

    const APPID = $("div.featured__inner-wrap a.global__image-outer-wrap").attr('href').match(/\/(\d+)/)[1];

    function getCachedJSONValue(key) {
        try {
            let result = JSON.parse(GM_getValue(key));
            if ((new Date()).getTime() - result.UPDATE_TIME < INVALIDATION_TIME)
                return result;
        } catch (err) { }
    }

    function cacheJSONValue(key, value) {
        value.UPDATE_TIME = (new Date()).getTime();
        GM_setValue(key, JSON.stringify(value));
    }

    var STEAM_API_KEY = GM_getValue("STEAM_API_KEY");

    if (STEAM_API_KEY == "undefined" || STEAM_API_KEY === undefined) {
        var apiDiv = $(`<form><input class="steamApiKey" style="margin-left: 15px; width: 300px" type="text" value="STEAM_API_KEY_HERE"/>
<input style="float:left;" name="btnSubmit" type="button" value="Submit"></input></form>`);
        apiDiv.find("input[name='btnSubmit']").click(function(){
            const api_key = $(this).parents("form:first").find("input.steamApiKey").val();
            if (api_key.match(API_KEY_REGEXP)) {
                GM_setValue("STEAM_API_KEY", api_key);
                $(this).parent().text(" - API key set");
            } else
                alert("Error: Invalid API Key. Please try again.");
        });
        $("div.page__heading__breadcrumbs").append(apiDiv);
        return;
    } else {
        var apiDelDiv = $(`<div style="margin-left: 15px"><a href="#">Delete API Key for Did they even play?</a></div>`);
        apiDelDiv.find("a").one("click", function(){
            $(this).parent().text("Deleted");
            GM_deleteValue("STEAM_API_KEY");
        });
        $("div.page__heading__breadcrumbs").append(apiDelDiv);
        main();
    }

    function fetchGamePlaytimes(steamID64, callback) {
        GM_xmlhttpRequest({
            "method": "GET",
            "url": PLAYTIME_URL + "?steamid=" + steamID64 + "&key=" + STEAM_API_KEY,
            "onload": function(response) {
                try {
                    callback(JSON.parse(response.responseText).response.games);
                } catch(err) {
                    callback();
                }
            }
        });
    }

    function fetchGamePlaytime(steamID64, gameid, callback) {
        const cachedPlaytime = getCachedPlaytime(steamID64, gameid);
        if (cachedPlaytime !== undefined)
            return callback(cachedPlaytime.playtime_forever);
        fetchGamePlaytimes(steamID64, function(games) {
            if (games === undefined)
                callback(-1); // Profile is private, so the games array is empty
            for(var i = 0; i < games.length; i++) {
                if (games[i].appid == gameid) {
                    setCachedPlaytime(steamID64, gameid, games[i]);
                    return callback(games[i].playtime_forever); // playtime in minutes
                }
            }
            callback();
        });
    }

    function fetchAchievementStats(steamID64, appid, callback) {
        const cachedAchievements = getCachedAchievements(steamID64, appid);
        if (cachedAchievements !== undefined)
            return callback(cachedAchievements);
        GM_xmlhttpRequest({
            "method": "GET",
            "url": ACHIEVEMENTS_URL + "?appid=" + appid + "&steamid=" + steamID64 + "&key=" + STEAM_API_KEY,
            "onload": function(response) {
                let results = {"achieved": 0, "total": 0};
                try {
                    const data = JSON.parse(response.responseText);
                    results.achieved = data.playerstats.achievements.filter(function(a) { return a.achieved == 1; }).length;
                    results.total = data.playerstats.achievements.length;
                } catch(err) { }
                setCachedAchievements(steamID64, appid, results);
                return callback(results);
            }
        });
    }

    function fetchSteamID(username, callback) {
        const cachedSteamID = getCachedSteamID(username);
        if (cachedSteamID !== undefined)
            return callback(cachedSteamID);
        GM_xmlhttpRequest({
            "method": "GET",
            "url": SG_USER_URL + username,
            "onload": function(response) {
                const steamID = $('a[data-tooltip="Visit Steam Profile"]', response.responseText).attr("href").match(/\d{17}/)[0];
                setCachedSteamID(username, steamID);
                callback(steamID);
            }
        });
    }

    function steamIDRetrieved(steamID, heading) {
        const achUrl = GAME_ACHIEVEMENTS_URL.replace("$1", steamID).replace("$2", APPID);
        heading.append(`<div style="display:inline-block"><a href="${achUrl}"> - <span class="DTEP_ACHIEVEMENTS"/> <span style="text-decoration:underline">Achievements</span></a><span class="DTEP_PLAYTIME"/></div>`);

        fetchGamePlaytime(steamID, APPID, function(playtime) {
            if (playtime === undefined)
                heading.find(".DTEP_PLAYTIME").parent().text("Game appears unactivated").css({'color':'crimson', "font-weight":"bold"});
            else if (playtime === -1)
                heading.find(".DTEP_PLAYTIME").parent().text("Profile is private").css({'color':'crimson', "font-weight":"bold"});
            else {
                const hours = +(playtime / 60).toFixed(2);
                heading.find(".DTEP_PLAYTIME").text(", " + hours + " hours total");
            }
        });

        fetchAchievementStats(steamID, APPID, function(achievements) {
            if (achievements.total === 0)
                heading.find(".DTEP_ACHIEVEMENTS").parent().text("Game has no achievements");
            else
                heading.find(".DTEP_ACHIEVEMENTS").text(achievements.achieved + " / " + achievements.total + " ");
        });
    }

    function main() {
        $("p.table__column__heading a").each(function(){
            var self = $(this);
            fetchSteamID(self.text(), function(sid) { steamIDRetrieved(sid, self.parents("div:first")); });
        });
    }
})();