Youtube: expand description and long comments; show all the replies

Video description, long comments and list of subscriptions are expanded automatically; all the replies are shown after pressing "View all N replies" button

当前为 2022-12-16 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name          Youtube: expand description and long comments; show all the replies
// @description   Video description, long comments and list of subscriptions are expanded automatically; all the replies are shown after pressing "View all N replies" button
// @author        MK
// @namespace     max44
// @homepage      https://greasyfork.org/en/users/309172-max44
// @match         *://*.youtube.com/*
// @match         *://*.youtu.be/*
// @icon          https://cdn.icon-icons.com/icons2/1488/PNG/512/5295-youtube-i_102568.png
// @version       1.1.1
// @license       MIT
// @grant         none
// @require       https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @run-at        document-idle
// ==/UserScript==

(function () {
  'use strict';

  var videoIdAtLastCheck = "";
  var btnClick = null;
  var waitVideo;
  var i;

  //Listen to page changes
  const rootCallback = function (mutationsList, observer) {

    //Check whether video is new to expand description
    var pathArray = window.location.pathname.split('/');
    var firstPath = pathArray[1];
    if (firstPath === "watch") {
      waitVideo = setInterval(function() { //Wait for video
        var player = $( "div#content ytd-watch-flexy" );
        if (player != null && player.length > 0) {
          clearInterval(waitVideo); //Stop waiting for video
          var videoId = player[0].getAttribute("video-id");
          player = null;

          if (videoIdAtLastCheck != videoId) {
            videoIdAtLastCheck = videoId;
            //console.log("new video");
            expandDesc();
          }
        }
      }, 100);
    }

    /*//Detect spinner at main comments
    var spinnerMain = $( "#primary div#replies div#expander tp-yt-paper-spinner#spinner[active]" );
    if (spinnerMain != null && spinnerMain.length > 0) {
      console.log("main active spinner detected");
      spinnerActive = true;

      //Listen to spinner changes
      const spinnerCallback = function (mutationsList, observer) {
        expandComments();

        //spinnerMain = $( "#primary div#replies div#expander tp-yt-paper-spinner#spinner[active]" );
        if (spinnerMain[0].getAttribute("active") == null || spinnerMain[0].getAttribute("active") == "") {
          console.log("main spinner deactivated");
          spinnerObserver.disconnet();
        }
      }

      var spinnerNode = document.querySelector("#primary div#replies div#expander tp-yt-paper-spinner#spinner[active]");
      if (spinnerNode != null) {
        const spinnerObserver = new MutationObserver(spinnerCallback);
        spinnerObserver.observe(spinnerNode, {childList: true, subtree: true, attributes: true});
      }

    } else if (spinnerActive) {
      console.log("spinner stopped");
      spinnerActive = false;
      expandComments();
    }*/

    //Expand on any change of content
    expandSubs();
    expandComPost();
    expandComments();
  }

  const rootNode = document.querySelector("body");
  if (rootNode != null) {
    const rootObserver = new MutationObserver(rootCallback);
    //console.log("body observer added");
    rootObserver.observe(rootNode, {childList: true, subtree: true, attributes: true});
  }

  //Listen to replies changes
  /*const repliesCallback = function (mutationsList, observer) {
    expandComments();
  }

  const repliesNode = document.querySelector("div#replies div#expander-contents");
  if (repliesNode != null) {
    const repliesObserver = new MutationObserver(repliesCallback);
    console.log("replies observer added");
    repliesObserver.observe(repliesNode, {childList: true, subtree: true, attributes: true});
  }*/

  /*//Check what buttons to click after each scroll of main window
  $( window ).scroll(function() {
    //expandComPost();
    expandComments();
  });*/


  //---------------------------------------
  // Expand description
  //---------------------------------------
  function expandDesc() {
    //Expand description
    btnClick = $( "div#description ytd-text-inline-expander tp-yt-paper-button#expand[role='button']:not([hidden=''])" );
    if (btnClick != null && btnClick.length > 0) {// && isVisible(btnClick)) {
      btnClick[0].click();
    }

    //Expand description after 7ktTube | 2016 REDUX script
    btnClick = $( "div#meta-contents ytd-video-secondary-info-renderer div ytd-expander tp-yt-paper-button#more:not([hidden=''])" );
    if (btnClick != null && btnClick.length > 0) {// && isVisible(btnClick)) {
      btnClick[0].click();
    }
  }

  //---------------------------------------
  // Expand post in community section
  //---------------------------------------
  function expandComPost() {
    btnClick = $( "div#post ytd-expander#contentTextExpander tp-yt-paper-button#more[role='button']:not([hidden='']):not([clicked-by-script='true'])" );
    if (btnClick != null && btnClick.length > 0) {
      btnClick[0].click();
      btnClick[0].setAttribute("clicked-by-script", "true"); //Do not click it again
    }
  }

  //---------------------------------------
  // Expand comments
  //---------------------------------------
  function expandComments() {

    //Expand long comments and hide "show less" button in comments section
    btnClick = $( "#primary ytd-comment-renderer #comment-content tp-yt-paper-button#more:not([hidden='']) > span.more-button[slot='more-button']:not([clicked-by-script='true'])" );
    if (btnClick != null) {
      for (i = 0; i < btnClick.length; i++) {
        btnClick[i].click();
        btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again
        btnClick[i].parentNode.previousElementSibling.setAttribute("style", "display:none;"); //Hide "Show less" button
      }
    }

    //Expand long comments and hide "show less" button in notification submenu
    btnClick = $( "#submenu ytd-comment-renderer #comment-content tp-yt-paper-button#more:not([hidden='']) > span.more-button[slot='more-button']:not([clicked-by-script='true'])" );
    if (btnClick != null) {
      for (i = 0; i < btnClick.length; i++) {
        btnClick[i].click();
        btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again
        btnClick[i].parentNode.previousElementSibling.setAttribute("style", "display:none;"); //Hide "Show less" button
      }
    }

    //Show all replies upon pressing "Show more replies" button
    btnClick = $( "#primary div#replies div#expander div#button.ytd-continuation-item-renderer ytd-button-renderer.ytd-continuation-item-renderer button.yt-spec-button-shape-next:not([clicked-by-script='true'])" );
    if (btnClick != null) {
      for (i = 0; i < btnClick.length; i++) {
        btnClick[i].click();
        btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again
      }
    }

    //Show all replies upon pressing "View all N replies" button (7ktTube | 2016 REDUX script)
    btnClick = $( "#primary div#replies div#expander div#button.ytd-continuation-item-renderer ytd-button-renderer tp-yt-paper-button#button[role='button']:not([clicked-by-script='true'])" );
    if (btnClick != null) {
      for (i = 0; i < btnClick.length; i++) {
        btnClick[i].click();
        btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again
      }
    }
  }

  //---------------------------------------
  // Show all subscriptions
  //---------------------------------------
  function expandSubs() {
    btnClick = $( "#guide div#sections div#items ytd-guide-collapsible-entry-renderer.ytd-guide-section-renderer[can-show-more=''] #expander-item:not([clicked-by-script='true'])" );
    if (btnClick != null) {
      for (i = 0; i < btnClick.length; i++) {
        btnClick[i].click();
        btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again
      }
    }
  }

  //---------------------------------------
  // Check all the parents of element to find whether it is visible or not
  //---------------------------------------
  function isVisible(pObj) {
    if (pObj != null) {
      var checkNext = true;
      var vObj = pObj;

      while (checkNext) {
        checkNext = false;
        //console.log("checking element " + vObj.tagName + "#" + vObj.id + ": '" + document.defaultView.getComputedStyle(vObj,null)['display'] + "'");
        if (document.defaultView.getComputedStyle(vObj,null)['display'] != "none") {
          if (vObj.parentElement != null) {
            vObj = vObj.parentElement;
            checkNext = true;
          }
        } else {
          return false;
        }
      }
      return true;
    }
    return false;
  }

})();