AC Content Manager Installation Buttons

Adds Content Manager support to RSR Live Timing website, The Setup Market, AC Club and Assetto-DB.

  1. // ==UserScript==
  2. // @name AC Content Manager Installation Buttons
  3. // @namespace http://tampermonkey.net/
  4. // @homepageURL https://github.com/gro-ove/actools-cm-download-extension
  5. // @version 0.2.5
  6. // @description Adds Content Manager support to RSR Live Timing website, The Setup Market, AC Club and Assetto-DB.
  7. // @author x4fab
  8. // @match http://assettocorsa.club/*
  9. // @match http://www.assetto-db.com/*
  10. // @match http://assetto-db.com/*
  11. // @match http://thesetupmarket.com/*
  12. // @match http://www.radiators-champ.com/RSRLiveTiming/*
  13. // @grant none
  14. // @license MIT License
  15. // @run-at document-end
  16. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBQTFRF/wAAzAAAmf8AmQAAZv8AZswAZpkAZmZmZjMzM5kAM2YzM2YAMzMzMzMAAAAAXl5e7+St3wAAABB0Uk5T////////////////////AOAjXRkAAAHSSURBVHjatNfZsoMgDIBhcGkUI7z/2x5Ay2ZiqM7hppNO/89ujqjcy6X+B1gWeAWA1q8A0OoV4PtXQOjfALF/ARz9c+DsHwPf/imQ+odA7p8BRV8B0AmUvRqh97xQZK8xRYseu4Cmz8fXqgIAm0mJfQWAtc2kxL4EfGGbSYl9AYTCNpMS+wzEwjaTSq/j+gQchW0mJR0/AWdhm8kDQn8C38I2UwWQ/QGkwjZTCdB9BHJhm6kAmD4ARWGbKQO+ByD68Lwtk3pKQHjdOMo9B8RejXLPAEcfAaGngbMPwE2/xQVm2/YG+PYeAL7fpyGsyT+sNZB6tdy9/31K61MBuVf67vOzQO6rdfn+OMB19jzQ2fMfobPngc7+F4DsfwDongSQAi49IgdguLSB2J+nzxVARwBE7y7AmvoLQPUO4mm4ZmCOTxg4AC317jNMxBqmE8ByUb0zE72A2icSvYOZ7I0IYLoOUsIGTgAwX4h3rr8ASPQewPZrGFZg9spEH7ZC0Agf4wQAm70ZbGU/oxMAvOztYKV6DkBib2jy/wmdACC5t8S5/APcAcjsTU9hA3cPILu3DUL6AVkAb/bGXkg/IAfc9Q6MAeGmC7tvNf715vuH9SfAAHw2q5zSfJAiAAAAAElFTkSuQmCC
  17. // ==/UserScript==
  18.  
  19. (function() {
  20. function _$(selector, fn, p){
  21. var e = (p || document).querySelector(selector);
  22. return fn ? e ? fn(e) : undefined : e;
  23. }
  24.  
  25. function _$each(selector, fn, p){ Array.prototype.forEach.call((p || document).querySelectorAll(selector), fn); }
  26. function _$map(selector, fn, p){ return Array.prototype.map.call((p || document).querySelectorAll(selector), fn); }
  27. function _$some(selector, fn, p){ return Array.prototype.some.call((p || document).querySelectorAll(selector), fn); }
  28. function _$every(selector, fn, p){ return Array.prototype.every.call((p || document).querySelectorAll(selector), fn); }
  29. function _$filter(selector, fn, p){ return Array.prototype.filter.call((p || document).querySelectorAll(selector), fn); }
  30.  
  31. // custom CSS
  32. function _$css(data, id){
  33. if (!id){ id = '__cm_extention_style'; }
  34. var s = document.getElementById('__cm_extention_style');
  35. if (s){ s.parentNode.removeChild(s); }
  36. s = document.body.appendChild(document.createElement('style'));
  37. s.id = '__cm_extention_style';
  38. if (s.styleSheet) {
  39. s.styleSheet.cssText = css;
  40. } else {
  41. s.appendChild(document.createTextNode(typeof data === 'function' ? ''.slice.call(data, 14, -3) : data));
  42. }
  43. }
  44.  
  45. // as a variable, it can be easily redefined later for userscript format
  46. var _$res = function (url){ return (typeof browser !== 'undefined' ? browser : chrome).extension.getURL(url); };
  47.  
  48. _$res = function (url){
  49. if (url == "img/icon-acclub.png") return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA9QTFRFmZmZZmZmMzMzAAAAgYGBlaSnFAAAAAV0Uk5T/////wD7tg5TAAABkElEQVR42qSXSwLDIAgFBbz/mVvjJ4CgQbN7qTOmVgxN+fJK9t2UrgRABDeCP38lKPyN4OEvBJU/FzT+WND5U8HgDwUvfyZg/JGA8ycCwTMBIHwSSP4V7Ooi2fyYVdcFgExdsOK5AFAkolb3S16sh0jUBWuerQeq1WmCDT+Qhyf5aRHs+I5UfiTqgi3fkMb3RF2QcMdXpPMtkSOw+AcZfE3kCEy+IC//JHIEmJy6YHxJ5AjQqwvO/xM5AsyIYO4rsUwyMcGf1yv03v8gqONg5tXv7AnaPLDlHUF/TtjytmB8zz1vCvQ6rXhLEOInwX+XpQg/C3JofvMJQrwhiPGzAGP8N8GC/yRY8bI20RRoHlGcWTIZglX9lQNDplkw8++Q58CRaRIY/BhSDyyZtMDi+5B2ZstUdiK/wOAb0s98mXSjafH15nhnyKQFZqODnFDJ61TFex05oZISJLPRQk5kwa/WwOv0ZPIFcNbuY7RV9QTHfzgwyDuC77wtCPCmIMJbWznEz0+AMT6nfHldC34CDADQEDTb2F/V3AAAAABJRU5ErkJggg==";
  50. if (url == "img/icon-thesetupmarket-16.png") return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXxJREFUeNqMk7EvBFEQxt/e7l7uGnH+AIlCgY4gEoUEhRONQnKVUPkP5FqFQqGSoCDXKYRaSSUhIiERQbLonKwlud3mbNY38l2MjZOb5JedNzvf7Hszby3f943rukaZA+ZBBcTmH6vX68aEYWiSJNHsgttU7E+iKDIZcZRtggUQmRZMtJmUeIl+yGcWlIDOy/3ya7Wa7GIj+bFn0Ackvg+u1La3QIn+KI5/JAW02AM9TKgwdsz1OtdF0AveUMCTApfqyyNM3lFFD8CqWq+AJ3FQ4Nrh2B6BB8bAHFjkGW/YhzLXMtZp0KlnfgK6wQQYAG1KfA9m0uNPX5oPMAmsJmI9AZuahuXl5RTFpok44EfEHsCZyj2UanegwEAVvCix+LNgj1svgnHmroFlmUIWDc2RIdXtKujnVE75Tvwy2BZffgMpoO/3MMWvYJAxB7SrnELDlwKZVIfzPIZs9ZyxT/CucgItsIIgMLZtG8v67mMX6AAXrfxIcRybLwEGAPyuf5tj/yp0AAAAAElFTkSuQmCC";
  51. if (url == "img/icon-radiatorschamp-30.png") return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACFQTFRF///////M/8zM/8yZ/5mZzJmZzJlmzGZmzGYzzDMz////Hc17DAAAAAt0Uk5T/////////////wBKTwHyAAAA5ElEQVR42nzT2xaEIAgF0BNBaP//wcNFDWfWxFOyVwRquFfg/o0nB+CFwfTyNs7+wqYv7PqfQ5O/+sNSicdjlMMapipp5gmp2LUHQ3yJQ82pajDE10DrxlrV2dQSri350X7B1TJH64MlWgjV1M5RNNhUUFWJyGZIJi+wvcunqjIn59e3ypc3IcF3fKVq52gueaQebQ/PuWtlSpExve5qA1Pw2di3TqxNvZbaBvhMOV2cSsSjfYav5rmP9TzfcRCVedwBGd3cG/N6lqmFufwRajuy3fND6h3ERTt/31D8/+9KfAQYAH4FGSoAsxbPAAAAAElFTkSuQmCC";
  52. if (url == "img/icon-radiatorschamp-48.png") return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADxQTFRF/8wA/5kA/wAAzJkAzAAAmWYAmQAzmQAAZmYAZjMAZgAzZgAAMzMzMzMAMwAzMwAAADMzAAAzAAAAogAl5T9rCwAAABR0Uk5T/////////////////////////wBPT+cRAAACAElEQVR42pSVi5KDIAwAqUoU0EvB///XSyCAUOzUzPRBu8sjAVFnFxbOr6G6Njj7SIB1ck8E4h8JzC8PBOafCJF/ICT+d0H4nxdd+B9HKPy0imAdfBEqv2Di7DKVkkNVAVTPJ8yu05IF+MPMu92qngfhiwC4/0HmozDsvwjE7zJN4nen7ngRmBeBeRLu+CREPgmRJ8Hd8FFIfBQSz8LS8TAVQXgWhK9CyX+tIJzC71j4IlD/sbKVX1zun4TCZ2FxNp5Ne6144XfETiDe8Ta94Tsh/su5stDx3l+n9PZvGYHnH6GWfx96O/aDYj+QXps2PgprnA9RHb/NH7G9SbDC10jzOebZGIYyTS1lPO2lc8j7TekQNL2JQS36yVsFQ3735qU9WZs3InivqWWVXUY8TUkTY6jPPAJ/OWhKrVDz79nQF0EzH7oRrvUKZEjHohwhOGiEbj8EyovOa5gN+kA79Co0PHWGMVUlS5E/qXCLxOoanp4W3LtO/Gvz6eApwBK26Z8Erl6pW0gnRkGNlmch1BUL39wP2PB8QAPqnCHhh0LiSQjO4kYKbdvMNxcKNjxdqLwQ5F2IhR8ImT9Fw3nGy+P4Qwj9Y97Ns7u543DEk/D6InS8M8bwounDDYWOB/OSfUqVHqW1nw/wCBKDOsDHtQaU2RwwEAZXYN03+Zd/AQYAX0xuXwD83e4AAAAASUVORK5CYII=";
  53. return '';
  54. };
  55.  
  56. if (/^http:\/\/assettocorsa\.club\/.*/i.test(location.href) || /^https:\/\/assettocorsa\.club\/.*/i.test(location.href)){
  57. if (_$('p.download a', function (x){ return x.textContent; }) == 'DOWNLOAD'){
  58. _$('.spec > div', function (x) { x.style.width = '60%'; });
  59. _$('.spec > div:last-child', function (x) { x.style.width = '40%'; });
  60. _$each('.__cmspecial', function (x){ x.parentNode.removeChild(x); });
  61. _$('p.download a', function (x) {
  62. var c = x.cloneNode();
  63. c.classList.add('__cmspecial');
  64. c.removeAttribute('target');
  65. c.setAttribute('href', 'acmanager://install?url=' + encodeURIComponent(x.href));
  66. c.textContent = 'INSTALL';
  67. c.setAttribute('style',
  68. 'color: rgb(100, 166, 112); padding: 0px 0px 6px 40px; line-height: 33px; margin: 2px 0px 2px 12px;' +
  69. 'background: url(' + JSON.stringify(_$res('img/icon-acclub.png')) + ') left center / contain no-repeat;' +
  70. 'display: inline-block;');
  71. x.parentNode.insertBefore(c, x.nextSibling);
  72. });
  73. }
  74. } else if (/^http:\/\/www\.assetto-db\.com\/.*/i.test(location.href) || /^http:\/\/assetto-db\.com\/.*/i.test(location.href)){
  75. _$each('.__cmspecial', function (x){ x.parentNode.removeChild(x); });
  76. _$('.carDetails a[href^="/"][href$="/download"]', function (x) {
  77. var c = x.cloneNode();
  78. c.classList.add('__cmspecial');
  79. c.removeAttribute('target');
  80. c.setAttribute('href', 'acmanager://install?url=' + encodeURIComponent(location.href));
  81. c.textContent = 'Install using Content Manager';
  82.  
  83. // with hue filter, hover/active colors are already there, and also it won’t look weird
  84. // in case of sudden redesign
  85. c.setAttribute('style', 'filter:hue-rotate(-120deg);-webkit-filter:hue-rotate(-120deg)');
  86. c.classList.remove('btn-default');
  87. c.classList.add('btn-primary');
  88. x.parentNode.insertBefore(c, x.nextSibling);
  89. });
  90. } else if (/^http:\/\/thesetupmarket\.com\/.*/i.test(location.href)){
  91. if (!_$('#__cm_stop')){
  92. // if you would need to stop CM, just add empty element with ID=__cm_stop somewhere
  93.  
  94. var observeDOM = (function(){
  95. var MutationObserver = window.MutationObserver || window.WebKitMutationObserver,
  96. eventListenerSupported = window.addEventListener;
  97. return function(obj, callback){
  98. if (MutationObserver){
  99. var obs = new MutationObserver(function(mutations, observer){
  100. if (mutations[0].addedNodes.length || mutations[0].removedNodes.length){
  101. callback();
  102. }
  103. });
  104.  
  105. obs.observe(obj, { childList: true, subtree: true });
  106. } else if (eventListenerSupported){
  107. obj.addEventListener('DOMNodeInserted', callback, false);
  108. }
  109. };
  110. })();
  111.  
  112. observeDOM(document.body, function(){
  113. _$each('.icon-details.icon-link[href^="#/setups/Assetto Corsa/"]:not(.__cmspecial)', function (x){
  114. x.classList.add('__cmspecial');
  115. var c = x.cloneNode(true);
  116. x.parentNode.appendChild(c);
  117. c.setAttribute('href', 'acmanager://thesetupmarket/setup?id=' + (x.href.match(/\/([\w-]+)\/?$/) || {})[1]);
  118. c.setAttribute('style', 'color:transparent;background:url(' + JSON.stringify(_$res('img/icon-thesetupmarket-16.png')) +
  119. ');background-repeat:no-repeat;background-position:center;');
  120. });
  121.  
  122. _$each('.link.icon-download.fixed-download-link:not(.__cmspecial)', function (x){
  123. var i = setInterval(function (){
  124. var id = (x.href.match(/\/([\w-]+)\/?$/) || {})[1];
  125. if (id == null) return;
  126. clearInterval(i);
  127.  
  128. x.classList.add('__cmspecial');
  129. var c = x.cloneNode(true);
  130. x.parentNode.appendChild(c);
  131. c.classList.remove('icon-download');
  132. c.textContent = 'install using CM';
  133. c.setAttribute('href', 'acmanager://thesetupmarket/setup?id=' + id);
  134. c.setAttribute('style', 'right:220px;filter:hue-rotate(-60deg);-webkit-filter:hue-rotate(-60deg)')
  135. }, 100);
  136. });
  137. });
  138. }
  139. } else if (/^http:\/\/www\.radiators-champ\.com\/RSRLiveTiming\/.*/i.test(location.href)){
  140. if (_$('#__cmext_style', function (x){ x.parentNode.removeChild(x); return true; })){
  141. // cleaning up after RSR Live Timing Content Manager Support extension
  142. _$('#__cmext_start_btn', function (x){ x.parentNode.removeChild(x); return true; });
  143.  
  144. _$each('th:last-child', function (x){
  145. if (x.textContent === 'Install'){
  146. x.textContent = 'Download';
  147. }
  148. });
  149.  
  150. _$each('a', function (x){
  151. var m = x.href.match(/^acmanager:\/\/rsr\/setup\?id=(\d+)/);
  152. if (m){
  153. x.href = 'http://www.radiators-champ.com/RSRLiveTiming/ajax.php?action=download_setup&id=' + m[1];
  154. }
  155. });
  156. }
  157.  
  158. // start button if needed or possible
  159. var eventId = (location.href.match(/\beventId?=(\d+)\b/i) || {})[1];
  160. var carId = (location.href.match(/\bcar(?:Id)?=(\d+)\b/i) || {})[1];
  161. var trackId = (location.href.match(/\btrack(?:Id)?=(\d+)\b/i) || {})[1];
  162.  
  163. if (eventId != null || carId != null && trackId != null){
  164. _$css(function(){/*
  165. #__cmext_start_btn {
  166. display: block !important;
  167. position: fixed !important;
  168. bottom: 20px !important;
  169. right: 20px !important;
  170. width: 72px !important;
  171. height: 72px !important;
  172. border-radius: 2px !important;
  173. background: #A20025 !important;
  174. color: white !important;
  175. text-transform: uppercase !important;
  176. text-decoration: none !important;
  177. font-size: 13px !important;
  178. font-weight: bold !important;
  179. line-height: 27px !important;
  180. padding: 8px !important;
  181. text-align: center !important;
  182. color: #FFF !important;
  183. }
  184.  
  185. #__cmext_start_btn:hover, #__cmext_start_btn:active {
  186. color: #FFF !important;
  187. background: #990024 !important;
  188. text-decoration: none !important;
  189. } */});
  190.  
  191. var c = eventId || trackId + '/' + carId;
  192. var b = document.createElement('a');
  193. b.id = '__cmext_start_btn';
  194. b.appendChild(document.createElement('img')).src = _$res('img/icon-radiatorschamp-48.png');
  195. b.appendChild(document.createElement('br'));
  196. b.appendChild(document.createTextNode('Start'));
  197. b.href = 'acmanager://rsr?id=' + encodeURIComponent(c);
  198. document.body.appendChild(b);
  199. }
  200.  
  201. // setups table: new column with quick install buttons
  202. _$each('th:last-child', function (x){
  203. if (x.textContent === 'Download'){
  204. x.textContent = 'Download​';
  205. x.parentNode.appendChild(x.cloneNode()).textContent = 'Install';
  206. }
  207. });
  208.  
  209. _$each('a', function (x){
  210. var m = x.href.match(/=download_setup&id=(\d+)/);
  211. if (m){
  212. var c = x.parentNode.parentNode.appendChild(x.parentNode.cloneNode(true)).querySelector('a');
  213. c.href = 'acmanager://rsr/setup?id=' + m[1];
  214. c.querySelector('img').src = _$res('img/icon-radiatorschamp-30.png');
  215. x.href = x.href.replace(/&id/, '&proc=1&id');
  216. }
  217. });
  218. }
  219. })();