Steam Badge Viewer

try to take over the world!

  1. // ==UserScript==
  2. // @name Steam Badge Viewer
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.0
  5. // @description try to take over the world!
  6. // @icon http://www.steamcardexchange.net/include/design/img/favicon_blue.png
  7. // @author Bisumaruko
  8. // @match http://www.steamcardexchange.net/*
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. /* global $, GM_xmlhttpRequest, confirm */
  14.  
  15. (function($) {
  16. 'use strict';
  17.  
  18. //load data
  19. var ignoredGames = JSON.parse(localStorage.getItem('SBV_ignored_games') || '[]');
  20. var cache = JSON.parse(localStorage.getItem('SBV_cache') || '{}');
  21. var urls = [];
  22. var apps = [];
  23.  
  24. //construct functions
  25. const init = function() {
  26. $('#content-area')
  27. .text('')
  28. .html(`
  29. <div class="content-box">
  30. <div class="content-box-topbar-large">
  31. <span class="left"><h1 class="empty">BADGE</h1></span>
  32. </div>
  33. <a href="index.php?showcase-filter-ac" class="showcase-navigation-link">A - C</a>
  34. <a href="index.php?showcase-filter-df" class="showcase-navigation-link">D - F</a>
  35. <a href="index.php?showcase-filter-gi" class="showcase-navigation-link">G - I</a>
  36. <a href="index.php?showcase-filter-jl" class="showcase-navigation-link">J - L</a>
  37. <a href="index.php?showcase-filter-mo" class="showcase-navigation-link">M - O</a>
  38. <a href="index.php?showcase-filter-pr" class="showcase-navigation-link">P - R</a>
  39. <a href="index.php?showcase-filter-su" class="showcase-navigation-link">S - U</a>
  40. <a href="index.php?showcase-filter-vx" class="showcase-navigation-link">V - X</a>
  41. <a href="index.php?showcase-filter-yz" class="showcase-navigation-link">Y - Z</a>
  42. <a href="index.php?showcase-filter-09" class="showcase-navigation-link">0 - 9</a>
  43. <a href="index.php?showcase-filter-recadded" class="showcase-navigation-link recent">Recently<br>Added</a>
  44. <a href="index.php?showcase-filter-all" class="showcase-navigation-link">All</a>
  45. </div>
  46. `);
  47.  
  48. $('.showcase-navigation-link').click(function(e) {
  49. e.preventDefault();
  50.  
  51. message('Loading...');
  52.  
  53. if (!e.target.href.includes('filter')) return;
  54.  
  55. urls = [];
  56. apps = [];
  57.  
  58. if (e.target.href.includes('filter-all')) {
  59. ['ac', 'df', 'gi', 'jl', 'mo', 'pr', 'su', 'vx', 'yz', '09'].forEach(filter => {
  60. urls.push('http://www.steamcardexchange.net/index.php?showcase-filter-' + filter);
  61. });
  62. } else urls.push(e.target.href);
  63.  
  64. fetchFilter();
  65. });
  66. //append clear cache button
  67. $('<a/>', {
  68. 'text': 'Clear Cache',
  69. 'style': 'float: right; margin-right: 20px;'
  70. })
  71. .on('click', function() {
  72. if (confirm('Are you sure to delete cache data?')) {
  73. localStorage.removeItem('SBV_cache');
  74. cache = [];
  75. }
  76. })
  77. .appendTo('.content-box-topbar-large');
  78. //append clear ignored games button
  79. $('<a/>', {
  80. 'text': 'Clear Ignored Games',
  81. 'style': 'float: right; margin-right: 20px;'
  82. })
  83. .on('click', function() {
  84. if (confirm('Are you sure to delete ignored games?')) {
  85. localStorage.removeItem('SBV_ignored_games');
  86. ignoredGames = [];
  87. }
  88. })
  89. .appendTo('.content-box-topbar-large');
  90. };
  91. const fetchFilter = function() {
  92. let url = urls.shift();
  93.  
  94. if (url) {
  95. GM_xmlhttpRequest({
  96. method: 'GET',
  97. url: url,
  98. onload: function(res) {
  99. if (res.status === 200) {
  100. $('<div/>', {
  101. 'html': res.responseText
  102. })
  103. .find('.showcase-game-item > a')
  104. .each(function() {
  105. apps.push({
  106. id: parseInt(this.href.split('-').pop()),
  107. title: $(this).find('img').attr('alt'),
  108. imgURL: $(this).find('img').attr('data-original'),
  109. url: this.href
  110. });
  111. });
  112. }
  113.  
  114. fetchFilter();
  115. }
  116. });
  117. } else { //Finished fetching filters
  118. if (!apps.length) return message('Fetching failed, please try again later.');
  119.  
  120. $('.SBV_message').remove();
  121. $('.showcase-game-item').remove();
  122. processGame();
  123. }
  124. };
  125. const processGame = function() {
  126. let app = apps.shift();
  127. if (!app) return;
  128.  
  129. while (ignoredGames.includes(app.id)) {
  130. app = apps.shift();
  131. }
  132.  
  133. let badges = cache[app.id];
  134. let interval = 0;
  135.  
  136. if (Array.isArray(badges)) appendGame(app, badges);
  137. else {
  138. fetchGame(app, appendGame);
  139. interval = 1000;
  140. }
  141.  
  142. setTimeout(processGame, interval);
  143. };
  144. const appendGame = function(app, badges) {
  145. let gameItem = $(`
  146. <div class="showcase-game-item">
  147. <div class="game-image-background"></div>
  148. <a title="Click to get game details" href="index.php?gamepage-appid-${app.id}">
  149. <img class="game-image lazy" src="${app.imgURL}">
  150. </a>
  151. <div class="game-title">
  152. <h2 class="empty">
  153. <a href="http://store.steampowered.com/app/${app.id}/">${app.title}</a>
  154. </h2>
  155. <a><span>&#9747;</span></a>
  156. </div>
  157. <div class="game-info"></div>
  158. </div>
  159. `);
  160.  
  161. if (badges !== null) {
  162. if (badges.length) {
  163. appendBadges(gameItem.find('.game-info'), app, badges);
  164. } else {
  165. gameItem.find('.game-info').text('This game does not have badges.');
  166. }
  167. } else {
  168. gameItem.find('.game-info').text('Fetching failed, click to reload');
  169. gameItem.click(function() {
  170. let info = $(this).find('.game-info');
  171.  
  172. info.text('Reloading...');
  173. fetchGame(app, function(_app, _badges) {
  174. info.text('');
  175. appendBadges(info, _app, _badges);
  176. });
  177. });
  178. }
  179.  
  180. gameItem.find('.game-title > a')
  181. .attr('title', 'Hide this game')
  182. .css({
  183. 'float': 'right',
  184. 'margin-right': '20px'
  185. })
  186. .click(function() {
  187. ignoredGames.push(app.id);
  188. localStorage.setItem('SBV_ignored_games', JSON.stringify(ignoredGames));
  189. gameItem.remove();
  190. });
  191.  
  192. $('#content-area > .content-box').append(gameItem);
  193. };
  194. const fetchGame = function(app, callback) {
  195. GM_xmlhttpRequest({
  196. method: 'GET',
  197. url: app.url,
  198. onload: function(res) {
  199. let badges = null;
  200.  
  201. if (res.status === 200) {
  202. badges = [];
  203. let temp = $(res.responseText);
  204.  
  205. temp
  206. .find('#foilbadges .element-image')
  207. .each(function() {
  208. badges[0] = {
  209. name: $(this).attr('alt'),
  210. imgURL: $(this).attr('src').split('/').pop()
  211. };
  212. });
  213.  
  214. temp
  215. .find('#badges .element-image')
  216. .each(function() {
  217. let level = parseInt($(this).next().next().text().trim().slice(6, 7));
  218. if (isNaN(level)) return true;
  219.  
  220. badges[level] = {
  221. name: $(this).attr('alt'),
  222. imgURL: $(this).attr('src').split('/').pop()
  223. };
  224. });
  225.  
  226. cache[app.id] = badges;
  227. localStorage.setItem('SBV_cache', JSON.stringify(cache));
  228. }
  229.  
  230. callback(app, badges);
  231. }
  232. });
  233. };
  234. const appendBadges = function(target, app, badges) {
  235. let container = $('<div class="SBV_container"></div>');
  236.  
  237. badges.forEach((badge, index) => {
  238. if (!badge) return;
  239.  
  240. let text = index === 0 ? 'Foil' : 'Level ' + index;
  241. let link = 'http://steamcommunity.com/my/gamecards/' + app.id + '/' + (index === 0 ? '?border=1' : '');
  242.  
  243. $('<div/>', {
  244. 'html': `
  245. <img title="${badge.name}" src="http://cdn.akamai.steamstatic.com/steamcommunity/public/images/items/${app.id}/${badge.imgURL}" >
  246. <a href="${link}">${text}</a>`
  247. })
  248. .appendTo(container);
  249. });
  250.  
  251. target.append(container);
  252. };
  253. const message = function(msgText) {
  254. $('#content-area > .content-box').append(`
  255. <div class="showcase-game-item SBV_message">
  256. <span>${msgText}</span>
  257. </div>
  258. `);
  259. };
  260.  
  261. //append style
  262. $('#navbar-menu').css({
  263. 'width': 'initial',
  264. 'right': '0px'
  265. });
  266. $('#logout').css({
  267. 'position': 'fixed',
  268. 'right': '8px'
  269. });
  270.  
  271. GM_addStyle(`
  272. .SBV_container, .SBV_container > div {
  273. height: 70px;
  274. box-sizing: border-box;
  275. text-align: center;
  276. }
  277. .SBV_container > div {
  278. width: 111px;
  279. display: inline-block;
  280. }
  281. .SBV_container img {
  282. height: 54px;
  283. display: block;
  284. margin: auto;
  285. }
  286. `);
  287.  
  288. //append button
  289. $('#navbar-menu').append('<div class="navbar-menu-item" id="SBV"><a class="item-link">BADGE</a></div>');
  290.  
  291. //attach event
  292. $('#SBV').click(function() {
  293. $(document.body).css('background-image', 'none');
  294. init();
  295. });
  296.  
  297. })(jQuery);