Sleazy Fork is available in English.

Xtube Enhancer - Animated Thumbnails, Inline Video Loading, and Sponsor/Premium-Free Videos

Animates thumbnails, inlines video loading, and cleans up sponsored content

  1. // ==UserScript==
  2. // @name Xtube Enhancer - Animated Thumbnails, Inline Video Loading, and Sponsor/Premium-Free Videos
  3. // @description Animates thumbnails, inlines video loading, and cleans up sponsored content
  4. // @namespace xtube
  5. // @version 4.3.3
  6. // @include http*://www.xtube.com/*
  7. // @require http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
  8. // @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. const thumbSelectors = [
  13. '#mainSection > section > div > ul > li > article > a > div > div > img',
  14. '#mainSection > ul > li > article > a > div > div > img',
  15. '#tabVideos > ul > li > article > a > div > div > img',
  16. 'div.mainContent>ul>li>article>a>div>div>img',
  17. '[id*="vid_id_"]',
  18. '[id*="2_frame"]> a > img',
  19. '#tabMorefromthisuser > ul > li > article > a > div > div > img',
  20. '#mainSection > div > div > div > ul > li > article > a > div > div > img',
  21. '#contentVideos > div > div > ul > li > article > a > div > div.imageWrapper.video > img',
  22. '#tabVideos > div > ul > li > article > a > div > div.imageWrapper.video > img',
  23. '#contentActivities > div > div > ul > li > article > a > img',
  24. '#relatedVideoCarousel > ul > li.item.active > ul > li > article > a > div > div > img',
  25. ];
  26.  
  27. const scoreArchiveSelectors = [
  28. ['#mainSection > section > div > ul > li', '#mainSection > section > div > ul'],
  29. ['#mainSection > section > div.mainContent > ul > li', '#mainSection > section > div.mainContent > ul'],
  30. ['#mainSection > section > div > div > ul > li', '#mainSection > section > div > div > ul'],
  31. ['#tabVideos > div > ul > li', '#tabVideos > div > ul'],
  32. ['#tabVideos > ul > li', '#tabVideos > ul'],
  33. ['#mainSection > ul > li', '#mainSection > ul']
  34. ];
  35.  
  36. const linkSelectors = [
  37. '#mainSection > section > div > div > ul > li > article > a:nth-child(1)',
  38. '#mainSection > ul > li > article > a:nth-child(1)',
  39. ];
  40.  
  41. jQuery(document).ready(function($) {
  42. let route = location.pathname.split('/')[1];
  43. let state = localStorage.getItem('__xte__');
  44. let watched = localStorage.getItem('__watched__');
  45.  
  46. const addWatchedVideo = (url) => {
  47. if (watched.includes(url)) return;
  48.  
  49. watched.push(url);
  50.  
  51. url = _.uniq(url);
  52.  
  53. localStorage.setItem('__watched__', JSON.stringify(watched));
  54. }
  55.  
  56. if (!state) {
  57. state = {showPremium: false};
  58. localStorage.setItem('__xte__', JSON.stringify(state));
  59. } else {
  60. state = JSON.parse(state);
  61. }
  62.  
  63. if (!watched) {
  64. watched = [];
  65. localStorage.setItem('__watched__', JSON.stringify(watched));
  66. } else {
  67. watched = JSON.parse(watched);
  68. }
  69.  
  70. if (route === 'video-watch') {
  71. addWatchedVideo(location.href);
  72. }
  73.  
  74. $(`<div title="Xtube Enhancer Settings" class="form-group" style="position: relative; top: 11px; left: 230px; color: #fff;">
  75. <label style="font-size: 12px; font-weight: 500;">Show premium videos:</label>
  76. <input type="checkbox" id="xte1" value="${state.showPremium}" style="margin-top: 1px;">
  77. </div>`
  78. ).insertAfter(
  79. '#searchForm'
  80. );
  81.  
  82. if (state.showPremium) {
  83. $('#xte2').text(' Enabled');
  84. $('#xte1').attr('checked', 'checked')
  85. }
  86.  
  87. $('#xte1').on('click', function(e) {
  88. state.showPremium = !state.showPremium;
  89. localStorage.setItem('__xte__', JSON.stringify(state))
  90. location.reload();
  91. });
  92.  
  93.  
  94.  
  95. setTimeout(function() {
  96. $('div.advertisement').remove();
  97. $('a.clearfix').remove();
  98. $('li.pull-right').remove();
  99. $('h2.h1').remove();
  100. $('section.overviewPage>div:nth-child(5)').remove();
  101. $('body > div > div.container > div > div').remove();
  102. $('#mainSection > a').remove();
  103. $('[class*="Promotion"]').remove();
  104. $('[class*="Banner"]').remove();
  105. $('.lineSeparator').remove();
  106.  
  107. $('.panelBottomSpace').each(function() {
  108. if (!$(this).children().length) {
  109. $(this).remove();
  110. }
  111. });
  112. }, 500);
  113. let selectors = [
  114. '#mainSection > section > div > ul > li',
  115. '#tabVideos > ul > li',
  116. '#mainSection > ul > li',
  117. '#mainSection > section > div.mainContent > ul > li',
  118. '#mainSection > section > div > div > ul > li',
  119. 'section.row>div>div>ul>li'
  120. ];
  121. let keywords = ['premium', 'preview', 'xtube_sponsor', 'ambassador', 'verified'];
  122.  
  123. $('#mainSection > div > div > section.cntPanel > article.box.contentInfo.hasButtonFooter').insertAfter('#mainSection > div > div > section.cntPanel > div.playerWrapper.videoWrapper');
  124. $('body > div > div.container > div').remove();
  125.  
  126. const removeSpam = function() {
  127. const handleSelector = function(selector) {
  128. $(selector).each(function() {
  129. if ($(this).find('article > a:nth-child(1) > h3').text().trim().indexOf($(this).find('article > a.userLink.ellipsis').text().trim().split('by ')[1]) !== -1) {
  130. $(this).remove();
  131. } else {
  132. if ($(this).find('article > a:nth-child(1) > h3').text().trim().indexOf('*****') !== -1) {
  133. let titleBegin = $(this).find('article > a:nth-child(1) > h3').text().trim().split('*****')[0];
  134. if (titleBegin === $(this).find('article > a.userLink.ellipsis').text().trim().split('by ')[1].substring(0, titleBegin.length)) {
  135. $(this).remove();
  136. }
  137. }
  138. }
  139. for (let i = 0; i < keywords.length; i++) {
  140. let keyword = keywords[i];
  141. if ($(this).find('article > a').text().toLowerCase().includes(keyword)) {
  142. $(this).remove();
  143. }
  144. if ($(this).find('article > a > div > span > span').text().toLowerCase().includes(keyword)) {
  145. $(this).remove();
  146. }
  147. if ($(this).find('article>a>span>span').text().toLowerCase() === keyword || $(this).find('article>a>div>span>span').text() === keyword) {
  148. $(this).remove();
  149. }
  150. if ($(this).find('article>dl>dd>a').text().toLowerCase() === keyword) {
  151. }
  152. if ($(this).find('article>a>span>span').text().toLowerCase() === keyword) {
  153. $(this).remove();
  154. }
  155. let img = $(this).find('article > div > div.userLink > div > a > img')
  156. if (img && img[0] && img[0].src.indexOf('Sponsor') > -1) {
  157. $(this).remove();
  158. }
  159. let duration = $(this).find('article > a.titleRemover.js-pop > div > span.duration');
  160. if (duration && duration.text().indexOf('0:1') > -1) {
  161. $(this).remove();
  162. }
  163. }
  164. });
  165. };
  166. // v2 - Remove videos that have similar title and author strings
  167. if (!state.showPremium) {
  168. for (let i = selectors.length - 1; i >= 0; i--) {
  169. if ($(selectors[i]).length > 0) {
  170. try {
  171. handleSelector(selectors[i]);
  172. } catch (e) {console.log(e)}
  173. }
  174. }
  175. // Kill profile ads
  176. $('#mainSection > section > div > ul > li > article').each(function(i, el) {
  177. if ($(el).hasClass('profile')) $(el).remove();
  178. });
  179. $('.weeklyTopAmateurVideoPlaceholder').each(function(i, el) {
  180. $(el).parent().remove();
  181. });
  182. }
  183. };
  184. removeSpam();
  185.  
  186. const cleanVidPage = function() {
  187. $('#mainSection > div > aside > div.cntPanel').remove();
  188. $('#mainSection > div > div > section.cntPanel > div.onderSellamPlayer').remove();
  189. let relatedVideos = null;
  190. $('div#related_videos>div').each(function() {
  191. relatedVideos = $(this).text().split(' ');
  192. for (let i = relatedVideos.length - 1; i >= 0; i--) {
  193. if (relatedVideos[i] === '0:15') {
  194. $(this).prev().remove();
  195. $(this).remove();
  196. }
  197. }
  198. });
  199. // Remove sponsored content below video player.
  200. $('div#watchPageLeft>div>div').each(function() {
  201. if ($(this).find('a>span:nth-child(3)').text() === '0:15') {
  202. $(this).remove();
  203. }
  204. });
  205. // Remove sponsored content in full related videos view.
  206. $('div.Card-list>article').each(function() {
  207. if ($(this).find('div>div>div:nth-child(3)').text() === '0:15') {
  208. $(this).remove();
  209. }
  210. });
  211. // Remove footer ad.
  212. $('#mainSection > div > div > div.onderSellamPlayer').remove();
  213. $('.underPlayerBanner').remove();
  214. // Remove "Ads by Traffic Junky"
  215. // $('#mainSection > div > div > div.expandStage > div.playerWrapper > div > div > div.header').remove();
  216. // $('body.desktopView.hasFooterAd .mainSection').css({paddingBottom: '0px'});
  217. // $('#xtubePlayer > div:nth-child(1)').remove();
  218. // $('#playerWrapper > div > p').remove();
  219. //$('#playerWrapper > div > a').unwrap();
  220. };
  221. cleanVidPage();
  222. let paused = false;
  223. let animateThumbnails = function(selector) {
  224. let content = _.isString(selector) ? $(selector) : selector;
  225. if (content.length > 0) {
  226. content.each(function(i, el) {
  227. let originalSrc = $(el).attr('src');
  228. let setAnimations = () => {
  229. try {
  230. // let clone = $(el).clone();
  231. // clone.insertBefore($(el));
  232. // $(el).hide();
  233. el.__animation = [];
  234. let images;
  235. let _src = $(this).attr('src');
  236. let src = _src.split('/');
  237. let regexp = /_(\d\d\d\d)\.jpg$/;
  238. let match = _src.match(regexp);
  239.  
  240. if (_.last(src).length <= 6 || match) {
  241. let imgSrc;
  242. let n = -1;
  243.  
  244. if (match) {
  245. images = ['_0000.jpg', '_0001.jpg', '_0002.jpg', '_0003.jpg', '_0004.jpg', '_0005.jpg', '_0006.jpg', '_0007.jpg', '_0008.jpg', '_0009.jpg', '_0010.jpg', '_0011.jpg', '_0012.jpg', '_0013.jpg', '_0014.jpg'];
  246. imgSrc = _src.split(match[0])[0];
  247. } else {
  248. images = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg', '7.jpg', '8.jpg', '9.jpg', '10.jpg', '11.jpg', '12.jpg', '13.jpg', '14.jpg', '15.jpg'];
  249. let src3 = _.without(src, _.last(src));
  250. imgSrc = src3.join('/') + '/';
  251. }
  252.  
  253. for (let z = 0; z < images.length; z++) {
  254. el.__animation.push(imgSrc + images[z]);
  255. }
  256.  
  257. let animate = function() {
  258. if (el.__timeout) clearTimeout(el.__timeout);
  259.  
  260. el.onload = () => el.__timeout = setTimeout(animate, 500);
  261. el.onerror = () => {
  262. n = -1;
  263. el.onload();
  264. };
  265.  
  266. if (!paused) {
  267. let newSrc = el.__animation[++n];
  268. if (!newSrc) {
  269. n = 0;
  270. newSrc = el.__animation[0];
  271. }
  272. el.src = newSrc;
  273. }
  274.  
  275. };
  276. animate();
  277. }
  278. } catch (e) {console.log(e)}
  279. };
  280. let related = $('#mainSection > div > div > div.cntPanel.relatedVideosPanel');
  281. if (related.length) {
  282. paused = true;
  283. related.on('mouseenter', function() {
  284. paused = false;
  285. })
  286. related.on('mouseleave', function() {
  287. paused = true;
  288. })
  289. }
  290. if (originalSrc.indexOf('placehold') === -1) {
  291. setAnimations();
  292. } else {
  293. el.onload = function() {
  294. setTimeout(() => setAnimations(), 0);
  295. };
  296. }
  297. });
  298. }
  299. };
  300.  
  301. // Animate thumbnails
  302. $('#relatedVideoCarousel > footer').on('click', function() {
  303. animateThumbnails('#relatedVideoCarousel > ul > li > ul > li > article > a > div > div > img');
  304. });
  305. setTimeout(function() {
  306. for (let i = 0; i < thumbSelectors.length; i++) {
  307. if ($(thumbSelectors[i]).length > 0) {
  308. animateThumbnails(thumbSelectors[i]);
  309. }
  310. }
  311.  
  312. // Order each page by best score
  313. let __videos = [];
  314. let orderByScore = function(selector1, selector2) {
  315. $(selector1).each(function(i, el) {
  316. let views = parseInt($(el).find('article > div > div > div.metaInfoRight > span:nth-child(1)').text().trim().split('%')[0]);
  317. let score = parseInt($(el).find('article > div > div > div.metaInfoRight > span:nth-child(2)').text().trim().split('%')[0]);
  318. let duration = parseInt($(el).find('.videoDuration').text().trim().split(/\s+/)[0].replace(/:/g, ''));
  319.  
  320. if (isNaN(views)) {
  321. views = parseInt($(el).find('article > div > div.metaInfoRight > span.viewCounter').text().trim().split('%')[0]);
  322. }
  323.  
  324. if (isNaN(score)) {
  325. score = parseInt($(el).find('article > div > div.metaInfoRight > span.voting.score.like').text().trim().split('%')[0]);
  326. }
  327.  
  328. duration = isNaN(duration) ? 0 : duration;
  329.  
  330. __videos.push({
  331. score: isNaN(score) ? 0 : score,
  332. views: isNaN(views) ? 0 : views,
  333. duration,
  334. el: el
  335. });
  336.  
  337. $(el).remove();
  338. });
  339.  
  340. __videos = _.chain(__videos).orderBy(['score', 'duration', 'views'], ['asc', 'asc', 'asc']).uniq().value().reverse();
  341.  
  342. $(selector2).each(function(el) {
  343. $(el).remove();
  344. });
  345.  
  346. _.each(__videos, function(vid) {
  347. $(selector2).eq(0).append($(vid.el));
  348. });
  349. };
  350.  
  351. for (let z = scoreArchiveSelectors.length - 1; z >= 0; z--) {
  352. if ($(scoreArchiveSelectors[z][0]).length > 0) {
  353. orderByScore(scoreArchiveSelectors[z][0], scoreArchiveSelectors[z][1]);
  354. }
  355. }
  356.  
  357. for (let i = 0, len = linkSelectors.length; i < len; i++) {
  358. $(linkSelectors[i]).each((i, el) => {
  359. let duration = $(el).find('.videoDuration');
  360. let durationText = duration.text();
  361.  
  362. if (watched.indexOf(el.href) > -1) {
  363. duration.text(`${durationText}‎‎‎‏‏‎‏‏‎ ‎‏‏‎ ‎‏‎‏ ‎✓ Watched`);
  364. }
  365.  
  366. $(el).on('click', (e) => {
  367. e.preventDefault();
  368.  
  369. addWatchedVideo(el.href);
  370. duration.text(`${durationText}‏‏‎‏‏‎ ‎‏‏‎ ‎‏‏‎‏‏‎ ‎✓ Watched`);
  371.  
  372. window.open(el.href);
  373. })
  374. });
  375. }
  376.  
  377. setTimeout(() => {
  378. removeSpam();
  379. $('#mainSection > section > div > ul > li.col-xs-12.col-s-12.col-l-8.col10-xl-2.col-xxl-4').remove();
  380. }, 6000);
  381. }, 0);
  382. });