Greasy Fork is available in English.

YouTube Like/Dislike Shortcut

Enables keyboard shortcuts to like/dislike a video on YouTube.

// ==UserScript==
// @name               YouTube Like/Dislike Shortcut
// @name:pt-BR         Atalhos Gostei/Não Gostei no YouTube
// @namespace          will64gamer
// @author             will64gamer
// @description        Enables keyboard shortcuts to like/dislike a video on YouTube.
// @description:pt-BR  Cria atalhos para os botões gostei/não gostei em um vídeo no YouTube.
// @include            https://www.youtube.com/*
// @license            MIT
// @version            2.3
// ==/UserScript==

// You can change the codes to whichever keys you want to use for liking, disliking, and opening or writing comments on Shorts.
const codeLike = "NumpadAdd";
const codeDislike = "NumpadSubtract";
const codeComments = "NumpadMultiply";
const codeWrite = "NumpadDivide";

// Change this to false if you don't want Shorts to refresh on load.
const shortsRefresh = true;

let isShort = false;
let tag, like, dislike, sLike, sDislike, comments, closeComments, textbox, initialRefresh;

const observer = new MutationObserver(findButtons);

addEventListener('yt-page-data-updated', reset);
addEventListener('popstate', reset);

function reset() {
  isVideo = /^\/watch/.test(location.pathname);
  isShort = /^\/shorts/.test(location.pathname);
  if (isVideo||isShort) {
    removeEventListener("keydown", press);
    like = null; dislike = null; sLike = null; sDislike = null; comments = null; closeComments = null; textbox = null;
    observer.observe(document.documentElement, {childList: true, subtree: true});
    findButtons();
  } else {initialRefresh = true;}
}

function findButtons() {
  if ((like && dislike) || (sLike && sDislike && comments)) {
    addEventListener("keydown", press);
    observer.disconnect();
    let currentURL = location.href;
    if (isShort && shortsRefresh) {
      let shortInterval = setInterval(() => {
        if (location.href !== currentURL) {
          clearInterval(shortInterval);
          location.reload();
          }
        }, 400);
    } else if (isVideo) {initialRefresh = true;}
  }

  if (isShort) {
    if (initialRefresh) {
      initialRefresh = false;
      location.reload();
    }
    sLike = document.getElementById("like-button")?.getElementsByTagName('button')[0];
    sDislike = document.getElementById("dislike-button")?.getElementsByTagName('button')[0];
    comments = document.getElementById("comments-button")?.getElementsByTagName('button')[0];
  } else {
    like = document.getElementsByTagName("like-button-view-model")[0]?.firstElementChild?.firstElementChild?.firstElementChild;
    dislike = document.getElementsByTagName("dislike-button-view-model")[0]?.firstElementChild?.firstElementChild?.firstElementChild;
  }
}

function openComments() {
  comments.click();
  let closeCommentsInterval = setInterval(() => {
    if (!closeComments) {
      closeComments = document.getElementById("visibility-button")?.getElementsByTagName('button')[0];
    } else {
      clearInterval(closeCommentsInterval);
    }
  }, 300);
}

function press(e) {
  if (e.target.getAttribute("contenteditable") === "true") {return;}

  tag = e.target.tagName.toLowerCase();
  if (tag === "input" || tag === "textarea") {return;}

  switch (e.code) {
    case codeComments:
      if (comments) {
        if (closeComments) {
          closeComments.click();
          closeComments = null;
        } else {
          openComments();
        }
      }
      break;
    case codeWrite:
      if (textbox) {
        openComments();
        setTimeout(() => {
          textbox.click();
        }, 100);
      } else if (comments) {
        openComments();
        let textboxInterval = setInterval(() => {
          if (!textbox) {
            textbox = document.getElementById("simplebox-placeholder");
          } else {
            textbox.focus();
            clearInterval(textboxInterval);
          }
        }, 300);
      }
      break;
    case codeLike:
      if (like) {like.click();}
      else if (sLike) {sLike.click();}
      break;
    case codeDislike:
      if (dislike) {dislike.click();}
      else if (sDislike) {sDislike.click();}
      break;
  }
}