General URL Cleaner

Cleans URL's from various popular sites.

  1. // ==UserScript==
  2. // @run-at document-start
  3. // @name General URL Cleaner
  4. // @namespace https://greasyfork.org/en/scripts/10096-general-url-cleaner
  5. // @description Cleans URL's from various popular sites.
  6. // @include https://www.newegg.com/*
  7. // @include https://www.newegg.ca/*
  8. // @include https://www.bing.com/*
  9. // @include https://www.youtube.com/*
  10. // @include https://www.imdb.com/*
  11. // @include https://www.facebook.com/*
  12. // @include https://disqus.com/embed/comments/*
  13. // @include /^https://(www|smile)\.amazon(\.com?)?\.\w{2,3}/.*$/
  14. // @include /^https?://\w+\.google(\.com?)?\.\w{2,3}/.*$/
  15. // @include /^https://[\w.]+\.ebay(desc)?(\.com?)?\.\w{2,3}/.*$/
  16. // @include /^https://[\w\d.]*twitter.com/.*$/
  17. // @include /^https?://(www\.)?staticice\.com\.au/.*$/
  18. // @exclude https://apis.google.com/*
  19. // @exclude https://accounts.google.com/*
  20. // @exclude https://support.google.com/*
  21. // @exclude https://www.google.com/recaptcha/*
  22. // @exclude https://hangouts.google.com/webchat/*
  23. // @version 3.3
  24. // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  25. // ==/UserScript==
  26.  
  27. /*
  28. * Vars
  29. */
  30.  
  31. var ebay = /\.ebay(desc)?(\.com?)?\.\w{2,3}$/;
  32. var google = /\.google\.com?(\.\w{2,3})?$/;
  33. var amazon = /^(www|smile)\.amazon?\.com?(\.\w{2,3})?$/;
  34. var amazonAd = /\.amazon-adsystem\.com?(\.\w{2,3})?$/;
  35.  
  36. var utmParams = /&utm_[^&]+/g;
  37. var neweggParams = /&(cm_sp|icid|ignorebbr)=[^&#]*/g;
  38. var imdbParams = /&(p\w_rd_\w+|ref_)=[^&#]*/g;
  39. var bingParams = /&(go|qs|form|FORM|filt|pq|s[cpk]|qpvt|cvid)=[^&#]*/g;
  40. var youtubeParams = /&(feature|src_vid|annotation_id|[gh]l)=[^&#]*/g;
  41. var ebayParams = /&(_(o?sacat|odkw|from|trksid|trkparms)|frcectupt|rt|epid|amp;[^=]+)=[^&#]*/g;
  42. var amazonParams = /&(url|ie|th|psc|p\w_rd_\w\w?|bbn|rw_html_to_wsrp|ref_?|_encoding|refRID)=[^&#]*/g;
  43. var googleParams = /&(sa(fe)?|ved|source(id)?|s?ei|tab|tbo|h[ls]|authuser|n?um|ie|aqs|as_qdr|bav|bi[wh]|bs|bvm|cad|channel|complete|cp|s?client|d[pc]r|e(ch|msg|s_sm)|g(fe|ws)_rd|gpsrc|noj|btnG|o[eq]|p(si|bx|f|q)|rct|rlz|site|spell|tbas|usg|xhr|gs_\w+)=[^&#]*/g;
  44.  
  45. var youtubeRedir = /[?&]q=([^&]+)/;
  46. var genericRedir1 = /[?&](new|img)?u(rl)?=([^&]+)/i;
  47. var genericRedir2 = /[?&]\w*url=([^&]+)/i;
  48.  
  49. let currHost = location.host;
  50. let currPath = location.pathname;
  51. let currSearch = location.search;
  52.  
  53. /*
  54. * Main
  55. */
  56.  
  57. if (currHost === 'www.bing.com') {
  58. cleanCurrParams(bingParams);
  59. cleanLinks(parserAll);
  60. return;
  61. }
  62.  
  63. if (currHost === 'www.youtube.com') {
  64. if (currPath === '/redirect')
  65. cleanRedir(location, youtureRedir);
  66.  
  67. if (currPath === '/watch')
  68. cleanCurrParams(youtubeParams);
  69.  
  70. cleanLinks(parserYoutube);
  71. return;
  72. }
  73.  
  74. if (currHost.endsWith('.newegg.com') || currHost.endsWith('.newegg.ca')) {
  75. cleanCurrParams(neweggParams);
  76. cleanLinks(parserNewegg);
  77. return;
  78. }
  79.  
  80. if (currHost === 'www.imdb.com') {
  81. cleanCurrParams(imdbParams);
  82. cleanLinks(parserIMDB);
  83. onhashchange = deleteHash();
  84. return;
  85. }
  86.  
  87. if (google.test(currHost)) {
  88. if (currPath === '/url' || currPath === '/imgres')
  89. cleanRedir(location, googleParams);
  90.  
  91. if (!currSearch && !/[&#]q=/.test(location.hash))
  92. return;
  93.  
  94. cleanCurrParams(googleParams);
  95. changeState(googleInstant);
  96.  
  97. if (currSearch.includes('tbm=isch'))
  98. cleanLinksAlways(parserGoogleImages);
  99. else
  100. cleanLinks(parserGoogle);
  101.  
  102. return;
  103. }
  104.  
  105. if (ebay.test(currHost)) {
  106. if (currPath.includes('/itm/')) {
  107. let item = currPath.match(/\/\d{12}/);
  108. let origList = currSearch.replace(/\?.*&?(orig_cvip=[^&]+).*/, '?$1');
  109. setCurrUrl('/itm' + item + origList + location.hash);
  110. }
  111. else if (currPath.startsWith('/p/')) {
  112. if (currSearch.includes('iid='))
  113. setCurrUrl('/itm/' + currSearch.match(/[?&]iid=(\d{12})/).pop());
  114.  
  115. else
  116. setCurrUrl(currPath);
  117. }
  118.  
  119. cleanCurrParams(ebayParams);
  120. cleanLinks(parserEbay);
  121. onhashchange = deleteHash;
  122. return;
  123. }
  124.  
  125. if (amazon.test(currHost)) {
  126. let item = location.pathname.match(/\/[A-Z\d]{10}(?=\/|$)/);
  127. if (currPath.includes('/dp/'))
  128. setCurrUrl('/dp' + item);
  129.  
  130. else if (currPath.includes('/gp/product'))
  131. setCurrUrl('/gp/product' + item);
  132.  
  133. else if (currSearch)
  134. cleanCurrParams(amazonParams);;
  135.  
  136. cleanLinks(parserAmazon);
  137. onhashchange = deleteHash;
  138. return;
  139. }
  140.  
  141. if (currHost.endsWith('staticice.com.au')) {
  142. cleanLinks(parserStaticice);
  143. return;
  144. }
  145.  
  146. if (currHost=='twitter.com') {
  147. cleanLinks(parserTwitter);
  148. return;
  149. }
  150.  
  151. if(currHost=='www.facebook.com') {
  152. cleanLinks(parserFacebook);
  153. return;
  154. }
  155.  
  156. if (currHost=='disqus.com') {
  157. cleanLinks(parserDisqus);
  158. return;
  159. }
  160.  
  161. /*
  162. * Boilerplate functions
  163. */
  164.  
  165. function setCurrUrl(url) {
  166. history.replaceState(null, null, url);
  167. }
  168.  
  169. function cleanCurrParams(params) {
  170. let search = location.search.replace('?','?&').replace(params,'').replace('&','').replace(/\?$/,'');
  171. if (search.length<2)
  172. setCurrUrl(location.pathname);
  173. else
  174. setCurrUrl(search);
  175. }
  176.  
  177. function deleteHash() {
  178. history.replaceState(null, null, ' ');
  179. }
  180.  
  181. function observe(func) {
  182. new MutationObserver(func).observe(document, {childList:true, subtree:true});
  183. }
  184.  
  185. // Clean links once, mark as cleaned, then ignore them
  186. function cleanLinks(linkParser) {
  187. observe(function() {
  188. for (let a of document.links) {
  189. if (a.cleaned)
  190. continue;
  191.  
  192. if (a.protocol && a.protocol.startsWith('http'))
  193. linkParser(a);
  194.  
  195. a.cleaned = 1;
  196. }
  197. });
  198. }
  199.  
  200. // Always clean links
  201. function cleanLinksAlways(linkParser) {
  202. observe(function() {
  203. for (let a of document.links)
  204. if (a.protocol && a.protocol.startsWith('http'))
  205. linkParser(a);
  206. });
  207. }
  208.  
  209. function googleInstant(url) {
  210. let parts = url.split('#');
  211. if (parts.length !== 2)
  212. return url;
  213.  
  214. let hash = parts[1];
  215. if (hash === 'imgrc=_')
  216. return ' ';
  217.  
  218. if (/(^|&)q=/.test(hash))
  219. return '?' + hash;
  220.  
  221. return '#' + hash;
  222. }
  223.  
  224. // Intercept & modify url passed into history.replaceState/pushState
  225. function changeState(mod) {
  226. history.realPushState = history.pushState;
  227. history.realReplaceState = history.replaceState;
  228.  
  229. history.pushState = function() {
  230. history.realPushState(null, null, mod(arguments[2]));
  231. };
  232.  
  233. history.replaceState = function() {
  234. history.realReplaceState(null, null, mod(arguments[2]));
  235. };
  236. }
  237.  
  238. /*
  239. * Link parsing functions
  240. */
  241.  
  242. function parserAll(a) {
  243. let host = a.host;
  244. let path = a.pathname;
  245.  
  246. if (google.test(host)) {
  247. if (path === '/imgres' || path === '/url')
  248. cleanRedir(a,genericRedir1);
  249.  
  250. else
  251. cleanParams(a,googleParams);
  252.  
  253. return;
  254. }
  255.  
  256. if (host === 'www.youtube.com') {
  257. if (path === '/watch')
  258. cleanParams(a,youtubeParams);
  259.  
  260. else if (path === '/redirect')
  261. cleanRedir(a,youtubeRedir);
  262. }
  263.  
  264. if (a.host.endsWith('.bing.com'))
  265. cleanParams(a,bingParams);
  266.  
  267. parserAmazon(a);
  268. parserEbay(a);
  269. parserNewegg(a);
  270. parserIMDB(a);
  271. cleanParams(a,utmParams);
  272. }
  273.  
  274. function parserGoogle(a) {
  275. a.removeAttribute('onmousedown');
  276. parserAll(a);
  277. }
  278.  
  279. function parserGoogleImages(a) {
  280. let jsaction = a.getAttribute('jsaction');
  281. if (jsaction && jsaction.includes('down:irc.rl'))
  282. a.removeAttribute('jsaction');
  283.  
  284. a.removeAttribute('onmousedown');
  285. parserAll(a);
  286. }
  287.  
  288. function parserYoutube(a) {
  289. parserAll(a);
  290. let text = a.innerText;
  291. let href = a.href;
  292. if (text === href || text.endsWith('...') && href.startsWith(text.slice(0,-3)))
  293. a.innerText = href;
  294. }
  295.  
  296. function parserAmazon(a) {
  297. if (amazonAd.test(a.host))
  298. a.href = 'https:' + a.pathname.split('/https:').pop() + a.search;
  299.  
  300. if (!amazon.test(a.host))
  301. return;
  302.  
  303. if (a.pathname.includes('/picassoRedirect'))
  304. cleanRedir(a,genericRedir1);
  305.  
  306. if (a.pathname.includes('/dp/')) {
  307. a.pathname = '/dp' + a.pathname.match(/\/[A-Z\d]{10}(?=\/|$)/);
  308. a.search = '';
  309. }
  310.  
  311. else if (a.pathname.includes('/gp/product')) {
  312. a.pathname = '/gp/product' + a.pathname.match(/\/[A-Z\d]{10}(?=\/|$)/);
  313. a.search = '';
  314. }
  315.  
  316. else if (a.pathname.includes('/ref='))
  317. a.pathname = a.pathname.replace(/\/ref=[^\/]+/,'');
  318.  
  319. cleanParams(a,amazonParams);
  320. }
  321.  
  322. function parserEbay(a) {
  323. if (!ebay.test(a.host))
  324. return;
  325.  
  326. if (a.pathname.includes('/itm/')) {
  327. a.pathname = '/itm' + a.pathname.match(/\/\d{12}/);
  328. a.search = '';
  329. }
  330.  
  331. else if (a.pathname.startsWith('/p/') && a.search.includes('iid=')) {
  332. a.pathname = '/itm/' + a.search.match(/[?&]iid=(\d{12})/).pop();
  333. a.search = '';
  334. }
  335.  
  336. else if (a.host.startsWith('pulsar.')) {
  337. a.pathname = '/itm/' + a.search.match(/%7B%22mecs%22%3A%22(\d{12})/).pop();
  338. a.host = location.host;
  339. a.search = '';
  340. }
  341.  
  342. cleanParams(a,ebayParams);
  343. a.removeAttribute('data-navsrc-tracking');
  344. if (a.hash && a.pathname===location.pathname)
  345. a.href = a.hash;
  346. }
  347.  
  348. function parserNewegg(a) {
  349. if (!a.host.endsWith('.newegg.com') && !a.host.endsWith('.newegg.ca'))
  350. return;
  351.  
  352. if (!a.pathname.includes('/marketplace/'))
  353. cleanParams(a,neweggParams);
  354. }
  355.  
  356. function parserIMDB(a) {
  357. if (a.host === 'www.imdb.com')
  358. cleanParams(a,imdbParams);
  359. }
  360.  
  361. function parserTwitter(a) {
  362. if (a.host !== 't.co')
  363. return;
  364.  
  365. let fake = 't.co' + a.pathname;
  366. let real = a.getAttribute('data-expanded-url');
  367. if (real) {
  368. a.href = real;
  369. a.removeAttribute('data-expanded-url');
  370. sessionStorage.setItem(fake, real);
  371. return;
  372. }
  373.  
  374. if (!a.classList.contains('TwitterCard-container'))
  375. return;
  376.  
  377. real = sessionStorage.getItem(fake);
  378. if (real)
  379. a.href = real;
  380. }
  381.  
  382. function parserFacebook(a) {
  383. let onclick = a.getAttribute('onclick');
  384. if (!onclick || !onclick.startsWith('LinkshimAsyncLink'))
  385. return;
  386.  
  387. if (a.host !== 'l.facebook.com')
  388. return;
  389.  
  390. cleanRedir(a,genericRedir1);
  391. a.removeAttribute('onclick');
  392. a.removeAttribute('onmouseover');
  393. }
  394.  
  395. function parserDisqus(a) {
  396. if (a.host === 'disq.us' && a.pathname === '/url')
  397. cleanRedir(a,genericRedir1);
  398.  
  399. parserAll(a);
  400. }
  401.  
  402. function parserStaticice(a) {
  403. if (a.host.endsWith('staticice.com.au')) {
  404. if (a.pathname.startsWith('/cgi-bin/www.'))
  405. a.href = 'http://'+a.pathname.slice(9);
  406.  
  407. else if (a.pathname !== '/cgi-bin/redirect.cgi')
  408. return;
  409.  
  410. cleanRedir(a,genericRedir1);
  411. }
  412.  
  413. if (a.host === 'www.clixgalore.com' && a.pathname === '/PSale.aspx')
  414. cleanRedir(a,genericRedir2);
  415.  
  416. if (a.host === 't.dgm-au.com' || a.host === 'www.kqzyfj.com')
  417. cleanRedir(a,genericRedir1);
  418.  
  419. if (a.host === 't.cfjump.com')
  420. parserStaticiceTCF(a);
  421.  
  422. cleanParams(a,utmParams);
  423. }
  424.  
  425. function parserStaticiceTCF(a) {
  426. if (a.search) {
  427. cleanRedir(a, genericRedir1);
  428. return;
  429. }
  430.  
  431. if (a.innerText.startsWith('$'))
  432. return;
  433.  
  434. let siteText = a.parentNode;
  435. let itemLink = siteText.parentNode.parentNode.firstChild.firstChild;
  436. if (itemLink.host !== 't.cfjump.com') {
  437. a.href = itemLink.origin;
  438. return;
  439. }
  440.  
  441. let origin = 'https://' + siteText.innerText.split(/ +\| +/)[1];
  442. let itemPath = itemLink.pathname.match(/^\/t\/\d+\/\d+(\/.+)/).pop()
  443. a.href = origin;
  444. itemLink.href = origin + itemPath;
  445. }
  446.  
  447. /*
  448. * URL string functions
  449. */
  450.  
  451. function cleanRedir(a, param) {
  452. a.href = decodeURIComponent(a.search.match(param).pop());
  453. }
  454.  
  455. function cleanParams(a, params) {
  456. if (a.search)
  457. a.search = a.search.replace('?','?&').replace(params,'').replace('&','').replace(/\?$/,'');
  458.  
  459. if (a.hash)
  460. a.hash = a.hash.replace('#','#&').replace(params,'').replace('&','').replace(/#$/,'');
  461. }