Show Metacritic.com ratings

Show metacritic metascore and user ratings on: Bandcamp, Apple Itunes (Music), Amazon (Music,Movies,TV Shows), IMDb (Movies), Google Play (Music, Movies), TV.com, Steam, Gamespot (PS4, XONE, PC), Rotten Tomatoes, Serienjunkies, BoxOfficeMojo, allmovie.com, movie.com, Wikipedia (en), themoviedb.org, letterboxd, TVmaze, TVGuide, followshows.com, TheTVDB.com, ConsequenceOfSound, Pitchfork, Last.fm, TVRage.com, rateyourmusic.com

目前為 2017-04-30 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Show Metacritic.com ratings
  3. // @description Show metacritic metascore and user ratings on: Bandcamp, Apple Itunes (Music), Amazon (Music,Movies,TV Shows), IMDb (Movies), Google Play (Music, Movies), TV.com, Steam, Gamespot (PS4, XONE, PC), Rotten Tomatoes, Serienjunkies, BoxOfficeMojo, allmovie.com, movie.com, Wikipedia (en), themoviedb.org, letterboxd, TVmaze, TVGuide, followshows.com, TheTVDB.com, ConsequenceOfSound, Pitchfork, Last.fm, TVRage.com, rateyourmusic.com
  4. // @namespace cuzi
  5. // @oujs:author cuzi
  6. // @grant GM_xmlhttpRequest
  7. // @grant GM_setValue
  8. // @grant GM_getValue
  9. // @grant unsafeWindow
  10. // @require http://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
  11. // @license GNUGPL
  12. // @version 21
  13. // @include https://*.bandcamp.com/*
  14. // @include https://itunes.apple.com/*/album/*
  15. // @include https://play.google.com/store/music/album/*
  16. // @include https://play.google.com/store/movies/details/*
  17. // @include http://www.amazon.com/*
  18. // @include https://www.amazon.com/*
  19. // @include http://www.amazon.co.uk/*
  20. // @include https://www.amazon.co.uk/*
  21. // @include http://www.amazon.fr/*
  22. // @include https://www.amazon.fr/*
  23. // @include http://www.amazon.de/*
  24. // @include https://www.amazon.de/*
  25. // @include http://www.amazon.es/*
  26. // @include https://www.amazon.es/*
  27. // @include http://www.amazon.ca/*
  28. // @include https://www.amazon.ca/*
  29. // @include http://www.amazon.in/*
  30. // @include https://www.amazon.in/*
  31. // @include http://www.amazon.it/*
  32. // @include https://www.amazon.it/*
  33. // @include http://www.amazon.co.jp/*
  34. // @include https://www.amazon.co.jp/*
  35. // @include http://www.amazon.com.mx/*
  36. // @include https://www.amazon.com.mx/*
  37. // @include http://www.amazon.com.au/*
  38. // @include https://www.amazon.com.au/*
  39. // @include http://www.imdb.com/title/*
  40. // @include https://www.imdb.com/title/*
  41. // @include http://store.steampowered.com/app/*
  42. // @include https://store.steampowered.com/app/*
  43. // @include http://www.gamespot.com/*
  44. // @include https://www.gamespot.com/*
  45. // @include http://www.serienjunkies.de/*
  46. // @include https://www.serienjunkies.de/*
  47. // @include http://www.tv.com/shows/*
  48. // @include http://www.rottentomatoes.com/m/*
  49. // @include https://www.rottentomatoes.com/m/*
  50. // @include http://www.rottentomatoes.com/tv/*
  51. // @include https://www.rottentomatoes.com/tv/*
  52. // @include http://www.rottentomatoes.com/tv/*/s*/
  53. // @include https://www.rottentomatoes.com/tv/*/s*/
  54. // @include http://www.boxofficemojo.com/movies/*
  55. // @include http://www.allmovie.com/movie/*
  56. // @include https://en.wikipedia.org/*
  57. // @include http://www.movies.com/*/m*
  58. // @include https://www.themoviedb.org/movie/*
  59. // @include https://www.themoviedb.org/tv/*
  60. // @include http://letterboxd.com/film/*
  61. // @include https://letterboxd.com/film/*
  62. // @include http://www.tvmaze.com/shows/*
  63. // @include http://www.tvguide.com/tvshows/*
  64. // @include https://www.tvguide.com/tvshows/*
  65. // @include http://followshows.com/show/*
  66. // @include https://followshows.com/show/*
  67. // @include http://thetvdb.com/*tab=series*
  68. // @include https://thetvdb.com/*tab=series*
  69. // @include http://consequenceofsound.net/*
  70. // @include https://consequenceofsound.net/*
  71. // @include http://pitchfork.com/*
  72. // @include http://www.last.fm/*
  73. // @include https://www.last.fm/*
  74. // @include http://www.tvrage.com/*
  75. // @include http://rateyourmusic.com/release/album/*
  76. // @include https://rateyourmusic.com/release/album/*
  77. // ==/UserScript==
  78.  
  79.  
  80. // ########## Conversion from Script Version 15 to 16+ ######
  81. // Type of "black" value changed from {} to []
  82. if(!("length" in JSON.parse(GM_getValue("black","[]")))) {
  83. GM_setValue("black","[]");
  84. }
  85. // ########## ######
  86.  
  87.  
  88. var baseURL = "http://www.metacritic.com/";
  89.  
  90. var baseURL_music = "http://www.metacritic.com/music/";
  91. var baseURL_movie = "http://www.metacritic.com/movie/";
  92. var baseURL_pcgame = "http://www.metacritic.com/game/pc/";
  93. var baseURL_ps4 = "http://www.metacritic.com/game/playstation-4/";
  94. var baseURL_xone = "http://www.metacritic.com/game/xbox-one/";
  95. var baseURL_tv = "http://www.metacritic.com/tv/";
  96.  
  97. var baseURL_search = "http://www.metacritic.com/search/{type}/{query}/results";
  98. var baseURL_autosearch = "http://www.metacritic.com/autosearch";
  99.  
  100. var baseURL_database = "https://php-cuzi.rhcloud.com/r.php";
  101. var baseURL_whitelist = "https://php-cuzi.rhcloud.com/whitelist.php";
  102. var baseURL_blacklist = "https://php-cuzi.rhcloud.com/blacklist.php";
  103.  
  104. var mybrowser = "other";
  105. if(~navigator.userAgent.indexOf("Chrome")) {
  106. mybrowser = "chrome";
  107. }
  108.  
  109. // http://www.designcouch.com/home/why/2013/05/23/dead-simple-pure-css-loading-spinner/
  110. var CSS = "#mcdiv123 .grespinner{height:16px;width:16px;margin:0 auto;position:relative;-webkit-animation:rotation .6s infinite linear;-moz-animation:rotation .6s infinite linear;-o-animation:rotation .6s infinite linear;animation:rotation .6s infinite linear;border-left:6px solid rgba(0,174,239,.15);border-right:6px solid rgba(0,174,239,.15);border-bottom:6px solid rgba(0,174,239,.15);border-top:6px solid rgba(0,174,239,.8);border-radius:100%}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(359deg)}}@-moz-keyframes rotation{from{-moz-transform:rotate(0)}to{-moz-transform:rotate(359deg)}}@-o-keyframes rotation{from{-o-transform:rotate(0)}to{-o-transform:rotate(359deg)}}@keyframes rotation{from{transform:rotate(0)}to{transform:rotate(359deg)}}#mcdiv123searchresults .result{font:12px arial,helvetica,serif;border-top-width:1px;border-top-color:#ccc;border-top-style:solid;padding:5px}#mcdiv123searchresults .result .result_type{display:inline}#mcdiv123searchresults .result .result_wrap{float:left;width:100%}#mcdiv123searchresults .result .has_score{padding-left:42px}#mcdiv123searchresults .result .basic_stats{height:1%;overflow:hidden}#mcdiv123searchresults .result h3{font-size:14px;font-weight:700}#mcdiv123searchresults .result a{color:#09f;font-weight:700;text-decoration:none}#mcdiv123searchresults .metascore_w.game.seventyfive,#mcdiv123searchresults .metascore_w.positive,#mcdiv123searchresults .metascore_w.score_favorable,#mcdiv123searchresults .metascore_w.score_outstanding,#mcdiv123searchresults .metascore_w.sixtyone{background-color:#6c3}#mcdiv123searchresults .metascore_w.forty,#mcdiv123searchresults .metascore_w.game.fifty,#mcdiv123searchresults .metascore_w.mixed,#mcdiv123searchresults .metascore_w.score_mixed{background-color:#fc3}#mcdiv123searchresults .metascore_w.negative,#mcdiv123searchresults .metascore_w.score_terrible,#mcdiv123searchresults .metascore_w.score_unfavorable{background-color:red}#mcdiv123searchresults a.metascore_w,#mcdiv123searchresults span.metascore_w{display:inline-block}#mcdiv123searchresults .result .metascore_w{color:#fff!important;font-family:Arial,Helvetica,sans-serif;font-size:17px;font-style:normal!important;font-weight:700!important;height:2em;line-height:2em;text-align:center;vertical-align:middle;width:2em;float:left;margin:0 0 0 -42px}#mcdiv123searchresults .result .more_stats{font-size:10px;color:#444}#mcdiv123searchresults .result .release_date .data{font-weight:700;color:#000}#mcdiv123searchresults ol,#mcdiv123searchresults ul{list-style:none}#mcdiv123searchresults .result li.stat{background:0 0;display:inline;float:left;margin:0;padding:0 6px 0 0;white-space:nowrap}#mcdiv123searchresults .result .deck{margin:3px 0 0}#mcdiv123searchresults .result .basic_stat{display:inline;float:right;overflow:hidden;width:100%}";
  111.  
  112. function getHostname(url) {
  113. with(document.createElement("a")) {
  114. href = url;
  115. return hostname;
  116. }
  117. }
  118. function name2metacritic(s) {
  119. return s.normalize('NFKD').replace(/\//g,"").replace(/[\u0300-\u036F]/g, '').replace(/&/g,"and").replace(/\W+/g, " ").toLowerCase().trim().replace(/\W+/g,"-");
  120. }
  121. function minutesSince(time) {
  122. var seconds = ((new Date()).getTime() - time.getTime()) / 1000;
  123. return seconds>60?parseInt(seconds/60)+" min ago":"now";
  124. }
  125. function randomStringId() {
  126. var id10 = () => Math.floor((1 + Math.random()) * 0x10000000000).toString(16).substring(1);
  127. return id10()+id10()+id10()+id10()+id10()+id10();
  128. }
  129. function fixMetacriticURLs(html) {
  130. return html.replace(/<a /g,'<a target="_blank" ').replace(/href="\//g,'href="'+baseURL).replace(/src="\//g,'src="'+baseURL);
  131. }
  132. function searchType2metacritic(type) {
  133. return ({
  134. 'movie' : 'movie',
  135. 'pcgame' : 'game',
  136. 'xonegame' : 'game',
  137. 'ps4game' : 'game',
  138. 'music' : 'album',
  139. 'tv' : 'tv'
  140. })[type];
  141. }
  142. function metacritic2searchType(type) {
  143. return ({
  144. "Album" : "music",
  145. "TV" : "tv",
  146. "Movie" : "movie",
  147. "PC Game" : "pcgame",
  148. "PS4 Game" : "ps4game",
  149. "XONE Game" : "onegame",
  150. "WIIU Game" : "xxxxx",
  151. "3DS Game" : "xxxx"
  152. })[type];
  153. }
  154.  
  155.  
  156. function metaScore(score, word) {
  157. var fg,bg,t;
  158. if(score == null) {
  159. fg = "black";
  160. bg = "#ccc";
  161. t = "tbd";
  162. } else if(score >= 75) {
  163. fg = "white";
  164. bg = "#6c3";
  165. t = parseInt(score);
  166. } else if(score < 40) {
  167. fg = "white";
  168. bg = "#f00";
  169. t = parseInt(score);
  170. } else {
  171. fg = "white";
  172. bg = "#fc3";
  173. t = parseInt(score);
  174. }
  175. return '<span title="'+(word?word:'')+'" style="display: inline-block; color: '+fg+';background:'+bg+';font-family: Arial,Helvetica,sans-serif;font-size: 17px;font-style: normal;font-weight: bold;height: 2em;width: 2em;line-height: 2em;text-align: center;vertical-align: middle;">'+t+'</span>';
  176. }
  177.  
  178. function balloonAlert(message, timeout, title, css, click) {
  179. var header;
  180. if(title) {
  181. header = '<div style="background:rgb(220,230,150); padding: 2px 12px;">' + title +"</div>";
  182. } else if(title === false) {
  183. header = '';
  184. } else {
  185. header = '<div style="background:rgb(220,230,150); padding: 2px 12px;">Userscript alert</div>';
  186. }
  187. var div = $("<div>" + header + '<div style="padding:5px">' + message.split("\n").join("<br>") + "</div></div>");
  188. div.css({
  189. position : "fixed",
  190. top : 10,
  191. left : 10,
  192. maxWidth: 200,
  193. zIndex : "5010002",
  194. background : "rgb(240,240,240)",
  195. border : "2px solid yellow",
  196. borderRadius :"6px",
  197. boxShadow: "0 0 3px 3px rgba(100, 100, 100, 0.2)",
  198. fontFamily: "sans-serif",
  199. color: "black"
  200. });
  201. if(css) {
  202. div.css(css);
  203. }
  204. div.appendTo(document.body);
  205. if(click) {
  206. div.click(function(ev) {
  207. $(this).hide(500);
  208. click.call(this,ev);
  209. });
  210. }
  211. if(!click) {
  212. var close = $('<div title="Close" style="cursor:pointer; position:absolute; top:0px; right:3px;">&#10062;</div>').appendTo(div);
  213. close.click(function(){
  214. $(this.parentNode).hide(1000);
  215. });
  216. }
  217. if(timeout && timeout > 0) {
  218. window.setTimeout(function() {
  219. div.hide(3000);
  220. }, timeout);
  221. }
  222. return div;
  223. }
  224.  
  225.  
  226. function filterUniversalUrl(url) {
  227. try {
  228. url = url.match(/http.+/)[0];
  229. } catch(e) { }
  230. try {
  231. url = url.replace(/https?:\/\/(www.)?/,"");
  232. } catch(e) { }
  233. if(url.startsWith("imdb.com/") && url.match(/(imdb\.com\/\w+\/\w+\/)/)) {
  234. // Remove movie subpage from imdb url
  235. return url.match(/(imdb\.com\/\w+\/\w+\/)/)[1];
  236. } else if(url.startsWith("thetvdb.com/")) {
  237. // Do nothing with thetvdb.com urls
  238. return url;
  239. } else {
  240. // Default: Remove parameters
  241. return url.split("?")[0].split("&")[0];
  242. }
  243. }
  244.  
  245. function addToMap(url, metaurl) {
  246. var data = JSON.parse(GM_getValue("map","{}"));
  247. var url = filterUniversalUrl(url);
  248. var metaurl = metaurl.replace(/^http:\/\/(www.)?metacritic\.com\//,"");
  249.  
  250. data[url] = metaurl;
  251. GM_setValue("map", JSON.stringify(data));
  252. (new Image()).src = baseURL_whitelist + "?docurl="+encodeURIComponent(url)+"&metaurl="+encodeURIComponent(metaurl)+"&ref="+encodeURIComponent(randomStringId());
  253. return [url, metaurl];
  254. }
  255.  
  256. function addToBlacklist(url, metaurl) {
  257. var data = JSON.parse(GM_getValue("black","[]"));
  258. var url = filterUniversalUrl(url);
  259. var metaurl = metaurl.replace(/^http:\/\/(www.)?metacritic\.com\//,"");
  260.  
  261. data.push([url,metaurl]);
  262. GM_setValue("black", JSON.stringify(data));
  263. (new Image()).src = baseURL_blacklist + "?docurl="+encodeURIComponent(url)+"&metaurl="+encodeURIComponent(metaurl)+"&ref="+encodeURIComponent(randomStringId());
  264. return [url, metaurl];
  265. }
  266.  
  267.  
  268.  
  269.  
  270. function isBlacklistedUrl(docurl, metaurl) {
  271.  
  272. docurl = filterUniversalUrl(docurl);
  273. docurl = docurl.replace(/https?:\/\/(www.)?/,"");
  274. metaurl = metaurl.replace(/^http:\/\/(www.)?metacritic\.com\//,"");
  275. metaurl = metaurl.replace(/\/\//g,"/").replace(/\/\//g,"/");; // remove double slash
  276. metaurl = metaurl.replace(/^\/+/,""); // remove starting slash
  277. var data = JSON.parse(GM_getValue("black","[]")); // [ [docurl0, metaurl0] , [docurl1, metaurl1] , ... ]
  278. for(var i = 0; i < data.length; i++) {
  279. if(data[i][0] == docurl && data[i][1] == metaurl) {
  280. return true;
  281. }
  282. }
  283. return false;
  284. }
  285.  
  286. function isBlacklisted(metaurl) {
  287. return isBlacklistedUrl("" + document.location.host.replace(/^www\./,"") + document.location.pathname + document.location.search, metaurl);
  288. }
  289.  
  290.  
  291.  
  292. function listenForHotkeys(code, cb) {
  293. // Call cb() as soon as the code sequence was typed
  294. var i = 0;
  295. $(document).bind("keydown.listenForHotkeys",function(ev) {
  296. if(document.activeElement == document.body) {
  297. if(ev.key != code[i]) {
  298. i = 0;
  299. } else {
  300. i++;
  301. if(i == code.length) {
  302. ev.preventDefault();
  303. $(document).unbind("keydown.listenForHotkeys");
  304. cb();
  305. }
  306. }
  307. }
  308. });
  309. }
  310.  
  311.  
  312. function metacritic_hoverInfo(url, docurl, cb, errorcb) {
  313. // Get the metacritic hover info. Requests are cached.
  314. var handleresponse = function(response, cached) {
  315. if(response.status == 200 && cb) {
  316. if(~response.responseText.indexOf('"jsonRedirect"')) { // {"viewer":{},"mixpanelToken":"6e219fd....","mixpanelDistinctId":"255.255.255.255","omnitureDebug":0,"jsonRedirect":"\/movie\/national-lampoons-vacation"}
  317. var blacklistedredirect = false;
  318. var j = JSON.parse(response.responseText);
  319. current.url = baseURL + j["jsonRedirect"];
  320. delete cache[url]; // Delete original url from cache. The redirect URL will then be saved in metacritic_hoverInfo(...)
  321.  
  322. // Blacklist items from database received?
  323. if("blacklist" in j && j.blacklist && j.blacklist.length) {
  324. // Save new blacklist items
  325. var data = JSON.parse(GM_getValue("black","[]"));
  326. for(var i = 0; i < j.blacklist.length; i++) {
  327. var save_docurl = j.blacklist[i].docurl;
  328. var save_metaurl = j.blacklist[i].metaurl;
  329. data.push([save_docurl,save_metaurl]);
  330. if(j["jsonRedirect"] == "/"+save_metaurl) {
  331. // Redirect is blacklisted!
  332. blacklistedredirect = true;
  333. }
  334. }
  335. GM_setValue("black", JSON.stringify(data));
  336. }
  337. if(blacklistedredirect && errorcb) {
  338. // Redirect was blacklisted, show nothing
  339. errorcb(response.responseText, new Date(response.time));
  340. } else {
  341. // Load redirect
  342. metacritic_hoverInfo(baseURL + j["jsonRedirect"], false, cb, errorcb);
  343. }
  344. } else {
  345. cb(response.responseText, new Date(response.time));
  346. }
  347. } else if(response.status != 200 && errorcb) {
  348. errorcb(response.responseText, new Date(response.time));
  349. if(!cached)
  350. console.log("Show metacritic ratings: Error:"+response.status+"\n"+url);
  351. }
  352. };
  353. var cache = JSON.parse(GM_getValue("hovercache","{}"));
  354. for(var prop in cache) {
  355. // Delete cached values, that are older than 2 hours
  356. if((new Date()).getTime() - (new Date(cache[prop].time)).getTime() > 2*60*60*1000) {
  357. delete cache[prop];
  358. }
  359. }
  360. if(url in cache) {
  361. handleresponse(cache[url], true);
  362. } else {
  363. var requestURL = url;
  364. var requestParams = "hoverinfo=1";
  365. if(docurl && docurl.indexOf("metacritic.com") == -1 && docurl.indexOf(baseURL_database) == -1) {
  366. // Ask database for correct metacritic entry:
  367. requestURL = baseURL_database;
  368. requestParams = "m=" + encodeURIComponent(docurl) + "&a=" + encodeURIComponent(url);
  369. }
  370. GM_xmlhttpRequest({
  371. method: "POST",
  372. url: requestURL,
  373. data: requestParams,
  374. headers: {
  375. "Referer" : url,
  376. "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
  377. "Host" : getHostname(requestURL), // This is important, otherwise Metacritic refuses to answer!
  378. "User-Agent" : "MetacriticUserscript "+navigator.userAgent,
  379. "X-Requested-With" : "XMLHttpRequest"
  380. },
  381. onload: function(response) {
  382. response.time = (new Date()).toJSON();
  383. cache[url] = response;
  384. GM_setValue("hovercache",JSON.stringify(cache));
  385. handleresponse(response, false);
  386. },
  387. onerror: function(response) {
  388. console.log("Show metacritic ratings: Hover info error: "+response.status+"\nURL: "+requestURL+"\nResponse:\n"+response.responseText);
  389. },
  390. });
  391. }
  392. }
  393. function metacritic_searchResults(url, cb, errorcb) {
  394. // Get metacritic search results. Requests are cached.
  395. var handleresponse = function(response, cached) {
  396. if(response.results.length && cb) {
  397. cb(response.results, new Date(response.time));
  398. } else if(response.results.length == 0 && errorcb) {
  399. errorcb(response.results, new Date(response.time));
  400. }
  401. };
  402. var cache = JSON.parse(GM_getValue("searchcache","{}"));
  403. for(var prop in cache) {
  404. // Delete cached values, that are older than 2 hours
  405. if((new Date()).getTime() - (new Date(cache[prop].time)).getTime() > 2*60*60*1000) {
  406. delete cache[prop];
  407. }
  408. }
  409. if(url in cache) {
  410. handleresponse(cache[url], true);
  411. } else {
  412. GM_xmlhttpRequest({
  413. method: "GET",
  414. url: url,
  415. headers: {
  416. "Referer" : url,
  417. "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
  418. "Host" : "www.metacritic.com",
  419. "User-Agent" : "MetacriticUserscript "+navigator.userAgent,
  420. },
  421. onload: function(response) {
  422. var results = [];
  423. if(!~response.responseText.indexOf("No search results found.")) {
  424. var d = $('<html>').html(response.responseText);
  425. d.find("ul.search_results.module .result").each(function() {
  426. results.push(this.innerHTML);
  427. });
  428. }
  429.  
  430. response = {
  431. time : (new Date()).toJSON(),
  432. results : results,
  433. };
  434. cache[url] = response;
  435. GM_setValue("searchcache",JSON.stringify(cache));
  436. handleresponse(response, false);
  437. },
  438. onerror: function(response) {
  439. console.log("Show metacritic ratings: Search error: "+response.status+"\n"+url);
  440. handleresponse({
  441. time : (new Date()).toJSON(),
  442. results : [],
  443. }, false);
  444. }
  445. });
  446. }
  447. }
  448.  
  449. function metacritic_showHoverInfo(url, docurl) {
  450. if(!url) {
  451. return;
  452. }
  453. metacritic_hoverInfo(url, docurl?docurl:false,
  454. // On Success
  455. function(html, time) {
  456. $("#mcdiv123").remove();
  457. var div = $('<div id="mcdiv123"></div>').appendTo(document.body);
  458. div.css({
  459. position:"fixed",
  460. bottom :0,
  461. left: 0,
  462. minWidth: 300,
  463. backgroundColor: "#fff",
  464. border: "2px solid #bbb",
  465. borderRadius:" 6px",
  466. boxShadow: "0 0 3px 3px rgba(100, 100, 100, 0.2)",
  467. color: "#000",
  468. padding:" 3px",
  469. zIndex: "5010001",
  470. });
  471. // Functions for communication between page and iframe
  472. // Mozilla can access parent.document
  473. // Chrome can use postMessage()
  474. var frame_status = false; // if this remains false, loading the frame content failed. A reason could be "Content Security Policy"
  475. var functions = {
  476. "other" : {
  477. "parent": function() {
  478. var f = parent.document.getElementById('mciframe123');
  479. window.addEventListener("message", function(e){
  480. if(typeof e.data != "object") {
  481. return;
  482. } else if("mcimessage0" in e.data) {
  483. frame_status = true; // Frame content was loaded successfully
  484. }
  485. });
  486. },
  487. "frame" : function sizecorrection() {
  488. parent.postMessage({"mcimessage0":true},'*'); // Loading frame content was successfull
  489. var f = parent.document.getElementById('mciframe123');
  490. for(var i =0; f.clientHeight < document.body.scrollHeight && i < 100; i++) {
  491. f.style.width = parseInt(f.style.width)+10+"px";
  492. }
  493. if(f.clientHeight < document.body.scrollHeight) {
  494. f.style.height = parseInt(f.style.height)+15+"px";
  495. f.style.width = "300px";
  496. if(parseInt(f.style.height) > 500) {
  497. return;
  498. }
  499. sizecorrection();
  500. }
  501. }
  502. },
  503. "chrome" : {
  504. "parent" : function() {
  505. var f = parent.document.getElementById('mciframe123');
  506. window.addEventListener("message", function(e){
  507. if(typeof e.data != "object") {
  508. return;
  509. } else if("mcimessage0" in e.data) {
  510. frame_status = true; // Frame content was loaded successfully
  511. } else if("mcimessage1" in e.data) {
  512. f.style.width = parseInt(f.style.width)+10+"px";
  513. } else if("mcimessage2" in e.data) {
  514. f.style.height = parseInt(f.style.height)+15+"px";
  515. f.style.width = "300px";
  516. } else {
  517. return;
  518. }
  519. f.contentWindow.postMessage({
  520. "mcimessage3" : true,
  521. "mciframe123_clientHeight" : f.clientHeight,
  522. "mciframe123_clientWidth" : f.clientWidth,
  523. },'*');
  524. });
  525. },
  526. "frame" : function() {
  527. parent.postMessage({"mcimessage0":true},'*'); // Loading frame content was successfull
  528. var i = 0;
  529. window.addEventListener("message", function(e){
  530. if(!("mcimessage3" in e.data)) return;
  531. if(e.data.mciframe123_clientHeight < document.body.scrollHeight && i < 100) {
  532. parent.postMessage({"mcimessage1":1},'*');
  533. i++;
  534. }
  535. if(i >= 100) {
  536. parent.postMessage({"mcimessage2":1},'*')
  537. i = 0;
  538. }
  539. });
  540. parent.postMessage({"mcimessage1":1},'*');
  541. }
  542. }
  543. };
  544. var css = "#hover_div .clr { clear: both}#hover_div { background-color: #fff; color: #666; font-family:Arial,Helvetica,sans-serif; font-size:12px; font-weight:400; font-style:normal;} #hover_div .hoverinfo .hover_left { float: left} #hover_div .hoverinfo .product_image_wrapper { color: #999; font-size: 6px; font-weight: normal; min-height: 98px; min-width: 98px;} #hover_div .hoverinfo .product_image_wrapper a { color: #999; font-size: 6px; font-weight: normal;} #hover_div a * { cursor: pointer}a { color: #09f; font-weight: bold;} #hover_div a:link, #hover_div a:visited { text-decoration: none;} #hover_div a:hover { text-decoration: underline;} #hover_div .hoverinfo .hover_right { float: left; margin-left: 15px; max-width: 395px;} #hover_div .hoverinfo .product_title { color: #333; font-family: georgia,serif; font-size: 24px; line-height: 26px; margin-bottom: 10px;} #hover_div .hoverinfo .product_title a { color:#333; font-family: georgia,serif; font-size: 24px;} #hover_div .hoverinfo .summary_detail.publisher, .hoverinfo .summary_detail.release_data { float: left} #hover_div .hoverinfo .summary_detail { font-size: 11px; margin-bottom: 10px;} #hover_div .hoverinfo .summary_detail.product_credits a { color: #999; font-weight: normal; } #hover_div .hoverinfo .hr { background-color: #ccc; height: 2px; margin: 15px 0 10px;} #hover_div .hoverinfo .hover_scores { width: 100%; border-collapse: collapse; border-spacing: 0;} #hover_div .hoverinfo .hover_scores td.num { width: 39px} #hover_div .hoverinfo .hover_scores td { vertical-align: middle} #hover_div caption, #hover_div th, #hover_div td { font-weight: normal; text-align: left;} #hover_div .metascore_anchor, #hover_div a.metascore_w { text-decoration: none !important} #hover_div span.metascore_w, #hover_div a.metascore_w { display: inline-block}.metascore_w { background-color: transparent; color: #fff !important; font-family: Arial,Helvetica,sans-serif; font-size: 17px; font-style: normal !important; font-weight: bold !important; height: 2em; line-height: 2em; text-align: center; vertical-align: middle; width: 2em;} #hover_div .metascore, #hover_div .metascore a, #hover_div .avguserscore, #hover_div .avguserscore a { color: #fff} #hover_div .critscore, #hover_div .critscore a, #hover_div .userscore, #hover_div .userscore a { color: #333}.score_tbd { background: #eaeaea; color: #333; font-size: 14px;}.score_tbd a { color: #333}.negative, .score_terrible, .score_unfavorable, .carousel_set a.product_terrible:hover, .carousel_set a.product_unfavorable:hover { background-color: #f00}.mixed, .neutral, .score_mixed, .carousel_set a.product_mixed:hover { background-color: #fc3; color: #333;}.score_mixed a { color: #333}.positive, .score_favorable, .score_outstanding, .carousel_set a.product_favorable:hover, .carousel_set a.product_outstanding:hover { background-color: #6c3}.critscore_terrible, .critscore_unfavorable { border-color: #f00}.critscore_mixed { border-color: #fc3}.critscore_favorable, .critscore_outstanding { border-color: #6c3}.metascore .score_total, .userscore .score_total { display: none; visibility: hidden;}.hoverinfo .metascore_label, .hoverinfo .userscore_label { font-size: 12px; font-weight: bold; line-height: 16px; margin-top: 2%;}.hoverinfo .metascore_review_count, .hoverinfo .userscore_review_count { font-size: 11px}.hoverinfo .hover_scores td { vertical-align: middle}.hoverinfo .hover_scores td.num { width: 39px}.hoverinfo .hover_scores td.usr.num { padding-left: 20px}.metascore_anchor, a.metascore_w { text-decoration: none !important}.metascore_w.user { border-radius: 55%; color: #fff;}.metascore_anchor, a.metascore_w { text-decoration: none!important}.metascore_anchor:hover { text-decoration: none!important}.metascore_w:hover { text-decoration: none!important}span.metascore_w, a.metascore_w { display: inline-block}.metascore_w.xlarge, .metascore_w.xl { font-size: 42px}.metascore_w.large, .metascore_w.lrg { font-size: 25px}.m .metascore_w.medium, .m .metascore_w.med { font-size: 19px}.metascore_w.med_small { font-size: 14px}.metascore_w.small, .metascore_w.sm { font-size: 12px}.metascore_w.tiny { height: 1.9em; font-size: 11px; line-height: 1.9em;}.metascore_w.user { border-radius: 55%; color: #fff;}.metascore_w.user.small, .metascore_w.user.sm { font-size: 11px}.metascore_w.tbd, .metascore_w.score_tbd { color: #000!important; background-color: #ccc;}.metascore_w.tbd.hide_tbd, .metascore_w.score_tbd.hide_tbd { visibility: hidden}.metascore_w.tbd.no_tbd, .metascore_w.score_tbd.no_tbd { display: none}.metascore_w.noscore::before, .metascore_w.score_noscore::before { content: '\2022\2022\2022'}.metascore_w.noscore, .metascore_w.score_noscore { color: #fff!important; background-color: #ccc;}.metascore_w.rip, .metascore_w.score_rip { border-radius: 4px; color: #fff!important; background-color: #999;}.metascore_w.negative, .metascore_w.score_terrible, .metascore_w.score_unfavorable { background-color: #f00}.metascore_w.mixed, .metascore_w.forty, .metascore_w.game.fifty, .metascore_w.score_mixed { background-color: #fc3}.metascore_w.positive, .metascore_w.sixtyone, .metascore_w.game.seventyfive, .metascore_w.score_favorable, .metascore_w.score_outstanding { background-color: #6c3}.metascore_w.indiv { height: 1.9em; width: 1.9em; font-size: 15px; line-height: 1.9em;}.metascore_w.indiv.large, .metascore_w.indiv.lrg { font-size: 24px}.m .metascore_w.indiv.medium, .m .metascore_w.indiv.med { font-size: 16px}.metascore_w.indiv.small, .metascore_w.indiv.sm { font-size: 11px}.metascore_w.indiv.perfect { padding-right: 1px}.promo_amazon .esite_btn { margin: 3px 0 0 7px;}.esite_amazon { background-color: #fdc354; border: 1px solid #aaa;}.esite_label_wrapper { display:none;}.esite_btn { border-radius: 4px; color: #222; font-size: 12px; height: 40px; line-height: 40px; width: 120px;}";
  545. var framesrc = 'data:text/html,';
  546. framesrc += encodeURIComponent('<!DOCTYPE html>\
  547. <html lang="en">\
  548. <head>\
  549. <meta charset="utf-8">\
  550. <title>Metacritic info</title>\
  551. <style>body { margin:0px; padding:0px; background:white; }' + css
  552. +'\
  553. </style>\
  554. <script>\
  555. function on_load() {\
  556. ('+functions[mybrowser].frame.toString()+')();\
  557. }\
  558. </script>\
  559. </head>\
  560. <body onload="on_load();">\
  561. <div style="border:0px solid; display:block; position:relative; border-radius:0px; padding:0px; margin:0px; box-shadow:none;" class="hover_div" id="hover_div">\
  562. <div class="hover_content">'+fixMetacriticURLs(html)+'</div>\
  563. </div>\
  564. </body>\
  565. </html>');
  566. var frame = $("<iframe></iframe>").appendTo(div);
  567. frame.attr("id","mciframe123");
  568. frame.attr("src",framesrc);
  569. frame.attr("scrolling","auto");
  570. frame.css({
  571. width: 300,
  572. height: 170,
  573. border: "none"
  574. });
  575. window.setTimeout(function() {
  576. if(!frame_status) { // Loading frame content failed.
  577. // Directly inject the html without an iframe (this may break the site or the metacritic)
  578. console.log("Loading iframe content failed. Injecting directly.");
  579. $("head").append("<style>"+css+"</style>");
  580. var noframe = $('<div style="border:0px solid; display:block; position:relative; border-radius:0px; padding:0px; margin:0px; box-shadow:none;" class="hover_div" id="hover_div">\
  581. <div class="hover_content">'+fixMetacriticURLs(html)+'</div>\
  582. </div>');
  583. frame.replaceWith(noframe);
  584. }
  585. },2000);
  586. functions[mybrowser].parent();
  587. var sub = $("<div></div>").appendTo(div);
  588. $('<time style="color:#b6b6b6; font-size: 11px;" datetime="'+time+'" title="'+time.toLocaleFormat()+'">'+minutesSince(time)+'</time>').appendTo(sub);
  589. $('<a style="color:#b6b6b6; font-size: 11px;" target="_blank" href="'+url+'" title="Open Metacritic">'+decodeURI(url.replace("http://www.","@"))+'</a>').appendTo(sub);
  590. $('<span title="Hide me" style="cursor:pointer; float:right; color:#b6b6b6; font-size: 11px;">&#10062;</span>').appendTo(sub).click(function() {
  591. document.body.removeChild(this.parentNode.parentNode);
  592. });
  593. $('<span title="Assist us: This is the correct entry!" style="cursor:pointer; float:right; color:green; font-size: 11px;">&check;</span>').data("url", url).appendTo(sub).click(function() {
  594. var docurl = document.location.href;
  595. var metaurl = $(this).data("url");
  596. var r = addToMap(docurl,metaurl);
  597. balloonAlert("Thanks for your submission!\n\nSaved as a correct entry.\n\n"+r[0]+"\n"+r[1], 6000, "Success");
  598. });
  599. $('<span title="Assist us: This is NOT the correct entry!" style="cursor:pointer; float:right; color:crimson; font-size: 11px;">&cross;</span>').data("url", url).appendTo(sub).click(function() {
  600. if(!confirm("This is NOT the correct entry!\n\nAdd to blacklist?")) return;
  601. var docurl = document.location.href;
  602. var metaurl = $(this).data("url");
  603. var r = addToBlacklist(docurl,metaurl);
  604. balloonAlert("Thanks for your submission!\n\nSaved to blacklist.\n\n"+r[0]+"\n"+r[1], 6000, "Success");
  605. // Open search
  606. metacritic_searchcontainer(null, current.searchTerm);
  607. metacritic_search(null, current.searchTerm);
  608. });
  609.  
  610. },
  611. // On error i.e. no result on metacritic.com
  612. function(html, time) {
  613. // Make search available
  614. metacritic_waitForHotkeys();
  615. var handleresponse = function(response) {
  616. var data;
  617. var multiple = false;
  618. try {
  619. data = JSON.parse(response.responseText);
  620. } catch(e) {
  621. console.log("Error in JSON: search_term="+current.searchTerm);
  622. console.log(e);
  623. }
  624. if(data && data.autoComplete && data.autoComplete.results && data.autoComplete.results.length) {
  625. // Remove data with wrong type
  626. data.autoComplete = data.autoComplete.results;
  627. var newdata = [];
  628. data.autoComplete.forEach(function(result) {
  629. if(metacritic2searchType(result.refType) == current.type) {
  630. newdata.push(result);
  631. }
  632. });
  633. data.autoComplete = newdata;
  634. if(data.autoComplete.length == 0) {
  635. // No results
  636. console.log("No results (after filtering by type) for search_term="+current.searchTerm);
  637. } else if(data.autoComplete.length == 1) {
  638. // One result, let's show it
  639. if(!isBlacklisted(baseURL + data.autoComplete[0].url)) {
  640. metacritic_showHoverInfo(baseURL + data.autoComplete[0].url);
  641. return;
  642. }
  643. } else {
  644. // More than one result
  645. multiple = true;
  646. console.log("Multiple results for search_term="+current.searchTerm);
  647. var exactMatches = [];
  648. data.autoComplete.forEach(function(result,i) { // Try to find the correct result by matching the search term to exactly one movie title
  649. if(current.searchTerm == result.name) {
  650. exactMatches.push(result);
  651. }
  652. });
  653. if(exactMatches.length == 1) {
  654. // Only one exact match, let's show it
  655. console.log("Only one exact match for search_term="+current.searchTerm);
  656. if(!isBlacklisted(baseURL + exactMatches[0].url)) {
  657. metacritic_showHoverInfo(baseURL + exactMatches[0].url);
  658. return;
  659. }
  660. }
  661. }
  662. } else {
  663. console.log("No results (at all) for search_term="+current.searchTerm);
  664. }
  665. // HERE: multiple results or no result. The user may type "meta" now
  666. if(multiple) {
  667. balloonAlert("Multiple metacritic results. Type &#34;meta&#34; for manual search.", 10000, false, {bottom: 5, top:"auto", maxWidth: 400, paddingRight: 5}, metacritic_searchcontainer);
  668. }
  669. };
  670. var cache = JSON.parse(GM_getValue("autosearchcache","{}"));
  671. for(var prop in cache) {
  672. // Delete cached values, that are older than 2 hours
  673. if((new Date()).getTime() - (new Date(cache[prop].time)).getTime() > 2*60*60*1000) {
  674. delete cache[prop];
  675. }
  676. }
  677. if(current.type == "music") {
  678. current.searchTerm = current.data[0];
  679. } else {
  680. current.searchTerm = current.data.join(" ");
  681. }
  682. if(current.searchTerm in cache) {
  683. handleresponse(cache[current.searchTerm], true);
  684. } else {
  685. GM_xmlhttpRequest({
  686. method: "POST",
  687. url: baseURL_autosearch,
  688. data: "search_term="+encodeURIComponent(current.searchTerm)+"&image_size=98&search_each=1&sort_type=popular",
  689. headers: {
  690. "Referer" : url,
  691. "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
  692. "Host" : "www.metacritic.com",
  693. "User-Agent" : "MetacriticUserscript Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0",
  694. "X-Requested-With" : "XMLHttpRequest"
  695. },
  696. onload: function(response) {
  697. response = {
  698. time : (new Date()).toJSON(),
  699. responseText : response.responseText,
  700. };
  701. cache[current.searchTerm] = response;
  702. GM_setValue("autosearchcache",JSON.stringify(cache));
  703. handleresponse(response, false);
  704. }
  705. });
  706. }
  707. });
  708. }
  709.  
  710. function metacritic_waitForHotkeys() {
  711. listenForHotkeys("meta",metacritic_searchcontainer);
  712. }
  713.  
  714. function metacritic_searchcontainer(ev, query) {
  715. if(!query) {
  716. if(current.type == "music") {
  717. query = current.data[0];
  718. } else {
  719. query = current.data.join(" ");
  720. }
  721. }
  722. $("#mcdiv123").remove();
  723. var div = $('<div id="mcdiv123"></div>').appendTo(document.body);
  724. div.css({
  725. position:"fixed",
  726. bottom :0,
  727. left: 0,
  728. minWidth: 300,
  729. maxHeight: "80%",
  730. maxWidth: 640,
  731. overflow:"auto",
  732. backgroundColor: "#fff",
  733. border: "2px solid #bbb",
  734. borderRadius:" 6px",
  735. boxShadow: "0 0 3px 3px rgba(100, 100, 100, 0.2)",
  736. color: "#000",
  737. padding:" 3px",
  738. zIndex: "5010001",
  739. });
  740. var query = $('<input type="text" size="60" id="mcisearchquery">').appendTo(div).focus().val(query).on('keypress', function(e) {
  741. var code = e.keyCode || e.which;
  742. if(code == 13) { // Enter key
  743. metacritic_search.call(this,e);
  744. }
  745. });
  746. $('<button id="mcisearchbutton">').text("Search").appendTo(div).click(metacritic_search);
  747. }
  748.  
  749.  
  750. function metacritic_search(ev, query) {
  751. if(!query) { // Use values from search form
  752. query = $("#mcisearchquery").val();
  753. }
  754. var type = searchType2metacritic(current.type);
  755.  
  756. var style = document.createElement('style');
  757. style.type = 'text/css';
  758. style.innerHTML = CSS;
  759. document.head.appendChild(style);
  760.  
  761. var div = $("#mcdiv123");
  762. var loader = $('<div style="width:20px; height:20px;" class="grespinner"></div>').appendTo($("#mcisearchbutton"));
  763. var url = baseURL_search.replace("{type}",encodeURIComponent(type)).replace("{query}",encodeURIComponent(query));
  764.  
  765. metacritic_searchResults(url,
  766. // On success
  767. function(results, time) {
  768. loader.remove();
  769. var accept = function(ev) {
  770. var a = $(this.parentNode).find("a[href*='metacritic.com']");
  771. var metaurl = a.attr("href");
  772. var docurl = document.location.href;
  773.  
  774. addToMap(docurl,metaurl);
  775. metacritic_showHoverInfo(metaurl);
  776. };
  777. var denyAll = function(ev) {
  778. var urls = [];
  779. var docurl = document.location.href;
  780. $("#mcdiv123searchresults").find("div.result a[href*='metacritic.com']").each(function() {
  781. addToBlacklist(docurl, this.href);
  782. });
  783. };
  784. var resultdiv = $("#mcdiv123searchresults").length?$("#mcdiv123searchresults").html(""):$('<div id="mcdiv123searchresults"></div>').css("max-width","95%").appendTo(div);
  785. results.forEach(function(html) {
  786. var singleresult = $('<div class="result"></div>').html(fixMetacriticURLs(html)+'<div style="clear:left"></div>').appendTo(resultdiv);
  787. $('<span title="Assist us: This is the correct entry!" style="cursor:pointer; color:green; font-size: 13px;">&check;</span>').prependTo(singleresult).click(accept);
  788. });
  789. var sub = $("<div></div>").appendTo(div);
  790. $('<time style="color:#b6b6b6; font-size: 11px;" datetime="'+time+'" title="'+time.toLocaleFormat()+'">'+minutesSince(time)+'</time>').appendTo(sub);
  791. $('<a style="color:#b6b6b6; font-size: 11px;" target="_blank" href="'+url+'" title="Open Metacritic">'+decodeURI(url.replace("http://www.","@"))+'</a>').appendTo(sub);
  792. $('<span title="Hide me" style="cursor:pointer; float:right; color:#b6b6b6; font-size: 11px;">&#10062;</span>').appendTo(sub).click(function() {
  793. document.body.removeChild(this.parentNode.parentNode);
  794. });
  795. $('<span title="Assist us: None of the above is the correct item!" style="cursor:pointer; float:right; color:crimson; font-size: 11px;">&cross;</span>').appendTo(sub).click(function() {if(confirm("None of the above is the correct item\nConfirm?")) denyAll()});
  796. },
  797. // On error i.e. no results
  798. function(results, time) {
  799. loader.remove();
  800. var resultdiv = $("#mcdiv123searchresults").length?$("#mcdiv123searchresults").html(""):$('<div id="mcdiv123searchresults"></div>').appendTo(div);
  801. resultdiv.html("No search results.");
  802. var sub = $("<div></div>").appendTo(div);
  803. $('<time style="color:#b6b6b6; font-size: 11px;" datetime="'+time+'" title="'+time.toLocaleFormat()+'">'+minutesSince(time)+'</time>').appendTo(sub);
  804. $('<a style="color:#b6b6b6; font-size: 11px;" target="_blank" href="'+url+'" title="Open Metacritic">'+decodeURI(url.replace("http://www.","@"))+'</a>').appendTo(sub);
  805. $('<span title="Hide me" style="cursor:pointer; float:right; color:#b6b6b6; font-size: 11px;">&#10062;</span>').appendTo(sub).click(function() {
  806. document.body.removeChild(this.parentNode.parentNode);
  807. });
  808. }
  809. );
  810. }
  811.  
  812. var current = {
  813. url : null,
  814. type : null,
  815. data : null, // Array of raw search keys
  816. searchTerm : null
  817. };
  818.  
  819.  
  820. function showURL(url) {
  821. if(!isBlacklisted(url)) {
  822. var docurl = document.location.host.replace(/^www\./,"") + document.location.pathname + document.location.search;
  823. docurl = filterUniversalUrl(docurl);
  824. metacritic_showHoverInfo(url, docurl);
  825. } else {
  826. console.log(url +" is blacklisted!");
  827. }
  828. }
  829.  
  830.  
  831. var metacritic = {
  832. "mapped" : function metacritic_mapped(url, type) {
  833. // url was in the map/whitelist
  834. current.data = [url]
  835. current.url = url;
  836. current.type = type;
  837. current.searchTerm = url;
  838. showURL(url);
  839. },
  840. "music" : function metacritic_music(artistname, albumname) {
  841. current.data = [albumname.trim(),artistname.trim()]
  842. artistname = name2metacritic(artistname);
  843. albumname = albumname.replace("&"," ");
  844. albumname = name2metacritic(albumname);
  845. var url = baseURL_music + albumname + "/" + artistname;
  846. current.url = url;
  847. current.type = "music";
  848. current.searchTerm = albumname + "/" + artistname;
  849. showURL(url);
  850. },
  851. "movie" : function metacritic_movie(moviename) {
  852. current.data = [moviename.trim()]
  853. moviename = name2metacritic(moviename);
  854. var url = baseURL_movie + moviename;
  855. current.url = url;
  856. current.type = "movie";
  857. current.searchTerm = moviename;
  858. showURL(url);
  859. },
  860. "tv" : function metacritic_tv(seriesname) {
  861. current.data = [seriesname.trim()]
  862. seriesname = name2metacritic(seriesname);
  863. var url = baseURL_tv + seriesname;
  864. current.url = url;
  865. current.type = "tv";
  866. current.searchTerm = seriesname;
  867. showURL(url);
  868. },
  869. "pcgame" : function metacritic_pcgame(gamename) {
  870. current.data = [gamename.trim()]
  871. gamename = name2metacritic(gamename);
  872. var url = baseURL_pcgame + gamename;
  873. current.url = url;
  874. current.type = "pcgame";
  875. current.searchTerm = gamename;
  876. showURL(url);
  877. },
  878. "ps4game" : function metacritic_ps4game(gamename) {
  879. current.data = [gamename.trim()]
  880. gamename = name2metacritic(gamename);
  881. var url = baseURL_ps4 + gamename;
  882. current.url = url;
  883. current.type = "ps4game";
  884. current.searchTerm = gamename;
  885. showURL(url);
  886. },
  887. "xonegame" : function metacritic_xonegame(gamename) {
  888. current.data = [gamename.trim()]
  889. gamename = name2metacritic(gamename);
  890. var url = baseURL_xone + gamename;
  891. current.url = url;
  892. current.type = "xonegame";
  893. current.searchTerm = gamename;
  894. showURL(url);
  895. }
  896. };
  897.  
  898.  
  899. var Always = () => true;
  900. var sites = {
  901. 'bandcamp' : {
  902. host : ["bandcamp.com"],
  903. condition : function() {
  904. return unsafeWindow.TralbumData
  905. },
  906. products : [{
  907. condition : Always,
  908. type : "music",
  909. data : () => [unsafeWindow.TralbumData.artist, unsafeWindow.TralbumData.current.title]
  910. }]
  911. },
  912. 'itunes' : {
  913. host : ["itunes.apple.com"],
  914. condition : Always,
  915. products : [{
  916. condition : () => ~document.location.href.indexOf("/album/") ,
  917. type : "music",
  918. data : () => [document.querySelector("*[itemprop=byArtist]").textContent, document.querySelector("*[itemprop=name]").textContent]
  919. }]
  920. },
  921. 'googleplay' : {
  922. host : ["play.google.com"],
  923. condition : Always,
  924. products : [
  925. {
  926. condition : () => ~document.location.href.indexOf("/album/"),
  927. type : "music",
  928. data : () => [document.querySelector("*[itemprop=byArtist] a").textContent, document.querySelector("*[itemprop=name]").textContent]
  929. },
  930. {
  931. condition : () => ~document.location.href.indexOf("/movies/details/"),
  932. type : "movie",
  933. data : () => document.querySelector("*[itemprop=name]").textContent
  934. }
  935. ]
  936. },
  937. 'imdb' : {
  938. host : ["imdb.com"],
  939. condition : Always,
  940. products : [
  941. {
  942. condition : function() {
  943. var e = document.querySelector("meta[property='og:type']");
  944. if(e) {
  945. return e.content == "video.movie"
  946. }
  947. return false;
  948. },
  949. type : "movie",
  950. data : function() {
  951. if(document.querySelector("h1[itemprop=name]")) { // Movie homepage (New design 2015-12)
  952. return document.querySelector("h1[itemprop=name]").firstChild.textContent.trim();
  953. } else if(document.querySelector("*[itemprop=name] a") && document.querySelector("*[itemprop=name] a").firstChild.data) { // Subpage of a move
  954. return document.querySelector("*[itemprop=name] a").firstChild.data.trim();
  955. } else if(document.querySelector(".title-extra[itemprop=name]")) { // Movie homepage: sub-/alternative-/original title
  956. return document.querySelector(".title-extra[itemprop=name]").firstChild.textContent.replace(/\"/g,"").trim();
  957. } else { // Movie homepage (old design)
  958. return document.querySelector("*[itemprop=name]").firstChild.textContent.trim();
  959. }
  960. }
  961. },
  962. {
  963. condition : function() {
  964. var e = document.querySelector("meta[property='og:type']");
  965. if(e) {
  966. return e.content == "video.tv_show"
  967. }
  968. return false;
  969. },
  970. type : "tv",
  971. data : () => document.querySelector("*[itemprop=name]").textContent
  972. }
  973. ]
  974. },
  975. 'steam' : {
  976. host : ["store.steampowered.com"],
  977. condition : () => document.querySelector("*[itemprop=name]"),
  978. products : [{
  979. condition : Always,
  980. type : "pcgame",
  981. data : () => document.querySelector("*[itemprop=name]").textContent
  982. }]
  983. },
  984. 'tv.com' : {
  985. host : ["www.tv.com"],
  986. condition : () => document.querySelector("meta[property='og:type']"),
  987. products : [{
  988. condition : () => document.querySelector("meta[property='og:type']").content == "tv_show" && document.querySelector("h1[data-name]"),
  989. type : "tv",
  990. data : () => document.querySelector("h1[data-name]").dataset.name
  991. }]
  992. },
  993. 'rottentomatoes' : {
  994. host : ["www.rottentomatoes.com"],
  995. condition : Always,
  996. products : [{
  997. condition : () => document.location.pathname.startsWith("/m/"),
  998. type : "movie",
  999. data : () => document.querySelector("h1").firstChild.textContent
  1000. },
  1001. {
  1002. condition : () => document.location.pathname.startsWith("/tv/") ,
  1003. type : "tv",
  1004. data : () => unsafeWindow.BK.TvSeriesTitle
  1005. }
  1006. ]
  1007. },
  1008. 'serienjunkies' : {
  1009. host : ["www.serienjunkies.de"],
  1010. condition : Always,
  1011. products : [{
  1012. condition : () => Always,
  1013. type : "tv",
  1014. data : function() {
  1015. if(document.querySelector("h1[itemprop=name]")) {
  1016. return document.querySelector("h1[itemprop=name]").textContent;
  1017. } else {
  1018. var n = $("a:contains(Details zur)");
  1019. if(n) {
  1020. var name = n.text().match(/Details zur Produktion der Serie (.+)/)[1];
  1021. return name;
  1022. }
  1023. }
  1024. }
  1025. }]
  1026. },
  1027. 'gamespot' : {
  1028. host : ["gamespot.com"],
  1029. condition : () => document.querySelector("[itemprop=device]"),
  1030. products : [
  1031. {
  1032. condition : () => ~$("[itemprop=device]").text().indexOf("PC"),
  1033. type : "pcgame",
  1034. data : () => document.querySelector("h1[itemprop=name]").textContent
  1035. },
  1036. {
  1037. condition : () => ~$("[itemprop=device]").text().indexOf("PS4"),
  1038. type : "ps4game",
  1039. data : () => document.querySelector("h1[itemprop=name]").textContent
  1040. },
  1041. {
  1042. condition : () => ~$("[itemprop=device]").text().indexOf("XONE"),
  1043. type : "xonegame",
  1044. data : () => document.querySelector("h1[itemprop=name]").textContent
  1045. }
  1046. ]
  1047. },
  1048. 'amazon' : {
  1049. host : ["amazon."],
  1050. condition : Always,
  1051. products : [
  1052. {
  1053. condition : function() {
  1054. var music = ["Music","Musique","Musik","Música","Musica","音楽"];
  1055. return music.some(function(s) {
  1056. if(~document.title.indexOf(s)) {
  1057. return true;
  1058. } else {
  1059. return false;
  1060. }
  1061. });
  1062. },
  1063. type : "music",
  1064. data : function() {
  1065. var artist = document.querySelector("#byline .author a").textContent;
  1066. var title = document.getElementById("productTitle").textContent;
  1067. title = title.replace(/\[([^\]]*)\]/g,""); // Remove [brackets] and their content
  1068. return [artist, title];
  1069. }
  1070. },
  1071. {
  1072. condition : () => (document.getElementById("aiv-content-title") && document.getElementsByClassName("season-single-dark").length),
  1073. type : "tv",
  1074. data : () => document.getElementById("aiv-content-title").firstChild.data.trim()
  1075. },
  1076. {
  1077. condition : () => document.getElementById("aiv-content-title"),
  1078. type : "movie",
  1079. data : () => document.getElementById("aiv-content-title").firstChild.data.trim()
  1080. }
  1081. ]
  1082. },
  1083. 'BoxOfficeMojo' : {
  1084. host : ["boxofficemojo.com"],
  1085. condition : () => ~document.location.search.indexOf("id="),
  1086. products : [{
  1087. condition : () => document.querySelector("#body table:nth-child(2) tr:first-child b"),
  1088. type : "movie",
  1089. data : () => document.querySelector("#body table:nth-child(2) tr:first-child b").firstChild.data
  1090. }]
  1091. },
  1092. 'AllMovie' : {
  1093. host : ["allmovie.com"],
  1094. condition : () => document.querySelector("h2[itemprop=name].movie-title"),
  1095. products : [{
  1096. condition : () => document.querySelector("h2[itemprop=name].movie-title"),
  1097. type : "movie",
  1098. data : () => document.querySelector("h2[itemprop=name].movie-title").firstChild.data.trim()
  1099. }]
  1100. },
  1101. 'en.wikipedia' : {
  1102. host : ["en.wikipedia.org"],
  1103. condition : Always,
  1104. products : [{
  1105. condition : function() {
  1106. if(!document.querySelector(".infobox .summary")) {
  1107. return false;
  1108. }
  1109. var r = /\d\d\d\d films/;
  1110. return $("#catlinks a").filter((i,e) => e.firstChild.data.match(r)).length;
  1111. },
  1112. type : "movie",
  1113. data : () => document.querySelector(".infobox .summary").firstChild.data
  1114. },
  1115. {
  1116. condition : function() {
  1117. if(!document.querySelector(".infobox .summary")) {
  1118. return false;
  1119. }
  1120. var r = /television series/;
  1121. return $("#catlinks a").filter((i,e) => e.firstChild.data.match(r)).length;
  1122. },
  1123. type : "tv",
  1124. data : () => document.querySelector(".infobox .summary").firstChild.data
  1125. }]
  1126. },
  1127. 'movies.com' : {
  1128. host : ["movies.com"],
  1129. condition : () => document.querySelector("meta[property='og:title']"),
  1130. products : [{
  1131. condition : Always,
  1132. type : "movie",
  1133. data : () => document.querySelector("meta[property='og:title']").content
  1134. }]
  1135. },
  1136. 'themoviedb' : {
  1137. host : ["themoviedb.org"],
  1138. condition : () => document.querySelector("meta[property='og:type']"),
  1139. products : [{
  1140. condition : () => document.querySelector("meta[property='og:type']").content == "movie",
  1141. type : "movie",
  1142. data : () => document.querySelector("meta[property='og:title']").content
  1143. },
  1144. {
  1145. condition : () => document.querySelector("meta[property='og:type']").content == "tv_series",
  1146. type : "tv",
  1147. data : () => document.querySelector("meta[property='og:title']").content
  1148. }]
  1149. },
  1150. 'letterboxd' : {
  1151. host : ["letterboxd.com"],
  1152. condition : () => unsafeWindow.filmData && "name" in unsafeWindow.filmData,
  1153. products : [{
  1154. condition : Always,
  1155. type : "movie",
  1156. data : () => unsafeWindow.filmData.name
  1157. }]
  1158. },
  1159. 'TVmaze' : {
  1160. host : ["tvmaze.com"],
  1161. condition : () => document.querySelector("h1"),
  1162. products : [{
  1163. condition : Always,
  1164. type : "tv",
  1165. data : () => document.querySelector("h1").firstChild.data
  1166. }]
  1167. },
  1168. 'TVGuide' : {
  1169. host : ["tvguide.com"],
  1170. condition : Always,
  1171. products : [{
  1172. condition : () => document.location.pathname.startsWith("/tvshows/"),
  1173. type : "tv",
  1174. data : () => document.querySelector("meta[property='og:title']").content
  1175. }]
  1176. },
  1177. 'followshows' : {
  1178. host : ["followshows.com"],
  1179. condition : Always,
  1180. products : [{
  1181. condition : () => document.querySelector("meta[property='og:type']").content == "video.tv_show",
  1182. type : "tv",
  1183. data : () => document.querySelector("meta[property='og:title']").content
  1184. }]
  1185. },
  1186. 'TheTVDB' : {
  1187. host : ["thetvdb.com"],
  1188. condition : Always,
  1189. products : [{
  1190. condition : () => ~document.location.search.indexOf("tab=series"),
  1191. type : "tv",
  1192. data : () => document.querySelector("#content h1").firstChild.data
  1193. }]
  1194. },
  1195. 'ConsequenceOfSound' : {
  1196. host : ["consequenceofsound.net"],
  1197. condition : () => document.querySelector("meta[property='og:title']"),
  1198. products : [{
  1199. condition : () => document.querySelector("meta[property='og:title']").content.match(/.+: (.+) [-–] (.+)/),
  1200. type : "music",
  1201. data : function() {
  1202. var m = document.querySelector("meta[property='og:title']").content.match(/.+: (.+) [-–] (.+)/);
  1203. m.shift();
  1204. return m;
  1205. }
  1206. }]
  1207. },
  1208. 'Pitchfork' : {
  1209. host : ["pitchfork.com"],
  1210. condition : () => ~document.location.href.indexOf("/reviews/albums/"),
  1211. products : [{
  1212. condition : () => document.querySelector(".review-article .tombstone .score"),
  1213. type : "music",
  1214. data : function() {
  1215. var artist = document.querySelector(".review-article .tombstone h2.artists").innerText.trim();
  1216. var album = document.querySelector(".review-article .tombstone h1.review-title").innerText.trim();
  1217. return [artist, album];
  1218. }
  1219. }]
  1220. },
  1221. 'Last.fm' : {
  1222. host : ["last.fm"],
  1223. condition : () => document.querySelector("*[data-page-resource-type]") && document.querySelector("*[data-page-resource-type]").dataset.pageResourceType == "album",
  1224. products : [{
  1225. condition : () => document.querySelector("*[data-page-resource-type]").dataset.pageResourceName,
  1226. type : "music",
  1227. data : function() {
  1228. var artist = document.querySelector("*[data-page-resource-type]").dataset.pageResourceArtistName;
  1229. var album = document.querySelector("*[data-page-resource-type]").dataset.pageResourceName;
  1230. return [artist, album];
  1231. }
  1232. }]
  1233. },
  1234. 'TVRage' : {
  1235. host : ["tvrage.com"],
  1236. condition : () => document.querySelector(".content_title"),
  1237. products : [{
  1238. condition : Always,
  1239. type : "tv",
  1240. data : () => document.querySelector(".content_title").textContent
  1241. }]
  1242. },
  1243. 'rateyourmusic' : {
  1244. host : ["rateyourmusic.com"],
  1245. condition : () => document.querySelector("meta[property='og:type']"),
  1246. products : [{
  1247. condition : () => document.querySelector("meta[property='og:type']").content == "music.album",
  1248. type : "music",
  1249. data : function() {
  1250. var artist = document.querySelector(".section_main_info .artist").innerText.trim();
  1251. var album = document.querySelector(".section_main_info .album_title").innerText.trim();
  1252. return [artist, album];
  1253. }
  1254. }]
  1255. },
  1256. };
  1257.  
  1258.  
  1259. function main() {
  1260.  
  1261. var map = false;
  1262.  
  1263. for(var name in sites) {
  1264. var site = sites[name];
  1265. if(site.host.some(function(e) {return ~this.indexOf(e)}, document.location.hostname))
  1266. if(site.host.some(function(e) {return ~this.indexOf(e)}, document.location.hostname) && site.condition()) {
  1267. for(var i = 0; i < site.products.length; i++) {
  1268. if(site.products[i].condition()) {
  1269. // Check map for a match
  1270. if(map === false) {
  1271. map = JSON.parse(GM_getValue("map","{}"));
  1272. }
  1273. var docurl = document.location.host.replace(/^www\./,"") + document.location.pathname + document.location.search;
  1274. docurl = filterUniversalUrl(docurl);
  1275. if(docurl in map) {
  1276. // Found in map, show result
  1277. var metaurl = map[docurl];
  1278. metacritic["mapped"].apply(undefined, [baseURL + metaurl, site.products[i].type]);
  1279. break;
  1280. }
  1281. // Try to retrieve item name from page
  1282. var data;
  1283. try {
  1284. data = site.products[i].data();
  1285. } catch(e) {
  1286. data = false;
  1287. console.log(e);
  1288. }
  1289. if(data) {
  1290. metacritic[site.products[i].type].apply(undefined, Array.isArray(data)?data:[data]);
  1291. }
  1292. break;
  1293. }
  1294. }
  1295. break;
  1296. }
  1297. }
  1298. }
  1299.  
  1300.  
  1301.  
  1302. main();
  1303. var lastLoc = document.location.href;
  1304. window.setInterval(function() {
  1305. if(document.location.href != lastLoc) {
  1306. lastLoc = document.location.href;
  1307. $("#mcdiv123").remove();
  1308. window.setTimeout(main,1000);
  1309. }
  1310. },500);
  1311.