AnnouncementsMatrixEventsFunnyVideosMusicAncapsTechnologyEconomicsPrivacyGIFSCringeAnarchyFilmPicsThemesIdeas4MatrixAskMatrixHelpTop Subs
2

So I wrote this userscript to hide long time waste videos. This sort of solves part of the problem DeArrow solves but it addresses it in a different route. I find 70% of videos over 20 minutes on youtube are fully invested in a model of using a clickbait title and thumbnail, having 5 seconds of meaningful content related to the hook, and 20 minutes plus of fluff.

Most television episodes are about 20 minutes long and a lot happens in them. It doesn't take 20 minutes to explain why ditto is actually an OP pokemon or some other meaningless fake consumer media bullshit.

It's just better if I don't even need to process those titles. They will always have the best ones because these are people really investing in hacking people to waste time.

But videos that are under 20 minutes are the opposite. They have more value, not even per second, but in total. They have to plan what they are going to say, figure out how to communicate it efficiently, and then actually edit the content. Forcing creators through that process makes them produce something that's good, where they are delivering value to the viewer instead of trying to vampire time.

So this userscript is pretty freqin good. Better than DeArrow. DeArrow makes it harder for low value videos to sell themselves. This doesn't even show them. It would be good if I didn't have to hunt down new selectors every other day.

It needs to know just two selectors. First one is to be able to find the duration elements. Second one is to go up the tree stopping where we have all of the content for the suggestion but not beyond that.

If there was more than one person using it I could have it check a server for up to date selectors.

See how many CARD_NODES and TIME_NODES selectors I have. I just add one more to the list when it breaks.

// ==UserScript==
// @name        YouTube: Hide 20+ Minute Videos
// @version     1.0.0
// @description Auto-hides YouTube videos longer than 20 minutes.  This reduces distraction from long winded clickbait, fixes pacing, and saves time.
// @match       https://www.youtube.com/*
// @run-at      document-start
// @grant       none
// ==/UserScript==
 var exports = {};
 window.youtubehide = exports;
 var LIMIT = 20*60;
 var TIME_NODES = [
  '.yt-badge-shape__text',
  'ytd-thumbnail-overlay-time-status-renderer span',
  'span.ytd-thumbnail-overlay-time-status-renderer',
  '.badge-shape-wiz__text'
 ].join(',');
 var CARD_NODES = [
  '.ytd-item-section-renderer',
  'yt-lockup-view-model',
  'ytd-rich-item-renderer',
  'ytd-video-renderer',
  'ytd-compact-video-renderer',
  'ytd-grid-video-renderer',
  'ytd-playlist-video-renderer',
  'ytd-playlist-panel-video-renderer'
 ].join(',');
 exports.addStyle = addStyle;
 function addStyle(){
  if (document.getElementById('yt-hide-long-style')) return;
  var s = document.createElement('style');
  s.id = 'yt-hide-long-style';
  s.textContent = '.yt-hide-long{display:none!important}';
  document.documentElement.appendChild(s);
 }
 exports.parseSeconds = parseSeconds;
 function parseSeconds(txt){
  if (!txt || txt.indexOf(':')<0) return 0;
  txt = txt.trim().replace(/[^\d:]/g,'');
  var parts = txt.split(':');
  var sec = 0;
  for (var i=0;i<parts.length;i++) sec = sec*60 + (parseInt(parts[i],10)||0);
  return sec;
 }
 exports.scan = scan;
 function scan(root=document){
  var out = [];
  var els = root.querySelectorAll(TIME_NODES);
  for (var i=0;i<els.length;i++){
   var t = (els[i].textContent||'').trim();
   if (t.indexOf(':')<0) continue;
   var s = parseSeconds(t);
   if (s >= LIMIT){
    console.log('Bad',els[i]);
    var card = els[i].closest(CARD_NODES);
    if (card) {
     card.classList.add('yt-hide-long');
     out.push(card);
    }
   }
  }
  return out;
 }
 exports.start = start;
 function start(){
  if (!document.body) return setTimeout(start,50);
  addStyle();
  scan(document);
  var mo = new MutationObserver(function(muts){
   for (var i=0;i<muts.length;i++){
    var a = muts[i].addedNodes;
    for (var j=0;j<a.length;j++){
     var n = a[j];
     if (n && n.nodeType===1) scan(n);
    }
   }
  });
  mo.observe(document.body,{subtree:true,childList:true});
 }

 start();

function toadd__edit__wasadded() {
    document.querySelectorAll('.ytd-promoted-video-renderer').forEach(i=>i.closest('#contents').remove())
    document.querySelectorAll('ytd-in-feed-ad-layout-renderer').forEach(i=>i.remove())
}

(function(){
 var KILL = '.ytd-promoted-video-renderer, ytd-in-feed-ad-layout-renderer';
 function nuke(root){
  var els = root.querySelectorAll(KILL);
  for (var i=0;i<els.length;i++){
   var e = els[i];
   if (e.classList && e.classList.contains('ytd-promoted-video-renderer')){
    var p = e.closest('#contents');
    if (p) p.remove(); else e.remove();
   } else {
    e.remove();
   }
  }
 }
 function begin(){
  if (!document.body) return setTimeout(begin,50);
  nuke(document);
  var mo = new MutationObserver(function(m){
   for (var i=0;i<m.length;i++){
    var a = m[i].addedNodes;
    for (var j=0;j<a.length;j++){
     var n = a[j];
     if (n && n.nodeType===1) nuke(n);
    }
   }
  });
  mo.observe(document.body,{subtree:true,childList:true});
 }
 begin();
})();
Comment preview