您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shows if an Itch.io link has been claimed or not
当前为
// ==UserScript== // @name Itch.io Web Integration // @namespace Lex@GreasyFork // @match *://*/* // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @version 0.1.2.1 // @author Lex // @description Shows if an Itch.io link has been claimed or not // @connect itch.io // ==/UserScript== // TODO // Add ability to claim the game with one click (function(){ 'use strict'; const INVALIDATION_TIME = 5*60*60*1000; // 5 hour cache time const ITCH_GAME_CACHE_KEY = 'ItchGameCache'; var ItchGameCache; // Promise wrapper for GM_xmlhttpRequest const Request = details => new Promise((resolve, reject) => { details.onerror = details.ontimeout = reject; details.onload = resolve; GM_xmlhttpRequest(details); }); function loadItchCache() { ItchGameCache = JSON.parse(GM_getValue(ITCH_GAME_CACHE_KEY) || '{}'); } function _saveItchCache() { if (ItchGameCache === undefined) return; GM_setValue(ITCH_GAME_CACHE_KEY, JSON.stringify(ItchGameCache)); } function setItchGameCache(key, game) { loadItchCache(); // refresh our cache in case another tab has edited it ItchGameCache[key] = game; _saveItchCache(); } function deleteItchGameCache(key) { if (key === undefined) return; loadItchCache(); delete ItchGameCache[key]; _saveItchCache(); } function getItchGameCache(link) { if (!ItchGameCache) loadItchCache(); if (Object.prototype.hasOwnProperty.call(ItchGameCache, link)) { return ItchGameCache[link]; } return null; } // Sends an XHR request and parses the results into a game object async function fetchItchGame(url) { const response = await Request({method: "GET", url: url}); const parser = new DOMParser(); const dom = parser.parseFromString(response.responseText, 'text/html'); const h2 = dom.querySelector(".purchase_banner_inner .key_row .ownership_reason"); const game = {}; game.cachetime = (new Date()).getTime(); game.url = url; game.isOwned = h2 !== null return game; } // Loads an itch game from cache or fetches the page if needed async function getItchGame(url) { let game = getItchGameCache(url); if (game !== null) { const isExpired = (new Date()).getTime() - game.cachetime > INVALIDATION_TIME; if (isExpired) { game = null; } } if (game === null) { game = await fetchItchGame(url); setItchGameCache(url, game); } return game; } // Appends the isOwned tag to an anchor link function appendTags(a, isOwned) { const div = document.createElement("div"); a.after(div); const ownMark = isOwned ? `<span title="Game is already claimed on itch.io">✔️</span>` : `<span title="Game is not claimed">❌</span>`; div.outerHTML = `<div style="margin-left: 5px; background:rgb(200,200,200); border-radius: 5px; display: inline-block;">${ownMark}</div>`; } function addClickHandler(a) { a.addEventListener('mouseup', event => { deleteItchGameCache(event.target.href); }); } // Handles an itch.io link on a page async function handleLink(a) { addClickHandler(a); const game = await getItchGame(a.href); appendTags(a, game.isOwned); } // Finds all the itch.io links on the current page function getItchLinks() { let links = [...document.querySelectorAll("a[href*='itch.io/']")]; links = links.filter(a => /^https:\/\/[^.]+\.itch\.io\/[^/]+$/.test(a.href)); links = links.filter(a => !a.classList.contains("return_link")); return links; } function handlePage() { const as = getItchLinks(); as.forEach(handleLink); } handlePage(); })();