您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Highlights games on GameSieve that are owned on GOG
// ==UserScript== // @name GOG Owned Games Highlighter for GameSieve // @namespace http://tampermonkey.net/ // @version 1.1 // @description Highlights games on GameSieve that are owned on GOG // @author shakeyourbunny // @license MIT // @match https://gamesieve.com/* // @grant GM.xmlHttpRequest // @grant GM.setValue // @grant GM.getValue // @connect gog.com // ==/UserScript== (function() { 'use strict'; // Configuration const DEBUG = false; // Set to true to enable detailed console logging const OWNED_GAMES_TTL = 60 * 60 * 1000; // 1 hour in milliseconds const HIGHLIGHT_COLOR = '#bc9aca'; // GOG color // Logging function const log = (message, forceLog = false) => { if (DEBUG || forceLog) { console.log(`[GOG Highlighter] ${message}`); } }; // Error logging function (always shown) const error = (message) => { console.error(`[GOG Highlighter ERROR] ${message}`); }; // Function to fetch owned games from GOG const fetchOwnedGames = async () => { log('Fetching owned games from GOG'); return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: 'https://www.gog.com/user/data/games', onload: function(response) { // Check if we got a redirect (not logged in) if (response.finalUrl !== 'https://www.gog.com/user/data/games') { error('You are not logged into GOG. Please log in to see owned games.'); reject('Not logged in'); return; } try { const data = JSON.parse(response.responseText); if (data && data.owned && data.owned.length > 0) { log(`Found ${data.owned.length} owned games`, true); resolve(data.owned); } else { error('No owned games found or invalid response format'); reject('No owned games'); } } catch (e) { error(`Failed to parse GOG response: ${e.message}`); reject(e); } }, onerror: function(response) { error(`Failed to fetch owned games: ${response.statusText}`); reject(response.statusText); } }); }); }; // Cache management functions const saveOwnedGames = async (games) => { await GM.setValue('ownedGames', games); await GM.setValue('ownedGamesTimestamp', Date.now()); log(`Saved ${games.length} owned games to cache`); }; const getOwnedGames = async () => { const games = await GM.getValue('ownedGames', null); const timestamp = await GM.getValue('ownedGamesTimestamp', 0); const isExpired = Date.now() - timestamp > OWNED_GAMES_TTL; if (!games || isExpired) { log('Owned games cache expired or not found, fetching fresh data'); try { const freshGames = await fetchOwnedGames(); await saveOwnedGames(freshGames); return freshGames; } catch (e) { log(`Error fetching fresh owned games: ${e}`, true); if (games) { log('Using expired cache as fallback', true); return games; } return []; } } log(`Using cached owned games (${games.length} games)`); return games; }; // Function to highlight owned games on GameSieve const highlightOwnedGames = async () => { log('Starting highlighting process', true); try { const ownedIds = await getOwnedGames(); if (ownedIds.length === 0) { log('No owned games found to highlight', true); return; } // Convert owned IDs to a Set for fast lookup const ownedIdsSet = new Set(ownedIds.map(id => id.toString())); // Select game list on gamesieve.com const gameList = document.querySelector('body > main > article.main > ol'); if (!gameList) { log('Game list not found on page', true); return; } // Process each game in the list const gameItems = gameList.querySelectorAll('li[id]'); let highlightedCount = 0; gameItems.forEach(item => { const gogId = item.getAttribute('id'); if (!gogId) return; // If the game is owned, highlight it if (ownedIdsSet.has(gogId)) { item.style.backgroundColor = HIGHLIGHT_COLOR; highlightedCount++; // Add a visual indicator to the game title for accessibility const titleElement = item.querySelector('h3 .title'); if (titleElement && !titleElement.textContent.includes(' ✓')) { titleElement.textContent += ' ✓'; } } }); log(`Highlighted ${highlightedCount} owned games out of ${gameItems.length} games on page`, true); } catch (e) { error(`Failed to highlight games: ${e.message}`); } }; // Function to observe DOM changes for dynamic content loading const observePageChanges = () => { const observer = new MutationObserver((mutations) => { let shouldRecheck = false; mutations.forEach((mutation) => { // Check if new game items were added if (mutation.type === 'childList') { mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE) { // Check if it's a game item or contains game items if (node.tagName === 'LI' && node.hasAttribute('id')) { shouldRecheck = true; } else if (node.querySelector && node.querySelector('li[id]')) { shouldRecheck = true; } } }); } }); if (shouldRecheck) { log('New content detected, re-highlighting games'); setTimeout(highlightOwnedGames, 100); // Small delay to ensure DOM is settled } }); // Observe the main content area for changes const mainContent = document.querySelector('body > main'); if (mainContent) { observer.observe(mainContent, { childList: true, subtree: true }); log('Started observing page changes'); } return observer; }; // Initialize the script const initialize = () => { log('Script started', true); highlightOwnedGames(); observePageChanges(); }; // Run when the page is fully loaded if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { // Page is already loaded initialize(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址