Better.Caoliu

This script removes redirection and ads of Caoliu.

  1. // ==UserScript==
  2. // @name Better.Caoliu
  3. // @version 3.0.1
  4. // @namespace me.opengg
  5. // @description This script removes redirection and ads of Caoliu.
  6. // @license GPL-3.0-or-later
  7. // @supportURL https://github.com/OpenGG/Better.Caoliu/issues
  8. // @grant none
  9. // @run-at document-start
  10. // t66y:
  11. // @match http://t66y.com/htm_data/*
  12. // @match http://www.t66y.com/htm_data/*
  13. // ==/UserScript==
  14.  
  15. (function () {
  16. 'use strict';
  17.  
  18. var toArray = function toArray(input) {
  19. return Array.prototype.slice.call(input);
  20. };
  21.  
  22. var querySelectorAll = function querySelectorAll(selector) {
  23. return toArray(document.querySelectorAll(selector));
  24. };
  25.  
  26.  
  27.  
  28. var parseQuery = function parseQuery(query) {
  29. var ret = Object.create(null);
  30. query.split('&').forEach(function (part) {
  31. var pair = part.split('=');
  32. var decodedKey = decodeURIComponent(pair[0]);
  33. ret[decodedKey] = pair.length > 1 ? decodeURIComponent(pair[1]) : '';
  34. });
  35. return ret;
  36. };
  37.  
  38. var tmp = null;
  39.  
  40. var parseUrl = function parseUrl(url) {
  41. if (!tmp) {
  42. tmp = document.createElement('a');
  43. }
  44.  
  45. tmp.href = url;
  46.  
  47. return tmp;
  48. };
  49.  
  50. var hasOwnPropertyInternal = Object.prototype.hasOwnProperty;
  51.  
  52. var hasOwnProperty = function hasOwnProperty(obj, key) {
  53. return hasOwnPropertyInternal.call(obj, key);
  54. };
  55.  
  56. var isReady = function isReady() {
  57. var _document = document,
  58. readyState = _document.readyState;
  59.  
  60.  
  61. return readyState === 'interactive' || readyState === 'complete';
  62. };
  63.  
  64. var ready = function ready(fn) {
  65. if (isReady()) {
  66. fn();
  67. } else {
  68. var called = false;
  69. var listener = function listener() {
  70. if (called) {
  71. return;
  72. }
  73. if (isReady()) {
  74. called = true;
  75. document.removeEventListener('readystatechange', listener, false);
  76. fn();
  77. }
  78. };
  79. document.addEventListener('readystatechange', listener, false);
  80. }
  81. };
  82.  
  83. var removeUnderscores = function removeUnderscores(url) {
  84. return url.replace(/______/g, '.');
  85. };
  86.  
  87. var parseJump = function parseJump(url) {
  88. var _parseUrl = parseUrl(url),
  89. hostname = _parseUrl.hostname,
  90. search = _parseUrl.search;
  91.  
  92. if (hostname !== 'www.viidii.info') {
  93. return null;
  94. }
  95.  
  96. var simple = /^\?https?:\/\//.test(search);
  97.  
  98. if (simple) {
  99. return removeUnderscores(search.slice(1));
  100. }
  101.  
  102. var query = parseQuery(search.slice(1));
  103.  
  104. return query.url;
  105. };
  106.  
  107. var isAllowLink = function isAllowLink(url, allowLinks) {
  108. var jump = parseJump(url);
  109. if (!jump) {
  110. return true;
  111. }
  112. for (var i = 0; i < allowLinks.length; ++i) {
  113. var allowLink = allowLinks[i];
  114. if (jump.indexOf(allowLink) !== -1) {
  115. return true;
  116. }
  117. }
  118.  
  119. return false;
  120. };
  121.  
  122. var hide = function hide(el) {
  123. // eslint-disable-next-line no-param-reassign
  124. el.style.display = 'none';
  125. };
  126.  
  127. var findContainer = function findContainer(el) {
  128. var curr = el;
  129. while (curr.parentNode.childNodes.length === 1) {
  130. curr = curr.parentNode;
  131. }
  132. return curr;
  133. };
  134.  
  135. var shouldHideBr = function shouldHideBr(br) {
  136. var nextSibling = br.nextSibling;
  137.  
  138.  
  139. if (nextSibling && nextSibling.tagName) {
  140. if (nextSibling.tagName.toLowerCase() === 'br') {
  141. return true;
  142. }
  143.  
  144. if (nextSibling.style.display === 'none') {
  145. return true;
  146. }
  147. }
  148.  
  149. return false;
  150. };
  151.  
  152. var wrapImage = function wrapImage(img, link) {
  153. var el = document.createElement('a');
  154. el.href = link;
  155. el.referrerPolicy = 'no-referrer';
  156. el.target = '_blank';
  157.  
  158. var parentNode = img.parentNode,
  159. nextSibling = img.nextSibling;
  160.  
  161.  
  162. el.appendChild(img);
  163.  
  164. parentNode.insertBefore(el, nextSibling);
  165. };
  166.  
  167. var parseOnClick = function parseOnClick(img, onClick) {
  168. if (!/^window\.open\(/.test(onClick)) {
  169. return null;
  170. }
  171.  
  172. var matches = onClick.match(/https?:\/\/[^'"]+/);
  173.  
  174. if (!matches) {
  175. return null;
  176. }
  177.  
  178. return matches[0];
  179. };
  180.  
  181. var allowLinks = ['rmdown.com', '88files.net', 'pan.com'];
  182.  
  183. var imgRules = {
  184. 'imagetwist.com': ['/th/', '/i/'],
  185. 'img599.net': ['.th.', '.'],
  186. 'img588.net': ['.th.', '.']
  187. };
  188.  
  189. var getImageRect = function getImageRect(url) {
  190. return new Promise(function (resolve) {
  191. var img = new Image();
  192. img.onerror = function () {
  193. return resolve([0, 0]);
  194. };
  195.  
  196. img.onload = function () {
  197. return resolve([img.naturalWidth, img.naturalHeight]);
  198. };
  199.  
  200. img.src = url;
  201. });
  202. };
  203.  
  204. var detectImgUrl = function detectImgUrl(url) {
  205. var _parseUrl = parseUrl(url),
  206. hostname = _parseUrl.hostname;
  207.  
  208. var matches = hostname.match(/[^.]+\.[^.]+$/);
  209.  
  210. if (!matches) {
  211. return null;
  212. }
  213.  
  214. var top = matches[0];
  215.  
  216. if (!hasOwnProperty(imgRules, top)) {
  217. return null;
  218. }
  219.  
  220. var _imgRules$top = imgRules[top],
  221. find = _imgRules$top[0],
  222. replacement = _imgRules$top[1];
  223.  
  224. var transformed = url.replace(find, replacement);
  225. var jpeg = transformed.replace('.jpg', '.jpeg');
  226.  
  227. var promises = [getImageRect(transformed)];
  228.  
  229. promises.push(jpeg !== transformed ? getImageRect(jpeg) : [0, 0]);
  230.  
  231. var limit = 200 * 200;
  232.  
  233. return Promise.all(promises).then(function (_ref) {
  234. var _ref$ = _ref[0],
  235. w = _ref$[0],
  236. h = _ref$[1],
  237. _ref$2 = _ref[1],
  238. wJ = _ref$2[0],
  239. hJ = _ref$2[1];
  240.  
  241. var size = w * h;
  242. var sizeJ = wJ * hJ;
  243. if (sizeJ > size && sizeJ > limit) {
  244. return jpeg;
  245. } else if (size > limit) {
  246. return transformed;
  247. }
  248. return null;
  249. });
  250. };
  251.  
  252. var init = function init() {
  253. // hide non-allow links
  254. querySelectorAll('.tpc_content a').forEach(function (a) {
  255. var attr = a.getAttribute('onclick');
  256. if (attr && attr.indexOf('iframe')) {
  257. hide(a);
  258. return;
  259. }
  260.  
  261. var allow = a.querySelector('img') || isAllowLink(a.href, allowLinks);
  262.  
  263. if (!allow) {
  264. var container = findContainer(a);
  265. hide(container);
  266. } else {
  267. // do nothing
  268. }
  269. });
  270.  
  271. // hide gif images
  272. querySelectorAll('.tpc_content iframe').forEach(hide);
  273.  
  274. // hide gif images
  275. querySelectorAll('.tpc_content img').forEach(function (image) {
  276. var isGif = image.src.indexOf('.gif') !== -1;
  277. if (isGif) {
  278. hide(image);
  279. }
  280. });
  281.  
  282. // hide unnecessary <br>
  283. querySelectorAll('.tpc_content br').forEach(function (br) {
  284. if (shouldHideBr(br)) {
  285. hide(br);
  286. }
  287. });
  288.  
  289. // rewrite img
  290. querySelectorAll('.tpc_content img').forEach(function (img) {
  291. var url = parseOnClick(img, img.getAttribute('onclick'));
  292.  
  293. if (img.style.display === 'none') {
  294. return;
  295. }
  296.  
  297. if (!url) {
  298. return;
  299. }
  300.  
  301. img.removeAttribute('onclick');
  302.  
  303. // eslint-disable-next-line no-param-reassign
  304. img.onclick = null;
  305.  
  306. wrapImage(img, url);
  307. });
  308.  
  309. // rewrite links
  310. querySelectorAll('.tpc_content a').forEach(function (a) {
  311. // eslint-disable-next-line no-param-reassign
  312. a.referrerPolicy = 'no-referrer';
  313.  
  314. var url = parseJump(a.href);
  315.  
  316. if (url) {
  317. // eslint-disable-next-line no-param-reassign
  318. a.href = url;
  319. }
  320. });
  321.  
  322. querySelectorAll('.tpc_content a>img').forEach(function (img) {
  323. return Promise.resolve(detectImgUrl(img.src)).then(function (url) {
  324. if (url) {
  325. // eslint-disable-next-line no-param-reassign
  326. img.parentNode.href = url;
  327. }
  328. });
  329. });
  330. };
  331.  
  332. ready(init);
  333.  
  334. }());