Humble Enhancer

Enhances Humble Bundle pages with additional info

  1. // ==UserScript==
  2. // @name Humble Enhancer
  3. // @author Nathaniel Watson <nathaniel@nwatson.nz> (http://nwatson.nz)
  4. // @namespace http://www.nwatson.nz
  5. // @description Enhances Humble Bundle pages with additional info
  6. // @license https://github.com/nathanielw/humble-enhancer/blob/master/LICENSE
  7. // @supportURL https://github.com/nathanielw/humble-enhancer/issues
  8. // @homepageURL https://github.com/nathanielw/humble-enhancer
  9. // @source https://github.com/nathanielw/humble-enhancer
  10. // @compatible firefox
  11. // @compatible chrome
  12. // @include https://www.humblebundle.com/*
  13. // @exclude https://www.humblebundle.com/books*
  14. // @exclude https://www.humblebundle.com/monthly*
  15. // @exclude https://www.humblebundle.com/store*
  16. // @version 0.3.0
  17. // @grant GM_xmlhttpRequest
  18. // @grant GM_getValue
  19. // @grant GM_setValue
  20. // @grant GM_listValues
  21. // @grant GM_deleteValue
  22. // @grant GM_getResourceText
  23. // @grant GM_addStyle
  24. // @connect humblebundle.com
  25. // @connect cheapshark.com
  26. // @connect www.cheapshark.com
  27. // @resource style https://cdn.rawgit.com/nathanielw/humble-enhancer/v0.3.0/dist/style.css
  28. // ==/UserScript==
  29. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  30. 'use strict';
  31.  
  32. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  33.  
  34. Object.defineProperty(exports, "__esModule", {
  35. value: true
  36. });
  37.  
  38. var _quantizer = require('./quantizer');
  39.  
  40. var _quantizer2 = _interopRequireDefault(_quantizer);
  41.  
  42. var _cheapshark = require('./cheapshark');
  43.  
  44. var Cheapshark = _interopRequireWildcard(_cheapshark);
  45.  
  46. var _htmlEscape = require('./util/html-escape');
  47.  
  48. var _htmlEscape2 = _interopRequireDefault(_htmlEscape);
  49.  
  50. var _constants = require('./constants');
  51.  
  52. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  53.  
  54. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  55.  
  56. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  57.  
  58. var scoreQuantizer = new _quantizer2.default(40, 99, ['lowest', 'low', 'medium', 'high', 'highest']);
  59.  
  60. var BundleGameView = function () {
  61. function BundleGameView(element, model) {
  62. _classCallCheck(this, BundleGameView);
  63.  
  64. this.element = element;
  65. this.model = model;
  66. }
  67.  
  68. _createClass(BundleGameView, [{
  69. key: 'displayInfo',
  70. value: function displayInfo(storeManager) {
  71. var _this = this;
  72.  
  73. var outer = this.element.querySelector('.table-wrapper');
  74.  
  75. if (outer) {
  76. (function () {
  77. var buttonContainer = document.createElement('div');
  78. buttonContainer.className = 'he-button-container';
  79. buttonContainer.innerHTML = '\n\t\t\t\t<div class=\'he-button-container__group he-button-container__group--left\'>\n\t\t\t\t\t' + (_this.model.info.metacriticScore && _this.model.info.metacriticLink ? '<a class=\'he-info-button tooltip-top he-metacritic he-metacritic--' + scoreQuantizer.quantize(_this.model.info.metacriticScore) + '\'\n\t\t\t\t\t\t\tdata-tooltip=\'Metacritic score for ' + (0, _htmlEscape2.default)(_this.model.info.external) + '\'\n\t\t\t\t\t\t\thref=\'http://www.metacritic.com' + _this.model.info.metacriticLink + '\'>\n\t\t\t\t\t\t' + _this.model.info.metacriticScore + '\n\t\t\t\t\t\t</a>' : '') + '\n\t\t\t\t</div>\n\t\t\t\t<div class=\'he-button-container__group he-button-container__group--right\'>\n\t\t\t\t\t' + (_this.model.steamLink ? '<a class=\'he-info-button\' href=\'' + _this.model.steamLink + '\'>\n\t\t\t\t\t\t\t<i class=\'fa fa-steam\'></i>\n\t\t\t\t\t\t</a>' : '') + '\n\t\t\t\t\t<span class=\'he-info-button he-info-button--price he-tooltipped\'>\n\t\t\t\t\t\t<i class=\'fa fa-usd\'></i>\n\t\t\t\t\t\t<div class=\'he-tooltip he-tooltip--medium\'>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</span>\n\t\t\t\t</div>';
  80.  
  81. var priceButton = buttonContainer.querySelector('.he-info-button--price');
  82. var priceTooltip = priceButton.querySelector('.he-tooltip');
  83.  
  84. if (_this.model.deals) {
  85. _this._createTooltip(priceTooltip, storeManager);
  86. } else {
  87. (function () {
  88. var hoverHandler = function hoverHandler() {
  89. priceButton.removeEventListener('mouseover', hoverHandler);
  90. priceTooltip.innerHTML = '<div class="he-tooltip__inner">Loading deals...</div>';
  91. Cheapshark.deals({ title: _this.model.info.external, exact: 1 }, function (err, dealsData) {
  92. if (!err && dealsData.length > 0) {
  93. _this.model.deals = dealsData;
  94. _this._createTooltip(priceTooltip, storeManager);
  95. } else {
  96. priceTooltip.innerHTML = '<div class="he-tooltip__inner">No deals found</div>';
  97. }
  98. });
  99. };
  100.  
  101. priceButton.addEventListener('mouseover', hoverHandler);
  102. })();
  103. }
  104.  
  105. outer.insertBefore(buttonContainer, outer.firstChild);
  106. })();
  107. }
  108. }
  109. }, {
  110. key: '_createTooltip',
  111. value: function _createTooltip(tooltipEl, storeManager) {
  112. var self = this;
  113.  
  114. tooltipEl.innerHTML = '\n\t\t\t<div class=\'he-tooltip__inner\'>\n\t\t\t\t<h3 class=\'he-tooltip__title\'>External Prices</h3>\n\t\t\t\t<span class=\'he-tooltip__subtitle\'>' + this.model.info.external + '</span>\n\t\t\t</div>\n\t\t\t<div class=\'he-price-list\'>\n\t\t\t\t' + function () {
  115. var list = '';
  116.  
  117. for (var i = 0; i < self.model.deals.length; i++) {
  118. var deal = self.model.deals[i];
  119. var store = storeManager.getStore(parseInt(deal.storeID));
  120.  
  121. if (store) {
  122. list += '\n\t\t\t\t\t\t\t\t<a class=\'he-price-list__item\' href=' + (_constants.DEAL_BASE + deal.dealID) + '>\n\t\t\t\t\t\t\t\t\t<span class=\'he-price-list__cell\'>\n\t\t\t\t\t\t\t\t\t\t<img src=\'//cheapshark.com/' + (0, _htmlEscape2.default)(store.images.icon) + '\' />\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span class=\'he-price-list__cell\'>\n\t\t\t\t\t\t\t\t\t\t' + (0, _htmlEscape2.default)(store.storeName) + '\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span class=\'he-price-list__cell he-price-list__cell--right\'>\n\t\t\t\t\t\t\t\t\t\t$' + deal.salePrice + '\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</a>';
  123. }
  124. }
  125. return list;
  126. }() + '\n\t\t\t</div>\n\t\t';
  127. }
  128. }]);
  129.  
  130. return BundleGameView;
  131. }();
  132.  
  133. exports.default = BundleGameView;
  134. },{"./cheapshark":3,"./constants":4,"./quantizer":7,"./util/html-escape":9}],2:[function(require,module,exports){
  135. 'use strict';
  136.  
  137. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
  138.  
  139. Object.defineProperty(exports, "__esModule", {
  140. value: true
  141. });
  142. exports.getValue = getValue;
  143. exports.setValue = setValue;
  144. exports.clearExpired = clearExpired;
  145. exports.clearAll = clearAll;
  146. exports.getLastCleared = getLastCleared;
  147. var EXPIRY_PREFIX = 'expiry';
  148. var LAST_CLEARED_KEY = 'lastcleared';
  149.  
  150. function getValue(type, id) {
  151. var value = GM_getValue(type + ':' + id);
  152.  
  153. try {
  154. return JSON.parse(value);
  155. } catch (ex) {
  156. return value;
  157. }
  158. }
  159.  
  160. function setValue(type, id, value, expiry) {
  161. if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value !== null) {
  162. value = JSON.stringify(value);
  163. }
  164.  
  165. GM_setValue(formatKey(type, id), value);
  166.  
  167. if (expiry !== undefined) {
  168. GM_setValue(formatKey(EXPIRY_PREFIX, formatKey(type, id)), expiry);
  169. }
  170. }
  171.  
  172. function clearExpired() {
  173. var keys = GM_listValues();
  174. var now = Date.now();
  175.  
  176. GM_setValue(LAST_CLEARED_KEY, now);
  177.  
  178. keys.forEach(function (key) {
  179. if (key.lastIndexOf(EXPIRY_PREFIX, 0) === 0) {
  180. var expiry = GM_getValue(key);
  181. if (expiry <= now) {
  182. var mainKey = expiryKeyToKey(key);
  183. GM_deleteValue(mainKey);
  184. }
  185. }
  186. });
  187. }
  188.  
  189. function clearAll() {
  190. GM_listValues().forEach(function (key) {
  191. GM_deleteValue(key);
  192. });
  193. }
  194.  
  195. function getLastCleared() {
  196. var time = GM_getValue(LAST_CLEARED_KEY);
  197.  
  198. if (time === undefined) {
  199. time = Date.now();
  200. GM_setValue(LAST_CLEARED_KEY, time);
  201. }
  202.  
  203. return time;
  204. }
  205.  
  206. function formatKey(type, id) {
  207. return type + ':' + id;
  208. }
  209.  
  210. function expiryKeyToKey(expiryKey) {
  211. return expiryKey.substring(EXPIRY_PREFIX.length + 1);
  212. }
  213. },{}],3:[function(require,module,exports){
  214. 'use strict';
  215.  
  216. Object.defineProperty(exports, "__esModule", {
  217. value: true
  218. });
  219. exports.games = games;
  220. exports.deals = deals;
  221. exports.stores = stores;
  222.  
  223. var _networkUtil = require('./util/network-util');
  224.  
  225. var net = _interopRequireWildcard(_networkUtil);
  226.  
  227. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  228.  
  229. var API_URL = 'http://www.cheapshark.com/api/1.0/';
  230.  
  231. function games(opts, callback) {
  232. sendGet('games', opts, callback);
  233. }
  234.  
  235. function deals(opts, callback) {
  236. sendGet('deals', opts, callback);
  237. }
  238.  
  239. function stores(callback) {
  240. sendGet('stores', null, callback);
  241. }
  242.  
  243. function sendGet(endpoint, opts, callback) {
  244. net.httpGet(API_URL + endpoint, opts, responseHandler(callback), responseHandler(callback));
  245. }
  246.  
  247. function responseHandler(callback) {
  248. return function (err, response) {
  249. if (err) {
  250. callback(err, null);
  251. } else {
  252. var data = JSON.parse(response);
  253. callback(null, data);
  254. }
  255. };
  256. }
  257. },{"./util/network-util":10}],4:[function(require,module,exports){
  258. 'use strict';
  259.  
  260. Object.defineProperty(exports, "__esModule", {
  261. value: true
  262. });
  263. var SECONDS = exports.SECONDS = 1000;
  264. var MINUTES = exports.MINUTES = 60000;
  265. var HOURS = exports.HOURS = 3600000;
  266. var DAYS = exports.DAYS = 8640000;
  267.  
  268. var DEAL_BASE = exports.DEAL_BASE = 'http://www.cheapshark.com/redirect.php?dealID=';
  269. },{}],5:[function(require,module,exports){
  270. 'use strict';
  271.  
  272. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  273.  
  274. Object.defineProperty(exports, "__esModule", {
  275. value: true
  276. });
  277.  
  278. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  279.  
  280. var TITLE_REGEX = /[^a-zA-Z0-9\s]/g;
  281. var STEAM_BASE = 'http://store.steampowered.com/app/';
  282.  
  283. var Game = function () {
  284. function Game(title) {
  285. _classCallCheck(this, Game);
  286.  
  287. this.title = title;
  288. this.info = {};
  289. }
  290.  
  291. _createClass(Game, [{
  292. key: 'setInfo',
  293. value: function setInfo(info) {
  294. for (var attr in info) {
  295. this.info[attr] = info[attr];
  296. }
  297. }
  298. }, {
  299. key: 'setMetacriticInfo',
  300. value: function setMetacriticInfo(score, link) {
  301. if (typeof score !== 'number') {
  302. throw Error('Invalid type: Metacritic score must be a number');
  303. }
  304.  
  305. this.info.metacriticScore = score;
  306. this.info.metacriticLink = link;
  307. }
  308. }, {
  309. key: 'id',
  310. get: function get() {
  311. return this.title.replace(TITLE_REGEX, '');
  312. }
  313. }, {
  314. key: 'deals',
  315. set: function set(deals) {
  316. this._deals = deals.sort(function (a, b) {
  317. return parseFloat(a.salePrice) - parseFloat(b.salePrice);
  318. });
  319. },
  320. get: function get() {
  321. return this._deals;
  322. }
  323. }, {
  324. key: 'steamLink',
  325. set: function set(steamLink) {
  326. this.info.steamLink = steamLink;
  327. },
  328. get: function get() {
  329. if (this.info.steamAppID != null) {
  330. return STEAM_BASE + this.info.steamAppID;
  331. } else {
  332. return this.info.steamLink;
  333. }
  334. }
  335. }]);
  336.  
  337. return Game;
  338. }();
  339.  
  340. exports.default = Game;
  341. },{}],6:[function(require,module,exports){
  342. 'use strict';
  343.  
  344. var _cheapshark = require('./cheapshark');
  345.  
  346. var Cheapshark = _interopRequireWildcard(_cheapshark);
  347.  
  348. var _cache = require('./cache');
  349.  
  350. var Cache = _interopRequireWildcard(_cache);
  351.  
  352. var _game = require('./game');
  353.  
  354. var _game2 = _interopRequireDefault(_game);
  355.  
  356. var _bundleGameView = require('./bundle-game-view');
  357.  
  358. var _bundleGameView2 = _interopRequireDefault(_bundleGameView);
  359.  
  360. var _storeManager = require('./store-manager');
  361.  
  362. var _storeManager2 = _interopRequireDefault(_storeManager);
  363.  
  364. var _constants = require('./constants');
  365.  
  366. var Constants = _interopRequireWildcard(_constants);
  367.  
  368. var _updateTasks = require('./util/update-tasks');
  369.  
  370. var _updateTasks2 = _interopRequireDefault(_updateTasks);
  371.  
  372. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  373.  
  374. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  375.  
  376. function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
  377.  
  378. var TYPE_GAME = 'game';
  379.  
  380. function main() {
  381. (0, _updateTasks2.default)();
  382. cleanCache();
  383. GM_addStyle(GM_getResourceText('style'));
  384.  
  385. var stores = new _storeManager2.default();
  386. stores.init(initGameInfo);
  387. }
  388.  
  389. function initGameInfo(storeManager) {
  390. var games = findBundleGames();
  391. var expiry = Date.now() + Constants.DAYS * 14;
  392.  
  393. games.forEach(function (g) {
  394. var gameInfo = Cache.getValue(TYPE_GAME, g.model.id);
  395. if (gameInfo !== undefined) {
  396. if (gameInfo !== null) {
  397. g.model.setInfo(gameInfo);
  398. g.displayInfo(storeManager);
  399. }
  400. } else {
  401. Cheapshark.games({ title: g.model.title, limit: 10, exact: 1 }, function (err, gamesData) {
  402. if (!err) {
  403. if (gamesData.length > 0) {
  404. g.model.setInfo(gamesData[0]);
  405.  
  406. Cheapshark.deals({ title: g.model.info.external, exact: 1 }, function (err, dealsData) {
  407. if (!err && dealsData.length > 0) {
  408. g.model.deals = dealsData;
  409.  
  410. var hasSteam = g.model.info.steamAppID != null;
  411. var hasMetacritic = false;
  412.  
  413. for (var i = 0; i < dealsData.length && !(hasSteam && hasMetacritic); i++) {
  414. var deal = dealsData[i];
  415.  
  416. if (!hasMetacritic && deal.metacriticLink && deal.metacriticScore) {
  417. g.model.setMetacriticInfo(parseInt(deal.metacriticScore), deal.metacriticLink);
  418. hasMetacritic = true;
  419. }
  420.  
  421. if (!hasSteam && deal.storeID == 1) {
  422. g.model.steamLink = Constants.DEAL_BASE + deal.dealID;
  423. hasSteam = true;
  424. }
  425. }
  426.  
  427. Cache.setValue(TYPE_GAME, g.model.id, g.model.info, expiry);
  428. } else {
  429. g.model.deals = [];
  430. }
  431.  
  432. g.displayInfo(storeManager);
  433. });
  434. } else {
  435. Cache.setValue(TYPE_GAME, g.model.id, null, expiry);
  436. }
  437. }
  438. });
  439. }
  440. });
  441. }
  442.  
  443. function cleanCache() {
  444. var now = Date.now();
  445.  
  446. if (now - Cache.getLastCleared() >= Constants.DAYS) {
  447. Cache.clearExpired();
  448. }
  449. }
  450.  
  451. function findBundleGames() {
  452. var gameEls = [].concat(_toConsumableArray(document.querySelectorAll('.promo-body .game-border:not(.charity) .game-boxes > li')));
  453.  
  454. var gameList = gameEls.map(function (gameEl) {
  455. var titleEl = gameEl.querySelector('.game-description h2');
  456.  
  457. if (titleEl !== null) {
  458. var title = titleEl.textContent.trim();
  459.  
  460. var game = new _game2.default(title);
  461. return new _bundleGameView2.default(gameEl, game);
  462. } else {
  463. return null;
  464. }
  465. }).filter(function (game) {
  466. return game !== null;
  467. });
  468.  
  469. return gameList;
  470. }
  471.  
  472. main();
  473. },{"./bundle-game-view":1,"./cache":2,"./cheapshark":3,"./constants":4,"./game":5,"./store-manager":8,"./util/update-tasks":11}],7:[function(require,module,exports){
  474. 'use strict';
  475.  
  476. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  477.  
  478. Object.defineProperty(exports, "__esModule", {
  479. value: true
  480. });
  481.  
  482. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  483.  
  484. var Quantizer = function () {
  485. function Quantizer(low, high, values) {
  486. _classCallCheck(this, Quantizer);
  487.  
  488. this.low = low;
  489. this.high = high;
  490. this.values = values;
  491. }
  492.  
  493. _createClass(Quantizer, [{
  494. key: 'quantize',
  495. value: function quantize(value) {
  496. var maxIndex = this.values.length - 1;
  497. var ratio = (value - this.low) / (this.high - this.low);
  498. var index = Math.ceil(ratio * this.values.length) - 1;
  499. index = Math.max(Math.min(index, maxIndex), 0);
  500.  
  501. return this.values[index];
  502. }
  503. }]);
  504.  
  505. return Quantizer;
  506. }();
  507.  
  508. exports.default = Quantizer;
  509. },{}],8:[function(require,module,exports){
  510. 'use strict';
  511.  
  512. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  513.  
  514. Object.defineProperty(exports, "__esModule", {
  515. value: true
  516. });
  517.  
  518. var _cheapshark = require('./cheapshark');
  519.  
  520. var Cheapshark = _interopRequireWildcard(_cheapshark);
  521.  
  522. var _cache = require('./cache');
  523.  
  524. var Cache = _interopRequireWildcard(_cache);
  525.  
  526. var _constants = require('./constants');
  527.  
  528. var Constants = _interopRequireWildcard(_constants);
  529.  
  530. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  531.  
  532. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  533.  
  534. var TYPE_STORES = 'stores';
  535. var STORES_KEY = 'all-stores';
  536.  
  537. var StoreManager = function () {
  538. function StoreManager() {
  539. _classCallCheck(this, StoreManager);
  540. }
  541.  
  542. _createClass(StoreManager, [{
  543. key: 'init',
  544. value: function init(callback) {
  545. var _this = this;
  546.  
  547. var stores = Cache.getValue(TYPE_STORES, STORES_KEY);
  548. var expiry = Date.now() + Constants.DAYS * 14;
  549.  
  550. if (stores !== undefined) {
  551. this._setStores(stores);
  552. callback(this);
  553. } else {
  554. Cheapshark.stores(function (err, data) {
  555. if (!err) {
  556. Cache.setValue(TYPE_STORES, STORES_KEY, data, expiry);
  557. _this._setStores(data);
  558. } else {
  559. _this._setStores([]);
  560. }
  561.  
  562. callback(_this);
  563. });
  564. }
  565. }
  566. }, {
  567. key: '_setStores',
  568. value: function _setStores(stores) {
  569. var _this2 = this;
  570.  
  571. this._storeDict = {};
  572. stores.forEach(function (store) {
  573. _this2._storeDict[store.storeID] = store;
  574. });
  575. }
  576. }, {
  577. key: 'getStore',
  578. value: function getStore(id) {
  579. if (this._storeDict === undefined) {
  580. throw Error('Store manager has not been initialised.');
  581. }
  582.  
  583. return this._storeDict[id];
  584. }
  585. }]);
  586.  
  587. return StoreManager;
  588. }();
  589.  
  590. exports.default = StoreManager;
  591. },{"./cache":2,"./cheapshark":3,"./constants":4}],9:[function(require,module,exports){
  592. 'use strict';
  593.  
  594. Object.defineProperty(exports, "__esModule", {
  595. value: true
  596. });
  597. exports.default = htmlEscape;
  598. function htmlEscape(str) {
  599. return str.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/`/g, '&#96;');
  600. }
  601. },{}],10:[function(require,module,exports){
  602. 'use strict';
  603.  
  604. Object.defineProperty(exports, "__esModule", {
  605. value: true
  606. });
  607. exports.httpGet = httpGet;
  608. exports.queryStringify = queryStringify;
  609. function httpGet(url, params, callback) {
  610. GM_xmlhttpRequest({
  611. url: url + '?' + queryStringify(params),
  612. method: 'GET',
  613. onload: responseHandler(callback),
  614. onerror: responseHandler(callback, true)
  615. });
  616. }
  617.  
  618. function queryStringify(params) {
  619. var queryString = '';
  620.  
  621. if (params) {
  622. queryString = Object.keys(params).reduce(function (a, k) {
  623. a.push(k + '=' + encodeURIComponent(params[k]));
  624. return a;
  625. }, []).join('&');
  626. }
  627.  
  628. return queryString;
  629. }
  630.  
  631. function responseHandler(callback, wasError) {
  632. return function (response) {
  633. if (wasError || response.status !== 200) {
  634. callback(new Error('Error communicating with server. ' + response.status + ' ' + response.statusText), null);
  635. } else {
  636. callback(null, response.responseText);
  637. }
  638. };
  639. }
  640. },{}],11:[function(require,module,exports){
  641.  
  642.  
  643. 'use strict';
  644.  
  645. Object.defineProperty(exports, "__esModule", {
  646. value: true
  647. });
  648. exports.default = updateTasks;
  649.  
  650. var _cache = require('../cache');
  651.  
  652. var Cache = _interopRequireWildcard(_cache);
  653.  
  654. var _versionUtil = require('./version-util');
  655.  
  656. var VersionUtil = _interopRequireWildcard(_versionUtil);
  657.  
  658. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  659.  
  660. var TYPE_VERSION = 'version';
  661. var ID_VERSION = 'installed';
  662. var VERSION = '0.3.0';
  663.  
  664. function updateTasks() {
  665. var oldVersion = Cache.getValue(TYPE_VERSION, ID_VERSION);
  666.  
  667. if (!oldVersion) {
  668. performTasks();
  669. } else {
  670. var oldMajor = VersionUtil.getMajorVersion(oldVersion);
  671. var newMajor = VersionUtil.getMajorVersion(VERSION);
  672. var oldMinor = VersionUtil.getMinorVersion(oldVersion);
  673. var newMinor = VersionUtil.getMinorVersion(VERSION);
  674.  
  675. if (newMajor !== oldMajor || newMajor === 0 && oldMinor !== newMinor) {
  676. performTasks();
  677. }
  678. }
  679. }
  680.  
  681. function performTasks() {
  682. Cache.clearAll();
  683. Cache.setValue(TYPE_VERSION, ID_VERSION, VERSION);
  684. }
  685. },{"../cache":2,"./version-util":12}],12:[function(require,module,exports){
  686. 'use strict';
  687.  
  688. Object.defineProperty(exports, "__esModule", {
  689. value: true
  690. });
  691. exports.getMajorVersion = getMajorVersion;
  692. exports.getMinorVersion = getMinorVersion;
  693. function getMajorVersion(verString) {
  694. return parseInt(verString.split('.')[0]);
  695. }
  696.  
  697. function getMinorVersion(verString) {
  698. return parseInt(verString.split('.')[1]);
  699. }
  700. },{}]},{},[6]);