IGDB List Extra Info

Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button // click. Needs an IGDB api key.

当前为 2017-11-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name IGDB List Extra Info
  3. // @namespace https://greasyfork.org/de/users/155913-nkay08
  4. // @description Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button // click. Needs an IGDB api key.
  5. // @author NKay
  6. // @include http*://www.igdb.com/*
  7. // @grant none
  8. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
  9. // @version 0.0.1.20171118153241
  10. // ==/UserScript==
  11.  
  12.  
  13. //insert your API-KEY here
  14. var apikey = '';
  15.  
  16. var gametextarray = [];
  17. var genresnodearray = [];
  18. var keywordsnodearray = [];
  19. var ratingnodearray = [];
  20.  
  21.  
  22. function addAdditionalInfo(jnode) {
  23. 'use strict';
  24. // Your code here...
  25. console.log('Adding button and placeholders for extra info');
  26. //api urls
  27. var apikey = 'a219bebccdba1921822242709439c6e4';
  28. var apiurl = 'https://api-2445582011268.apicast.io';
  29. var req = '/games/?search=';
  30. var reqid = '/games/1942?fields=*';
  31. var corsproxy = 'https://cors-anywhere.herokuapp.com/';
  32.  
  33. var sidebar = document.getElementsByClassName("nopad");
  34. var sidebarchild = sidebar[0].childNodes[0];
  35. if (sidebar && sidebarchild) {
  36.  
  37.  
  38. }
  39.  
  40.  
  41. // btn.appendChild(btntext);
  42. // sidebar[0].appendChild(btn);
  43.  
  44.  
  45. var pageDivs = document.getElementsByClassName("media-body");
  46.  
  47. var promises = [];
  48. var sequence = Promise.resolve();
  49. //set header for apikey and json
  50. var myheaders = new Headers();
  51. myheaders.append('user-key', apikey);
  52. //myheaders.append('Accept', 'application/json');
  53.  
  54. //for every element "media-body" do
  55. for (var i = 0; i < pageDivs.length; i++)
  56. //for (var i = 0; i < 1; i++)
  57. {
  58. //add a textnode
  59. // modify with .nodeValue=
  60.  
  61. //set some elements
  62. // var filler = document.createTextNode(' | ');
  63. var genrestext = document.createTextNode('Genres: ');
  64. var genresspan = document.createElement('span');
  65. genresspan.style.fontSize = 'medium';
  66. genresspan.style.textDecoration = 'underline';
  67. genresspan.appendChild(genrestext);
  68. pageDivs[i].appendChild(genresspan);
  69. var genresnode = document.createElement('span');
  70. genresnode.setAttribute("id", "usgenre" + i.toString());
  71. pageDivs[i].appendChild(genresnode);
  72. genresnodearray.push(genresnode);
  73. pageDivs[i].appendChild(document.createTextNode(' | '));
  74. var keywordstext = document.createTextNode('Keywords: ');
  75. var kwspan = document.createElement('span');
  76. kwspan.style.fontSize = 'medium';
  77. kwspan.style.textDecoration = "underline";
  78. kwspan.appendChild(keywordstext);
  79. pageDivs[i].appendChild(kwspan);
  80. var keywordsnode = document.createElement('span');
  81. keywordsnode.setAttribute("id", "uskw" + i.toString());
  82. pageDivs[i].appendChild(keywordsnode);
  83. keywordsnodearray.push(keywordsnode);
  84. pageDivs[i].appendChild(document.createTextNode(' | '));
  85. var ratingtext = document.createTextNode('Rating: ');
  86. var rtspan = document.createElement('span');
  87. rtspan.style.fontSize = 'medium';
  88. rtspan.style.textDecoration = "underline";
  89. rtspan.appendChild(ratingtext);
  90. pageDivs[i].appendChild(rtspan);
  91. var ratingnode = document.createTextNode('');
  92. pageDivs[i].appendChild(ratingnode);
  93. ratingnodearray.push(ratingnode);
  94.  
  95.  
  96. //get the game name
  97. var gametext = 'test';
  98. var span1 = pageDivs[i].getElementsByTagName('span');
  99. gametext = span1[0].innerHTML;
  100. gametextarray.push(corsproxy + apiurl + req + gametext);
  101.  
  102. // var ref = pageDivs[i].getElementsByClassName("link-dark");
  103. // text = document.createTextNode(ref[0].href);
  104. }
  105.  
  106. var btn = document.createElement("button");
  107. var btntext = document.createTextNode('Load additional info');
  108. btn.appendChild(btntext);
  109. var firstbtn = document.getElementsByClassName("btn btn-primary btn-block mar-md-bottom");
  110. firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]);
  111. firstbtn[0].parentNode.insertBefore(btn, firstbtn[0]);
  112. firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]);
  113. btn.addEventListener("click", load, false);
  114.  
  115. function load() {
  116. genresnodearray.forEach(element => element.innerHTML = 'loading..');
  117. keywordsnodearray.forEach(element => element.innerHTML = 'loading..');
  118. ratingnodearray.forEach(element => element.nodeValue = 'loading..');
  119.  
  120. //execute multiple fetch promises
  121. //first fetch the game-id for a given name
  122. Promise.all(
  123. gametextarray.map(
  124. (url, index) => fetch(url, {
  125. headers: myheaders
  126. })
  127. .then(res => res.json())
  128. .then(data => {
  129. var gameidnum = data[0].id;
  130. var gameid = gameidnum.toString();
  131. //generate new url with id to query for the data
  132. var newurl = (corsproxy + apiurl + '/games/' + gameid + '?fields=*');
  133. return fetch(newurl, {
  134. headers: myheaders
  135. });
  136. })
  137. .then(res2 => res2.json())
  138. .then(data2 => {
  139. if (data2) {
  140. var ratingstr = '';
  141. ratingstr = ratingstr.concat('User: ');
  142. if (data2[0].rating) {
  143. ratingstr = ratingstr.concat(Math.round(data2[0].rating).toString());
  144. ratingstr = ratingstr.concat(' (' + data2[0].rating_count.toString() + ')');
  145. } else {
  146. ratingstr = ratingstr.concat('/');
  147. }
  148. ratingstr = ratingstr.concat(', ');
  149. ratingstr = ratingstr.concat('Critics: ');
  150. if (data2[0].aggregated_rating) {
  151. ratingstr = ratingstr.concat(Math.round(data2[0].aggregated_rating).toString());
  152. ratingstr = ratingstr.concat(' (' + data2[0].aggregated_rating_count.toString() + ')');
  153. } else {
  154. ratingstr = ratingstr.concat('/');
  155. }
  156. ratingstr = ratingstr.concat(', ');
  157. ratingstr = ratingstr.concat('Total: ');
  158. if (data2[0].total_rating) {
  159. ratingstr = ratingstr.concat(Math.round(data2[0].total_rating).toString());
  160. ratingstr = ratingstr.concat(' (' + data2[0].total_rating_count.toString() + ')');
  161. } else {
  162. ratingstr = ratingstr.concat('/');
  163. }
  164. ratingnodearray[index].nodeValue = ratingstr;
  165.  
  166.  
  167.  
  168.  
  169. //concat all genrenames. fetch for all genre-ids at once
  170. if (data2[0].genres) {
  171. var genresid = data2[0].genres;
  172. var genresurl = corsproxy + apiurl + '/genres/' + data2[0].genres.toString();
  173. fetch(genresurl, {
  174. headers: myheaders
  175. })
  176. .then(resgenre => resgenre.json())
  177. .then(datagenre => {
  178. var newgenres = '';
  179. genresnodearray[index].innerHTML = '';
  180. datagenre.forEach((tgenre, genreindex) => {
  181. var newgenre = document.createElement('a');
  182. newgenre.setAttribute("href", tgenre.url);
  183. var comma = ', ';
  184. if (genreindex == datagenre.length) {
  185. comma = '';
  186. }
  187. newgenre.appendChild(document.createTextNode(tgenre.name + comma));
  188. genresnodearray[index].appendChild(newgenre);
  189.  
  190. });
  191. });
  192. }
  193.  
  194. //concat all keywords. fetch for all keyword-ids at once
  195. if (data2[0].keywords) {
  196. var keywordsid = data2[0].keywords;
  197. var keywordsurl = corsproxy + apiurl + '/keywords/' + data2[0].keywords.toString();
  198. fetch(keywordsurl, {
  199. headers: myheaders
  200. })
  201. .then(reskey => reskey.json())
  202. .then(datakey => {
  203. keywordsnodearray[index].innerHTML = '';
  204. datakey.forEach((tkey, keyindex) => {
  205. var newkey = document.createElement('a');
  206. newkey.setAttribute('href', tkey.url);
  207. var comma = ', ';
  208. if (keyindex == datakey.length) {
  209. comma = '';
  210. }
  211. newkey.appendChild(document.createTextNode(tkey.name + comma));
  212. keywordsnodearray[index].appendChild(newkey);
  213. });
  214.  
  215.  
  216. });
  217.  
  218. }
  219.  
  220. }
  221. })
  222. )
  223. );
  224.  
  225. }
  226. }
  227.  
  228. //only execute function if this element is loaded via ajax
  229. waitForKeyElements("#content-page > div > div.content-left.col-md-pull-10.col-md-2 > div > a:nth-child(3)", addAdditionalInfo, true);
  230.  
  231. /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
  232. that detects and handles AJAXed content.
  233.  
  234. Usage example:
  235.  
  236. waitForKeyElements (
  237. "div.comments"
  238. , commentCallbackFunction
  239. );
  240.  
  241. //--- Page-specific function to do what we want when the node is found.
  242. function commentCallbackFunction (jNode) {
  243. jNode.text ("This comment changed by waitForKeyElements().");
  244. }
  245.  
  246. IMPORTANT: This function requires your script to have loaded jQuery.
  247. */
  248. function waitForKeyElements (
  249. selectorTxt, /* Required: The jQuery selector string that
  250. specifies the desired element(s).
  251. */
  252. actionFunction, /* Required: The code to run when elements are
  253. found. It is passed a jNode to the matched
  254. element.
  255. */
  256. bWaitOnce, /* Optional: If false, will continue to scan for
  257. new elements even after the first match is
  258. found.
  259. */
  260. iframeSelector /* Optional: If set, identifies the iframe to
  261. search.
  262. */
  263. ) {
  264. var targetNodes, btargetsFound;
  265.  
  266. if (typeof iframeSelector == "undefined")
  267. targetNodes = $(selectorTxt);
  268. else
  269. targetNodes = $(iframeSelector).contents ()
  270. .find (selectorTxt);
  271.  
  272. if (targetNodes && targetNodes.length > 0) {
  273. btargetsFound = true;
  274. /*--- Found target node(s). Go through each and act if they
  275. are new.
  276. */
  277. targetNodes.each ( function () {
  278. var jThis = $(this);
  279. var alreadyFound = jThis.data ('alreadyFound') || false;
  280.  
  281. if (!alreadyFound) {
  282. //--- Call the payload function.
  283. var cancelFound = actionFunction (jThis);
  284. if (cancelFound)
  285. btargetsFound = false;
  286. else
  287. jThis.data ('alreadyFound', true);
  288. }
  289. } );
  290. }
  291. else {
  292. btargetsFound = false;
  293. }
  294.  
  295. //--- Get the timer-control variable for this selector.
  296. var controlObj = waitForKeyElements.controlObj || {};
  297. var controlKey = selectorTxt.replace (/[^\w]/g, "_");
  298. var timeControl = controlObj [controlKey];
  299.  
  300. //--- Now set or clear the timer as appropriate.
  301. if (btargetsFound && bWaitOnce && timeControl) {
  302. //--- The only condition where we need to clear the timer.
  303. clearInterval (timeControl);
  304. delete controlObj [controlKey];
  305. }
  306. else {
  307. //--- Set a timer, if needed.
  308. if ( ! timeControl) {
  309. timeControl = setInterval ( function () {
  310. waitForKeyElements ( selectorTxt,
  311. actionFunction,
  312. bWaitOnce,
  313. iframeSelector
  314. );
  315. },
  316. 300
  317. );
  318. controlObj [controlKey] = timeControl;
  319. }
  320. }
  321. waitForKeyElements.controlObj = controlObj;
  322. }