// ==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")); });
});
}
})();