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-19 提交的版本,查看 最新版本

  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. //
  6. // @author NKay
  7. // @include http*://www.igdb.com/*
  8. // @grant none
  9. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
  10. // @version 0.0.1.20171119132304
  11. // ==/UserScript==
  12.  
  13.  
  14. //insert your API-KEY here
  15. var apikey = '';
  16.  
  17.  
  18. var apiurl;
  19. var req;
  20. var reqid;
  21. var corsproxy;
  22. var fields;
  23.  
  24.  
  25. var myheaders;
  26.  
  27. var gametextarray;
  28. var gameidarray;
  29. var genresnodearray;
  30. var keywordsnodearray;
  31. var ratingnodearray;
  32.  
  33. var idortext;
  34.  
  35. var keyelement = "div.content-left.col-md-pull-10.col-md-2";
  36. //only execute function if this element is loaded via ajax
  37. waitForKeyElements(keyelement, checkForElement);
  38. //waitForKeyElements(keyelement,alert1);
  39.  
  40. function alert1(){
  41. alert('alert');
  42. }
  43.  
  44. function init() {
  45. apiurl = 'https://api-2445582011268.apicast.io';
  46. req = '/games/?search=';
  47. reqid = '/games/1942?fields=*';
  48. corsproxy = 'https://cors-anywhere.herokuapp.com/';
  49. fields = '?fields=genres,keywords,rating,rating_count,aggregated_rating,aggregated_rating_count,total_rating,total_rating_count';
  50. myheaders = new Headers();
  51. myheaders.append('user-key', apikey);
  52. //myheaders.append('Accept', 'application/json');
  53. gametextarray = [];
  54. gameidarray = [];
  55. genresnodearray = [];
  56. keywordsnodearray = [];
  57. ratingnodearray = [];
  58.  
  59. idortext = 'text';
  60.  
  61. }
  62.  
  63. function checkForElement(jnode) {
  64. if (!document.getElementById('btnaddinfo')) {
  65. init();
  66. addButton();
  67. addAdditionalInfo();
  68. }
  69. }
  70.  
  71. function populateGametextarray(element) {
  72. //get the game name
  73. var span1 = element.getElementsByTagName('span');
  74. var gametext = span1[0].innerHTML;
  75. var cururl = corsproxy + apiurl + req + gametext;
  76. gametextarray.push(cururl);
  77. }
  78.  
  79. function populateGameidarray(element) {
  80. // get sibling. sibling has game id
  81. var sib = element.nextSibling;
  82. var gameid = sib.getAttribute("data-game");
  83. }
  84.  
  85. function addTextNodes(div) {
  86. for (var i = 0; i < div.length; i++) {
  87. // console.log(div[i]);
  88. addTextNode(div[i], i);
  89. }
  90. }
  91.  
  92. function addTextNode(el, i) {
  93. var genrestext = document.createTextNode('Genres: ');
  94. var genresspan = document.createElement('span');
  95. genresspan.style.fontSize = 'medium';
  96. genresspan.style.textDecoration = 'underline';
  97. genresspan.appendChild(genrestext);
  98. el.appendChild(genresspan);
  99. var genresnode = document.createElement('span');
  100. genresnode.setAttribute("id", "usgenre" + i.toString());
  101. el.appendChild(genresnode);
  102. genresnodearray.push(genresnode);
  103. el.appendChild(document.createTextNode(' | '));
  104. var keywordstext = document.createTextNode('Keywords: ');
  105. var kwspan = document.createElement('span');
  106. kwspan.style.fontSize = 'medium';
  107. kwspan.style.textDecoration = "underline";
  108. kwspan.appendChild(keywordstext);
  109. el.appendChild(kwspan);
  110. var keywordsnode = document.createElement('span');
  111. keywordsnode.setAttribute("id", "uskw" + i.toString());
  112. el.appendChild(keywordsnode);
  113. keywordsnodearray.push(keywordsnode);
  114. el.appendChild(document.createTextNode(' | '));
  115. var ratingtext = document.createTextNode('Rating: ');
  116. var rtspan = document.createElement('span');
  117. rtspan.style.fontSize = 'medium';
  118. rtspan.style.textDecoration = "underline";
  119. rtspan.appendChild(ratingtext);
  120. el.appendChild(rtspan);
  121. var ratingnode = document.createTextNode('');
  122. el.appendChild(ratingnode);
  123. ratingnodearray.push(ratingnode);
  124.  
  125. if (idortext == 'text') {
  126. populateGametextarray(el);
  127. }
  128. if (idortext == 'id') {
  129. populateGameidarray(el);
  130. }
  131.  
  132.  
  133.  
  134. }
  135.  
  136.  
  137. function addButton() {
  138. //add Button
  139. var btn = document.createElement("button");
  140. var btntext = document.createTextNode('Load additional info');
  141. btn.appendChild(btntext);
  142. btn.addEventListener("click", function() {
  143. load(idortext);
  144. }, false);
  145. btn.setAttribute("id", "btnaddinfo");
  146. var sidebar = document.getElementsByClassName("user-details-sidebar");
  147. if (sidebar) {
  148. var sibling = sidebar[0].nextSibling;
  149. sibling.parentNode.insertBefore(btn, sibling);
  150. sibling.parentNode.insertBefore(document.createElement("hr"), sibling);
  151. }
  152.  
  153. function load(str) {
  154. if (str == "text") {
  155. loadbytext();
  156. }
  157. if (str == "id") {
  158. loadbyid();
  159. }
  160. }
  161.  
  162. // var firstbtn = document.getElementsByClassName("panel-title");
  163. // firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]);
  164. // firstbtn[0].parentNode.insertBefore(btn, firstbtn[0]);
  165. // firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]);
  166. }
  167.  
  168. function addAdditionalInfo(jnode) {
  169. console.log('Adding button and placeholders for extra info');
  170. // var pageDivs = document.getElementsByClassName("media-body");
  171. // addTextNodes(pageDivs);
  172.  
  173. 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";
  174. 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";
  175. var selectorgen ="div > div.panel-body.listentries > div > div:nth-child(n) > div";
  176. var queryres = document.querySelectorAll(selectorgen);
  177. addTextNodes(queryres);
  178. // console.log(queryres);
  179.  
  180. }
  181.  
  182. function loadbytext() {
  183. genresnodearray.forEach(element => element.innerHTML = 'loading..');
  184. keywordsnodearray.forEach(element => element.innerHTML = 'loading..');
  185. ratingnodearray.forEach(element => element.nodeValue = 'loading..');
  186.  
  187. //execute multiple fetch promises
  188. //first fetch the game-id for a given name
  189. Promise.all(
  190. gametextarray.map(
  191. (url, index) => fetch(url, {
  192. headers: myheaders
  193. })
  194. .then(res => res.json())
  195. .then(data => {
  196. var gameidnum = data[0].id;
  197. var gameid = gameidnum.toString();
  198.  
  199. //generate new url with id to query for the data
  200. var newurl = (corsproxy + apiurl + '/games/' + gameid + fields);
  201. return fetch(newurl, {
  202. headers: myheaders
  203. });
  204. })
  205. .then(res2 => res2.json())
  206. .then(data2 => {
  207. if (data2) {
  208. var ratingstr = '';
  209. ratingstr = ratingstr.concat('User: ');
  210. if (data2[0].rating) {
  211. ratingstr = ratingstr.concat(Math.round(data2[0].rating).toString());
  212. ratingstr = ratingstr.concat(' (' + data2[0].rating_count.toString() + ')');
  213. } else {
  214. ratingstr = ratingstr.concat('/');
  215. }
  216. ratingstr = ratingstr.concat(', ');
  217. ratingstr = ratingstr.concat('Critics: ');
  218. if (data2[0].aggregated_rating) {
  219. ratingstr = ratingstr.concat(Math.round(data2[0].aggregated_rating).toString());
  220. ratingstr = ratingstr.concat(' (' + data2[0].aggregated_rating_count.toString() + ')');
  221. } else {
  222. ratingstr = ratingstr.concat('/');
  223. }
  224. ratingstr = ratingstr.concat(', ');
  225. ratingstr = ratingstr.concat('Total: ');
  226. if (data2[0].total_rating) {
  227. ratingstr = ratingstr.concat(Math.round(data2[0].total_rating).toString());
  228. ratingstr = ratingstr.concat(' (' + data2[0].total_rating_count.toString() + ')');
  229. } else {
  230. ratingstr = ratingstr.concat('/');
  231. }
  232. ratingnodearray[index].nodeValue = ratingstr;
  233.  
  234.  
  235.  
  236.  
  237. //concat all genrenames. fetch for all genre-ids at once
  238. if (data2[0].genres) {
  239. var genresid = data2[0].genres;
  240. var genresurl = corsproxy + apiurl + '/genres/' + data2[0].genres.toString();
  241. fetch(genresurl, {
  242. headers: myheaders
  243. })
  244. .then(resgenre => resgenre.json())
  245. .then(datagenre => {
  246. var newgenres = '';
  247. genresnodearray[index].innerHTML = '';
  248. datagenre.forEach((tgenre, genreindex) => {
  249. var newgenre = document.createElement('a');
  250. newgenre.setAttribute("href", tgenre.url);
  251. var comma = ', ';
  252. if (genreindex == datagenre.length - 1) {
  253. comma = '';
  254. }
  255. newgenre.appendChild(document.createTextNode(tgenre.name + comma));
  256. genresnodearray[index].appendChild(newgenre);
  257.  
  258. });
  259. });
  260. }
  261.  
  262. //concat all keywords. fetch for all keyword-ids at once
  263. if (data2[0].keywords) {
  264. var keywordsid = data2[0].keywords;
  265. var keywordsurl = corsproxy + apiurl + '/keywords/' + data2[0].keywords.toString();
  266. fetch(keywordsurl, {
  267. headers: myheaders
  268. })
  269. .then(reskey => reskey.json())
  270. .then(datakey => {
  271. keywordsnodearray[index].innerHTML = '';
  272. datakey.forEach((tkey, keyindex) => {
  273. var newkey = document.createElement('a');
  274. newkey.setAttribute('href', tkey.url);
  275. var comma = ', ';
  276. if (keyindex == datakey.length - 1) {
  277. comma = '';
  278. }
  279. newkey.appendChild(document.createTextNode(tkey.name + comma));
  280. keywordsnodearray[index].appendChild(newkey);
  281. });
  282.  
  283.  
  284. });
  285.  
  286. }
  287.  
  288. }
  289. })
  290. )
  291. );
  292.  
  293. }
  294.  
  295. function loadbyid() {
  296. genresnodearray.forEach(element => element.innerHTML = 'loading..');
  297. keywordsnodearray.forEach(element => element.innerHTML = 'loading..');
  298. ratingnodearray.forEach(element => element.nodeValue = 'loading..');
  299.  
  300. Promise.all(
  301. gameidarray.map(
  302. (url, index) => fetch(url, {
  303. headers: myheaders
  304. })
  305. .then(res2 => res2.json())
  306. .then(data2 => {
  307. if (data2) {
  308. var ratingstr = '';
  309. ratingstr = ratingstr.concat('User: ');
  310. if (data2[0].rating) {
  311. ratingstr = ratingstr.concat(Math.round(data2[0].rating).toString());
  312. ratingstr = ratingstr.concat(' (' + data2[0].rating_count.toString() + ')');
  313. } else {
  314. ratingstr = ratingstr.concat('/');
  315. }
  316. ratingstr = ratingstr.concat(', ');
  317. ratingstr = ratingstr.concat('Critics: ');
  318. if (data2[0].aggregated_rating) {
  319. ratingstr = ratingstr.concat(Math.round(data2[0].aggregated_rating).toString());
  320. ratingstr = ratingstr.concat(' (' + data2[0].aggregated_rating_count.toString() + ')');
  321. } else {
  322. ratingstr = ratingstr.concat('/');
  323. }
  324. ratingstr = ratingstr.concat(', ');
  325. ratingstr = ratingstr.concat('Total: ');
  326. if (data2[0].total_rating) {
  327. ratingstr = ratingstr.concat(Math.round(data2[0].total_rating).toString());
  328. ratingstr = ratingstr.concat(' (' + data2[0].total_rating_count.toString() + ')');
  329. } else {
  330. ratingstr = ratingstr.concat('/');
  331. }
  332. ratingnodearray[index].nodeValue = ratingstr;
  333.  
  334.  
  335.  
  336.  
  337. //concat all genrenames. fetch for all genre-ids at once
  338. if (data2[0].genres) {
  339. var genresid = data2[0].genres;
  340. var genresurl = corsproxy + apiurl + '/genres/' + data2[0].genres.toString();
  341. fetch(genresurl, {
  342. headers: myheaders
  343. })
  344. .then(resgenre => resgenre.json())
  345. .then(datagenre => {
  346. var newgenres = '';
  347. genresnodearray[index].innerHTML = '';
  348. datagenre.forEach((tgenre, genreindex) => {
  349. var newgenre = document.createElement('a');
  350. newgenre.setAttribute("href", tgenre.url);
  351. var comma = ', ';
  352. if (genreindex == datagenre.length - 1) {
  353. comma = '';
  354. }
  355. newgenre.appendChild(document.createTextNode(tgenre.name + comma));
  356. genresnodearray[index].appendChild(newgenre);
  357.  
  358. });
  359. });
  360. }
  361.  
  362. //concat all keywords. fetch for all keyword-ids at once
  363. if (data2[0].keywords) {
  364. var keywordsid = data2[0].keywords;
  365. var keywordsurl = corsproxy + apiurl + '/keywords/' + data2[0].keywords.toString();
  366. fetch(keywordsurl, {
  367. headers: myheaders
  368. })
  369. .then(reskey => reskey.json())
  370. .then(datakey => {
  371. keywordsnodearray[index].innerHTML = '';
  372. datakey.forEach((tkey, keyindex) => {
  373. var newkey = document.createElement('a');
  374. newkey.setAttribute('href', tkey.url);
  375. var comma = ', ';
  376. if (keyindex == datakey.length - 1) {
  377. comma = '';
  378. }
  379. newkey.appendChild(document.createTextNode(tkey.name + comma));
  380. keywordsnodearray[index].appendChild(newkey);
  381. });
  382.  
  383.  
  384. });
  385.  
  386. }
  387.  
  388. }
  389. })
  390. )
  391. );
  392.  
  393.  
  394.  
  395.  
  396. }
  397.  
  398.  
  399.  
  400.  
  401. /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
  402. that detects and handles AJAXed content.
  403.  
  404. Usage example:
  405.  
  406. waitForKeyElements (
  407. "div.comments"
  408. , commentCallbackFunction
  409. );
  410.  
  411. //--- Page-specific function to do what we want when the node is found.
  412. function commentCallbackFunction (jNode) {
  413. jNode.text ("This comment changed by waitForKeyElements().");
  414. }
  415.  
  416. IMPORTANT: This function requires your script to have loaded jQuery.
  417. */
  418. function waitForKeyElements(
  419. selectorTxt,
  420. /* Required: The jQuery selector string that
  421. specifies the desired element(s).
  422. */
  423. actionFunction,
  424. /* Required: The code to run when elements are
  425. found. It is passed a jNode to the matched
  426. element.
  427. */
  428. bWaitOnce,
  429. /* Optional: If false, will continue to scan for
  430. new elements even after the first match is
  431. found.
  432. */
  433. iframeSelector
  434. /* Optional: If set, identifies the iframe to
  435. search.
  436. */
  437. ) {
  438. var targetNodes, btargetsFound;
  439.  
  440. if (typeof iframeSelector == "undefined")
  441. targetNodes = $(selectorTxt);
  442. else
  443. targetNodes = $(iframeSelector).contents()
  444. .find(selectorTxt);
  445.  
  446. if (targetNodes && targetNodes.length > 0) {
  447. btargetsFound = true;
  448. /*--- Found target node(s). Go through each and act if they
  449. are new.
  450. */
  451. targetNodes.each(function() {
  452. var jThis = $(this);
  453. var alreadyFound = jThis.data('alreadyFound') || false;
  454.  
  455. if (!alreadyFound) {
  456. //--- Call the payload function.
  457. var cancelFound = actionFunction(jThis);
  458. if (cancelFound)
  459. btargetsFound = false;
  460. else
  461. jThis.data('alreadyFound', true);
  462. }
  463. });
  464. } else {
  465. btargetsFound = false;
  466. }
  467.  
  468. //--- Get the timer-control variable for this selector.
  469. var controlObj = waitForKeyElements.controlObj || {};
  470. var controlKey = selectorTxt.replace(/[^\w]/g, "_");
  471. var timeControl = controlObj[controlKey];
  472.  
  473. //--- Now set or clear the timer as appropriate.
  474. if (btargetsFound && bWaitOnce && timeControl) {
  475. //--- The only condition where we need to clear the timer.
  476. clearInterval(timeControl);
  477. delete controlObj[controlKey];
  478. } else {
  479. //--- Set a timer, if needed.
  480. if (!timeControl) {
  481. timeControl = setInterval(function() {
  482. waitForKeyElements(selectorTxt,
  483. actionFunction,
  484. bWaitOnce,
  485. iframeSelector
  486. );
  487. },
  488. 300
  489. );
  490. controlObj[controlKey] = timeControl;
  491. }
  492. }
  493. waitForKeyElements.controlObj = controlObj;
  494. }