您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button // click. Needs an IGDB api key.
// ==UserScript== // @name IGDB List Extra Info // @namespace https://greasyfork.org/de/users/155913-nkay08 // @description Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button // click. Needs an IGDB api key. // // @author NKay // @include http*://www.igdb.com/* // @grant none // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js // @version 0.0.3.201808121415 // ==/UserScript== //insert your API-KEY here var apikey = ''; var apiurl; var req; var reqid; var corsproxy; var fields; var fieldsall var myheaders; var gametextarray; var gameidarray; var genresnodearray; var keywordsnodearray; var ratingnodearray; var ttbnodearray; var keyword_dict = {}; var genres_dict = {}; var id_list = {}; var genres_list_list = {}; var genres_list = {}; var keyword_list = {}; var games_info = {}; var games_text_info = {}; var idortext; var keyelement = "div.content-left.col-md-pull-10.col-md-2"; //only execute function if this element is loaded via ajax waitForKeyElements(keyelement, checkForElement); //waitForKeyElements(keyelement,alert1); function alert1() { alert('alert'); } function init() { apiurl = 'https://api-endpoint.igdb.com'; req = '/games/?search='; reqid = '/games/1942?fields=*'; corsproxy = 'https://cors-anywhere.herokuapp.com/'; fields = '?fields=genres,keywords,rating,rating_count,aggregated_rating,aggregated_rating_count,total_rating,total_rating_count,time_to_beat'; fieldsall = 'fields=*'; myheaders = new Headers(); myheaders.append('user-key', apikey); myheaders.append('Accept', 'application/json'); gametextarray = []; gameidarray = []; genresnodearray = []; keywordsnodearray = []; ratingnodearray = []; ttbnodearray = []; reset_data(); idortext = 'text'; /*var fe = fetch('https://cors-anywhere.herokuapp.com/https://api-endpoint.igdb.com/games/?search=Halo&fields=*', {headers: myheaders}) .then(res2 => res2.json()) .then(data => console.log("halo",data)) .catch(function (err) { console.log(err.message); console.log(err.stack); }) .catch(function (err) { console.log(err.message); console.log(err.stack); });*/ } function checkForElement(jnode) { if (!document.getElementById('btnaddinfo')) { init(); addButton(); addAdditionalInfo(); } } function populateGametextarray(element) { //get the game name //console.log(element); var gameurlelement = element.getElementsByTagName('a'); var gameurl = gameurlelement[0].getAttribute("href"); var found = gameurl.match(/[A-Za-z0-9_\-]*$/); var textfromurl = found[0].replace(/-/g, " "); var span1 = element.getElementsByTagName('span'); var gametext = span1[0].innerHTML; var cururl = corsproxy + apiurl + req + gametext; gametextarray.push(gametext); //console.log(textfromurl); //gametextarray.push(cururl); //console.log(cururl) } function populateGameidarray(element) { // get sibling. sibling has game id var sib = element.nextSibling; var gameid = sib.getAttribute("data-game"); } function addTextNodes(div) { for (var i = 0; i < div.length; i++) { // console.log(div[i]); addTextNode(div[i], i); } } function addTextNode(el, i) { var genrestext = document.createTextNode('Genres: '); var genresspan = document.createElement('span'); genresspan.style.fontSize = 'medium'; genresspan.style.textDecoration = 'underline'; genresspan.appendChild(genrestext); el.appendChild(genresspan); var genresnode = document.createElement('span'); genresnode.setAttribute("id", "usgenre" + i.toString()); el.appendChild(genresnode); genresnodearray.push(genresnode); el.appendChild(document.createTextNode(' | ')); var keywordstext = document.createTextNode('Keywords: '); var kwspan = document.createElement('span'); kwspan.style.fontSize = 'medium'; kwspan.style.textDecoration = "underline"; kwspan.appendChild(keywordstext); el.appendChild(kwspan); var keywordsnode = document.createElement('span'); keywordsnode.setAttribute("id", "uskw" + i.toString()); el.appendChild(keywordsnode); keywordsnodearray.push(keywordsnode); el.appendChild(document.createTextNode(' | ')); var ratingtext = document.createTextNode('Rating: '); var rtspan = document.createElement('span'); rtspan.style.fontSize = 'medium'; rtspan.style.textDecoration = "underline"; rtspan.appendChild(ratingtext); el.appendChild(rtspan); var ratingnode = document.createTextNode(''); el.appendChild(ratingnode); ratingnodearray.push(ratingnode); el.appendChild(document.createTextNode(' | ')); var ttbtext = document.createTextNode('TTB: '); var ttbspan = document.createElement('span'); ttbspan.style.fontSize = 'medium'; ttbspan.style.textDecoration = 'underline'; ttbspan.appendChild(ttbtext); var ttbnode = document.createElement('span'); el.appendChild(ttbspan); el.appendChild(ttbnode); ttbnodearray.push(ttbnode); if (idortext == 'text') { populateGametextarray(el); } if (idortext == 'id') { populateGameidarray(el); } } function addButton() { //add Button var btn = document.createElement("button"); var btntext = document.createTextNode('Load info (less hits)'); btn.appendChild(btntext); btn.addEventListener("click", function () { load(idortext); }, false); btn.setAttribute("id", "btnaddinfo"); var btn2 = document.createElement("button"); var btntext2 = document.createTextNode('Load genres (more hits)'); btn2.appendChild(btntext2); btn2.addEventListener("click", function () { loadgenres(idortext); }, false); btn2.setAttribute("id", "btnaddinfo2"); var btn3 = document.createElement("button"); var btntext3 = document.createTextNode('Load keywords (more hits)'); btn3.appendChild(btntext3); btn3.addEventListener("click", function () { loadkws(idortext); }, false); btn3.setAttribute("id", "btnaddinfo3"); var sidebar = document.getElementsByClassName("user-details-sidebar"); if (sidebar) { var sibling = sidebar[0].nextSibling; sibling.parentNode.insertBefore(btn, sibling); sibling.parentNode.insertBefore(btn2, sibling); sibling.parentNode.insertBefore(btn3, sibling); sibling.parentNode.insertBefore(document.createElement("hr"), sibling); } function load(str) { loadbytext4(gametextarray, 1, 1, 0, 0, 0); } function loadgenres(str) { loadbytext4(gametextarray, 0, 0, 1, 0, 0); } function loadkws(str) { loadbytext4(gametextarray, 0, 0, 0, 1, 0); } // var firstbtn = document.getElementsByClassName("panel-title"); // firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]); // firstbtn[0].parentNode.insertBefore(btn, firstbtn[0]); // firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]); } function addAdditionalInfo(jnode) { console.log('Adding button and placeholders for extra info'); // var pageDivs = document.getElementsByClassName("media-body"); // addTextNodes(pageDivs); var selector = "#content-page > div > div.content-left.col-md-push-2.col-md-10 > div:nth-child(2) > div.panel-body.listentries > div > div:nth-child(n) > div.media-body"; var selector2 = "#content-page > div > div.content-left.col-md-push-2.col-md-10 > div > div.panel-body.listentries > div > div:nth-child(5) > div"; var selectorgen = "div.listentries div.media div.media-body"; var queryres = document.querySelectorAll(selectorgen); addTextNodes(queryres); // console.log(queryres); } function removeChildren(element) { while (element.firstChild) { element.removeChild(element.firstChild); } } async function loadbytext4(textarray, r = 0, ttb = 0, g = 0, k = 0, reset = 0) { console.log("Try loading data"); if (reset != 0) { reset_data(); } else { if (r != 0) { ratingnodearray.forEach(element => element.nodeValue = 'loading..'); } if (g != 0) { genresnodearray.forEach(element => element.innerHTML = 'loading..'); } if (k != 0) { keywordsnodearray.forEach(element => element.innerHTML = 'loading..'); } if (ttb != 0) { //console.log(ttbnodearray); ttbnodearray.forEach(element => element.innerHTML = 'loading..'); } if (r != 0 || g != 0 || k != 0) { console.log("games_text_info", Object.keys(games_text_info).length, ", gametextarray", gametextarray.length); if (Object.keys(games_text_info).length == gametextarray.length) { console.log("processing data cached"); if (r != 0) { gather_ratings(); } if (g != 0) { gather_genres(); } if (k != 0) { gather_kws(); } if (ttb != 0) { gather_ttb(); } } else { reset_data(); var gamespromise = gather_games_text_info(textarray); gamespromise .then(function (result) { console.log("processing data"); //console.log("gg",games_text_info); if (r != 0) { gather_ratings(); } if (g != 0) { gather_genres(); } if (k != 0) { gather_kws(); } if (ttb != 0) { gather_ttb(); } }) .then(function () { //console.log("2. ", "id_list", Object.keys(id_list).length, ", games_info", Object.keys(games_info).length, ", gametextarray", gametextarray.length); }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } } } } function reset_data() { keyword_dict = {}; genres_dict = {}; id_list = {}; genres_list_list = {}; genres_list = {}; keyword_list = {}; games_info = {}; games_text_info = {}; } function gather_ttb() { console.log("gather ttb"); ttbnodearray.forEach(function (element, index) { //var curr_id = id_list[gametextarray[index]]; var curr_text = gametextarray[index]; //console.log(curr_id); var game_info = games_text_info[curr_text]; //console.log(game_info); removeChildren(element); if (game_info.time_to_beat) { var ttb = game_info.time_to_beat; var ttbstr = ""; if (ttb.hastly) { ttbstr += +(ttb.hastly / 3600).toFixed(2) + "(h), "; } if (ttb.normally) { ttbstr += +(ttb.normally / 3600).toFixed(2) + "(n), "; } if (ttb.completely) { ttbstr += (ttb.completely / 3600).toFixed(2) + "(c)"; } element.appendChild(document.createTextNode(ttbstr)); //console.log("ttb", game_info.time_to_beat); } else { element.appendChild(document.createTextNode('n/a')); } }); } function gather_ratings() { console.log("gather ratings"); ratingnodearray.forEach(function (element, index) { //console.log("ratingelement",element, index); //var curr_id = id_list[gametextarray[index]]; //var game_info = games_info[curr_id]; var curr_text = gametextarray[index]; var game_info = games_text_info[curr_text]; //console.log("curr", curr_id, game_info); removeChildren(element); var ratingstr = ''; ratingstr = ratingstr.concat('User: '); if (game_info.rating) { ratingstr = ratingstr.concat(Math.round(game_info.rating).toString()); ratingstr = ratingstr.concat(' (' + game_info.rating_count.toString() + ')'); } else { ratingstr = ratingstr.concat('/'); } ratingstr = ratingstr.concat(', '); ratingstr = ratingstr.concat('Critics: '); if (game_info.aggregated_rating) { ratingstr = ratingstr.concat(Math.round(game_info.aggregated_rating).toString()); ratingstr = ratingstr.concat(' (' + game_info.aggregated_rating_count.toString() + ')'); } else { ratingstr = ratingstr.concat('/'); } ratingstr = ratingstr.concat(', '); ratingstr = ratingstr.concat('Total: '); if (game_info.total_rating) { ratingstr = ratingstr.concat(Math.round(game_info.total_rating).toString()); ratingstr = ratingstr.concat(' (' + game_info.total_rating_count.toString() + ')'); } else { ratingstr = ratingstr.concat('/'); } element.nodeValue = ratingstr; }); } async function gather_genres() { var genresurl = corsproxy + apiurl + '/genres/' + Object.keys(genres_list).toString(); //console.log("genres list", genres_list); console.log("genres url", genresurl); fetch(genresurl, {headers: myheaders}) .then(res => res.json()) .then(function (data) { //console.log("gg", genrenodesarray); console.log('genres', data); //console.log("games_info",games_info); //console.log("id_list",id_list); genresnodearray.forEach(function (element, index) { removeChildren(element); //console.log("index", index); //var curr_id = id_list[gametextarray[index]]; var curr_text = gametextarray[index]; //console.log("curr_id", curr_id); var game_info = games_text_info[curr_text]; console.log("info",game_info); if(game_info.genres){ var curr_genre_ids = game_info.genres; for (let genre_id of curr_genre_ids) { //console.log("genre_id",genre_id); var curr_genre = data.find(item => item.id == genre_id); //console.log("curr_genre", curr_genre); var newgenre = document.createElement('a'); newgenre.setAttribute("href", curr_genre.url); newgenre.appendChild(document.createTextNode(curr_genre.name + ', ')); element.appendChild(newgenre); } } else { element.appendChild(document.createTextNode("n/a")); } }); }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } async function gather_kws() { var kwurl = corsproxy + apiurl + '/genres/' + Object.keys(genres_list).toString(); //console.log("genres list", genres_list); console.log("kw", kwurl); fetch(kwurl, {headers: myheaders}) .then(res => res.json()) .then(function (data) { //console.log("gg", genrenodesarray); console.log('kws', data); //console.log("games_info",games_info); //console.log("id_list",id_list); keywordsnodearray.forEach(function (element, index) { removeChildren(element); //console.log("index", index); //var curr_id = id_list[gametextarray[index]]; var curr_text = gametextarray[index]; //console.log("curr_id", curr_id); var game_info = games_text_info[curr_text]; if(game_info.keywords){ var curr_kw_ids = game_info.keywords; for (let kw_id of curr_kw_ids) { //console.log("genre_id",genre_id); var curr_kw = data.find(item => item.id == kw_id); //console.log("curr_genre", curr_genre); var newkw = document.createElement('a'); newgenre.setAttribute("href", curr_kw.url); newgenre.appendChild(document.createTextNode(curr_kw.name + ', ')); element.appendChild(newkw); } } else { element.appendChild(document.createTextNode("n/a")); } }); }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } function gather_games_text_info(textarray) { var sliced = textarray; return Promise.all(sliced.map(text => new Promise((resolve, reject) => { var info = load_info_by_text(text); info .then(data => new Promise((resolve2, reject2) => { var curr_info = data[0]; //console.log("curr_info",curr_info); games_text_info[text] = curr_info; if (curr_info.genres) { for (let genre of curr_info.genres) { //console.log("genre_num",genre); genres_list[genre] = genre; } } if (curr_info.keywords) { for (let kw of curr_info.keywords) { keyword_list[kw] = kw; } } resolve2("resolve2"); }) .catch(function (err) { console.log(err.message); console.log(err.stack); }) ) .then(function () { console.log("resolve", text) resolve("resolve"); }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); }) )) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } function gather_games_info(textarray) { //var sliced = textarray.slice(0,2); var sliced = textarray; console.log("Try loading for:", sliced); return Promise.all(sliced.map(text => new Promise((resolve, reject) => { var curr_id = get_game_id_by_text(text); curr_id .then(id => new Promise((resolve2, reject2) => { id_list[text] = id; var info = load_info_by_id(id); info.then( function (result) { return result; } ) .then(data => new Promise((resolve3, reject3) => { var curr_info = data[0]; games_info[id] = curr_info; //console.log("curr_info",curr_info); if (curr_info.genres) { for (let genre of curr_info.genres) { //console.log("genre_num",genre); genres_list[genre] = genre; } //console.log("genres",curr_info.genres); } if (curr_info.keywords) { for (let kw of curr_info.keywords) { keyword_list[kw] = kw; } } //console.log("resolve3"); resolve3("resolve3"); }) ) .then(function () { //console.log("resolve2"); resolve2("resolve2"); }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); }) ) .then(function () { //console.log("info", games_info); console.log("resolve", text); resolve("resolve"); //return true; }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); }) )) .then(function (data2) { console.log("glist", genres_list); }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } async function load_info_by_text(text) { var text_url = (corsproxy + apiurl + req + text + "&" + fieldsall); return fetch(text_url, { headers: myheaders } ) .then(res => res.json()) .then(function (data) { //console.log("data",data); return data; }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } async function load_info_by_id(id) { var id_url = (corsproxy + apiurl + '/games/' + id + fields); return fetch(id_url, {headers: myheaders}) .then(res => res.json()) .then(function (data) { return data; }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } function get_game_id_by_text(text) { return fetch(corsproxy + apiurl + req + text, {headers: myheaders}) .then(res => res.json()) .then(function (data) { var game_id_num = data[0].id; var game_id = game_id_num.toString(); return game_id; }) .catch(function (err) { console.log(err.message); console.log(err.stack); }); } function load_single_by_text(text, index) { var result = fetch(corsproxy + apiurl + req + text, {headers: myheaders}) .then(res => res.json()) .then(function (data) { var game_id_num = data[0].id; id_list.push(game_id_num); console.log("pushed", game_id_num); var game_id = game_id_num.toString(); load_single_by_id(game_id, index, 1, 0, 0); return data; }); } /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, that detects and handles AJAXed content. Usage example: waitForKeyElements ( "div.comments" , commentCallbackFunction ); //--- Page-specific function to do what we want when the node is found. function commentCallbackFunction (jNode) { jNode.text ("This comment changed by waitForKeyElements()."); } IMPORTANT: This function requires your script to have loaded jQuery. */ function waitForKeyElements( selectorTxt, /* Required: The jQuery selector string that specifies the desired element(s). */ actionFunction, /* Required: The code to run when elements are found. It is passed a jNode to the matched element. */ bWaitOnce, /* Optional: If false, will continue to scan for new elements even after the first match is found. */ iframeSelector /* Optional: If set, identifies the iframe to search. */ ) { var targetNodes, btargetsFound; if (typeof iframeSelector == "undefined") targetNodes = $(selectorTxt); else targetNodes = $(iframeSelector).contents() .find(selectorTxt); if (targetNodes && targetNodes.length > 0) { btargetsFound = true; /*--- Found target node(s). Go through each and act if they are new. */ targetNodes.each(function () { var jThis = $(this); var alreadyFound = jThis.data('alreadyFound') || false; if (!alreadyFound) { //--- Call the payload function. var cancelFound = actionFunction(jThis); if (cancelFound) btargetsFound = false; else jThis.data('alreadyFound', true); } }); } else { btargetsFound = false; } //--- Get the timer-control variable for this selector. var controlObj = waitForKeyElements.controlObj || {}; var controlKey = selectorTxt.replace(/[^\w]/g, "_"); var timeControl = controlObj[controlKey]; //--- Now set or clear the timer as appropriate. if (btargetsFound && bWaitOnce && timeControl) { //--- The only condition where we need to clear the timer. clearInterval(timeControl); delete controlObj[controlKey]; } else { //--- Set a timer, if needed. if (!timeControl) { timeControl = setInterval(function () { waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector ); }, 300 ); controlObj[controlKey] = timeControl; } } waitForKeyElements.controlObj = controlObj; }